Commit 4108e101 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfsd-5.12-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux

Pull nfsd fixes from Chuck Lever:
 "Miscellaneous NFSD fixes for v5.12-rc"

* tag 'nfsd-5.12-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
  svcrdma: Revert "svcrdma: Reduce Receive doorbell rate"
  NFSD: fix error handling in NFSv4.0 callbacks
  NFSD: fix dest to src mount in inter-server COPY
  Revert "nfsd4: a client's own opens needn't prevent delegations"
  Revert "nfsd4: remove check_conflicting_opens warning"
  rpc: fix NULL dereference on kmalloc failure
  sunrpc: fix refcount leak for rpc auth modules
  NFSD: Repair misuse of sv_lock in 5.10.16-rt30.
  nfsd: don't abort copies early
  fs: nfsd: fix kconfig dependency warning for NFSD_V4
  svcrdma: disable timeouts on rdma backchannel
  nfsd: Don't keep looking up unhashed files in the nfsd file cache
parents 1a4431a5 bade4be6
...@@ -1808,9 +1808,6 @@ check_conflicting_open(struct file *filp, const long arg, int flags) ...@@ -1808,9 +1808,6 @@ check_conflicting_open(struct file *filp, const long arg, int flags)
if (flags & FL_LAYOUT) if (flags & FL_LAYOUT)
return 0; return 0;
if (flags & FL_DELEG)
/* We leave these checks to the caller. */
return 0;
if (arg == F_RDLCK) if (arg == F_RDLCK)
return inode_is_open_for_write(inode) ? -EAGAIN : 0; return inode_is_open_for_write(inode) ? -EAGAIN : 0;
......
...@@ -73,6 +73,7 @@ config NFSD_V4 ...@@ -73,6 +73,7 @@ config NFSD_V4
select NFSD_V3 select NFSD_V3
select FS_POSIX_ACL select FS_POSIX_ACL
select SUNRPC_GSS select SUNRPC_GSS
select CRYPTO
select CRYPTO_MD5 select CRYPTO_MD5
select CRYPTO_SHA256 select CRYPTO_SHA256
select GRACE_PERIOD select GRACE_PERIOD
......
...@@ -898,6 +898,8 @@ nfsd_file_find_locked(struct inode *inode, unsigned int may_flags, ...@@ -898,6 +898,8 @@ nfsd_file_find_locked(struct inode *inode, unsigned int may_flags,
continue; continue;
if (!nfsd_match_cred(nf->nf_cred, current_cred())) if (!nfsd_match_cred(nf->nf_cred, current_cred()))
continue; continue;
if (!test_bit(NFSD_FILE_HASHED, &nf->nf_flags))
continue;
if (nfsd_file_get(nf) != NULL) if (nfsd_file_get(nf) != NULL)
return nf; return nf;
} }
......
...@@ -1189,6 +1189,7 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata) ...@@ -1189,6 +1189,7 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
switch (task->tk_status) { switch (task->tk_status) {
case -EIO: case -EIO:
case -ETIMEDOUT: case -ETIMEDOUT:
case -EACCES:
nfsd4_mark_cb_down(clp, task->tk_status); nfsd4_mark_cb_down(clp, task->tk_status);
} }
break; break;
......
...@@ -1302,7 +1302,7 @@ nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src, ...@@ -1302,7 +1302,7 @@ nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src,
struct nfsd_file *dst) struct nfsd_file *dst)
{ {
nfs42_ssc_close(src->nf_file); nfs42_ssc_close(src->nf_file);
/* 'src' is freed by nfsd4_do_async_copy */ fput(src->nf_file);
nfsd_file_put(dst); nfsd_file_put(dst);
mntput(ss_mnt); mntput(ss_mnt);
} }
......
...@@ -4940,31 +4940,6 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp, ...@@ -4940,31 +4940,6 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp,
return fl; return fl;
} }
static int nfsd4_check_conflicting_opens(struct nfs4_client *clp,
struct nfs4_file *fp)
{
struct nfs4_clnt_odstate *co;
struct file *f = fp->fi_deleg_file->nf_file;
struct inode *ino = locks_inode(f);
int writes = atomic_read(&ino->i_writecount);
if (fp->fi_fds[O_WRONLY])
writes--;
if (fp->fi_fds[O_RDWR])
writes--;
if (writes > 0)
return -EAGAIN;
spin_lock(&fp->fi_lock);
list_for_each_entry(co, &fp->fi_clnt_odstate, co_perfile) {
if (co->co_client != clp) {
spin_unlock(&fp->fi_lock);
return -EAGAIN;
}
}
spin_unlock(&fp->fi_lock);
return 0;
}
static struct nfs4_delegation * static struct nfs4_delegation *
nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh, nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
struct nfs4_file *fp, struct nfs4_clnt_odstate *odstate) struct nfs4_file *fp, struct nfs4_clnt_odstate *odstate)
...@@ -4984,12 +4959,9 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh, ...@@ -4984,12 +4959,9 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
nf = find_readable_file(fp); nf = find_readable_file(fp);
if (!nf) { if (!nf) {
/* /* We should always have a readable file here */
* We probably could attempt another open and get a read WARN_ON_ONCE(1);
* delegation, but for now, don't bother until the return ERR_PTR(-EBADF);
* client actually sends us one.
*/
return ERR_PTR(-EAGAIN);
} }
spin_lock(&state_lock); spin_lock(&state_lock);
spin_lock(&fp->fi_lock); spin_lock(&fp->fi_lock);
...@@ -5019,19 +4991,11 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh, ...@@ -5019,19 +4991,11 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
if (!fl) if (!fl)
goto out_clnt_odstate; goto out_clnt_odstate;
status = nfsd4_check_conflicting_opens(clp, fp);
if (status) {
locks_free_lock(fl);
goto out_clnt_odstate;
}
status = vfs_setlease(fp->fi_deleg_file->nf_file, fl->fl_type, &fl, NULL); status = vfs_setlease(fp->fi_deleg_file->nf_file, fl->fl_type, &fl, NULL);
if (fl) if (fl)
locks_free_lock(fl); locks_free_lock(fl);
if (status) if (status)
goto out_clnt_odstate; goto out_clnt_odstate;
status = nfsd4_check_conflicting_opens(clp, fp);
if (status)
goto out_clnt_odstate;
spin_lock(&state_lock); spin_lock(&state_lock);
spin_lock(&fp->fi_lock); spin_lock(&fp->fi_lock);
...@@ -5113,6 +5077,17 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, ...@@ -5113,6 +5077,17 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open,
goto out_no_deleg; goto out_no_deleg;
if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED)) if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
goto out_no_deleg; goto out_no_deleg;
/*
* Also, if the file was opened for write or
* create, there's a good chance the client's
* about to write to it, resulting in an
* immediate recall (since we don't support
* write delegations):
*/
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
goto out_no_deleg;
if (open->op_create == NFS4_OPEN_CREATE)
goto out_no_deleg;
break; break;
default: default:
goto out_no_deleg; goto out_no_deleg;
...@@ -5389,7 +5364,7 @@ nfs4_laundromat(struct nfsd_net *nn) ...@@ -5389,7 +5364,7 @@ nfs4_laundromat(struct nfsd_net *nn)
idr_for_each_entry(&nn->s2s_cp_stateids, cps_t, i) { idr_for_each_entry(&nn->s2s_cp_stateids, cps_t, i) {
cps = container_of(cps_t, struct nfs4_cpntf_state, cp_stateid); cps = container_of(cps_t, struct nfs4_cpntf_state, cp_stateid);
if (cps->cp_stateid.sc_type == NFS4_COPYNOTIFY_STID && if (cps->cp_stateid.sc_type == NFS4_COPYNOTIFY_STID &&
cps->cpntf_time > cutoff) cps->cpntf_time < cutoff)
_free_cpntf_state_locked(nn, cps); _free_cpntf_state_locked(nn, cps);
} }
spin_unlock(&nn->s2s_cp_lock); spin_unlock(&nn->s2s_cp_lock);
......
...@@ -104,7 +104,6 @@ struct svcxprt_rdma { ...@@ -104,7 +104,6 @@ struct svcxprt_rdma {
wait_queue_head_t sc_send_wait; /* SQ exhaustion waitlist */ wait_queue_head_t sc_send_wait; /* SQ exhaustion waitlist */
unsigned long sc_flags; unsigned long sc_flags;
u32 sc_pending_recvs;
struct list_head sc_read_complete_q; struct list_head sc_read_complete_q;
struct work_struct sc_work; struct work_struct sc_work;
......
...@@ -1825,11 +1825,14 @@ static int ...@@ -1825,11 +1825,14 @@ static int
svcauth_gss_release(struct svc_rqst *rqstp) svcauth_gss_release(struct svc_rqst *rqstp)
{ {
struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data; struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data;
struct rpc_gss_wire_cred *gc = &gsd->clcred; struct rpc_gss_wire_cred *gc;
struct xdr_buf *resbuf = &rqstp->rq_res; struct xdr_buf *resbuf = &rqstp->rq_res;
int stat = -EINVAL; int stat = -EINVAL;
struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
if (!gsd)
goto out;
gc = &gsd->clcred;
if (gc->gc_proc != RPC_GSS_PROC_DATA) if (gc->gc_proc != RPC_GSS_PROC_DATA)
goto out; goto out;
/* Release can be called twice, but we only wrap once. */ /* Release can be called twice, but we only wrap once. */
...@@ -1870,10 +1873,10 @@ svcauth_gss_release(struct svc_rqst *rqstp) ...@@ -1870,10 +1873,10 @@ svcauth_gss_release(struct svc_rqst *rqstp)
if (rqstp->rq_cred.cr_group_info) if (rqstp->rq_cred.cr_group_info)
put_group_info(rqstp->rq_cred.cr_group_info); put_group_info(rqstp->rq_cred.cr_group_info);
rqstp->rq_cred.cr_group_info = NULL; rqstp->rq_cred.cr_group_info = NULL;
if (gsd->rsci) if (gsd && gsd->rsci) {
cache_put(&gsd->rsci->h, sn->rsc_cache); cache_put(&gsd->rsci->h, sn->rsc_cache);
gsd->rsci = NULL; gsd->rsci = NULL;
}
return stat; return stat;
} }
......
...@@ -1413,7 +1413,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) ...@@ -1413,7 +1413,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
sendit: sendit:
if (svc_authorise(rqstp)) if (svc_authorise(rqstp))
goto close; goto close_xprt;
return 1; /* Caller can now send it */ return 1; /* Caller can now send it */
release_dropit: release_dropit:
...@@ -1425,6 +1425,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) ...@@ -1425,6 +1425,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
return 0; return 0;
close: close:
svc_authorise(rqstp);
close_xprt:
if (rqstp->rq_xprt && test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags)) if (rqstp->rq_xprt && test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags))
svc_close_xprt(rqstp->rq_xprt); svc_close_xprt(rqstp->rq_xprt);
dprintk("svc: svc_process close\n"); dprintk("svc: svc_process close\n");
...@@ -1433,7 +1435,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) ...@@ -1433,7 +1435,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
err_short_len: err_short_len:
svc_printk(rqstp, "short len %zd, dropping request\n", svc_printk(rqstp, "short len %zd, dropping request\n",
argv->iov_len); argv->iov_len);
goto close; goto close_xprt;
err_bad_rpc: err_bad_rpc:
serv->sv_stats->rpcbadfmt++; serv->sv_stats->rpcbadfmt++;
......
...@@ -1060,7 +1060,7 @@ static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, st ...@@ -1060,7 +1060,7 @@ static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, st
struct svc_xprt *xprt; struct svc_xprt *xprt;
int ret = 0; int ret = 0;
spin_lock(&serv->sv_lock); spin_lock_bh(&serv->sv_lock);
list_for_each_entry(xprt, xprt_list, xpt_list) { list_for_each_entry(xprt, xprt_list, xpt_list) {
if (xprt->xpt_net != net) if (xprt->xpt_net != net)
continue; continue;
...@@ -1068,7 +1068,7 @@ static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, st ...@@ -1068,7 +1068,7 @@ static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, st
set_bit(XPT_CLOSE, &xprt->xpt_flags); set_bit(XPT_CLOSE, &xprt->xpt_flags);
svc_xprt_enqueue(xprt); svc_xprt_enqueue(xprt);
} }
spin_unlock(&serv->sv_lock); spin_unlock_bh(&serv->sv_lock);
return ret; return ret;
} }
......
...@@ -252,9 +252,9 @@ xprt_setup_rdma_bc(struct xprt_create *args) ...@@ -252,9 +252,9 @@ xprt_setup_rdma_bc(struct xprt_create *args)
xprt->timeout = &xprt_rdma_bc_timeout; xprt->timeout = &xprt_rdma_bc_timeout;
xprt_set_bound(xprt); xprt_set_bound(xprt);
xprt_set_connected(xprt); xprt_set_connected(xprt);
xprt->bind_timeout = RPCRDMA_BIND_TO; xprt->bind_timeout = 0;
xprt->reestablish_timeout = RPCRDMA_INIT_REEST_TO; xprt->reestablish_timeout = 0;
xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO; xprt->idle_timeout = 0;
xprt->prot = XPRT_TRANSPORT_BC_RDMA; xprt->prot = XPRT_TRANSPORT_BC_RDMA;
xprt->ops = &xprt_rdma_bc_procs; xprt->ops = &xprt_rdma_bc_procs;
......
...@@ -266,46 +266,33 @@ void svc_rdma_release_rqst(struct svc_rqst *rqstp) ...@@ -266,46 +266,33 @@ void svc_rdma_release_rqst(struct svc_rqst *rqstp)
svc_rdma_recv_ctxt_put(rdma, ctxt); svc_rdma_recv_ctxt_put(rdma, ctxt);
} }
static bool svc_rdma_refresh_recvs(struct svcxprt_rdma *rdma, static int __svc_rdma_post_recv(struct svcxprt_rdma *rdma,
unsigned int wanted, bool temp) struct svc_rdma_recv_ctxt *ctxt)
{ {
const struct ib_recv_wr *bad_wr = NULL;
struct svc_rdma_recv_ctxt *ctxt;
struct ib_recv_wr *recv_chain;
int ret; int ret;
recv_chain = NULL; trace_svcrdma_post_recv(ctxt);
while (wanted--) { ret = ib_post_recv(rdma->sc_qp, &ctxt->rc_recv_wr, NULL);
ctxt = svc_rdma_recv_ctxt_get(rdma);
if (!ctxt)
break;
trace_svcrdma_post_recv(ctxt);
ctxt->rc_temp = temp;
ctxt->rc_recv_wr.next = recv_chain;
recv_chain = &ctxt->rc_recv_wr;
rdma->sc_pending_recvs++;
}
if (!recv_chain)
return false;
ret = ib_post_recv(rdma->sc_qp, recv_chain, &bad_wr);
if (ret) if (ret)
goto err_post; goto err_post;
return true; return 0;
err_post: err_post:
while (bad_wr) {
ctxt = container_of(bad_wr, struct svc_rdma_recv_ctxt,
rc_recv_wr);
bad_wr = bad_wr->next;
svc_rdma_recv_ctxt_put(rdma, ctxt);
}
trace_svcrdma_rq_post_err(rdma, ret); trace_svcrdma_rq_post_err(rdma, ret);
/* Since we're destroying the xprt, no need to reset svc_rdma_recv_ctxt_put(rdma, ctxt);
* sc_pending_recvs. */ return ret;
return false; }
static int svc_rdma_post_recv(struct svcxprt_rdma *rdma)
{
struct svc_rdma_recv_ctxt *ctxt;
if (test_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags))
return 0;
ctxt = svc_rdma_recv_ctxt_get(rdma);
if (!ctxt)
return -ENOMEM;
return __svc_rdma_post_recv(rdma, ctxt);
} }
/** /**
...@@ -316,7 +303,20 @@ static bool svc_rdma_refresh_recvs(struct svcxprt_rdma *rdma, ...@@ -316,7 +303,20 @@ static bool svc_rdma_refresh_recvs(struct svcxprt_rdma *rdma,
*/ */
bool svc_rdma_post_recvs(struct svcxprt_rdma *rdma) bool svc_rdma_post_recvs(struct svcxprt_rdma *rdma)
{ {
return svc_rdma_refresh_recvs(rdma, rdma->sc_max_requests, true); struct svc_rdma_recv_ctxt *ctxt;
unsigned int i;
int ret;
for (i = 0; i < rdma->sc_max_requests; i++) {
ctxt = svc_rdma_recv_ctxt_get(rdma);
if (!ctxt)
return false;
ctxt->rc_temp = true;
ret = __svc_rdma_post_recv(rdma, ctxt);
if (ret)
return false;
}
return true;
} }
/** /**
...@@ -324,6 +324,8 @@ bool svc_rdma_post_recvs(struct svcxprt_rdma *rdma) ...@@ -324,6 +324,8 @@ bool svc_rdma_post_recvs(struct svcxprt_rdma *rdma)
* @cq: Completion Queue context * @cq: Completion Queue context
* @wc: Work Completion object * @wc: Work Completion object
* *
* NB: The svc_xprt/svcxprt_rdma is pinned whenever it's possible that
* the Receive completion handler could be running.
*/ */
static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc) static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
{ {
...@@ -331,8 +333,6 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc) ...@@ -331,8 +333,6 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
struct ib_cqe *cqe = wc->wr_cqe; struct ib_cqe *cqe = wc->wr_cqe;
struct svc_rdma_recv_ctxt *ctxt; struct svc_rdma_recv_ctxt *ctxt;
rdma->sc_pending_recvs--;
/* WARNING: Only wc->wr_cqe and wc->status are reliable */ /* WARNING: Only wc->wr_cqe and wc->status are reliable */
ctxt = container_of(cqe, struct svc_rdma_recv_ctxt, rc_cqe); ctxt = container_of(cqe, struct svc_rdma_recv_ctxt, rc_cqe);
...@@ -340,6 +340,9 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc) ...@@ -340,6 +340,9 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
if (wc->status != IB_WC_SUCCESS) if (wc->status != IB_WC_SUCCESS)
goto flushed; goto flushed;
if (svc_rdma_post_recv(rdma))
goto post_err;
/* All wc fields are now known to be valid */ /* All wc fields are now known to be valid */
ctxt->rc_byte_len = wc->byte_len; ctxt->rc_byte_len = wc->byte_len;
...@@ -350,18 +353,11 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc) ...@@ -350,18 +353,11 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
spin_unlock(&rdma->sc_rq_dto_lock); spin_unlock(&rdma->sc_rq_dto_lock);
if (!test_bit(RDMAXPRT_CONN_PENDING, &rdma->sc_flags)) if (!test_bit(RDMAXPRT_CONN_PENDING, &rdma->sc_flags))
svc_xprt_enqueue(&rdma->sc_xprt); svc_xprt_enqueue(&rdma->sc_xprt);
if (!test_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags) &&
rdma->sc_pending_recvs < rdma->sc_max_requests)
if (!svc_rdma_refresh_recvs(rdma, RPCRDMA_MAX_RECV_BATCH,
false))
goto post_err;
return; return;
flushed: flushed:
svc_rdma_recv_ctxt_put(rdma, ctxt);
post_err: post_err:
svc_rdma_recv_ctxt_put(rdma, ctxt);
set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags); set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
svc_xprt_enqueue(&rdma->sc_xprt); svc_xprt_enqueue(&rdma->sc_xprt);
} }
......
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