get rid of kern_path_parent()
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 14 Jun 2012 23:01:42 +0000 (03:01 +0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 14 Jul 2012 12:35:02 +0000 (16:35 +0400)
all callers want the same thing, actually - a kinda-sorta analog of
kern_path_create().  I.e. they want parent vfsmount/dentry (with
->i_mutex held, to make sure the child dentry is still their child)
+ the child dentry.

Signed-off-by Al Viro <viro@zeniv.linux.org.uk>

drivers/base/devtmpfs.c
fs/namei.c
include/linux/namei.h
kernel/audit_watch.c

index 765c3a2..d91a3a0 100644 (file)
@@ -227,33 +227,24 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev)
 
 static int dev_rmdir(const char *name)
 {
-       struct nameidata nd;
+       struct path parent;
        struct dentry *dentry;
        int err;
 
-       err = kern_path_parent(name, &nd);
-       if (err)
-               return err;
-
-       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
-       dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
-       if (!IS_ERR(dentry)) {
-               if (dentry->d_inode) {
-                       if (dentry->d_inode->i_private == &thread)
-                               err = vfs_rmdir(nd.path.dentry->d_inode,
-                                               dentry);
-                       else
-                               err = -EPERM;
-               } else {
-                       err = -ENOENT;
-               }
-               dput(dentry);
+       dentry = kern_path_locked(name, &parent);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
+       if (dentry->d_inode) {
+               if (dentry->d_inode->i_private == &thread)
+                       err = vfs_rmdir(parent.dentry->d_inode, dentry);
+               else
+                       err = -EPERM;
        } else {
-               err = PTR_ERR(dentry);
+               err = -ENOENT;
        }
-
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-       path_put(&nd.path);
+       dput(dentry);
+       mutex_unlock(&parent.dentry->d_inode->i_mutex);
+       path_put(&parent);
        return err;
 }
 
@@ -305,50 +296,43 @@ static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *sta
 
 static int handle_remove(const char *nodename, struct device *dev)
 {
-       struct nameidata nd;
+       struct path parent;
        struct dentry *dentry;
-       struct kstat stat;
        int deleted = 1;
        int err;
 
-       err = kern_path_parent(nodename, &nd);
-       if (err)
-               return err;
+       dentry = kern_path_locked(nodename, &parent);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
 
-       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
-       dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
-       if (!IS_ERR(dentry)) {
-               if (dentry->d_inode) {
-                       err = vfs_getattr(nd.path.mnt, dentry, &stat);
-                       if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
-                               struct iattr newattrs;
-                               /*
-                                * before unlinking this node, reset permissions
-                                * of possible references like hardlinks
-                                */
-                               newattrs.ia_uid = 0;
-                               newattrs.ia_gid = 0;
-                               newattrs.ia_mode = stat.mode & ~0777;
-                               newattrs.ia_valid =
-                                       ATTR_UID|ATTR_GID|ATTR_MODE;
-                               mutex_lock(&dentry->d_inode->i_mutex);
-                               notify_change(dentry, &newattrs);
-                               mutex_unlock(&dentry->d_inode->i_mutex);
-                               err = vfs_unlink(nd.path.dentry->d_inode,
-                                                dentry);
-                               if (!err || err == -ENOENT)
-                                       deleted = 1;
-                       }
-               } else {
-                       err = -ENOENT;
+       if (dentry->d_inode) {
+               struct kstat stat;
+               err = vfs_getattr(parent.mnt, dentry, &stat);
+               if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
+                       struct iattr newattrs;
+                       /*
+                        * before unlinking this node, reset permissions
+                        * of possible references like hardlinks
+                        */
+                       newattrs.ia_uid = 0;
+                       newattrs.ia_gid = 0;
+                       newattrs.ia_mode = stat.mode & ~0777;
+                       newattrs.ia_valid =
+                               ATTR_UID|ATTR_GID|ATTR_MODE;
+                       mutex_lock(&dentry->d_inode->i_mutex);
+                       notify_change(dentry, &newattrs);
+                       mutex_unlock(&dentry->d_inode->i_mutex);
+                       err = vfs_unlink(parent.dentry->d_inode, dentry);
+                       if (!err || err == -ENOENT)
+                               deleted = 1;
                }
-               dput(dentry);
        } else {
-               err = PTR_ERR(dentry);
+               err = -ENOENT;
        }
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+       dput(dentry);
+       mutex_unlock(&parent.dentry->d_inode->i_mutex);
 
-       path_put(&nd.path);
+       path_put(&parent);
        if (deleted && strchr(nodename, '/'))
                delete_path(nodename);
        return err;
index 5abab91..6b29a51 100644 (file)
@@ -1814,9 +1814,27 @@ static int do_path_lookup(int dfd, const char *name,
        return retval;
 }
 
-int kern_path_parent(const char *name, struct nameidata *nd)
+/* does lookup, returns the object with parent locked */
+struct dentry *kern_path_locked(const char *name, struct path *path)
 {
-       return do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, nd);
+       struct nameidata nd;
+       struct dentry *d;
+       int err = do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, &nd);
+       if (err)
+               return ERR_PTR(err);
+       if (nd.last_type != LAST_NORM) {
+               path_put(&nd.path);
+               return ERR_PTR(-EINVAL);
+       }
+       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
+       d = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
+       if (IS_ERR(d)) {
+               mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+               path_put(&nd.path);
+               return d;
+       }
+       *path = nd.path;
+       return d;
 }
 
 int kern_path(const char *name, unsigned int flags, struct path *path)
index 23d8598..f593148 100644 (file)
@@ -67,7 +67,7 @@ extern int kern_path(const char *, unsigned, struct path *);
 
 extern struct dentry *kern_path_create(int, const char *, struct path *, int);
 extern struct dentry *user_path_create(int, const char __user *, struct path *, int);
-extern int kern_path_parent(const char *, struct nameidata *);
+extern struct dentry *kern_path_locked(const char *, struct path *);
 extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
                           const char *, unsigned int, struct path *);
 
index e683869..3823281 100644 (file)
@@ -355,34 +355,15 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
 /* Get path information necessary for adding watches. */
 static int audit_get_nd(struct audit_watch *watch, struct path *parent)
 {
-       struct nameidata nd;
-       struct dentry *d;
-       int err;
-
-       err = kern_path_parent(watch->path, &nd);
-       if (err)
-               return err;
-
-       if (nd.last_type != LAST_NORM) {
-               path_put(&nd.path);
-               return -EINVAL;
-       }
-
-       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
-       d = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
-       if (IS_ERR(d)) {
-               mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-               path_put(&nd.path);
+       struct dentry *d = kern_path_locked(watch->path, parent);
+       if (IS_ERR(d))
                return PTR_ERR(d);
-       }
+       mutex_unlock(&parent->dentry->d_inode->i_mutex);
        if (d->d_inode) {
                /* update watch filter fields */
                watch->dev = d->d_inode->i_sb->s_dev;
                watch->ino = d->d_inode->i_ino;
        }
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-
-       *parent = nd.path;
        dput(d);
        return 0;
 }