summaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorBenjamin Coddington <bcodding@redhat.com>2017-04-11 12:50:12 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2017-04-21 10:45:01 -0400
commitf30cb757f680f965ba8a2e53cb3588052a01aeb5 (patch)
tree071e925905e0931b326f5474619adb0aa645d07b /fs/nfs/nfs4proc.c
parentb1ece737f44f91dca8f4829cf0b442e752e406db (diff)
NFS: Always wait for I/O completion before unlock
NFS attempts to wait for read and write completion before unlocking in order to ensure that the data returned was protected by the lock. When this waiting is interrupted by a signal, the unlock may be skipped, and messages similar to the following are seen in the kernel ring buffer: [20.167876] Leaked locks on dev=0x0:0x2b ino=0x8dd4c3: [20.168286] POSIX: fl_owner=ffff880078b06940 fl_flags=0x1 fl_type=0x0 fl_pid=20183 [20.168727] POSIX: fl_owner=ffff880078b06680 fl_flags=0x1 fl_type=0x0 fl_pid=20185 For NFSv3, the missing unlock will cause the server to refuse conflicting locks indefinitely. For NFSv4, the leftover lock will be removed by the server after the lease timeout. This patch fixes this issue by skipping the usual wait in nfs_iocounter_wait if the FL_CLOSE flag is set when signaled. Instead, the wait happens in the unlock RPC task on the NFS UOC rpc_waitqueue. For NFSv3, use lockd's new nlmclnt_operations along with nfs_async_iocounter_wait to defer NLM's unlock task until the lock context's iocounter reaches zero. For NFSv4, call nfs_async_iocounter_wait() directly from unlock's current rpc_call_prepare. Signed-off-by: Benjamin Coddington <bcodding@redhat.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index c52f72c86940..dbfc7574fab0 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5784,6 +5784,7 @@ struct nfs4_unlockdata {
5784 struct nfs_locku_res res; 5784 struct nfs_locku_res res;
5785 struct nfs4_lock_state *lsp; 5785 struct nfs4_lock_state *lsp;
5786 struct nfs_open_context *ctx; 5786 struct nfs_open_context *ctx;
5787 struct nfs_lock_context *l_ctx;
5787 struct file_lock fl; 5788 struct file_lock fl;
5788 struct nfs_server *server; 5789 struct nfs_server *server;
5789 unsigned long timestamp; 5790 unsigned long timestamp;
@@ -5808,6 +5809,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
5808 atomic_inc(&lsp->ls_count); 5809 atomic_inc(&lsp->ls_count);
5809 /* Ensure we don't close file until we're done freeing locks! */ 5810 /* Ensure we don't close file until we're done freeing locks! */
5810 p->ctx = get_nfs_open_context(ctx); 5811 p->ctx = get_nfs_open_context(ctx);
5812 p->l_ctx = nfs_get_lock_context(ctx);
5811 memcpy(&p->fl, fl, sizeof(p->fl)); 5813 memcpy(&p->fl, fl, sizeof(p->fl));
5812 p->server = NFS_SERVER(inode); 5814 p->server = NFS_SERVER(inode);
5813 return p; 5815 return p;
@@ -5818,6 +5820,7 @@ static void nfs4_locku_release_calldata(void *data)
5818 struct nfs4_unlockdata *calldata = data; 5820 struct nfs4_unlockdata *calldata = data;
5819 nfs_free_seqid(calldata->arg.seqid); 5821 nfs_free_seqid(calldata->arg.seqid);
5820 nfs4_put_lock_state(calldata->lsp); 5822 nfs4_put_lock_state(calldata->lsp);
5823 nfs_put_lock_context(calldata->l_ctx);
5821 put_nfs_open_context(calldata->ctx); 5824 put_nfs_open_context(calldata->ctx);
5822 kfree(calldata); 5825 kfree(calldata);
5823} 5826}
@@ -5859,6 +5862,10 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
5859{ 5862{
5860 struct nfs4_unlockdata *calldata = data; 5863 struct nfs4_unlockdata *calldata = data;
5861 5864
5865 if (test_bit(NFS_CONTEXT_UNLOCK, &calldata->l_ctx->open_context->flags) &&
5866 nfs_async_iocounter_wait(task, calldata->l_ctx))
5867 return;
5868
5862 if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) 5869 if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
5863 goto out_wait; 5870 goto out_wait;
5864 nfs4_stateid_copy(&calldata->arg.stateid, &calldata->lsp->ls_stateid); 5871 nfs4_stateid_copy(&calldata->arg.stateid, &calldata->lsp->ls_stateid);
@@ -5910,6 +5917,8 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
5910 * canceled lock is passed in, and it won't be an unlock. 5917 * canceled lock is passed in, and it won't be an unlock.
5911 */ 5918 */
5912 fl->fl_type = F_UNLCK; 5919 fl->fl_type = F_UNLCK;
5920 if (fl->fl_flags & FL_CLOSE)
5921 set_bit(NFS_CONTEXT_UNLOCK, &ctx->flags);
5913 5922
5914 data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid); 5923 data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid);
5915 if (data == NULL) { 5924 if (data == NULL) {