mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
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> Change-Id: I58cc7b0a087646516db9af69962447d27fb3ee8b
This commit is contained in:
parent
722370c1a0
commit
f787204b2f
4 changed files with 65 additions and 82 deletions
|
@ -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);
|
||||||
|
if (dentry->d_inode) {
|
||||||
mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
|
if (dentry->d_inode->i_private == &thread)
|
||||||
dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
|
err = vfs_rmdir(parent.dentry->d_inode, dentry);
|
||||||
if (!IS_ERR(dentry)) {
|
else
|
||||||
if (dentry->d_inode) {
|
err = -EPERM;
|
||||||
if (dentry->d_inode->i_private == &thread)
|
|
||||||
err = vfs_rmdir(nd.path.dentry->d_inode,
|
|
||||||
dentry);
|
|
||||||
else
|
|
||||||
err = -EPERM;
|
|
||||||
} else {
|
|
||||||
err = -ENOENT;
|
|
||||||
}
|
|
||||||
dput(dentry);
|
|
||||||
} else {
|
} else {
|
||||||
err = PTR_ERR(dentry);
|
err = -ENOENT;
|
||||||
}
|
}
|
||||||
|
dput(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);
|
||||||
return err;
|
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)
|
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);
|
if (dentry->d_inode) {
|
||||||
dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
|
struct kstat stat;
|
||||||
if (!IS_ERR(dentry)) {
|
err = vfs_getattr(parent.mnt, dentry, &stat);
|
||||||
if (dentry->d_inode) {
|
if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
|
||||||
err = vfs_getattr(nd.path.mnt, dentry, &stat);
|
struct iattr newattrs;
|
||||||
if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
|
/*
|
||||||
struct iattr newattrs;
|
* before unlinking this node, reset permissions
|
||||||
/*
|
* of possible references like hardlinks
|
||||||
* before unlinking this node, reset permissions
|
*/
|
||||||
* of possible references like hardlinks
|
newattrs.ia_uid = 0;
|
||||||
*/
|
newattrs.ia_gid = 0;
|
||||||
newattrs.ia_uid = 0;
|
newattrs.ia_mode = stat.mode & ~0777;
|
||||||
newattrs.ia_gid = 0;
|
newattrs.ia_valid =
|
||||||
newattrs.ia_mode = stat.mode & ~0777;
|
ATTR_UID|ATTR_GID|ATTR_MODE;
|
||||||
newattrs.ia_valid =
|
mutex_lock(&dentry->d_inode->i_mutex);
|
||||||
ATTR_UID|ATTR_GID|ATTR_MODE;
|
notify_change(dentry, &newattrs);
|
||||||
mutex_lock(&dentry->d_inode->i_mutex);
|
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||||
notify_change(dentry, &newattrs);
|
err = vfs_unlink(parent.dentry->d_inode, dentry);
|
||||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
if (!err || err == -ENOENT)
|
||||||
err = vfs_unlink(nd.path.dentry->d_inode,
|
deleted = 1;
|
||||||
dentry);
|
|
||||||
if (!err || err == -ENOENT)
|
|
||||||
deleted = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = -ENOENT;
|
|
||||||
}
|
}
|
||||||
dput(dentry);
|
|
||||||
} else {
|
} 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, '/'))
|
if (deleted && strchr(nodename, '/'))
|
||||||
delete_path(nodename);
|
delete_path(nodename);
|
||||||
return err;
|
return err;
|
||||||
|
|
22
fs/namei.c
22
fs/namei.c
|
@ -1808,9 +1808,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)
|
||||||
|
|
|
@ -78,7 +78,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)
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue