Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+41 −57
Original line number Diff line number Diff line
@@ -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)) {
	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(nd.path.dentry->d_inode,
						dentry);
			err = vfs_rmdir(parent.dentry->d_inode, dentry);
		else
			err = -EPERM;
	} else {
		err = -ENOENT;
	}
	dput(dentry);
	} else {
		err = PTR_ERR(dentry);
	}

	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
	path_put(&nd.path);
	mutex_unlock(&parent.dentry->d_inode->i_mutex);
	path_put(&parent);
	return err;
}

@@ -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)
{
	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);
		struct kstat stat;
		err = vfs_getattr(parent.mnt, dentry, &stat);
		if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
			struct iattr newattrs;
			/*
@@ -334,8 +322,7 @@ static int handle_remove(const char *nodename, struct device *dev)
			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);
			err = vfs_unlink(parent.dentry->d_inode, dentry);
			if (!err || err == -ENOENT)
				deleted = 1;
		}
@@ -343,12 +330,9 @@ static int handle_remove(const char *nodename, struct device *dev)
		err = -ENOENT;
	}
	dput(dentry);
	} else {
		err = PTR_ERR(dentry);
	}
	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
	mutex_unlock(&parent.dentry->d_inode->i_mutex);

	path_put(&nd.path);
	path_put(&parent);
	if (deleted && strchr(nodename, '/'))
		delete_path(nodename);
	return err;
+20 −2
Original line number Diff line number Diff line
@@ -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)
+1 −1
Original line number Diff line number Diff line
@@ -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 *);

+3 −22
Original line number Diff line number Diff line
@@ -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;
}