Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 24246
b: refs/heads/master
c: 1aff3c8
h: refs/heads/master
v: v3
  • Loading branch information
Ian Kent authored and Linus Torvalds committed Mar 27, 2006
1 parent 005a2cd commit 04ece4d
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 12 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: 1ce12bad85863478619688c0c7363f93a9e5edb8
refs/heads/master: 1aff3c8b0511b5bb54acf7859e0c6ec9ae7287a9
1 change: 1 addition & 0 deletions trunk/fs/autofs4/autofs_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct autofs_info {

struct autofs_sb_info *sbi;
unsigned long last_used;
atomic_t count;

mode_t mode;
size_t size;
Expand Down
34 changes: 25 additions & 9 deletions trunk/fs/autofs4/expire.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
unsigned long timeout,
int do_now)
{
struct autofs_info *ino;
struct dentry *p;

DPRINTK("top %p %.*s",
Expand All @@ -110,14 +111,6 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
if (!simple_positive(top))
return 1;

/* Timeout of a tree mount is determined by its top dentry */
if (!autofs4_can_expire(top, timeout, do_now))
return 1;

/* Is someone visiting anywhere in the tree ? */
if (may_umount_tree(mnt))
return 1;

spin_lock(&dcache_lock);
for (p = top; p; p = next_dentry(p, top)) {
/* Negative dentry - give up */
Expand All @@ -130,17 +123,40 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
p = dget(p);
spin_unlock(&dcache_lock);

/*
* Is someone visiting anywhere in the subtree ?
* If there's no mount we need to check the usage
* count for the autofs dentry.
*/
ino = autofs4_dentry_ino(p);
if (d_mountpoint(p)) {
/* First busy => tree busy */
if (autofs4_mount_busy(mnt, p)) {
dput(p);
return 1;
}
} else {
unsigned int ino_count = atomic_read(&ino->count);

/* allow for dget above and top is already dgot */
if (p == top)
ino_count += 2;
else
ino_count++;

if (atomic_read(&p->d_count) > ino_count) {
dput(p);
return 1;
}
}
dput(p);
spin_lock(&dcache_lock);
}
spin_unlock(&dcache_lock);

/* Timeout of a tree mount is ultimately determined by its top dentry */
if (!autofs4_can_expire(top, timeout, do_now))
return 1;

return 0;
}

Expand Down
12 changes: 11 additions & 1 deletion trunk/fs/autofs4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
ino->size = 0;

ino->last_used = jiffies;
atomic_set(&ino->count, 0);

ino->sbi = sbi;

Expand All @@ -64,10 +65,19 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,

void autofs4_free_ino(struct autofs_info *ino)
{
struct autofs_info *p_ino;

if (ino->dentry) {
ino->dentry->d_fsdata = NULL;
if (ino->dentry->d_inode)
if (ino->dentry->d_inode) {
struct dentry *parent = ino->dentry->d_parent;
if (atomic_dec_and_test(&ino->count)) {
p_ino = autofs4_dentry_ino(parent);
if (p_ino && parent != ino->dentry)
atomic_dec(&p_ino->count);
}
dput(ino->dentry);
}
ino->dentry = NULL;
}
if (ino->free)
Expand Down
23 changes: 22 additions & 1 deletion trunk/fs/autofs4/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ static int autofs4_dir_symlink(struct inode *dir,
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
struct autofs_info *p_ino;
struct inode *inode;
char *cp;

Expand Down Expand Up @@ -523,6 +524,10 @@ static int autofs4_dir_symlink(struct inode *dir,

dentry->d_fsdata = ino;
ino->dentry = dget(dentry);
atomic_inc(&ino->count);
p_ino = autofs4_dentry_ino(dentry->d_parent);
if (p_ino && dentry->d_parent != dentry)
atomic_inc(&p_ino->count);
ino->inode = inode;

dir->i_mtime = CURRENT_TIME;
Expand All @@ -549,11 +554,17 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
struct autofs_info *p_ino;

/* This allows root to remove symlinks */
if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
return -EACCES;

if (atomic_dec_and_test(&ino->count)) {
p_ino = autofs4_dentry_ino(dentry->d_parent);
if (p_ino && dentry->d_parent != dentry)
atomic_dec(&p_ino->count);
}
dput(ino->dentry);

dentry->d_inode->i_size = 0;
Expand All @@ -570,6 +581,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
struct autofs_info *p_ino;

if (!autofs4_oz_mode(sbi))
return -EACCES;
Expand All @@ -584,8 +596,12 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);

if (atomic_dec_and_test(&ino->count)) {
p_ino = autofs4_dentry_ino(dentry->d_parent);
if (p_ino && dentry->d_parent != dentry)
atomic_dec(&p_ino->count);
}
dput(ino->dentry);

dentry->d_inode->i_size = 0;
dentry->d_inode->i_nlink = 0;

Expand All @@ -599,6 +615,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
struct autofs_info *p_ino;
struct inode *inode;

if ( !autofs4_oz_mode(sbi) )
Expand All @@ -621,6 +638,10 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)

dentry->d_fsdata = ino;
ino->dentry = dget(dentry);
atomic_inc(&ino->count);
p_ino = autofs4_dentry_ino(dentry->d_parent);
if (p_ino && dentry->d_parent != dentry)
atomic_inc(&p_ino->count);
ino->inode = inode;
dir->i_nlink++;
dir->i_mtime = CURRENT_TIME;
Expand Down

0 comments on commit 04ece4d

Please sign in to comment.