diff options
Diffstat (limited to 'fs/nfs/namespace.c')
-rw-r--r-- | fs/nfs/namespace.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index a155505c36f1..e426516c1116 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -18,6 +18,11 @@ | |||
18 | 18 | ||
19 | #define NFSDBG_FACILITY NFSDBG_VFS | 19 | #define NFSDBG_FACILITY NFSDBG_VFS |
20 | 20 | ||
21 | LIST_HEAD(nfs_automount_list); | ||
22 | static void nfs_expire_automounts(void *list); | ||
23 | static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list); | ||
24 | int nfs_mountpoint_expiry_timeout = 500 * HZ; | ||
25 | |||
21 | /* | 26 | /* |
22 | * nfs_follow_mountpoint - handle crossing a mountpoint on the server | 27 | * nfs_follow_mountpoint - handle crossing a mountpoint on the server |
23 | * @dentry - dentry of mountpoint | 28 | * @dentry - dentry of mountpoint |
@@ -59,7 +64,7 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
59 | goto out_err; | 64 | goto out_err; |
60 | 65 | ||
61 | mntget(mnt); | 66 | mntget(mnt); |
62 | err = do_add_mount(mnt, nd, nd->mnt->mnt_flags, NULL); | 67 | err = do_add_mount(mnt, nd, nd->mnt->mnt_flags|MNT_SHRINKABLE, &nfs_automount_list); |
63 | if (err < 0) { | 68 | if (err < 0) { |
64 | mntput(mnt); | 69 | mntput(mnt); |
65 | if (err == -EBUSY) | 70 | if (err == -EBUSY) |
@@ -70,6 +75,7 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
70 | dput(nd->dentry); | 75 | dput(nd->dentry); |
71 | nd->mnt = mnt; | 76 | nd->mnt = mnt; |
72 | nd->dentry = dget(mnt->mnt_root); | 77 | nd->dentry = dget(mnt->mnt_root); |
78 | schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout); | ||
73 | out: | 79 | out: |
74 | dprintk("%s: done, returned %d\n", __FUNCTION__, err); | 80 | dprintk("%s: done, returned %d\n", __FUNCTION__, err); |
75 | return ERR_PTR(err); | 81 | return ERR_PTR(err); |
@@ -87,3 +93,20 @@ struct inode_operations nfs_mountpoint_inode_operations = { | |||
87 | .follow_link = nfs_follow_mountpoint, | 93 | .follow_link = nfs_follow_mountpoint, |
88 | .getattr = nfs_getattr, | 94 | .getattr = nfs_getattr, |
89 | }; | 95 | }; |
96 | |||
97 | static void nfs_expire_automounts(void *data) | ||
98 | { | ||
99 | struct list_head *list = (struct list_head *)data; | ||
100 | |||
101 | mark_mounts_for_expiry(list); | ||
102 | if (!list_empty(list)) | ||
103 | schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout); | ||
104 | } | ||
105 | |||
106 | void nfs_release_automount_timer(void) | ||
107 | { | ||
108 | if (list_empty(&nfs_automount_list)) { | ||
109 | cancel_delayed_work(&nfs_automount_task); | ||
110 | flush_scheduled_work(); | ||
111 | } | ||
112 | } | ||