diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-02-19 20:04:22 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-02-26 00:40:36 -0500 |
commit | 5746006f1d17d9d5a3015051ea54de4341cb31f9 (patch) | |
tree | fc1d03a1e58a0a0a3cc03c46cbebdebf8cfe054e /fs/nfs | |
parent | 32bfb5c0f495dd88ef6bac4b76885d0820563739 (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.c | 37 | ||||
-rw-r--r-- | fs/nfs/internal.h | 1 |
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 | ||
1222 | struct workqueue_struct *nfsiod_workqueue; | ||
1223 | |||
1224 | /* | ||
1225 | * start up the nfsiod workqueue | ||
1226 | */ | ||
1227 | static 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 | */ | ||
1241 | static 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: | |||
1272 | out4: | 1306 | out4: |
1273 | nfs_fs_proc_exit(); | 1307 | nfs_fs_proc_exit(); |
1274 | out5: | 1308 | out5: |
1309 | nfsiod_stop(); | ||
1310 | out6: | ||
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[]; | |||
143 | extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); | 143 | extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); |
144 | 144 | ||
145 | /* inode.c */ | 145 | /* inode.c */ |
146 | extern struct workqueue_struct *nfsiod_workqueue; | ||
146 | extern struct inode *nfs_alloc_inode(struct super_block *sb); | 147 | extern struct inode *nfs_alloc_inode(struct super_block *sb); |
147 | extern void nfs_destroy_inode(struct inode *); | 148 | extern void nfs_destroy_inode(struct inode *); |
148 | extern int nfs_write_inode(struct inode *,int); | 149 | extern int nfs_write_inode(struct inode *,int); |