aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-02-19 20:04:22 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-02-26 00:40:36 -0500
commit5746006f1d17d9d5a3015051ea54de4341cb31f9 (patch)
treefc1d03a1e58a0a0a3cc03c46cbebdebf8cfe054e /fs/nfs
parent32bfb5c0f495dd88ef6bac4b76885d0820563739 (diff)
NFS: Add an nfsiod workqueue
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>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/inode.c37
-rw-r--r--fs/nfs/internal.h1
2 files changed, 38 insertions, 0 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index a499fb58d858..36cb99985d22 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1219,6 +1219,36 @@ static void nfs_destroy_inodecache(void)
1219 kmem_cache_destroy(nfs_inode_cachep); 1219 kmem_cache_destroy(nfs_inode_cachep);
1220} 1220}
1221 1221
1222struct workqueue_struct *nfsiod_workqueue;
1223
1224/*
1225 * start up the nfsiod workqueue
1226 */
1227static int nfsiod_start(void)
1228{
1229 struct workqueue_struct *wq;
1230 dprintk("RPC: creating workqueue nfsiod\n");
1231 wq = create_singlethread_workqueue("nfsiod");
1232 if (wq == NULL)
1233 return -ENOMEM;
1234 nfsiod_workqueue = wq;
1235 return 0;
1236}
1237
1238/*
1239 * Destroy the nfsiod workqueue
1240 */
1241static void nfsiod_stop(void)
1242{
1243 struct workqueue_struct *wq;
1244
1245 wq = nfsiod_workqueue;
1246 if (wq == NULL)
1247 return;
1248 nfsiod_workqueue = NULL;
1249 destroy_workqueue(wq);
1250}
1251
1222/* 1252/*
1223 * Initialize NFS 1253 * Initialize NFS
1224 */ 1254 */
@@ -1226,6 +1256,10 @@ static int __init init_nfs_fs(void)
1226{ 1256{
1227 int err; 1257 int err;
1228 1258
1259 err = nfsiod_start();
1260 if (err)
1261 goto out6;
1262
1229 err = nfs_fs_proc_init(); 1263 err = nfs_fs_proc_init();
1230 if (err) 1264 if (err)
1231 goto out5; 1265 goto out5;
@@ -1272,6 +1306,8 @@ out3:
1272out4: 1306out4:
1273 nfs_fs_proc_exit(); 1307 nfs_fs_proc_exit();
1274out5: 1308out5:
1309 nfsiod_stop();
1310out6:
1275 return err; 1311 return err;
1276} 1312}
1277 1313
@@ -1287,6 +1323,7 @@ static void __exit exit_nfs_fs(void)
1287#endif 1323#endif
1288 unregister_nfs_fs(); 1324 unregister_nfs_fs();
1289 nfs_fs_proc_exit(); 1325 nfs_fs_proc_exit();
1326 nfsiod_stop();
1290} 1327}
1291 1328
1292/* Not quite true; I just maintain it */ 1329/* Not quite true; I just maintain it */
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 0f5619611b8d..985dc2931031 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -143,6 +143,7 @@ extern struct rpc_procinfo nfs4_procedures[];
143extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); 143extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask);
144 144
145/* inode.c */ 145/* inode.c */
146extern struct workqueue_struct *nfsiod_workqueue;
146extern struct inode *nfs_alloc_inode(struct super_block *sb); 147extern struct inode *nfs_alloc_inode(struct super_block *sb);
147extern void nfs_destroy_inode(struct inode *); 148extern void nfs_destroy_inode(struct inode *);
148extern int nfs_write_inode(struct inode *,int); 149extern int nfs_write_inode(struct inode *,int);