Commit 873b779d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfs-for-3.5-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfixes from Trond Myklebust:
 "Highlights include:

   - Fix a couple of mount regressions due to the recent cleanups.
   - Fix an Oops in the open recovery code
   - Fix an rpc_pipefs upcall hang that results from some of the net
     namespace work from 3.4.x (stable kernel candidate).
   - Fix a couple of write and o_direct regressions that were found at
     last weeks Bakeathon testing event in Ann Arbor."

* tag 'nfs-for-3.5-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  NFS: add an endian notation for sparse
  NFSv4.1: integer overflow in decode_cb_sequence_args()
  rpc_pipefs: allow rpc_purge_list to take a NULL waitq pointer
  NFSv4 do not send an empty SETATTR compound
  NFSv2: EOF incorrectly set on short read
  NFS: Use the NFS_DEFAULT_VERSION for v2 and v3 mounts
  NFS: fix directio refcount bug on commit
  NFSv4: Fix unnecessary delegation returns in nfs4_do_open
  NFSv4.1: Convert another trivial printk into a dprintk
  NFS4: Fix open bug when pnfs module blacklisted
  NFS: Remove incorrect BUG_ON in nfs_found_client
  NFS: Map minor mismatch error to protocol not support error.
  NFS: Fix a commit bug
  NFS4: Set parsed mount data version to 4
  NFSv4.1: Ensure we clear session state flags after a session creation
  NFSv4.1: Convert a trivial printk into a dprintk
  NFSv4: Fix up decode_attr_mdsthreshold
  NFSv4: Fix an Oops in the open recovery code
  NFSv4.1: Fix a request leak on the back channel
