nfsd: Avoid taking state_lock while holding inode lock in nfsd_break_one_deleg
state_lock is a heavily contended global lock. We don't want to grab that while simultaneously holding the inode->i_lock. Add a new per-nfs4_file lock that we can use to protect the per-nfs4_file delegation list. Hold that while walking the list in the break_deleg callback and queue the workqueue job for each one. The workqueue job can then take the state_lock and do the list manipulations without the i_lock being held prior to starting the rpc call. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Jeff Layton <jlayton@primarydata.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:

committed by
J. Bruce Fields

parent
e8051c837b
commit
02e1215f9f
@@ -933,7 +933,7 @@ void nfsd4_shutdown_callback(struct nfs4_client *clp)
|
||||
set_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags);
|
||||
/*
|
||||
* Note this won't actually result in a null callback;
|
||||
* instead, nfsd4_do_callback_rpc() will detect the killed
|
||||
* instead, nfsd4_run_cb_null() will detect the killed
|
||||
* client, destroy the rpc client, and stop:
|
||||
*/
|
||||
do_probe_callback(clp);
|
||||
@@ -1011,10 +1011,9 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
|
||||
run_nfsd4_cb(cb);
|
||||
}
|
||||
|
||||
void
|
||||
nfsd4_do_callback_rpc(struct work_struct *w)
|
||||
static void
|
||||
nfsd4_run_callback_rpc(struct nfsd4_callback *cb)
|
||||
{
|
||||
struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work);
|
||||
struct nfs4_client *clp = cb->cb_clp;
|
||||
struct rpc_clnt *clnt;
|
||||
|
||||
@@ -1032,6 +1031,24 @@ nfsd4_do_callback_rpc(struct work_struct *w)
|
||||
cb->cb_ops, cb);
|
||||
}
|
||||
|
||||
void
|
||||
nfsd4_run_cb_null(struct work_struct *w)
|
||||
{
|
||||
struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback,
|
||||
cb_work);
|
||||
nfsd4_run_callback_rpc(cb);
|
||||
}
|
||||
|
||||
void
|
||||
nfsd4_run_cb_recall(struct work_struct *w)
|
||||
{
|
||||
struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback,
|
||||
cb_work);
|
||||
|
||||
nfsd4_prepare_cb_recall(cb->cb_op);
|
||||
nfsd4_run_callback_rpc(cb);
|
||||
}
|
||||
|
||||
void nfsd4_cb_recall(struct nfs4_delegation *dp)
|
||||
{
|
||||
struct nfsd4_callback *cb = &dp->dl_recall;
|
||||
|
Reference in New Issue
Block a user