Commit 79714f72 authored by Al Viro's avatar Al Viro

get rid of kern_path_parent()

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>
parent 1acf0af9
...@@ -227,33 +227,24 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev) ...@@ -227,33 +227,24 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev)
static int dev_rmdir(const char *name) static int dev_rmdir(const char *name)
{ {
struct nameidata nd; struct path parent;
struct dentry *dentry; struct dentry *dentry;
int err; int err;
err = kern_path_parent(name, &nd); dentry = kern_path_locked(name, &parent);
if (err) if (IS_ERR(dentry))
return err; 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) { if (dentry->d_inode) {
if (dentry->d_inode->i_private == &thread) if (dentry->d_inode->i_private == &thread)
err = vfs_rmdir(nd.path.dentry->d_inode, err = vfs_rmdir(parent.dentry->d_inode, dentry);
dentry);
else else
err = -EPERM; err = -EPERM;
} else { } else {
err = -ENOENT; err = -ENOENT;
} }
dput(dentry); dput(dentry);
} else { mutex_unlock(&parent.dentry->d_inode->i_mutex);
err = PTR_ERR(dentry); path_put(&parent);
}
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
path_put(&nd.path);
return err; return err;
} }
...@@ -305,21 +296,18 @@ static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *sta ...@@ -305,21 +296,18 @@ static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *sta
static int handle_remove(const char *nodename, struct device *dev) static int handle_remove(const char *nodename, struct device *dev)
{ {
struct nameidata nd; struct path parent;
struct dentry *dentry; struct dentry *dentry;
struct kstat stat;
int deleted = 1; int deleted = 1;
int err; int err;
err = kern_path_parent(nodename, &nd); dentry = kern_path_locked(nodename, &parent);
if (err) if (IS_ERR(dentry))
return err; 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) { if (dentry->d_inode) {
err = vfs_getattr(nd.path.mnt, dentry, &stat); struct kstat stat;
err = vfs_getattr(parent.mnt, dentry, &stat);
if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
struct iattr newattrs; struct iattr newattrs;
/* /*
...@@ -334,8 +322,7 @@ static int handle_remove(const char *nodename, struct device *dev) ...@@ -334,8 +322,7 @@ static int handle_remove(const char *nodename, struct device *dev)
mutex_lock(&dentry->d_inode->i_mutex); mutex_lock(&dentry->d_inode->i_mutex);
notify_change(dentry, &newattrs); notify_change(dentry, &newattrs);
mutex_unlock(&dentry->d_inode->i_mutex); mutex_unlock(&dentry->d_inode->i_mutex);
err = vfs_unlink(nd.path.dentry->d_inode, err = vfs_unlink(parent.dentry->d_inode, dentry);
dentry);
if (!err || err == -ENOENT) if (!err || err == -ENOENT)
deleted = 1; deleted = 1;
} }
...@@ -343,12 +330,9 @@ static int handle_remove(const char *nodename, struct device *dev) ...@@ -343,12 +330,9 @@ static int handle_remove(const char *nodename, struct device *dev)
err = -ENOENT; err = -ENOENT;
} }
dput(dentry); dput(dentry);
} else { mutex_unlock(&parent.dentry->d_inode->i_mutex);
err = PTR_ERR(dentry);
}
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
path_put(&nd.path); path_put(&parent);
if (deleted && strchr(nodename, '/')) if (deleted && strchr(nodename, '/'))
delete_path(nodename); delete_path(nodename);
return err; return err;
......
...@@ -1814,9 +1814,27 @@ static int do_path_lookup(int dfd, const char *name, ...@@ -1814,9 +1814,27 @@ static int do_path_lookup(int dfd, const char *name,
return retval; 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) int kern_path(const char *name, unsigned int flags, struct path *path)
......
...@@ -67,7 +67,7 @@ extern int kern_path(const char *, unsigned, struct path *); ...@@ -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 *kern_path_create(int, const char *, struct path *, int);
extern struct dentry *user_path_create(int, const char __user *, 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 *, extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
const char *, unsigned int, struct path *); const char *, unsigned int, struct path *);
......
...@@ -355,34 +355,15 @@ static void audit_remove_parent_watches(struct audit_parent *parent) ...@@ -355,34 +355,15 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
/* Get path information necessary for adding watches. */ /* Get path information necessary for adding watches. */
static int audit_get_nd(struct audit_watch *watch, struct path *parent) static int audit_get_nd(struct audit_watch *watch, struct path *parent)
{ {
struct nameidata nd; struct dentry *d = kern_path_locked(watch->path, parent);
struct dentry *d; if (IS_ERR(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);
return PTR_ERR(d); return PTR_ERR(d);
} mutex_unlock(&parent->dentry->d_inode->i_mutex);
if (d->d_inode) { if (d->d_inode) {
/* update watch filter fields */ /* update watch filter fields */
watch->dev = d->d_inode->i_sb->s_dev; watch->dev = d->d_inode->i_sb->s_dev;
watch->ino = d->d_inode->i_ino; watch->ino = d->d_inode->i_ino;
} }
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
*parent = nd.path;
dput(d); dput(d);
return 0; return 0;
} }
......
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