Merge branch 'for-3.18' of git://linux-nfs.org/~bfields/linux

Pull nfsd bugfixes from Bruce Fields:
 "These fix one mishandling of the case when security labels are
  configured out, and two races in the 4.1 backchannel code"

* 'for-3.18' of git://linux-nfs.org/~bfields/linux:
  nfsd: Fix slot wake up race in the nfsv4.1 callback code
  SUNRPC: Fix locking around callback channel reply receive
  nfsd: correctly define v4.2 support attributes
This commit is contained in:
Linus Torvalds 2014-11-25 19:05:41 -08:00
commit b914c5b213
3 changed files with 28 additions and 16 deletions

View file

@ -774,8 +774,12 @@ static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task)
{ {
if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); rpc_sleep_on(&clp->cl_cb_waitq, task, NULL);
dprintk("%s slot is busy\n", __func__); /* Race breaker */
return false; if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
dprintk("%s slot is busy\n", __func__);
return false;
}
rpc_wake_up_queued_task(&clp->cl_cb_waitq, task);
} }
return true; return true;
} }

View file

@ -335,12 +335,15 @@ void nfsd_lockd_shutdown(void);
(NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT) (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT)
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \ #define NFSD4_2_SECURITY_ATTRS FATTR4_WORD2_SECURITY_LABEL
(NFSD4_1_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SECURITY_LABEL)
#else #else
#define NFSD4_2_SUPPORTED_ATTRS_WORD2 0 #define NFSD4_2_SECURITY_ATTRS 0
#endif #endif
#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \
(NFSD4_1_SUPPORTED_ATTRS_WORD2 | \
NFSD4_2_SECURITY_ATTRS)
static inline u32 nfsd_suppattrs0(u32 minorversion) static inline u32 nfsd_suppattrs0(u32 minorversion)
{ {
return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0

View file

@ -1019,17 +1019,12 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
xid = *p++; xid = *p++;
calldir = *p; calldir = *p;
if (bc_xprt) if (!bc_xprt)
req = xprt_lookup_rqst(bc_xprt, xid);
if (!req) {
printk(KERN_NOTICE
"%s: Got unrecognized reply: "
"calldir 0x%x xpt_bc_xprt %p xid %08x\n",
__func__, ntohl(calldir),
bc_xprt, ntohl(xid));
return -EAGAIN; return -EAGAIN;
} spin_lock_bh(&bc_xprt->transport_lock);
req = xprt_lookup_rqst(bc_xprt, xid);
if (!req)
goto unlock_notfound;
memcpy(&req->rq_private_buf, &req->rq_rcv_buf, sizeof(struct xdr_buf)); memcpy(&req->rq_private_buf, &req->rq_rcv_buf, sizeof(struct xdr_buf));
/* /*
@ -1040,11 +1035,21 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
dst = &req->rq_private_buf.head[0]; dst = &req->rq_private_buf.head[0];
src = &rqstp->rq_arg.head[0]; src = &rqstp->rq_arg.head[0];
if (dst->iov_len < src->iov_len) if (dst->iov_len < src->iov_len)
return -EAGAIN; /* whatever; just giving up. */ goto unlock_eagain; /* whatever; just giving up. */
memcpy(dst->iov_base, src->iov_base, src->iov_len); memcpy(dst->iov_base, src->iov_base, src->iov_len);
xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len); xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len);
rqstp->rq_arg.len = 0; rqstp->rq_arg.len = 0;
spin_unlock_bh(&bc_xprt->transport_lock);
return 0; return 0;
unlock_notfound:
printk(KERN_NOTICE
"%s: Got unrecognized reply: "
"calldir 0x%x xpt_bc_xprt %p xid %08x\n",
__func__, ntohl(calldir),
bc_xprt, ntohl(xid));
unlock_eagain:
spin_unlock_bh(&bc_xprt->transport_lock);
return -EAGAIN;
} }
static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len) static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len)