diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 330 |
1 files changed, 166 insertions, 164 deletions
diff --git a/fs/namei.c b/fs/namei.c index 73e2e665817..941c8e8228c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -106,7 +106,7 @@ * any extra contention... */ -static int fastcall link_path_walk(const char *name, struct nameidata *nd); +static int link_path_walk(const char *name, struct nameidata *nd); /* In order to reduce some races, while at the same time doing additional * checking and hopefully speeding things up, we copy filenames to the @@ -231,7 +231,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) struct vfsmount *mnt = NULL; if (nd) - mnt = nd->mnt; + mnt = nd->path.mnt; if (mask & MAY_WRITE) { umode_t mode = inode->i_mode; @@ -296,7 +296,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) */ int vfs_permission(struct nameidata *nd, int mask) { - return permission(nd->dentry->d_inode, mask, nd); + return permission(nd->path.dentry->d_inode, mask, nd); } /** @@ -362,21 +362,31 @@ int deny_write_access(struct file * file) return 0; } -void path_release(struct nameidata *nd) +/** + * path_get - get a reference to a path + * @path: path to get the reference to + * + * Given a path increment the reference count to the dentry and the vfsmount. + */ +void path_get(struct path *path) { - dput(nd->dentry); - mntput(nd->mnt); + mntget(path->mnt); + dget(path->dentry); } +EXPORT_SYMBOL(path_get); -/* - * umount() mustn't call path_release()/mntput() as that would clear - * mnt_expiry_mark +/** + * path_put - put a reference to a path + * @path: path to put the reference to + * + * Given a path decrement the reference count to the dentry and the vfsmount. */ -void path_release_on_umount(struct nameidata *nd) +void path_put(struct path *path) { - dput(nd->dentry); - mntput_no_expire(nd->mnt); + dput(path->dentry); + mntput(path->mnt); } +EXPORT_SYMBOL(path_put); /** * release_open_intent - free up open intent resources @@ -539,16 +549,16 @@ walk_init_root(const char *name, struct nameidata *nd) struct fs_struct *fs = current->fs; read_lock(&fs->lock); - if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) { - nd->mnt = mntget(fs->altrootmnt); - nd->dentry = dget(fs->altroot); + if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) { + nd->path = fs->altroot; + path_get(&fs->altroot); read_unlock(&fs->lock); if (__emul_lookup_dentry(name,nd)) return 0; read_lock(&fs->lock); } - nd->mnt = mntget(fs->rootmnt); - nd->dentry = dget(fs->root); + nd->path = fs->root; + path_get(&fs->root); read_unlock(&fs->lock); return 1; } @@ -561,7 +571,7 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l goto fail; if (*link == '/') { - path_release(nd); + path_put(&nd->path); if (!walk_init_root(link, nd)) /* weird __emul_prefix() stuff did it */ goto out; @@ -577,31 +587,31 @@ out: */ name = __getname(); if (unlikely(!name)) { - path_release(nd); + path_put(&nd->path); return -ENOMEM; } strcpy(name, nd->last.name); nd->last.name = name; return 0; fail: - path_release(nd); + path_put(&nd->path); return PTR_ERR(link); } -static inline void dput_path(struct path *path, struct nameidata *nd) +static void path_put_conditional(struct path *path, struct nameidata *nd) { dput(path->dentry); - if (path->mnt != nd->mnt) + if (path->mnt != nd->path.mnt) mntput(path->mnt); } static inline void path_to_nameidata(struct path *path, struct nameidata *nd) { - dput(nd->dentry); - if (nd->mnt != path->mnt) - mntput(nd->mnt); - nd->mnt = path->mnt; - nd->dentry = path->dentry; + dput(nd->path.dentry); + if (nd->path.mnt != path->mnt) + mntput(nd->path.mnt); + nd->path.mnt = path->mnt; + nd->path.dentry = path->dentry; } static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) @@ -613,7 +623,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata touch_atime(path->mnt, dentry); nd_set_link(nd, NULL); - if (path->mnt != nd->mnt) { + if (path->mnt != nd->path.mnt) { path_to_nameidata(path, nd); dget(dentry); } @@ -628,8 +638,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata if (dentry->d_inode->i_op->put_link) dentry->d_inode->i_op->put_link(dentry, nd, cookie); } - dput(dentry); - mntput(path->mnt); + path_put(path); return error; } @@ -661,8 +670,8 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd) nd->depth--; return err; loop: - dput_path(path, nd); - path_release(nd); + path_put_conditional(path, nd); + path_put(&nd->path); return err; } @@ -743,37 +752,37 @@ static __always_inline void follow_dotdot(struct nameidata *nd) while(1) { struct vfsmount *parent; - struct dentry *old = nd->dentry; + struct dentry *old = nd->path.dentry; read_lock(&fs->lock); - if (nd->dentry == fs->root && - nd->mnt == fs->rootmnt) { + if (nd->path.dentry == fs->root.dentry && + nd->path.mnt == fs->root.mnt) { read_unlock(&fs->lock); break; } read_unlock(&fs->lock); spin_lock(&dcache_lock); - if (nd->dentry != nd->mnt->mnt_root) { - nd->dentry = dget(nd->dentry->d_parent); + if (nd->path.dentry != nd->path.mnt->mnt_root) { + nd->path.dentry = dget(nd->path.dentry->d_parent); spin_unlock(&dcache_lock); dput(old); break; } spin_unlock(&dcache_lock); spin_lock(&vfsmount_lock); - parent = nd->mnt->mnt_parent; - if (parent == nd->mnt) { + parent = nd->path.mnt->mnt_parent; + if (parent == nd->path.mnt) { spin_unlock(&vfsmount_lock); break; } mntget(parent); - nd->dentry = dget(nd->mnt->mnt_mountpoint); + nd->path.dentry = dget(nd->path.mnt->mnt_mountpoint); spin_unlock(&vfsmount_lock); dput(old); - mntput(nd->mnt); - nd->mnt = parent; + mntput(nd->path.mnt); + nd->path.mnt = parent; } - follow_mount(&nd->mnt, &nd->dentry); + follow_mount(&nd->path.mnt, &nd->path.dentry); } /* @@ -784,8 +793,8 @@ static __always_inline void follow_dotdot(struct nameidata *nd) static int do_lookup(struct nameidata *nd, struct qstr *name, struct path *path) { - struct vfsmount *mnt = nd->mnt; - struct dentry *dentry = __d_lookup(nd->dentry, name); + struct vfsmount *mnt = nd->path.mnt; + struct dentry *dentry = __d_lookup(nd->path.dentry, name); if (!dentry) goto need_lookup; @@ -798,7 +807,7 @@ done: return 0; need_lookup: - dentry = real_lookup(nd->dentry, name, nd); + dentry = real_lookup(nd->path.dentry, name, nd); if (IS_ERR(dentry)) goto fail; goto done; @@ -823,7 +832,7 @@ fail: * Returns 0 and nd will have valid dentry and mnt on success. * Returns error and drops reference to input namei data on failure. */ -static fastcall int __link_path_walk(const char * name, struct nameidata *nd) +static int __link_path_walk(const char *name, struct nameidata *nd) { struct path next; struct inode *inode; @@ -835,7 +844,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) if (!*name) goto return_reval; - inode = nd->dentry->d_inode; + inode = nd->path.dentry->d_inode; if (nd->depth) lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); @@ -883,7 +892,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) if (this.name[1] != '.') break; follow_dotdot(nd); - inode = nd->dentry->d_inode; + inode = nd->path.dentry->d_inode; /* fallthrough */ case 1: continue; @@ -892,8 +901,9 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) * See if the low-level filesystem might want * to use its own hash.. */ - if (nd->dentry->d_op && nd->dentry->d_op->d_hash) { - err = nd->dentry->d_op->d_hash(nd->dentry, &this); + if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { + err = nd->path.dentry->d_op->d_hash(nd->path.dentry, + &this); if (err < 0) break; } @@ -915,7 +925,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) if (err) goto return_err; err = -ENOENT; - inode = nd->dentry->d_inode; + inode = nd->path.dentry->d_inode; if (!inode) break; err = -ENOTDIR; @@ -943,13 +953,14 @@ last_component: if (this.name[1] != '.') break; follow_dotdot(nd); - inode = nd->dentry->d_inode; + inode = nd->path.dentry->d_inode; /* fallthrough */ case 1: goto return_reval; } - if (nd->dentry->d_op && nd->dentry->d_op->d_hash) { - err = nd->dentry->d_op->d_hash(nd->dentry, &this); + if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { + err = nd->path.dentry->d_op->d_hash(nd->path.dentry, + &this); if (err < 0) break; } @@ -962,7 +973,7 @@ last_component: err = do_follow_link(&next, nd); if (err) goto return_err; - inode = nd->dentry->d_inode; + inode = nd->path.dentry->d_inode; } else path_to_nameidata(&next, nd); err = -ENOENT; @@ -990,20 +1001,21 @@ return_reval: * We bypassed the ordinary revalidation routines. * We may need to check the cached dentry for staleness. */ - if (nd->dentry && nd->dentry->d_sb && - (nd->dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) { + if (nd->path.dentry && nd->path.dentry->d_sb && + (nd->path.dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) { err = -ESTALE; /* Note: we do not d_invalidate() */ - if (!nd->dentry->d_op->d_revalidate(nd->dentry, nd)) + if (!nd->path.dentry->d_op->d_revalidate( + nd->path.dentry, nd)) break; } return_base: return 0; out_dput: - dput_path(&next, nd); + path_put_conditional(&next, nd); break; } - path_release(nd); + path_put(&nd->path); return_err: return err; } @@ -1015,31 +1027,30 @@ return_err: * Retry the whole path once, forcing real lookup requests * instead of relying on the dcache. */ -static int fastcall link_path_walk(const char *name, struct nameidata *nd) +static int link_path_walk(const char *name, struct nameidata *nd) { struct nameidata save = *nd; int result; /* make sure the stuff we saved doesn't go away */ - dget(save.dentry); - mntget(save.mnt); + dget(save.path.dentry); + mntget(save.path.mnt); result = __link_path_walk(name, nd); if (result == -ESTALE) { *nd = save; - dget(nd->dentry); - mntget(nd->mnt); + dget(nd->path.dentry); + mntget(nd->path.mnt); nd->flags |= LOOKUP_REVAL; result = __link_path_walk(name, nd); } - dput(save.dentry); - mntput(save.mnt); + path_put(&save.path); return result; } -static int fastcall path_walk(const char * name, struct nameidata *nd) +static int path_walk(const char *name, struct nameidata *nd) { current->total_link_count = 0; return link_path_walk(name, nd); @@ -1054,9 +1065,9 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) if (path_walk(name, nd)) return 0; /* something went wrong... */ - if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) { - struct dentry *old_dentry = nd->dentry; - struct vfsmount *old_mnt = nd->mnt; + if (!nd->path.dentry->d_inode || + S_ISDIR(nd->path.dentry->d_inode->i_mode)) { + struct path old_path = nd->path; struct qstr last = nd->last; int last_type = nd->last_type; struct fs_struct *fs = current->fs; @@ -1067,19 +1078,17 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) */ nd->last_type = LAST_ROOT; read_lock(&fs->lock); - nd->mnt = mntget(fs->rootmnt); - nd->dentry = dget(fs->root); + nd->path = fs->root; + path_get(&fs->root); read_unlock(&fs->lock); if (path_walk(name, nd) == 0) { - if (nd->dentry->d_inode) { - dput(old_dentry); - mntput(old_mnt); + if (nd->path.dentry->d_inode) { + path_put(&old_path); return 1; } - path_release(nd); + path_put(&nd->path); } - nd->dentry = old_dentry; - nd->mnt = old_mnt; + nd->path = old_path; nd->last = last; nd->last_type = last_type; } @@ -1090,33 +1099,26 @@ void set_fs_altroot(void) { char *emul = __emul_prefix(); struct nameidata nd; - struct vfsmount *mnt = NULL, *oldmnt; - struct dentry *dentry = NULL, *olddentry; + struct path path = {}, old_path; int err; struct fs_struct *fs = current->fs; if (!emul) goto set_it; err = path_lookup(emul, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd); - if (!err) { - mnt = nd.mnt; - dentry = nd.dentry; - } + if (!err) + path = nd.path; set_it: write_lock(&fs->lock); - oldmnt = fs->altrootmnt; - olddentry = fs->altroot; - fs->altrootmnt = mnt; - fs->altroot = dentry; + old_path = fs->altroot; + fs->altroot = path; write_unlock(&fs->lock); - if (olddentry) { - dput(olddentry); - mntput(oldmnt); - } + if (old_path.dentry) + path_put(&old_path); } /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ -static int fastcall do_path_lookup(int dfd, const char *name, +static int do_path_lookup(int dfd, const char *name, unsigned int flags, struct nameidata *nd) { int retval = 0; @@ -1130,21 +1132,21 @@ static int fastcall do_path_lookup(int dfd, const char *name, if (*name=='/') { read_lock(&fs->lock); - if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) { - nd->mnt = mntget(fs->altrootmnt); - nd->dentry = dget(fs->altroot); + if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) { + nd->path = fs->altroot; + path_get(&fs->altroot); read_unlock(&fs->lock); if (__emul_lookup_dentry(name,nd)) goto out; /* found in altroot */ read_lock(&fs->lock); } - nd->mnt = mntget(fs->rootmnt); - nd->dentry = dget(fs->root); + nd->path = fs->root; + path_get(&fs->root); read_unlock(&fs->lock); } else if (dfd == AT_FDCWD) { read_lock(&fs->lock); - nd->mnt = mntget(fs->pwdmnt); - nd->dentry = dget(fs->pwd); + nd->path = fs->pwd; + path_get(&fs->pwd); read_unlock(&fs->lock); } else { struct dentry *dentry; @@ -1164,17 +1166,17 @@ static int fastcall do_path_lookup(int dfd, const char *name, if (retval) goto fput_fail; - nd->mnt = mntget(file->f_path.mnt); - nd->dentry = dget(dentry); + nd->path = file->f_path; + path_get(&file->f_path); fput_light(file, fput_needed); } retval = path_walk(name, nd); out: - if (unlikely(!retval && !audit_dummy_context() && nd->dentry && - nd->dentry->d_inode)) - audit_inode(name, nd->dentry); + if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && + nd->path.dentry->d_inode)) + audit_inode(name, nd->path.dentry); out_fail: return retval; @@ -1183,7 +1185,7 @@ fput_fail: goto out_fail; } -int fastcall path_lookup(const char *name, unsigned int flags, +int path_lookup(const char *name, unsigned int flags, struct nameidata *nd) { return do_path_lookup(AT_FDCWD, name, flags, nd); @@ -1208,13 +1210,13 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, nd->flags = flags; nd->depth = 0; - nd->mnt = mntget(mnt); - nd->dentry = dget(dentry); + nd->path.mnt = mntget(mnt); + nd->path.dentry = dget(dentry); retval = path_walk(name, nd); - if (unlikely(!retval && !audit_dummy_context() && nd->dentry && - nd->dentry->d_inode)) - audit_inode(name, nd->dentry); + if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && + nd->path.dentry->d_inode)) + audit_inode(name, nd->path.dentry); return retval; @@ -1236,7 +1238,7 @@ static int __path_lookup_intent_open(int dfd, const char *name, if (IS_ERR(nd->intent.open.file)) { if (err == 0) { err = PTR_ERR(nd->intent.open.file); - path_release(nd); + path_put(&nd->path); } } else if (err != 0) release_open_intent(nd); @@ -1333,10 +1335,10 @@ static struct dentry *lookup_hash(struct nameidata *nd) { int err; - err = permission(nd->dentry->d_inode, MAY_EXEC, nd); + err = permission(nd->path.dentry->d_inode, MAY_EXEC, nd); if (err) return ERR_PTR(err); - return __lookup_hash(&nd->last, nd->dentry, nd); + return __lookup_hash(&nd->last, nd->path.dentry, nd); } static int __lookup_one_len(const char *name, struct qstr *this, @@ -1409,7 +1411,7 @@ struct dentry *lookup_one_noperm(const char *name, struct dentry *base) return __lookup_hash(&this, base, NULL); } -int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags, +int __user_walk_fd(int dfd, const char __user *name, unsigned flags, struct nameidata *nd) { char *tmp = getname(name); @@ -1422,7 +1424,7 @@ int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags, return err; } -int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) +int __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) { return __user_walk_fd(AT_FDCWD, name, flags, nd); } @@ -1595,7 +1597,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, int may_open(struct nameidata *nd, int acc_mode, int flag) { - struct dentry *dentry = nd->dentry; + struct dentry *dentry = nd->path.dentry; struct inode *inode = dentry->d_inode; int error; @@ -1616,7 +1618,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { flag &= ~O_TRUNC; } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { - if (nd->mnt->mnt_flags & MNT_NODEV) + if (nd->path.mnt->mnt_flags & MNT_NODEV) return -EACCES; flag &= ~O_TRUNC; @@ -1678,14 +1680,14 @@ static int open_namei_create(struct nameidata *nd, struct path *path, int flag, int mode) { int error; - struct dentry *dir = nd->dentry; + struct dentry *dir = nd->path.dentry; if (!IS_POSIXACL(dir->d_inode)) mode &= ~current->fs->umask; error = vfs_create(dir->d_inode, path->dentry, mode, nd); mutex_unlock(&dir->d_inode->i_mutex); - dput(nd->dentry); - nd->dentry = path->dentry; + dput(nd->path.dentry); + nd->path.dentry = path->dentry; if (error) return error; /* Don't check for write permission, don't truncate */ @@ -1752,11 +1754,11 @@ int open_namei(int dfd, const char *pathname, int flag, if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len]) goto exit; - dir = nd->dentry; + dir = nd->path.dentry; nd->flags &= ~LOOKUP_PARENT; mutex_lock(&dir->d_inode->i_mutex); path.dentry = lookup_hash(nd); - path.mnt = nd->mnt; + path.mnt = nd->path.mnt; do_last: error = PTR_ERR(path.dentry); @@ -1812,11 +1814,11 @@ ok: return 0; exit_dput: - dput_path(&path, nd); + path_put_conditional(&path, nd); exit: if (!IS_ERR(nd->intent.open.file)) release_open_intent(nd); - path_release(nd); + path_put(&nd->path); return error; do_link: @@ -1861,10 +1863,10 @@ do_link: __putname(nd->last.name); goto exit; } - dir = nd->dentry; + dir = nd->path.dentry; mutex_lock(&dir->d_inode->i_mutex); path.dentry = lookup_hash(nd); - path.mnt = nd->mnt; + path.mnt = nd->path.mnt; __putname(nd->last.name); goto do_last; } @@ -1877,13 +1879,13 @@ do_link: * Simple function to lookup and return a dentry and create it * if it doesn't exist. Is SMP-safe. * - * Returns with nd->dentry->d_inode->i_mutex locked. + * Returns with nd->path.dentry->d_inode->i_mutex locked. */ struct dentry *lookup_create(struct nameidata *nd, int is_dir) { struct dentry *dentry = ERR_PTR(-EEXIST); - mutex_lock_nested(&nd->dentry->d_inode->i_mutex, I_MUTEX_PARENT); + mutex_lock_nested(&nd->path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); /* * Yucky last component or no last component at all? * (foo/., foo/.., /////) @@ -1962,19 +1964,19 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, dentry = lookup_create(&nd, 0); error = PTR_ERR(dentry); - if (!IS_POSIXACL(nd.dentry->d_inode)) + if (!IS_POSIXACL(nd.path.dentry->d_inode)) mode &= ~current->fs->umask; if (!IS_ERR(dentry)) { switch (mode & S_IFMT) { case 0: case S_IFREG: - error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd); + error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); break; case S_IFCHR: case S_IFBLK: - error = vfs_mknod(nd.dentry->d_inode,dentry,mode, + error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode, new_decode_dev(dev)); break; case S_IFIFO: case S_IFSOCK: - error = vfs_mknod(nd.dentry->d_inode,dentry,mode,0); + error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); break; case S_IFDIR: error = -EPERM; @@ -1984,8 +1986,8 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, } dput(dentry); } - mutex_unlock(&nd.dentry->d_inode->i_mutex); - path_release(&nd); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + path_put(&nd.path); out: putname(tmp); @@ -2039,13 +2041,13 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) if (IS_ERR(dentry)) goto out_unlock; - if (!IS_POSIXACL(nd.dentry->d_inode)) + if (!IS_POSIXACL(nd.path.dentry->d_inode)) mode &= ~current->fs->umask; - error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); + error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); dput(dentry); out_unlock: - mutex_unlock(&nd.dentry->d_inode->i_mutex); - path_release(&nd); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + path_put(&nd.path); out: putname(tmp); out_err: @@ -2143,17 +2145,17 @@ static long do_rmdir(int dfd, const char __user *pathname) error = -EBUSY; goto exit1; } - mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT); + mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto exit2; - error = vfs_rmdir(nd.dentry->d_inode, dentry); + error = vfs_rmdir(nd.path.dentry->d_inode, dentry); dput(dentry); exit2: - mutex_unlock(&nd.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); exit1: - path_release(&nd); + path_put(&nd.path); exit: putname(name); return error; @@ -2188,6 +2190,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) /* We don't d_delete() NFS sillyrenamed files--they still exist. */ if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { + fsnotify_link_count(dentry->d_inode); d_delete(dentry); } @@ -2218,7 +2221,7 @@ static long do_unlinkat(int dfd, const char __user *pathname) error = -EISDIR; if (nd.last_type != LAST_NORM) goto exit1; - mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT); + mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { @@ -2228,15 +2231,15 @@ static long do_unlinkat(int dfd, const char __user *pathname) inode = dentry->d_inode; if (inode) atomic_inc(&inode->i_count); - error = vfs_unlink(nd.dentry->d_inode, dentry); + error = vfs_unlink(nd.path.dentry->d_inode, dentry); exit2: dput(dentry); } - mutex_unlock(&nd.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); if (inode) iput(inode); /* truncate the inode here */ exit1: - path_release(&nd); + path_put(&nd.path); exit: putname(name); return error; @@ -2309,11 +2312,11 @@ asmlinkage long sys_symlinkat(const char __user *oldname, if (IS_ERR(dentry)) goto out_unlock; - error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); + error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO); dput(dentry); out_unlock: - mutex_unlock(&nd.dentry->d_inode->i_mutex); - path_release(&nd); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + path_put(&nd.path); out: putname(to); out_putname: @@ -2360,7 +2363,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de error = dir->i_op->link(old_dentry, dir, new_dentry); mutex_unlock(&old_dentry->d_inode->i_mutex); if (!error) - fsnotify_create(dir, new_dentry); + fsnotify_link(dir, old_dentry->d_inode, new_dentry); return error; } @@ -2398,20 +2401,20 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, if (error) goto out; error = -EXDEV; - if (old_nd.mnt != nd.mnt) + if (old_nd.path.mnt != nd.path.mnt) goto out_release; new_dentry = lookup_create(&nd, 0); error = PTR_ERR(new_dentry); if (IS_ERR(new_dentry)) goto out_unlock; - error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); + error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry); dput(new_dentry); out_unlock: - mutex_unlock(&nd.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); out_release: - path_release(&nd); + path_put(&nd.path); out: - path_release(&old_nd); + path_put(&old_nd.path); exit: putname(to); @@ -2587,15 +2590,15 @@ static int do_rename(int olddfd, const char *oldname, goto exit1; error = -EXDEV; - if (oldnd.mnt != newnd.mnt) + if (oldnd.path.mnt != newnd.path.mnt) goto exit2; - old_dir = oldnd.dentry; + old_dir = oldnd.path.dentry; error = -EBUSY; if (oldnd.last_type != LAST_NORM) goto exit2; - new_dir = newnd.dentry; + new_dir = newnd.path.dentry; if (newnd.last_type != LAST_NORM) goto exit2; @@ -2639,9 +2642,9 @@ exit4: exit3: unlock_rename(new_dir, old_dir); exit2: - path_release(&newnd); + path_put(&newnd.path); exit1: - path_release(&oldnd); + path_put(&oldnd.path); exit: return error; } @@ -2815,7 +2818,6 @@ EXPORT_SYMBOL(page_symlink); EXPORT_SYMBOL(page_symlink_inode_operations); EXPORT_SYMBOL(path_lookup); EXPORT_SYMBOL(vfs_path_lookup); -EXPORT_SYMBOL(path_release); EXPORT_SYMBOL(permission); EXPORT_SYMBOL(vfs_permission); EXPORT_SYMBOL(file_permission); |