summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Mammedov <niallain@gmail.com>2008-04-24 12:56:07 +0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-04-25 17:15:26 +0400
commit78d31a3a87f84cf56004b7bc154831f2ee1186e8 (patch)
tree0b18911e95f08dc2bce01c1555fe65f1865b0c71
parentb69d3987f4360a5e7e9e55465b3cdd0cc204b79e (diff)
downloadlinux-78d31a3a87f84cf56004b7bc154831f2ee1186e8.tar.xz
cifs: timeout dfs automounts +little fix.
Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/cifs/cifs_dfs_ref.c29
-rw-r--r--fs/cifs/cifsfs.c3
-rw-r--r--fs/cifs/cifsproto.h8
3 files changed, 23 insertions, 17 deletions
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index f53f41ff1665..95024c066d89 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -25,14 +25,26 @@
static LIST_HEAD(cifs_dfs_automount_list);
-/*
- * DFS functions
-*/
+static void cifs_dfs_expire_automounts(struct work_struct *work);
+static DECLARE_DELAYED_WORK(cifs_dfs_automount_task,
+ cifs_dfs_expire_automounts);
+static int cifs_dfs_mountpoint_expiry_timeout = 500 * HZ;
+
+static void cifs_dfs_expire_automounts(struct work_struct *work)
+{
+ struct list_head *list = &cifs_dfs_automount_list;
+
+ mark_mounts_for_expiry(list);
+ if (!list_empty(list))
+ schedule_delayed_work(&cifs_dfs_automount_task,
+ cifs_dfs_mountpoint_expiry_timeout);
+}
-void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
+void cifs_dfs_release_automount_timer(void)
{
- mark_mounts_for_expiry(&cifs_dfs_automount_list);
- mark_mounts_for_expiry(&cifs_dfs_automount_list);
+ BUG_ON(!list_empty(&cifs_dfs_automount_list));
+ cancel_delayed_work(&cifs_dfs_automount_task);
+ flush_scheduled_work();
}
/**
@@ -261,10 +273,11 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd,
err = do_add_mount(newmnt, nd, nd->path.mnt->mnt_flags, mntlist);
switch (err) {
case 0:
- dput(nd->path.dentry);
- mntput(nd->path.mnt);
+ path_put(&nd->path);
nd->path.mnt = newmnt;
nd->path.dentry = dget(newmnt->mnt_root);
+ schedule_delayed_work(&cifs_dfs_automount_task,
+ cifs_dfs_mountpoint_expiry_timeout);
break;
case -EBUSY:
/* someone else made a mount here whilst we were busy */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index a04b17e5a9d0..dbb2cd678bf5 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -471,8 +471,6 @@ static void cifs_umount_begin(struct vfsmount *vfsmnt, int flags)
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *tcon;
- dfs_shrink_umount_helper(vfsmnt);
-
if (!(flags & MNT_FORCE))
return;
cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
@@ -1100,6 +1098,7 @@ exit_cifs(void)
cFYI(DBG2, ("exit_cifs"));
cifs_proc_clean();
#ifdef CONFIG_CIFS_DFS_UPCALL
+ cifs_dfs_release_automount_timer();
unregister_key_type(&key_type_dns_resolver);
#endif
#ifdef CONFIG_CIFS_UPCALL
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 0c83da4a7dab..50f9fdae19b3 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -104,13 +104,7 @@ extern int mode_to_acl(struct inode *inode, const char *path, __u64);
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
const char *);
extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
-#ifdef CONFIG_CIFS_DFS_UPCALL
-extern void dfs_shrink_umount_helper(struct vfsmount *vfsmnt);
-#else
-static inline void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
-{
-}
-#endif /* DFS_UPCALL */
+extern void cifs_dfs_release_automount_timer(void);
void cifs_proc_init(void);
void cifs_proc_clean(void);