summaryrefslogtreecommitdiffstats
path: root/fs/autofs4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/autofs4')
-rw-r--r--fs/autofs4/autofs_i.h13
-rw-r--r--fs/autofs4/expire.c5
-rw-r--r--fs/autofs4/root.c15
-rw-r--r--fs/autofs4/waitq.c7
4 files changed, 34 insertions, 6 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index c7b2b8890188..9c09641ce907 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -185,6 +185,19 @@ int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify);
int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
void autofs4_catatonic_mode(struct autofs_sb_info *);
+static inline int autofs4_follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+{
+ int res = 0;
+
+ while (d_mountpoint(*dentry)) {
+ int followed = follow_down(mnt, dentry);
+ if (!followed)
+ break;
+ res = 1;
+ }
+ return res;
+}
+
static inline int simple_positive(struct dentry *dentry)
{
return dentry->d_inode && !d_unhashed(dentry);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 500425e24fba..feb6ac427d05 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -56,12 +56,9 @@ static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry)
mntget(mnt);
dget(dentry);
- if (!follow_down(&mnt, &dentry))
+ if (!autofs4_follow_mount(&mnt, &dentry))
goto done;
- while (d_mountpoint(dentry) && follow_down(&mnt, &dentry))
- ;
-
/* This is an autofs submount, we can't expire it */
if (is_autofs4_dentry(dentry))
goto done;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 3765c047f157..2a771ec66956 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -205,7 +205,11 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
struct vfsmount *fp_mnt = mntget(mnt);
struct dentry *fp_dentry = dget(dentry);
- while (follow_down(&fp_mnt, &fp_dentry) && d_mountpoint(fp_dentry));
+ if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) {
+ dput(fp_dentry);
+ mntput(fp_mnt);
+ return -ENOENT;
+ }
fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
status = PTR_ERR(fp);
@@ -302,7 +306,14 @@ static int try_to_fill_dentry(struct dentry *dentry,
DPRINTK("expire done status=%d", status);
- return 0;
+ /*
+ * If the directory still exists the mount request must
+ * continue otherwise it can't be followed at the right
+ * time during the walk.
+ */
+ status = d_invalidate(dentry);
+ if (status != -EBUSY)
+ return 0;
}
DPRINTK("dentry=%p %.*s ino=%p",
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 5a40d36e5a51..fa2348dcd671 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -191,6 +191,13 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
}
if ( !wq ) {
+ /* Can't wait for an expire if there's no mount */
+ if (notify == NFY_NONE && !d_mountpoint(dentry)) {
+ kfree(name);
+ up(&sbi->wq_sem);
+ return -ENOENT;
+ }
+
/* Create a new wait queue */
wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
if ( !wq ) {