X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fnamei.c;h=aac4502614d82cfc9c01cbeafe8ea7eb21d87695;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=8a1943d4f4030e132009efc536e82c45eadb901f;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/fs/namei.c b/fs/namei.c index 8a1943d4f..aac450261 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -886,29 +886,31 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) return 0; /* something went wrong... */ if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) { - struct nameidata nd_root; + struct dentry *old_dentry = nd->dentry; + struct vfsmount *old_mnt = nd->mnt; + struct qstr last = nd->last; + int last_type = nd->last_type; /* * NAME was not found in alternate root or it's a directory. Try to find * it in the normal root: */ - nd_root.last_type = LAST_ROOT; - nd_root.flags = nd->flags; - nd_root.depth = 0; - memcpy(&nd_root.intent, &nd->intent, sizeof(nd_root.intent)); + nd->last_type = LAST_ROOT; read_lock(¤t->fs->lock); - nd_root.mnt = mntget(current->fs->rootmnt); - nd_root.dentry = dget(current->fs->root); + nd->mnt = mntget(current->fs->rootmnt); + nd->dentry = dget(current->fs->root); read_unlock(¤t->fs->lock); - if (path_walk(name, &nd_root)) - return 1; - if (nd_root.dentry->d_inode) { + if (path_walk(name, nd) == 0) { + if (nd->dentry->d_inode) { + dput(old_dentry); + mntput(old_mnt); + return 1; + } path_release(nd); - nd->dentry = nd_root.dentry; - nd->mnt = nd_root.mnt; - nd->last = nd_root.last; - return 1; } - path_release(&nd_root); + nd->dentry = old_dentry; + nd->mnt = old_mnt; + nd->last = last; + nd->last_type = last_type; } return 1; } @@ -961,8 +963,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata } nd->mnt = mntget(current->fs->rootmnt); nd->dentry = dget(current->fs->root); - } - else{ + } else { nd->mnt = mntget(current->fs->pwdmnt); nd->dentry = dget(current->fs->pwd); } @@ -1112,8 +1113,12 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir) { int error; - if (!victim->d_inode || victim->d_parent->d_inode != dir) + + if (!victim->d_inode) return -ENOENT; + + BUG_ON(victim->d_parent->d_inode != dir); + error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); if (error) return error; @@ -1677,7 +1682,7 @@ out: * if it cannot handle the case of removing a directory * that is still in use by something else.. */ -static void d_unhash(struct dentry *dentry) +void dentry_unhash(struct dentry *dentry) { dget(dentry); spin_lock(&dcache_lock); @@ -1707,7 +1712,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) DQUOT_INIT(dir); down(&dentry->d_inode->i_sem); - d_unhash(dentry); + dentry_unhash(dentry); if (d_mountpoint(dentry)) error = -EBUSY; else { @@ -1838,13 +1843,12 @@ asmlinkage long sys_unlink(const char __user * pathname) dput(dentry); } up(&nd.dentry->d_inode->i_sem); + if (inode) + iput(inode); /* truncate the inode here */ exit1: path_release(&nd); exit: putname(name); - - if (inode) - iput(inode); /* truncate the inode here */ return error; slashes: @@ -2050,7 +2054,7 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, target = new_dentry->d_inode; if (target) { down(&target->i_sem); - d_unhash(new_dentry); + dentry_unhash(new_dentry); } if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) error = -EBUSY; @@ -2317,12 +2321,8 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) int page_follow_link_light(struct dentry *dentry, struct nameidata *nd) { struct page *page; - char *s = page_getlink(dentry, &page); - if (!IS_ERR(s)) { - nd_set_link(nd, s); - s = NULL; - } - return PTR_ERR(s); + nd_set_link(nd, page_getlink(dentry, &page)); + return 0; } void page_put_link(struct dentry *dentry, struct nameidata *nd) @@ -2428,4 +2428,5 @@ EXPORT_SYMBOL(vfs_rename); EXPORT_SYMBOL(vfs_rmdir); EXPORT_SYMBOL(vfs_symlink); EXPORT_SYMBOL(vfs_unlink); +EXPORT_SYMBOL(dentry_unhash); EXPORT_SYMBOL(generic_readlink);