Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 226706
b: refs/heads/master
c: 2fd6b7f
h: refs/heads/master
v: v3
  • Loading branch information
Nick Piggin committed Jan 7, 2011
1 parent a8e2c3f commit 269f531
Show file tree
Hide file tree
Showing 17 changed files with 340 additions and 161 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: da5029563a0a026c64821b09e8e7b4fd81d3fe1b
refs/heads/master: 2fd6b7f50797f2e993eea59e0a0b8c6399c811dc
4 changes: 4 additions & 0 deletions trunk/drivers/staging/smbfs/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ smb_invalidate_dircache_entries(struct dentry *parent)
struct dentry *dentry;

spin_lock(&dcache_lock);
spin_lock(&parent->d_lock);
next = parent->d_subdirs.next;
while (next != &parent->d_subdirs) {
dentry = list_entry(next, struct dentry, d_u.d_child);
dentry->d_fsdata = NULL;
smb_age_dentry(server, dentry);
next = next->next;
}
spin_unlock(&parent->d_lock);
spin_unlock(&dcache_lock);
}

Expand Down Expand Up @@ -97,6 +99,7 @@ smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)

/* If a pointer is invalid, we search the dentry. */
spin_lock(&dcache_lock);
spin_lock(&parent->d_lock);
next = parent->d_subdirs.next;
while (next != &parent->d_subdirs) {
dent = list_entry(next, struct dentry, d_u.d_child);
Expand All @@ -111,6 +114,7 @@ smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
}
dent = NULL;
out_unlock:
spin_unlock(&parent->d_lock);
spin_unlock(&dcache_lock);
return dent;
}
Expand Down
8 changes: 5 additions & 3 deletions trunk/drivers/usb/core/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,18 +344,20 @@ static int usbfs_empty (struct dentry *dentry)
struct list_head *list;

spin_lock(&dcache_lock);

spin_lock(&dentry->d_lock);
list_for_each(list, &dentry->d_subdirs) {
struct dentry *de = list_entry(list, struct dentry, d_u.d_child);
spin_lock(&de->d_lock);

spin_lock_nested(&de->d_lock, DENTRY_D_LOCK_NESTED);
if (usbfs_positive(de)) {
spin_unlock(&de->d_lock);
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
return 0;
}
spin_unlock(&de->d_lock);
}

spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
return 1;
}
Expand Down
11 changes: 11 additions & 0 deletions trunk/fs/autofs4/autofs_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,17 @@ static inline int simple_positive(struct dentry *dentry)
return dentry->d_inode && !d_unhashed(dentry);
}

static inline void __autofs4_add_expiring(struct dentry *dentry)
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
if (ino) {
if (list_empty(&ino->expiring))
list_add(&ino->expiring, &sbi->expiring_list);
}
return;
}

static inline void autofs4_add_expiring(struct dentry *dentry)
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
Expand Down
127 changes: 60 additions & 67 deletions trunk/fs/autofs4/expire.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,24 +91,64 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
}

/*
* Calculate next entry in top down tree traversal.
* From next_mnt in namespace.c - elegant.
* Calculate and dget next entry in top down tree traversal.
*/
static struct dentry *next_dentry(struct dentry *p, struct dentry *root)
static struct dentry *get_next_positive_dentry(struct dentry *prev,
struct dentry *root)
{
struct list_head *next = p->d_subdirs.next;
struct list_head *next;
struct dentry *p, *ret;

if (prev == NULL)
return dget(prev);

spin_lock(&dcache_lock);
relock:
p = prev;
spin_lock(&p->d_lock);
again:
next = p->d_subdirs.next;
if (next == &p->d_subdirs) {
while (1) {
if (p == root)
struct dentry *parent;

if (p == root) {
spin_unlock(&p->d_lock);
spin_unlock(&dcache_lock);
dput(prev);
return NULL;
}

parent = p->d_parent;
if (!spin_trylock(&parent->d_lock)) {
spin_unlock(&p->d_lock);
cpu_relax();
goto relock;
}
spin_unlock(&p->d_lock);
next = p->d_u.d_child.next;
if (next != &p->d_parent->d_subdirs)
p = parent;
if (next != &parent->d_subdirs)
break;
p = p->d_parent;
}
}
return list_entry(next, struct dentry, d_u.d_child);
ret = list_entry(next, struct dentry, d_u.d_child);

spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
/* Negative dentry - try next */
if (!simple_positive(ret)) {
spin_unlock(&ret->d_lock);
p = ret;
goto again;
}
dget_dlock(ret);
spin_unlock(&ret->d_lock);
spin_unlock(&p->d_lock);
spin_unlock(&dcache_lock);

dput(prev);

return ret;
}

/*
Expand Down Expand Up @@ -158,22 +198,11 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
if (!simple_positive(top))
return 1;

spin_lock(&dcache_lock);
for (p = top; p; p = next_dentry(p, top)) {
spin_lock(&p->d_lock);
/* Negative dentry - give up */
if (!simple_positive(p)) {
spin_unlock(&p->d_lock);
continue;
}

