Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 105472
b: refs/heads/master
c: 6e60a9a
h: refs/heads/master
v: v3
  • Loading branch information
Ian Kent authored and Linus Torvalds committed Jul 24, 2008
1 parent dd60764 commit 71e2268
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 97e7449a7ad883bf9f516fc970778d75999c7843
refs/heads/master: 6e60a9ab5f5d314735467752f623072f5b75157a
3 changes: 3 additions & 0 deletions trunk/fs/autofs4/autofs_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ struct autofs_info {

int flags;

struct completion expire_complete;

struct list_head active;
struct list_head expiring;

Expand All @@ -69,6 +71,7 @@ struct autofs_info {
};

#define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */
#define AUTOFS_INF_MOUNTPOINT (1<<1) /* mountpoint status for direct expire */

struct autofs_wait_queue {
wait_queue_head_t queue;
Expand Down
16 changes: 13 additions & 3 deletions trunk/fs/autofs4/expire.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,13 +259,15 @@ static struct dentry *autofs4_expire_direct(struct super_block *sb,
now = jiffies;
timeout = sbi->exp_timeout;

/* Lock the tree as we must expire as a whole */
spin_lock(&sbi->fs_lock);
if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
struct autofs_info *ino = autofs4_dentry_ino(root);

/* Set this flag early to catch sys_chdir and the like */
if (d_mountpoint(root)) {
ino->flags |= AUTOFS_INF_MOUNTPOINT;
root->d_mounted--;
}
ino->flags |= AUTOFS_INF_EXPIRING;
init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
return root;
}
Expand Down Expand Up @@ -392,6 +394,7 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb,
expired, (int)expired->d_name.len, expired->d_name.name);
ino = autofs4_dentry_ino(expired);
ino->flags |= AUTOFS_INF_EXPIRING;
init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
spin_lock(&dcache_lock);
list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
Expand Down Expand Up @@ -429,6 +432,7 @@ int autofs4_expire_run(struct super_block *sb,
spin_lock(&sbi->fs_lock);
ino = autofs4_dentry_ino(dentry);
ino->flags &= ~AUTOFS_INF_EXPIRING;
complete_all(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);

return ret;
Expand Down Expand Up @@ -457,8 +461,14 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
/* This is synchronous because it makes the daemon a
little easier */
ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);

spin_lock(&sbi->fs_lock);
if (ino->flags & AUTOFS_INF_MOUNTPOINT) {
sb->s_root->d_mounted++;
ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
}
ino->flags &= ~AUTOFS_INF_EXPIRING;
complete_all(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
dput(dentry);
}
Expand Down
72 changes: 49 additions & 23 deletions trunk/fs/autofs4/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
dentry, dentry->d_name.len, dentry->d_name.name);

status = autofs4_wait(sbi, dentry, NFY_NONE);
wait_for_completion(&ino->expire_complete);

DPRINTK("expire done status=%d", status);

Expand Down Expand Up @@ -227,14 +228,32 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d",
dentry, dentry->d_name.len, dentry->d_name.name, oz_mode,
nd->flags);

/* If it's our master or we shouldn't trigger a mount we're done */
lookup_type = nd->flags & (TRIGGER_FLAGS | TRIGGER_INTENTS);
if (oz_mode ||
!(lookup_type || dentry->d_flags & DCACHE_AUTOFS_PENDING))
/*
* For an expire of a covered direct or offset mount we need
* to beeak out of follow_down() at the autofs mount trigger
* (d_mounted--), so we can see the expiring flag, and manage
* the blocking and following here until the expire is completed.
*/
if (oz_mode) {
spin_lock(&sbi->fs_lock);
if (ino->flags & AUTOFS_INF_EXPIRING) {
spin_unlock(&sbi->fs_lock);
/* Follow down to our covering mount. */
if (!follow_down(&nd->path.mnt, &nd->path.dentry))
goto done;
/*
* We shouldn't need to do this but we have no way
* of knowing what may have been done so try a follow
* just in case.
*/
autofs4_follow_mount(&nd->path.mnt, &nd->path.dentry);
goto done;
}
spin_unlock(&sbi->fs_lock);
goto done;
}

/* If an expire request is pending wait for it. */
/* If an expire request is pending everyone must wait. */
spin_lock(&sbi->fs_lock);
if (ino->flags & AUTOFS_INF_EXPIRING) {
spin_unlock(&sbi->fs_lock);
Expand All @@ -243,17 +262,23 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
dentry, dentry->d_name.len, dentry->d_name.name);

status = autofs4_wait(sbi, dentry, NFY_NONE);
wait_for_completion(&ino->expire_complete);

DPRINTK("request done status=%d", status);

goto cont;
}
spin_unlock(&sbi->fs_lock);
cont:
/* We trigger a mount for almost all flags */
lookup_type = nd->flags & (TRIGGER_FLAGS | TRIGGER_INTENTS);
if (!(lookup_type || dentry->d_flags & DCACHE_AUTOFS_PENDING))
goto done;

/*
* If the dentry contains directories then it is an
* autofs multi-mount with no root mount offset. So
* don't try to mount it again.
* If the dentry contains directories then it is an autofs
* multi-mount with no root mount offset. So don't try to
* mount it again.
*/
spin_lock(&dcache_lock);
if (dentry->d_flags & DCACHE_AUTOFS_PENDING ||
Expand All @@ -264,22 +289,22 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
if (status)
goto out_error;

/*
* The mount succeeded but if there is no root mount
* it must be an autofs multi-mount with no root offset
* so we don't need to follow the mount.
*/
if (d_mountpoint(dentry)) {
if (!autofs4_follow_mount(&nd->path.mnt,
&nd->path.dentry)) {
status = -ENOENT;
goto out_error;
}
}

goto done;
goto follow;
}
spin_unlock(&dcache_lock);
follow:
/*
* If there is no root mount it must be an autofs
* multi-mount with no root offset so we don't need
* to follow it.
*/
if (d_mountpoint(dentry)) {
if (!autofs4_follow_mount(&nd->path.mnt,
&nd->path.dentry)) {
status = -ENOENT;
goto out_error;
}
}

done:
return NULL;
Expand Down Expand Up @@ -545,6 +570,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
expiring, expiring->d_name.len,
expiring->d_name.name);
autofs4_wait(sbi, expiring, NFY_NONE);
wait_for_completion(&ino->expire_complete);
DPRINTK("request completed");
goto cont;
}
Expand Down

0 comments on commit 71e2268

Please sign in to comment.