Skip to content

Commit 7d6ddf8

Browse files
bcodding-rhtrondmypd
authored andcommitted
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 <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Trond Myklebust <[email protected]>
1 parent 50f2112 commit 7d6ddf8

File tree

5 files changed

+37
-1
lines changed

5 files changed

+37
-1
lines changed

fs/nfs/client.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
218218
static void pnfs_init_server(struct nfs_server *server)
219219
{
220220
rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
221+
rpc_init_wait_queue(&server->uoc_rpcwaitq, "NFS UOC");
221222
}
222223

223224
#else

fs/nfs/pagelist.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,35 @@ nfs_iocounter_wait(struct nfs_lock_context *l_ctx)
102102
TASK_KILLABLE);
103103
}
104104

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+
105134
/*
106135
* nfs_page_group_lock - lock the head of the page group
107136
* @req - request in group that is to be locked
@@ -385,8 +414,11 @@ static void nfs_clear_request(struct nfs_page *req)
385414
req->wb_page = NULL;
386415
}
387416
if (l_ctx != NULL) {
388-
if (atomic_dec_and_test(&l_ctx->io_count))
417+
if (atomic_dec_and_test(&l_ctx->io_count)) {
389418
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+
}
390422
nfs_put_lock_context(l_ctx);
391423
req->wb_lock_context = NULL;
392424
}

include/linux/nfs_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct nfs_open_context {
7676
#define NFS_CONTEXT_ERROR_WRITE (0)
7777
#define NFS_CONTEXT_RESEND_WRITES (1)
7878
#define NFS_CONTEXT_BAD (2)
79+
#define NFS_CONTEXT_UNLOCK (3)
7980
int error;
8081

8182
struct list_head list;

include/linux/nfs_fs_sb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ struct nfs_server {
222222
u32 mountd_version;
223223
unsigned short mountd_port;
224224
unsigned short mountd_protocol;
225+
struct rpc_wait_queue uoc_rpcwaitq;
225226
};
226227

227228
/* Server capabilities */

include/linux/nfs_page.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ extern int nfs_page_group_lock(struct nfs_page *, bool);
141141
extern void nfs_page_group_lock_wait(struct nfs_page *);
142142
extern void nfs_page_group_unlock(struct nfs_page *);
143143
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 *);
144145

145146
/*
146147
* Lock the page of an asynchronous request

0 commit comments

Comments
 (0)