p = NULL;
while ((p = get_next_positive_dentry(p, top))) {
DPRINTK("dentry %p %.*s",
p, (int) p->d_name.len, p->d_name.name);

p = dget_dlock(p);
spin_unlock(&p->d_lock);
spin_unlock(&dcache_lock);

/*
* Is someone visiting anywhere in the subtree ?
* If there's no mount we need to check the usage
Expand Down Expand Up @@ -208,10 +237,7 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
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))
Expand All @@ -230,36 +256,21 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
DPRINTK("parent %p %.*s",
parent, (int)parent->d_name.len, parent->d_name.name);

spin_lock(&dcache_lock);
for (p = parent; p; p = next_dentry(p, parent)) {
spin_lock(&p->d_lock);
/* Negative dentry - give up */
if (!simple_positive(p)) {
spin_unlock(&p->d_lock);
continue;
}

p = NULL;
while ((p = get_next_positive_dentry(p, parent))) {
DPRINTK("dentry %p %.*s",
p, (int) p->d_name.len, p->d_name.name);

p = dget_dlock(p);
spin_unlock(&p->d_lock);
spin_unlock(&dcache_lock);

if (d_mountpoint(p)) {
/* Can we umount this guy */
if (autofs4_mount_busy(mnt, p))
goto cont;
continue;

/* Can we expire this guy */
if (autofs4_can_expire(p, timeout, do_now))
return p;
}
cont:
dput(p);
spin_lock(&dcache_lock);
}
spin_unlock(&dcache_lock);
return NULL;
}

Expand Down Expand Up @@ -310,8 +321,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
{
unsigned long timeout;
struct dentry *root = sb->s_root;
struct dentry *dentry;
struct dentry *expired = NULL;
struct list_head *next;
int do_now = how & AUTOFS_EXP_IMMEDIATE;
int exp_leaves = how & AUTOFS_EXP_LEAVES;
struct autofs_info *ino;
Expand All @@ -323,26 +334,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
now = jiffies;
timeout = sbi->exp_timeout;

spin_lock(&dcache_lock);
next = root->d_subdirs.next;

/* On exit from the loop expire is set to a dgot dentry
* to expire or it's NULL */
while ( next != &root->d_subdirs ) {
struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);

/* Negative dentry - give up */
spin_lock(&dentry->d_lock);
if (!simple_positive(dentry)) {
next = next->next;
spin_unlock(&dentry->d_lock);
continue;
}

dentry = dget_dlock(dentry);
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);

dentry = NULL;
while ((dentry = get_next_positive_dentry(dentry, root))) {
spin_lock(&sbi->fs_lock);
ino = autofs4_dentry_ino(dentry);

Expand Down Expand Up @@ -405,11 +398,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
}
next:
spin_unlock(&sbi->fs_lock);
dput(dentry);
spin_lock(&dcache_lock);
next = next->next;
}
spin_unlock(&dcache_lock);
return NULL;

found:
Expand All @@ -420,7 +409,11 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
spin_lock(&dcache_lock);
spin_lock(&expired->d_parent->d_lock);
spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
spin_unlock(&expired->d_lock);
spin_unlock(&expired->d_parent->d_lock);
spin_unlock(&dcache_lock);
return expired;
}
Expand Down
18 changes: 16 additions & 2 deletions trunk/fs/autofs4/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,13 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
* it.
*/
spin_lock(&dcache_lock);
spin_lock(&dentry->d_lock);
if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
return -ENOENT;
}
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);

out:
Expand Down Expand Up @@ -253,7 +256,9 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
lookup_type = autofs4_need_mount(nd->flags);
spin_lock(&sbi->fs_lock);
spin_lock(&dcache_lock);
spin_lock(&dentry->d_lock);
if (!(lookup_type || ino->flags & AUTOFS_INF_PENDING)) {
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
spin_unlock(&sbi->fs_lock);
goto follow;
Expand All @@ -266,6 +271,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
*/
if (ino->flags & AUTOFS_INF_PENDING ||
(!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs))) {
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
spin_unlock(&sbi->fs_lock);

Expand All @@ -275,6 +281,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)

goto follow;
}
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
spin_unlock(&sbi->fs_lock);
follow:
Expand Down Expand Up @@ -347,10 +354,12 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)

/* Check for a non-mountpoint directory with no contents */
spin_lock(&dcache_lock);
spin_lock(&dentry->d_lock);
if (S_ISDIR(dentry->d_inode->i_mode) &&
!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
DPRINTK("dentry=%p %.*s, emptydir",
dentry, dentry->d_name.len, dentry->d_name.name);
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);

/* The daemon never causes a mount to trigger */
Expand All @@ -367,6 +376,7 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)

return status;
}
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);

return 1;
Expand Down Expand Up @@ -776,12 +786,16 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
return -EACCES;

spin_lock(&dcache_lock);
spin_lock(&sbi->lookup_lock);
spin_lock(&dentry->d_lock);
if (!list_empty(&dentry->d_subdirs)) {
spin_unlock(&dentry->d_lock);
spin_unlock(&sbi->lookup_lock);
spin_unlock(&dcache_lock);
return -ENOTEMPTY;
}
autofs4_add_expiring(dentry);
spin_lock(&dentry->d_lock);
__autofs4_add_expiring(dentry);
spin_unlock(&sbi->lookup_lock);
__d_drop(dentry);
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
Expand Down
Loading

0 comments on commit 269f531

Please sign in to comment.