Commit 85d217f4 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] Re: 2.5.11 breakage

	OK, here comes.  Patch below is an attempt to do the fastwalk
stuff in right way and so far it seems to be working.

 - dentry leak is plugged
 - locked/unlocked state of nameidata doesn't depend on history - it
   depends only on point in code.
 - LOOKUP_LOCKED is gone.
 - following mounts and .. doesn't drop dcache_lock
 - light-weight permission check distinguishes between "don't know" and
   "permission denied", so we don't call full-blown permission() unless
   we have to.
 - code that changes root/pwd holds dcache_lock _and_ write lock on
   current->fs->lock.  I.e. if we hold dcache_lock we can safely
   access our ->fs->{root,pwd}{,mnt}
 - __d_lookup() does not increment refcount; callers do dget_locked()
   if they need it (behaviour of d_lookup() didn't change, obviously).
 - link_path_walk() logics had been (somewhat) cleaned up.
parent 7ca32047
......@@ -849,6 +849,8 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
struct dentry * dentry;
spin_lock(&dcache_lock);
dentry = __d_lookup(parent,name);
if (dentry)
__dget_locked(dentry);
spin_unlock(&dcache_lock);
return dentry;
}
......@@ -881,7 +883,6 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
if (memcmp(dentry->d_name.name, str, len))
continue;
}
__dget_locked(dentry);
dentry->d_vfs_flags |= DCACHE_REFERENCED;
return dentry;
}
......
This diff is collapsed.
......@@ -654,6 +654,8 @@ struct nameidata {
struct qstr last;
unsigned int flags;
int last_type;
struct dentry *old_dentry;
struct vfsmount *old_mnt;
};
#define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */
......@@ -1395,7 +1397,6 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *);
#define LOOKUP_CONTINUE (4)
#define LOOKUP_PARENT (16)
#define LOOKUP_NOALT (32)
#define LOOKUP_LOCKED (64)
/*
* Type of the last component on LOOKUP_PARENT
......
......@@ -35,10 +35,12 @@ static inline void set_fs_root(struct fs_struct *fs,
struct dentry *old_root;
struct vfsmount *old_rootmnt;
write_lock(&fs->lock);
spin_lock(&dcache_lock);
old_root = fs->root;
old_rootmnt = fs->rootmnt;
fs->rootmnt = mntget(mnt);
fs->root = dget(dentry);
spin_unlock(&dcache_lock);
write_unlock(&fs->lock);
if (old_root) {
dput(old_root);
......@@ -58,10 +60,12 @@ static inline void set_fs_pwd(struct fs_struct *fs,
struct dentry *old_pwd;
struct vfsmount *old_pwdmnt;
write_lock(&fs->lock);
spin_lock(&dcache_lock);
old_pwd = fs->pwd;
old_pwdmnt = fs->pwdmnt;
fs->pwdmnt = mntget(mnt);
fs->pwd = dget(dentry);
spin_unlock(&dcache_lock);
write_unlock(&fs->lock);
if (old_pwd) {
dput(old_pwd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment