diff options
author | Benjamin Coddington <bcodding@redhat.com> | 2017-04-11 12:50:10 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-04-21 10:45:01 -0400 |
commit | 7d6ddf88c4db372689c8aa65ea652d0514d66c06 (patch) | |
tree | 8fb586be995259ff4c98a01ee9ed183b107195b5 | |
parent | 50f2112cf7a3e62a8d33838eb205d5fef306457a (diff) |
NFS: Add an iocounter wait function for async RPC tasks
By sleeping on a new NFS Unlock-On-Close waitqueue, rpc tasks may wait for
a lock context's iocounter to reach zero. The rpc waitqueue is only woken
when the open_context has the NFS_CONTEXT_UNLOCK flag set in order to
mitigate spurious wake-ups for any iocounter reaching zero.
Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
Reviewed-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/client.c | 1 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 34 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_fs_sb.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_page.h | 1 |
5 files changed, 37 insertions, 1 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 3ffbffe8f39f..3e7b2e6a7cfb 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -218,6 +218,7 @@ static void nfs_cb_idr_remove_locked(struct nfs_client *clp) | |||
218 | static void pnfs_init_server(struct nfs_server *server) | 218 | static void pnfs_init_server(struct nfs_server *server) |
219 | { | 219 | { |
220 | rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC"); | 220 | rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC"); |
221 | rpc_init_wait_queue(&server->uoc_rpcwaitq, "NFS UOC"); | ||
221 | } | 222 | } |
222 | 223 | ||
223 | #else | 224 | #else |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index f53610672f03..ad92b401326c 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -102,6 +102,35 @@ nfs_iocounter_wait(struct nfs_lock_context *l_ctx) | |||
102 | TASK_KILLABLE); | 102 | TASK_KILLABLE); |
103 | } | 103 | } |
104 | 104 | ||
105 | /** | ||
106 | * nfs_async_iocounter_wait - wait on a rpc_waitqueue for I/O | ||
107 | * to complete | ||
108 | * @task: the rpc_task that should wait | ||
109 | * @l_ctx: nfs_lock_context with io_counter to check | ||
110 | * | ||
111 | * Returns true if there is outstanding I/O to wait on and the | ||
112 | * task has been put to sleep. | ||
113 | */ | ||
114 | bool | ||
115 | nfs_async_iocounter_wait(struct rpc_task *task, struct nfs_lock_context *l_ctx) | ||
116 | { | ||
117 | struct inode *inode = d_inode(l_ctx->open_context->dentry); | ||
118 | bool ret = false; | ||
119 | |||
120 | if (atomic_read(&l_ctx->io_count) > 0) { | ||
121 | rpc_sleep_on(&NFS_SERVER(inode)->uoc_rpcwaitq, task, NULL); | ||
122 | ret = true; | ||
123 | } | ||
124 | |||
125 | if (atomic_read(&l_ctx->io_count) == 0) { | ||
126 | rpc_wake_up_queued_task(&NFS_SERVER(inode)->uoc_rpcwaitq, task); | ||
127 | ret = false; | ||
128 | } | ||
129 | |||
130 | return ret; | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(nfs_async_iocounter_wait); | ||
133 | |||
105 | /* | 134 | /* |
106 | * nfs_page_group_lock - lock the head of the page group | 135 | * nfs_page_group_lock - lock the head of the page group |
107 | * @req - request in group that is to be locked | 136 | * @req - request in group that is to be locked |
@@ -385,8 +414,11 @@ static void nfs_clear_request(struct nfs_page *req) | |||
385 | req->wb_page = NULL; | 414 | req->wb_page = NULL; |
386 | } | 415 | } |
387 | if (l_ctx != NULL) { | 416 | if (l_ctx != NULL) { |
388 | if (atomic_dec_and_test(&l_ctx->io_count)) | 417 | if (atomic_dec_and_test(&l_ctx->io_count)) { |
389 | wake_up_atomic_t(&l_ctx->io_count); | 418 | wake_up_atomic_t(&l_ctx->io_count); |
419 | if (test_bit(NFS_CONTEXT_UNLOCK, &ctx->flags)) | ||
420 | rpc_wake_up(&NFS_SERVER(d_inode(ctx->dentry))->uoc_rpcwaitq); | ||
421 | } | ||
390 | nfs_put_lock_context(l_ctx); | 422 | nfs_put_lock_context(l_ctx); |
391 | req->wb_lock_context = NULL; | 423 | req->wb_lock_context = NULL; |
392 | } | 424 | } |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 1b29915247b2..9aa044e76820 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -76,6 +76,7 @@ struct nfs_open_context { | |||
76 | #define NFS_CONTEXT_ERROR_WRITE (0) | 76 | #define NFS_CONTEXT_ERROR_WRITE (0) |
77 | #define NFS_CONTEXT_RESEND_WRITES (1) | 77 | #define NFS_CONTEXT_RESEND_WRITES (1) |
78 | #define NFS_CONTEXT_BAD (2) | 78 | #define NFS_CONTEXT_BAD (2) |
79 | #define NFS_CONTEXT_UNLOCK (3) | ||
79 | int error; | 80 | int error; |
80 | 81 | ||
81 | struct list_head list; | 82 | struct list_head list; |
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index b34097c67848..2a70f34dffe8 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
@@ -222,6 +222,7 @@ struct nfs_server { | |||
222 | u32 mountd_version; | 222 | u32 mountd_version; |
223 | unsigned short mountd_port; | 223 | unsigned short mountd_port; |
224 | unsigned short mountd_protocol; | 224 | unsigned short mountd_protocol; |
225 | struct rpc_wait_queue uoc_rpcwaitq; | ||
225 | }; | 226 | }; |
226 | 227 | ||
227 | /* Server capabilities */ | 228 | /* Server capabilities */ |
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 6f01e28bba27..247cc3d3498f 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
@@ -141,6 +141,7 @@ extern int nfs_page_group_lock(struct nfs_page *, bool); | |||
141 | extern void nfs_page_group_lock_wait(struct nfs_page *); | 141 | extern void nfs_page_group_lock_wait(struct nfs_page *); |
142 | extern void nfs_page_group_unlock(struct nfs_page *); | 142 | extern void nfs_page_group_unlock(struct nfs_page *); |
143 | extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int); | 143 | extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int); |
144 | extern bool nfs_async_iocounter_wait(struct rpc_task *, struct nfs_lock_context *); | ||
144 | 145 | ||
145 | /* | 146 | /* |
146 | * Lock the page of an asynchronous request | 147 | * Lock the page of an asynchronous request |