aboutsummaryrefslogtreecommitdiff
path: root/fs/nfs
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2020-11-27 11:24:33 +1100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-12-30 11:53:31 +0100
commiteb9cc35ae98be96264791dac581eeb6ba95c53ab (patch)
treeb5e48f379ca0efd90943dfaa3219f4f246e22871 /fs/nfs
parent0e1c02e4e08540412cd403cad9d862eaf8d4f2b5 (diff)
NFS: switch nfsiod to be an UNBOUND workqueue.
[ Upstream commit bf701b765eaa82dd164d65edc5747ec7288bb5c3 ] nfsiod is currently a concurrency-managed workqueue (CMWQ). This means that workitems scheduled to nfsiod on a given CPU are queued behind all other work items queued on any CMWQ on the same CPU. This can introduce unexpected latency. Occaionally nfsiod can even cause excessive latency. If the work item to complete a CLOSE request calls the final iput() on an inode, the address_space of that inode will be dismantled. This takes time proportional to the number of in-memory pages, which on a large host working on large files (e.g.. 5TB), can be a large number of pages resulting in a noticable number of seconds. We can avoid these latency problems by switching nfsiod to WQ_UNBOUND. This causes each concurrent work item to gets a dedicated thread which can be scheduled to an idle CPU. There is precedent for this as several other filesystems use WQ_UNBOUND workqueue for handling various async events. Signed-off-by: NeilBrown <neilb@suse.de> Fixes: ada609ee2ac2 ("workqueue: use WQ_MEM_RECLAIM instead of WQ_RESCUER") Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/inode.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index aa6493905bbe..43af053f467a 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -2180,7 +2180,7 @@ static int nfsiod_start(void)
{
struct workqueue_struct *wq;
dprintk("RPC: creating workqueue nfsiod\n");
- wq = alloc_workqueue("nfsiod", WQ_MEM_RECLAIM, 0);
+ wq = alloc_workqueue("nfsiod", WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
if (wq == NULL)
return -ENOMEM;
nfsiod_workqueue = wq;