Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 312925
b: refs/heads/master
c: 79714f7
h: refs/heads/master
i:
  312923: b5e141b
v: v3
  • Loading branch information
Al Viro committed Jul 14, 2012
1 parent 41fb6e6 commit ed1a852
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 83 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1acf0af9b981027f3e73e93f0d3f85abdc794f71
refs/heads/master: 79714f72d3b964611997de512cb29198c9f2dbbb
98 changes: 41 additions & 57 deletions trunk/drivers/base/devtmpfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down
22 changes: 20 additions & 2 deletions trunk/fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion trunk/include/linux/namei.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);

Expand Down
25 changes: 3 additions & 22 deletions trunk/kernel/audit_watch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit ed1a852

Please sign in to comment.