From: Ian Kent <ikent@redhat.com> Date: Tue, 1 Dec 2009 17:07:46 -0500 Subject: [nfs] add an nfsiod workqueue Message-id: <20091201170746.12228.18836.stgit@zeus.themaw.net> Patchwork-id: 21575 O-Subject: [RHEL 5.4 PATCH 5/5] NFS: Add an nfsiod workqueue (bz489931) Bugzilla: 489931 RH-Acked-by: Jeff Layton <jlayton@redhat.com> From: Trond Myklebust <Trond.Myklebust@netapp.com> NFS post-rpciod cleanups often involve tasks that cannot be safely performed within the rpciod context (due to deadlock concerns). We therefore add a dedicated NFS workqueue that can perform tasks like cleaning up state after an interrupted NFSv4 open() call, or calling put_nfs_open_context() after an asynchronous read or write call. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 795339a..863c29b 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1170,6 +1170,36 @@ static void nfs_destroy_inodecache(void) printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n"); } +struct workqueue_struct *nfsiod_workqueue; + +/* + * start up the nfsiod workqueue + */ +static int nfsiod_start(void) +{ + struct workqueue_struct *wq; + dprintk("RPC: creating workqueue nfsiod\n"); + wq = create_singlethread_workqueue("nfsiod"); + if (wq == NULL) + return -ENOMEM; + nfsiod_workqueue = wq; + return 0; +} + +/* + * Destroy the nfsiod workqueue + */ +static void nfsiod_stop(void) +{ + struct workqueue_struct *wq; + + wq = nfsiod_workqueue; + if (wq == NULL) + return; + nfsiod_workqueue = NULL; + destroy_workqueue(wq); +} + /* * Initialize NFS */ @@ -1177,6 +1207,10 @@ static int __init init_nfs_fs(void) { int err; + err = nfsiod_start(); + if (err) + goto out6; + err = nfs_fs_proc_init(); if (err) goto out5; @@ -1223,6 +1257,8 @@ out3: out4: nfs_fs_proc_exit(); out5: + nfsiod_stop(); +out6: return err; } @@ -1238,6 +1274,7 @@ static void __exit exit_nfs_fs(void) #endif unregister_nfs_fs(); nfs_fs_proc_exit(); + nfsiod_stop(); } /* Not quite true; I just maintain it */ diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 83f8fc2..e9db77d 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -146,6 +146,7 @@ extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); /* inode.c */ +extern struct workqueue_struct *nfsiod_workqueue; extern struct inode *nfs_alloc_inode(struct super_block *sb); extern void nfs_destroy_inode(struct inode *); extern int nfs_write_inode(struct inode *,int);