aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-07-27 18:19:01 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-10-06 20:08:26 -0400
commit1daef0a868370c5a96d031b9202e3354bea060e6 (patch)
treea072a8486c67f3d26b576e5bace8aa45def2d328
parentd5e66348bbe39dc78509e7561f7252aa443df8c0 (diff)
NFS: Clean up nfs_sb_active/nfs_sb_deactive
Instead of causing umount requests to block on server->active_wq while the asynchronous sillyrename deletes are executing, we can use the sb->s_active counter to obtain a reference to the super_block, and then release that reference in nfs_async_unlink_release(). Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/client.c1
-rw-r--r--fs/nfs/internal.h4
-rw-r--r--fs/nfs/super.c24
-rw-r--r--fs/nfs/unlink.c5
-rw-r--r--include/linux/nfs_fs_sb.h1
5 files changed, 13 insertions, 22 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 5ee23e7058b3..2accb67427c6 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -850,7 +850,6 @@ static struct nfs_server *nfs_alloc_server(void)
850 INIT_LIST_HEAD(&server->client_link); 850 INIT_LIST_HEAD(&server->client_link);
851 INIT_LIST_HEAD(&server->master_link); 851 INIT_LIST_HEAD(&server->master_link);
852 852
853 init_waitqueue_head(&server->active_wq);
854 atomic_set(&server->active, 0); 853 atomic_set(&server->active, 0);
855 854
856 server->io_stats = nfs_alloc_iostats(); 855 server->io_stats = nfs_alloc_iostats();
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 24241fcbb98d..7bcf6ec2d458 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -163,8 +163,8 @@ extern struct rpc_stat nfs_rpcstat;
163 163
164extern int __init register_nfs_fs(void); 164extern int __init register_nfs_fs(void);
165extern void __exit unregister_nfs_fs(void); 165extern void __exit unregister_nfs_fs(void);
166extern void nfs_sb_active(struct nfs_server *server); 166extern void nfs_sb_active(struct super_block *sb);
167extern void nfs_sb_deactive(struct nfs_server *server); 167extern void nfs_sb_deactive(struct super_block *sb);
168 168
169/* namespace.c */ 169/* namespace.c */
170extern char *nfs_path(const char *base, 170extern char *nfs_path(const char *base,
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index e9b20173fef3..e527fab40419 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -209,7 +209,6 @@ static int nfs_get_sb(struct file_system_type *, int, const char *, void *, stru
209static int nfs_xdev_get_sb(struct file_system_type *fs_type, 209static int nfs_xdev_get_sb(struct file_system_type *fs_type,
210 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); 210 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
211static void nfs_kill_super(struct super_block *); 211static void nfs_kill_super(struct super_block *);
212static void nfs_put_super(struct super_block *);
213static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); 212static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
214 213
215static struct file_system_type nfs_fs_type = { 214static struct file_system_type nfs_fs_type = {
@@ -232,7 +231,6 @@ static const struct super_operations nfs_sops = {
232 .alloc_inode = nfs_alloc_inode, 231 .alloc_inode = nfs_alloc_inode,
233 .destroy_inode = nfs_destroy_inode, 232 .destroy_inode = nfs_destroy_inode,
234 .write_inode = nfs_write_inode, 233 .write_inode = nfs_write_inode,
235 .put_super = nfs_put_super,
236 .statfs = nfs_statfs, 234 .statfs = nfs_statfs,
237 .clear_inode = nfs_clear_inode, 235 .clear_inode = nfs_clear_inode,
238 .umount_begin = nfs_umount_begin, 236 .umount_begin = nfs_umount_begin,
@@ -337,26 +335,20 @@ void __exit unregister_nfs_fs(void)
337 unregister_filesystem(&nfs_fs_type); 335 unregister_filesystem(&nfs_fs_type);
338} 336}
339 337
340void nfs_sb_active(struct nfs_server *server) 338void nfs_sb_active(struct super_block *sb)
341{ 339{
342 atomic_inc(&server->active); 340 struct nfs_server *server = NFS_SB(sb);
343}
344 341
345void nfs_sb_deactive(struct nfs_server *server) 342 if (atomic_inc_return(&server->active) == 1)
346{ 343 atomic_inc(&sb->s_active);
347 if (atomic_dec_and_test(&server->active))
348 wake_up(&server->active_wq);
349} 344}
350 345
351static void nfs_put_super(struct super_block *sb) 346void nfs_sb_deactive(struct super_block *sb)
352{ 347{
353 struct nfs_server *server = NFS_SB(sb); 348 struct nfs_server *server = NFS_SB(sb);
354 /* 349
355 * Make sure there are no outstanding ops to this server. 350 if (atomic_dec_and_test(&server->active))
356 * If so, wait for them to finish before allowing the 351 deactivate_super(sb);
357 * unmount to continue.
358 */
359 wait_event(server->active_wq, atomic_read(&server->active) == 0);
360} 352}
361 353
362/* 354/*
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index f089e5839d7d..ecc295347775 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -99,7 +99,7 @@ static void nfs_async_unlink_release(void *calldata)
99 99
100 nfs_dec_sillycount(data->dir); 100 nfs_dec_sillycount(data->dir);
101 nfs_free_unlinkdata(data); 101 nfs_free_unlinkdata(data);
102 nfs_sb_deactive(NFS_SB(sb)); 102 nfs_sb_deactive(sb);
103} 103}
104 104
105static const struct rpc_call_ops nfs_unlink_ops = { 105static const struct rpc_call_ops nfs_unlink_ops = {
@@ -118,6 +118,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
118 .rpc_message = &msg, 118 .rpc_message = &msg,
119 .callback_ops = &nfs_unlink_ops, 119 .callback_ops = &nfs_unlink_ops,
120 .callback_data = data, 120 .callback_data = data,
121 .workqueue = nfsiod_workqueue,
121 .flags = RPC_TASK_ASYNC, 122 .flags = RPC_TASK_ASYNC,
122 }; 123 };
123 struct rpc_task *task; 124 struct rpc_task *task;
@@ -149,7 +150,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
149 nfs_dec_sillycount(dir); 150 nfs_dec_sillycount(dir);
150 return 0; 151 return 0;
151 } 152 }
152 nfs_sb_active(NFS_SERVER(dir)); 153 nfs_sb_active(dir->i_sb);
153 data->args.fh = NFS_FH(dir); 154 data->args.fh = NFS_FH(dir);
154 nfs_fattr_init(&data->res.dir_attr); 155 nfs_fattr_init(&data->res.dir_attr);
155 156
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index c9beacd16c00..4e477ae58699 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -119,7 +119,6 @@ struct nfs_server {
119 void (*destroy)(struct nfs_server *); 119 void (*destroy)(struct nfs_server *);
120 120
121 atomic_t active; /* Keep trace of any activity to this server */ 121 atomic_t active; /* Keep trace of any activity to this server */
122 wait_queue_head_t active_wq; /* Wait for any activity to stop */
123 122
124 /* mountd-related mount options */ 123 /* mountd-related mount options */
125 struct sockaddr_storage mountd_address; 124 struct sockaddr_storage mountd_address;