parents 56b880e2 e216c8c7
...@@ -455,7 +455,7 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp, ...@@ -455,7 +455,7 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
args->csa_nrclists = ntohl(*p++); args->csa_nrclists = ntohl(*p++);
args->csa_rclists = NULL; args->csa_rclists = NULL;
if (args->csa_nrclists) { if (args->csa_nrclists) {
args->csa_rclists = kmalloc(args->csa_nrclists * args->csa_rclists = kmalloc_array(args->csa_nrclists,
sizeof(*args->csa_rclists), sizeof(*args->csa_rclists),
GFP_KERNEL); GFP_KERNEL);
if (unlikely(args->csa_rclists == NULL)) if (unlikely(args->csa_rclists == NULL))
...@@ -696,7 +696,7 @@ static __be32 encode_cb_sequence_res(struct svc_rqst *rqstp, ...@@ -696,7 +696,7 @@ static __be32 encode_cb_sequence_res(struct svc_rqst *rqstp,
const struct cb_sequenceres *res) const struct cb_sequenceres *res)
{ {
__be32 *p; __be32 *p;
unsigned status = res->csr_status; __be32 status = res->csr_status;
if (unlikely(status != 0)) if (unlikely(status != 0))
goto out; goto out;
......
...@@ -544,8 +544,6 @@ nfs_found_client(const struct nfs_client_initdata *cl_init, ...@@ -544,8 +544,6 @@ nfs_found_client(const struct nfs_client_initdata *cl_init,
smp_rmb(); smp_rmb();
BUG_ON(clp->cl_cons_state != NFS_CS_READY);
dprintk("<-- %s found nfs_client %p for %s\n", dprintk("<-- %s found nfs_client %p for %s\n",
__func__, clp, cl_init->hostname ?: ""); __func__, clp, cl_init->hostname ?: "");
return clp; return clp;
......
...@@ -523,9 +523,9 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data) ...@@ -523,9 +523,9 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
nfs_list_remove_request(req); nfs_list_remove_request(req);
if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) { if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) {
/* Note the rewrite will go through mds */ /* Note the rewrite will go through mds */
kref_get(&req->wb_kref);
nfs_mark_request_commit(req, NULL, &cinfo); nfs_mark_request_commit(req, NULL, &cinfo);
} } else
nfs_release_request(req);
nfs_unlock_and_release_request(req); nfs_unlock_and_release_request(req);
} }
...@@ -716,12 +716,12 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) ...@@ -716,12 +716,12 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES)
bit = NFS_IOHDR_NEED_RESCHED; bit = NFS_IOHDR_NEED_RESCHED;
else if (dreq->flags == 0) { else if (dreq->flags == 0) {
memcpy(&dreq->verf, &req->wb_verf, memcpy(&dreq->verf, hdr->verf,
sizeof(dreq->verf)); sizeof(dreq->verf));
bit = NFS_IOHDR_NEED_COMMIT; bit = NFS_IOHDR_NEED_COMMIT;
dreq->flags = NFS_ODIRECT_DO_COMMIT; dreq->flags = NFS_ODIRECT_DO_COMMIT;
} else if (dreq->flags == NFS_ODIRECT_DO_COMMIT) { } else if (dreq->flags == NFS_ODIRECT_DO_COMMIT) {
if (memcmp(&dreq->verf, &req->wb_verf, sizeof(dreq->verf))) { if (memcmp(&dreq->verf, hdr->verf, sizeof(dreq->verf))) {
dreq->flags = NFS_ODIRECT_RESCHED_WRITES; dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
bit = NFS_IOHDR_NEED_RESCHED; bit = NFS_IOHDR_NEED_RESCHED;
} else } else
......
...@@ -295,7 +295,7 @@ is_ds_client(struct nfs_client *clp) ...@@ -295,7 +295,7 @@ is_ds_client(struct nfs_client *clp)
extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[];
extern const u32 nfs4_fattr_bitmap[2]; extern const u32 nfs4_fattr_bitmap[3];
extern const u32 nfs4_statfs_bitmap[2]; extern const u32 nfs4_statfs_bitmap[2];
extern const u32 nfs4_pathconf_bitmap[2]; extern const u32 nfs4_pathconf_bitmap[2];
extern const u32 nfs4_fsinfo_bitmap[3]; extern const u32 nfs4_fsinfo_bitmap[3];
......
...@@ -105,6 +105,8 @@ static int nfs4_map_errors(int err) ...@@ -105,6 +105,8 @@ static int nfs4_map_errors(int err)
return -EINVAL; return -EINVAL;
case -NFS4ERR_SHARE_DENIED: case -NFS4ERR_SHARE_DENIED:
return -EACCES; return -EACCES;
case -NFS4ERR_MINOR_VERS_MISMATCH:
return -EPROTONOSUPPORT;
default: default:
dprintk("%s could not handle NFSv4 error %d\n", dprintk("%s could not handle NFSv4 error %d\n",
__func__, -err); __func__, -err);
...@@ -116,7 +118,7 @@ static int nfs4_map_errors(int err) ...@@ -116,7 +118,7 @@ static int nfs4_map_errors(int err)
/* /*
* This is our standard bitmap for GETATTR requests. * This is our standard bitmap for GETATTR requests.
*/ */
const u32 nfs4_fattr_bitmap[2] = { const u32 nfs4_fattr_bitmap[3] = {
FATTR4_WORD0_TYPE FATTR4_WORD0_TYPE
| FATTR4_WORD0_CHANGE | FATTR4_WORD0_CHANGE
| FATTR4_WORD0_SIZE | FATTR4_WORD0_SIZE
...@@ -133,6 +135,24 @@ const u32 nfs4_fattr_bitmap[2] = { ...@@ -133,6 +135,24 @@ const u32 nfs4_fattr_bitmap[2] = {
| FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_MODIFY
}; };
static const u32 nfs4_pnfs_open_bitmap[3] = {
FATTR4_WORD0_TYPE
| FATTR4_WORD0_CHANGE
| FATTR4_WORD0_SIZE
| FATTR4_WORD0_FSID
| FATTR4_WORD0_FILEID,
FATTR4_WORD1_MODE
| FATTR4_WORD1_NUMLINKS
| FATTR4_WORD1_OWNER
| FATTR4_WORD1_OWNER_GROUP
| FATTR4_WORD1_RAWDEV
| FATTR4_WORD1_SPACE_USED
| FATTR4_WORD1_TIME_ACCESS
| FATTR4_WORD1_TIME_METADATA
| FATTR4_WORD1_TIME_MODIFY,
FATTR4_WORD2_MDSTHRESHOLD
};
const u32 nfs4_statfs_bitmap[2] = { const u32 nfs4_statfs_bitmap[2] = {
FATTR4_WORD0_FILES_AVAIL FATTR4_WORD0_FILES_AVAIL
| FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_FREE
...@@ -844,6 +864,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, ...@@ -844,6 +864,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
p->o_arg.name = &dentry->d_name; p->o_arg.name = &dentry->d_name;
p->o_arg.server = server; p->o_arg.server = server;
p->o_arg.bitmask = server->attr_bitmask; p->o_arg.bitmask = server->attr_bitmask;
p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];
p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
if (attrs != NULL && attrs->ia_valid != 0) { if (attrs != NULL && attrs->ia_valid != 0) {
__be32 verf[2]; __be32 verf[2];
...@@ -1820,6 +1841,7 @@ static int _nfs4_do_open(struct inode *dir, ...@@ -1820,6 +1841,7 @@ static int _nfs4_do_open(struct inode *dir,
opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc(); opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc();
if (!opendata->f_attr.mdsthreshold) if (!opendata->f_attr.mdsthreshold)
goto err_opendata_put; goto err_opendata_put;
opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0];
} }
if (dentry->d_inode != NULL) if (dentry->d_inode != NULL)
opendata->state = nfs4_get_open_state(dentry->d_inode, sp); opendata->state = nfs4_get_open_state(dentry->d_inode, sp);
...@@ -1880,6 +1902,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, ...@@ -1880,6 +1902,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
struct nfs4_state *res; struct nfs4_state *res;
int status; int status;
fmode &= FMODE_READ|FMODE_WRITE;
do { do {
status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred,
&res, ctx_th); &res, ctx_th);
...@@ -2526,6 +2549,14 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, ...@@ -2526,6 +2549,14 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
nfs_fattr_init(fattr); nfs_fattr_init(fattr);
/* Deal with open(O_TRUNC) */
if (sattr->ia_valid & ATTR_OPEN)
sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
/* Optimization: if the end result is no change, don't RPC */
if ((sattr->ia_valid & ~(ATTR_FILE)) == 0)
return 0;
/* Search for an existing open(O_WRITE) file */ /* Search for an existing open(O_WRITE) file */
if (sattr->ia_valid & ATTR_FILE) { if (sattr->ia_valid & ATTR_FILE) {
struct nfs_open_context *ctx; struct nfs_open_context *ctx;
...@@ -2537,10 +2568,6 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, ...@@ -2537,10 +2568,6 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
} }
} }
/* Deal with open(O_TRUNC) */
if (sattr->ia_valid & ATTR_OPEN)
sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
status = nfs4_do_setattr(inode, cred, fattr, sattr, state); status = nfs4_do_setattr(inode, cred, fattr, sattr, state);
if (status == 0) if (status == 0)
nfs_setattr_update_inode(inode, sattr); nfs_setattr_update_inode(inode, sattr);
...@@ -5275,7 +5302,7 @@ static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, ...@@ -5275,7 +5302,7 @@ static int _nfs4_proc_destroy_clientid(struct nfs_client *clp,
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
if (status) if (status)
pr_warn("NFS: Got error %d from the server %s on " dprintk("NFS: Got error %d from the server %s on "
"DESTROY_CLIENTID.", status, clp->cl_hostname); "DESTROY_CLIENTID.", status, clp->cl_hostname);
return status; return status;
} }
...@@ -5746,8 +5773,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, ...@@ -5746,8 +5773,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session,
status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
if (status) if (status)
printk(KERN_WARNING dprintk("NFS: Got error %d from the server on DESTROY_SESSION. "
"NFS: Got error %d from the server on DESTROY_SESSION. "
"Session has been destroyed regardless...\n", status); "Session has been destroyed regardless...\n", status);
dprintk("<-- nfs4_proc_destroy_session\n"); dprintk("<-- nfs4_proc_destroy_session\n");
......
...@@ -244,6 +244,16 @@ static int nfs4_begin_drain_session(struct nfs_client *clp) ...@@ -244,6 +244,16 @@ static int nfs4_begin_drain_session(struct nfs_client *clp)
return nfs4_wait_on_slot_tbl(&ses->fc_slot_table); return nfs4_wait_on_slot_tbl(&ses->fc_slot_table);
} }
static void nfs41_finish_session_reset(struct nfs_client *clp)
{
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
/* create_session negotiated new slot table */
clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state);
nfs41_setup_state_renewal(clp);
}
int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
{ {
int status; int status;
...@@ -259,8 +269,7 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) ...@@ -259,8 +269,7 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
status = nfs4_proc_create_session(clp, cred); status = nfs4_proc_create_session(clp, cred);
if (status != 0) if (status != 0)
goto out; goto out;
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); nfs41_finish_session_reset(clp);
nfs41_setup_state_renewal(clp);
nfs_mark_client_ready(clp, NFS_CS_READY); nfs_mark_client_ready(clp, NFS_CS_READY);
out: out:
return status; return status;
...@@ -1772,16 +1781,9 @@ static int nfs4_reset_session(struct nfs_client *clp) ...@@ -1772,16 +1781,9 @@ static int nfs4_reset_session(struct nfs_client *clp)
status = nfs4_handle_reclaim_lease_error(clp, status); status = nfs4_handle_reclaim_lease_error(clp, status);
goto out; goto out;
} }
clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); nfs41_finish_session_reset(clp);
/* create_session negotiated new slot table */
clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state);
dprintk("%s: session reset was successful for server %s!\n", dprintk("%s: session reset was successful for server %s!\n",
__func__, clp->cl_hostname); __func__, clp->cl_hostname);
/* Let the state manager reestablish state */
if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
nfs41_setup_state_renewal(clp);
out: out:
if (cred) if (cred)
put_rpccred(cred); put_rpccred(cred);
......
...@@ -1198,12 +1198,13 @@ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct c ...@@ -1198,12 +1198,13 @@ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct c
} }
static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask,
const u32 *open_bitmap,
struct compound_hdr *hdr) struct compound_hdr *hdr)
{ {
encode_getattr_three(xdr, encode_getattr_three(xdr,
bitmask[0] & nfs4_fattr_bitmap[0], bitmask[0] & open_bitmap[0],
bitmask[1] & nfs4_fattr_bitmap[1], bitmask[1] & open_bitmap[1],
bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD, bitmask[2] & open_bitmap[2],
hdr); hdr);
} }
...@@ -2221,7 +2222,7 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, ...@@ -2221,7 +2222,7 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
encode_putfh(xdr, args->fh, &hdr); encode_putfh(xdr, args->fh, &hdr);
encode_open(xdr, args, &hdr); encode_open(xdr, args, &hdr);
encode_getfh(xdr, &hdr); encode_getfh(xdr, &hdr);
encode_getfattr_open(xdr, args->bitmask, &hdr); encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
encode_nops(&hdr); encode_nops(&hdr);
} }
...@@ -4359,7 +4360,10 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr, ...@@ -4359,7 +4360,10 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr,
if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U))) if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U)))
return -EIO; return -EIO;
if (likely(bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD)) { if (bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD) {
/* Did the server return an unrequested attribute? */
if (unlikely(res == NULL))
return -EREMOTEIO;
p = xdr_inline_decode(xdr, 4); p = xdr_inline_decode(xdr, 4);
if (unlikely(!p)) if (unlikely(!p))
goto out_overflow; goto out_overflow;
...@@ -4372,6 +4376,7 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr, ...@@ -4372,6 +4376,7 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr,
__func__); __func__);
status = decode_first_threshold_item4(xdr, res); status = decode_first_threshold_item4(xdr, res);
bitmap[2] &= ~FATTR4_WORD2_MDSTHRESHOLD;
} }
return status; return status;
out_overflow: out_overflow:
......
...@@ -365,7 +365,7 @@ static inline bool ...@@ -365,7 +365,7 @@ static inline bool
pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src, pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src,
struct nfs_server *nfss) struct nfs_server *nfss)
{ {
return (dst && src && src->bm != 0 && return (dst && src && src->bm != 0 && nfss->pnfs_curr_ld &&
nfss->pnfs_curr_ld->id == src->l_type); nfss->pnfs_curr_ld->id == src->l_type);
} }
......
...@@ -651,7 +651,7 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) ...@@ -651,7 +651,7 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
/* Emulate the eof flag, which isn't normally needed in NFSv2 /* Emulate the eof flag, which isn't normally needed in NFSv2
* as it is guaranteed to always return the file attributes * as it is guaranteed to always return the file attributes
*/ */
if (data->args.offset + data->args.count >= data->res.fattr->size) if (data->args.offset + data->res.count >= data->res.fattr->size)
data->res.eof = 1; data->res.eof = 1;
} }
return 0; return 0;
......
...@@ -1867,6 +1867,7 @@ static int nfs23_validate_mount_data(void *options, ...@@ -1867,6 +1867,7 @@ static int nfs23_validate_mount_data(void *options,
if (data == NULL) if (data == NULL)
goto out_no_data; goto out_no_data;
args->version = NFS_DEFAULT_VERSION;
switch (data->version) { switch (data->version) {
case 1: case 1:
data->namlen = 0; data->namlen = 0;
...@@ -2637,6 +2638,8 @@ static int nfs4_validate_mount_data(void *options, ...@@ -2637,6 +2638,8 @@ static int nfs4_validate_mount_data(void *options,
if (data == NULL) if (data == NULL)
goto out_no_data; goto out_no_data;
args->version = 4;
switch (data->version) { switch (data->version) {
case 1: case 1:
if (data->host_addrlen > sizeof(args->nfs_server.address)) if (data->host_addrlen > sizeof(args->nfs_server.address))
......
...@@ -80,6 +80,7 @@ struct nfs_write_header *nfs_writehdr_alloc(void) ...@@ -80,6 +80,7 @@ struct nfs_write_header *nfs_writehdr_alloc(void)
INIT_LIST_HEAD(&hdr->rpc_list); INIT_LIST_HEAD(&hdr->rpc_list);
spin_lock_init(&hdr->lock); spin_lock_init(&hdr->lock);
atomic_set(&hdr->refcnt, 0); atomic_set(&hdr->refcnt, 0);
hdr->verf = &p->verf;
} }
return p; return p;
} }
...@@ -619,6 +620,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr) ...@@ -619,6 +620,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr)
goto next; goto next;
} }
if (test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) { if (test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) {
memcpy(&req->wb_verf, hdr->verf, sizeof(req->wb_verf));
nfs_mark_request_commit(req, hdr->lseg, &cinfo); nfs_mark_request_commit(req, hdr->lseg, &cinfo);
goto next; goto next;
} }
...@@ -1255,15 +1257,14 @@ static void nfs_writeback_release_common(void *calldata) ...@@ -1255,15 +1257,14 @@ static void nfs_writeback_release_common(void *calldata)
struct nfs_write_data *data = calldata; struct nfs_write_data *data = calldata;
struct nfs_pgio_header *hdr = data->header; struct nfs_pgio_header *hdr = data->header;
int status = data->task.tk_status; int status = data->task.tk_status;
struct nfs_page *req = hdr->req;
if ((status >= 0) && nfs_write_need_commit(data)) { if ((status >= 0) && nfs_write_need_commit(data)) {
spin_lock(&hdr->lock); spin_lock(&hdr->lock);
if (test_bit(NFS_IOHDR_NEED_RESCHED, &hdr->flags)) if (test_bit(NFS_IOHDR_NEED_RESCHED, &hdr->flags))
; /* Do nothing */ ; /* Do nothing */
else if (!test_and_set_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) else if (!test_and_set_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags))
memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); memcpy(hdr->verf, &data->verf, sizeof(*hdr->verf));
else if (memcmp(&req->wb_verf, &data->verf, sizeof(req->wb_verf))) else if (memcmp(hdr->verf, &data->verf, sizeof(*hdr->verf)))
set_bit(NFS_IOHDR_NEED_RESCHED, &hdr->flags); set_bit(NFS_IOHDR_NEED_RESCHED, &hdr->flags);
spin_unlock(&hdr->lock); spin_unlock(&hdr->lock);
} }
......
...@@ -348,6 +348,7 @@ struct nfs_openargs { ...@@ -348,6 +348,7 @@ struct nfs_openargs {
const struct qstr * name; const struct qstr * name;
const struct nfs_server *server; /* Needed for ID mapping */ const struct nfs_server *server; /* Needed for ID mapping */
const u32 * bitmask; const u32 * bitmask;
const u32 * open_bitmap;
__u32 claim; __u32 claim;
struct nfs4_sequence_args seq_args; struct nfs4_sequence_args seq_args;
}; };
...@@ -1236,6 +1237,7 @@ struct nfs_pgio_header { ...@@ -1236,6 +1237,7 @@ struct nfs_pgio_header {
struct list_head rpc_list; struct list_head rpc_list;
atomic_t refcnt; atomic_t refcnt;
struct nfs_page *req; struct nfs_page *req;
struct nfs_writeverf *verf;
struct pnfs_layout_segment *lseg; struct pnfs_layout_segment *lseg;
loff_t io_start; loff_t io_start;
const struct rpc_call_ops *mds_ops; const struct rpc_call_ops *mds_ops;
...@@ -1273,6 +1275,7 @@ struct nfs_write_data { ...@@ -1273,6 +1275,7 @@ struct nfs_write_data {
struct nfs_write_header { struct nfs_write_header {
struct nfs_pgio_header header; struct nfs_pgio_header header;
struct nfs_write_data rpc_data; struct nfs_write_data rpc_data;
struct nfs_writeverf verf;
}; };
struct nfs_mds_commit_info { struct nfs_mds_commit_info {
......
...@@ -71,6 +71,8 @@ static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head, ...@@ -71,6 +71,8 @@ static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head,
msg->errno = err; msg->errno = err;
destroy_msg(msg); destroy_msg(msg);
} while (!list_empty(head)); } while (!list_empty(head));
if (waitq)
wake_up(waitq); wake_up(waitq);
} }
...@@ -91,11 +93,9 @@ rpc_timeout_upcall_queue(struct work_struct *work) ...@@ -91,11 +93,9 @@ rpc_timeout_upcall_queue(struct work_struct *work)
} }
dentry = dget(pipe->dentry); dentry = dget(pipe->dentry);
spin_unlock(&pipe->lock); spin_unlock(&pipe->lock);
if (dentry) { rpc_purge_list(dentry ? &RPC_I(dentry->d_inode)->waitq : NULL,
rpc_purge_list(&RPC_I(dentry->d_inode)->waitq,
&free_list, destroy_msg, -ETIMEDOUT); &free_list, destroy_msg, -ETIMEDOUT);
dput(dentry); dput(dentry);
}
} }
ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg,
......
...@@ -1374,7 +1374,8 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, ...@@ -1374,7 +1374,8 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
sizeof(req->rq_snd_buf)); sizeof(req->rq_snd_buf));
return bc_send(req); return bc_send(req);
} else { } else {
/* Nothing to do to drop request */ /* drop request */
xprt_free_bc_request(req);
return 0; return 0;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment