Commit b05430fc authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs pile 3 (of many) from Al Viro:
 "Waiman's conversion of d_path() and bits related to it,
  kern_path_mountpoint(), several cleanups and fixes (exportfs
  one is -stable fodder, IMO).

  There definitely will be more...  ;-/"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  split read_seqretry_or_unlock(), convert d_walk() to resulting primitives
  dcache: Translating dentry into pathname without taking rename_lock
  autofs4 - fix device ioctl mount lookup
  introduce kern_path_mountpoint()
  rename user_path_umountat() to user_path_mountpoint_at()
  take unlazy_walk() into umount_lookup_last()
  Kill indirect include of file.h from eventfd.h, use fdget() in cgroup.c
  prune_super(): sb->s_op is never NULL
  exportfs: don't assume that ->iterate() won't feed us too long entries
  afs: get rid of redundant ->d_name.len checks
parents d0d27277 48f5ec21
...@@ -751,10 +751,6 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -751,10 +751,6 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
_enter("{%x:%u},{%s},%ho", _enter("{%x:%u},{%s},%ho",
dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode); dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
ret = -ENAMETOOLONG;
if (dentry->d_name.len >= AFSNAMEMAX)
goto error;
key = afs_request_key(dvnode->volume->cell); key = afs_request_key(dvnode->volume->cell);
if (IS_ERR(key)) { if (IS_ERR(key)) {
ret = PTR_ERR(key); ret = PTR_ERR(key);
...@@ -816,10 +812,6 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -816,10 +812,6 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
_enter("{%x:%u},{%s}", _enter("{%x:%u},{%s}",
dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name); dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
ret = -ENAMETOOLONG;
if (dentry->d_name.len >= AFSNAMEMAX)
goto error;
key = afs_request_key(dvnode->volume->cell); key = afs_request_key(dvnode->volume->cell);
if (IS_ERR(key)) { if (IS_ERR(key)) {
ret = PTR_ERR(key); ret = PTR_ERR(key);
...@@ -936,10 +928,6 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, ...@@ -936,10 +928,6 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
_enter("{%x:%u},{%s},%ho,", _enter("{%x:%u},{%s},%ho,",
dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode); dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
ret = -ENAMETOOLONG;
if (dentry->d_name.len >= AFSNAMEMAX)
goto error;
key = afs_request_key(dvnode->volume->cell); key = afs_request_key(dvnode->volume->cell);
if (IS_ERR(key)) { if (IS_ERR(key)) {
ret = PTR_ERR(key); ret = PTR_ERR(key);
...@@ -1005,10 +993,6 @@ static int afs_link(struct dentry *from, struct inode *dir, ...@@ -1005,10 +993,6 @@ static int afs_link(struct dentry *from, struct inode *dir,
dvnode->fid.vid, dvnode->fid.vnode, dvnode->fid.vid, dvnode->fid.vnode,
dentry->d_name.name); dentry->d_name.name);
ret = -ENAMETOOLONG;
if (dentry->d_name.len >= AFSNAMEMAX)
goto error;
key = afs_request_key(dvnode->volume->cell); key = afs_request_key(dvnode->volume->cell);
if (IS_ERR(key)) { if (IS_ERR(key)) {
ret = PTR_ERR(key); ret = PTR_ERR(key);
...@@ -1053,10 +1037,6 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -1053,10 +1037,6 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name,
content); content);
ret = -ENAMETOOLONG;
if (dentry->d_name.len >= AFSNAMEMAX)
goto error;
ret = -EINVAL; ret = -EINVAL;
if (strlen(content) >= AFSPATHMAX) if (strlen(content) >= AFSPATHMAX)
goto error; goto error;
...@@ -1127,10 +1107,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1127,10 +1107,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
new_dvnode->fid.vid, new_dvnode->fid.vnode, new_dvnode->fid.vid, new_dvnode->fid.vnode,
new_dentry->d_name.name); new_dentry->d_name.name);
ret = -ENAMETOOLONG;
if (new_dentry->d_name.len >= AFSNAMEMAX)
goto error;
key = afs_request_key(orig_dvnode->volume->cell); key = afs_request_key(orig_dvnode->volume->cell);
if (IS_ERR(key)) { if (IS_ERR(key)) {
ret = PTR_ERR(key); ret = PTR_ERR(key);
......
...@@ -183,13 +183,14 @@ static int autofs_dev_ioctl_protosubver(struct file *fp, ...@@ -183,13 +183,14 @@ static int autofs_dev_ioctl_protosubver(struct file *fp,
return 0; return 0;
} }
/* Find the topmost mount satisfying test() */
static int find_autofs_mount(const char *pathname, static int find_autofs_mount(const char *pathname,
struct path *res, struct path *res,
int test(struct path *path, void *data), int test(struct path *path, void *data),
void *data) void *data)
{ {
struct path path; struct path path;
int err = kern_path(pathname, 0, &path); int err = kern_path_mountpoint(AT_FDCWD, pathname, &path, 0);
if (err) if (err)
return err; return err;
err = -ENOENT; err = -ENOENT;
...@@ -197,10 +198,9 @@ static int find_autofs_mount(const char *pathname, ...@@ -197,10 +198,9 @@ static int find_autofs_mount(const char *pathname,
if (path.dentry->d_sb->s_magic == AUTOFS_SUPER_MAGIC) { if (path.dentry->d_sb->s_magic == AUTOFS_SUPER_MAGIC) {
if (test(&path, data)) { if (test(&path, data)) {
path_get(&path); path_get(&path);
if (!err) /* already found some */
path_put(res);
*res = path; *res = path;
err = 0; err = 0;
break;
} }
} }
if (!follow_up(&path)) if (!follow_up(&path))
...@@ -486,12 +486,11 @@ static int autofs_dev_ioctl_askumount(struct file *fp, ...@@ -486,12 +486,11 @@ static int autofs_dev_ioctl_askumount(struct file *fp,
* mount if there is one or 0 if it isn't a mountpoint. * mount if there is one or 0 if it isn't a mountpoint.
* *
* If we aren't supplied with a file descriptor then we * If we aren't supplied with a file descriptor then we
* lookup the nameidata of the path and check if it is the * lookup the path and check if it is the root of a mount.
* root of a mount. If a type is given we are looking for * If a type is given we are looking for a particular autofs
* a particular autofs mount and if we don't find a match * mount and if we don't find a match we return fail. If the
* we return fail. If the located nameidata path is the * located path is the root of a mount we return 1 along with
* root of a mount we return 1 along with the super magic * the super magic of the mount or 0 otherwise.
* of the mount or 0 otherwise.
* *
* In both cases the the device number (as returned by * In both cases the the device number (as returned by
* new_encode_dev()) is also returned. * new_encode_dev()) is also returned.
...@@ -519,9 +518,11 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp, ...@@ -519,9 +518,11 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp,
if (!fp || param->ioctlfd == -1) { if (!fp || param->ioctlfd == -1) {
if (autofs_type_any(type)) if (autofs_type_any(type))
err = kern_path(name, LOOKUP_FOLLOW, &path); err = kern_path_mountpoint(AT_FDCWD,
name, &path, LOOKUP_FOLLOW);
else else
err = find_autofs_mount(name, &path, test_by_type, &type); err = find_autofs_mount(name, &path,
test_by_type, &type);
if (err) if (err)
goto out; goto out;
devid = new_encode_dev(path.dentry->d_sb->s_dev); devid = new_encode_dev(path.dentry->d_sb->s_dev);
......
This diff is collapsed.
...@@ -231,7 +231,7 @@ static int filldir_one(void * __buf, const char * name, int len, ...@@ -231,7 +231,7 @@ static int filldir_one(void * __buf, const char * name, int len,
int result = 0; int result = 0;
buf->sequence++; buf->sequence++;
if (buf->ino == ino) { if (buf->ino == ino && len <= NAME_MAX) {
memcpy(buf->name, name, len); memcpy(buf->name, name, len);
buf->name[len] = '\0'; buf->name[len] = '\0';
buf->found = 1; buf->found = 1;
......
...@@ -45,6 +45,9 @@ extern void __init chrdev_init(void); ...@@ -45,6 +45,9 @@ extern void __init chrdev_init(void);
* namei.c * namei.c
*/ */
extern int __inode_permission(struct inode *, int); extern int __inode_permission(struct inode *, int);
extern int user_path_mountpoint_at(int, const char __user *, unsigned int, struct path *);
extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
const char *, unsigned int, struct path *);
/* /*
* namespace.c * namespace.c
......
...@@ -2209,7 +2209,7 @@ user_path_parent(int dfd, const char __user *path, struct nameidata *nd, ...@@ -2209,7 +2209,7 @@ user_path_parent(int dfd, const char __user *path, struct nameidata *nd,
} }
/** /**
* umount_lookup_last - look up last component for umount * mountpoint_last - look up last component for umount
* @nd: pathwalk nameidata - currently pointing at parent directory of "last" * @nd: pathwalk nameidata - currently pointing at parent directory of "last"
* @path: pointer to container for result * @path: pointer to container for result
* *
...@@ -2236,25 +2236,28 @@ user_path_parent(int dfd, const char __user *path, struct nameidata *nd, ...@@ -2236,25 +2236,28 @@ user_path_parent(int dfd, const char __user *path, struct nameidata *nd,
* to the link, and nd->path will *not* be put. * to the link, and nd->path will *not* be put.
*/ */
static int static int
umount_lookup_last(struct nameidata *nd, struct path *path) mountpoint_last(struct nameidata *nd, struct path *path)
{ {
int error = 0; int error = 0;
struct dentry *dentry; struct dentry *dentry;
struct dentry *dir = nd->path.dentry; struct dentry *dir = nd->path.dentry;
if (unlikely(nd->flags & LOOKUP_RCU)) { /* If we're in rcuwalk, drop out of it to handle last component */
WARN_ON_ONCE(1); if (nd->flags & LOOKUP_RCU) {
error = -ECHILD; if (unlazy_walk(nd, NULL)) {
goto error_check; error = -ECHILD;
goto out;
}
} }
nd->flags &= ~LOOKUP_PARENT; nd->flags &= ~LOOKUP_PARENT;
if (unlikely(nd->last_type != LAST_NORM)) { if (unlikely(nd->last_type != LAST_NORM)) {
error = handle_dots(nd, nd->last_type); error = handle_dots(nd, nd->last_type);
if (!error) if (error)
dentry = dget(nd->path.dentry); goto out;
goto error_check; dentry = dget(nd->path.dentry);
goto done;
} }
mutex_lock(&dir->d_inode->i_mutex); mutex_lock(&dir->d_inode->i_mutex);
...@@ -2268,44 +2271,43 @@ umount_lookup_last(struct nameidata *nd, struct path *path) ...@@ -2268,44 +2271,43 @@ umount_lookup_last(struct nameidata *nd, struct path *path)
dentry = d_alloc(dir, &nd->last); dentry = d_alloc(dir, &nd->last);
if (!dentry) { if (!dentry) {
error = -ENOMEM; error = -ENOMEM;
} else { goto out;
dentry = lookup_real(dir->d_inode, dentry, nd->flags);
if (IS_ERR(dentry))
error = PTR_ERR(dentry);
} }
dentry = lookup_real(dir->d_inode, dentry, nd->flags);
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto out;
} }
mutex_unlock(&dir->d_inode->i_mutex); mutex_unlock(&dir->d_inode->i_mutex);
error_check: done:
if (!error) { if (!dentry->d_inode) {
if (!dentry->d_inode) { error = -ENOENT;
error = -ENOENT; dput(dentry);
dput(dentry); goto out;
} else {
path->dentry = dentry;
path->mnt = mntget(nd->path.mnt);
if (should_follow_link(dentry->d_inode,
nd->flags & LOOKUP_FOLLOW))
return 1;
follow_mount(path);
}
} }
path->dentry = dentry;
path->mnt = mntget(nd->path.mnt);
if (should_follow_link(dentry->d_inode, nd->flags & LOOKUP_FOLLOW))
return 1;
follow_mount(path);
error = 0;
out:
terminate_walk(nd); terminate_walk(nd);
return error; return error;
} }
/** /**
* path_umountat - look up a path to be umounted * path_mountpoint - look up a path to be umounted
* @dfd: directory file descriptor to start walk from * @dfd: directory file descriptor to start walk from
* @name: full pathname to walk * @name: full pathname to walk
* @flags: lookup flags * @flags: lookup flags
* @nd: pathwalk nameidata
* *
* Look up the given name, but don't attempt to revalidate the last component. * Look up the given name, but don't attempt to revalidate the last component.
* Returns 0 and "path" will be valid on success; Retuns error otherwise. * Returns 0 and "path" will be valid on success; Retuns error otherwise.
*/ */
static int static int
path_umountat(int dfd, const char *name, struct path *path, unsigned int flags) path_mountpoint(int dfd, const char *name, struct path *path, unsigned int flags)
{ {
struct file *base = NULL; struct file *base = NULL;
struct nameidata nd; struct nameidata nd;
...@@ -2320,16 +2322,7 @@ path_umountat(int dfd, const char *name, struct path *path, unsigned int flags) ...@@ -2320,16 +2322,7 @@ path_umountat(int dfd, const char *name, struct path *path, unsigned int flags)
if (err) if (err)
goto out; goto out;
/* If we're in rcuwalk, drop out of it to handle last component */ err = mountpoint_last(&nd, path);
if (nd.flags & LOOKUP_RCU) {
err = unlazy_walk(&nd, NULL);
if (err) {
terminate_walk(&nd);
goto out;
}
}
err = umount_lookup_last(&nd, path);
while (err > 0) { while (err > 0) {
void *cookie; void *cookie;
struct path link = *path; struct path link = *path;
...@@ -2340,7 +2333,7 @@ path_umountat(int dfd, const char *name, struct path *path, unsigned int flags) ...@@ -2340,7 +2333,7 @@ path_umountat(int dfd, const char *name, struct path *path, unsigned int flags)
err = follow_link(&link, &nd, &cookie); err = follow_link(&link, &nd, &cookie);
if (err) if (err)
break; break;
err = umount_lookup_last(&nd, path); err = mountpoint_last(&nd, path);
put_link(&nd, &link, cookie); put_link(&nd, &link, cookie);
} }
out: out:
...@@ -2353,8 +2346,22 @@ path_umountat(int dfd, const char *name, struct path *path, unsigned int flags) ...@@ -2353,8 +2346,22 @@ path_umountat(int dfd, const char *name, struct path *path, unsigned int flags)
return err; return err;
} }
static int
filename_mountpoint(int dfd, struct filename *s, struct path *path,
unsigned int flags)
{
int error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_RCU);
if (unlikely(error == -ECHILD))
error = path_mountpoint(dfd, s->name, path, flags);
if (unlikely(error == -ESTALE))
error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_REVAL);
if (likely(!error))
audit_inode(s, path->dentry, 0);
return error;
}
/** /**
* user_path_umountat - lookup a path from userland in order to umount it * user_path_mountpoint_at - lookup a path from userland in order to umount it
* @dfd: directory file descriptor * @dfd: directory file descriptor
* @name: pathname from userland * @name: pathname from userland
* @flags: lookup flags * @flags: lookup flags
...@@ -2368,28 +2375,27 @@ path_umountat(int dfd, const char *name, struct path *path, unsigned int flags) ...@@ -2368,28 +2375,27 @@ path_umountat(int dfd, const char *name, struct path *path, unsigned int flags)
* Returns 0 and populates "path" on success. * Returns 0 and populates "path" on success.
*/ */
int int
user_path_umountat(int dfd, const char __user *name, unsigned int flags, user_path_mountpoint_at(int dfd, const char __user *name, unsigned int flags,
struct path *path) struct path *path)
{ {
struct filename *s = getname(name); struct filename *s = getname(name);
int error; int error;
if (IS_ERR(s)) if (IS_ERR(s))
return PTR_ERR(s); return PTR_ERR(s);
error = filename_mountpoint(dfd, s, path, flags);
error = path_umountat(dfd, s->name, path, flags | LOOKUP_RCU);
if (unlikely(error == -ECHILD))
error = path_umountat(dfd, s->name, path, flags);
if (unlikely(error == -ESTALE))
error = path_umountat(dfd, s->name, path, flags | LOOKUP_REVAL);
if (likely(!error))
audit_inode(s, path->dentry, 0);
putname(s); putname(s);
return error; return error;
} }
int
kern_path_mountpoint(int dfd, const char *name, struct path *path,
unsigned int flags)
{
struct filename s = {.name = name};
return filename_mountpoint(dfd, &s, path, flags);
}
EXPORT_SYMBOL(kern_path_mountpoint);
/* /*
* It's inline, so penalty for filesystems that don't use sticky bit is * It's inline, so penalty for filesystems that don't use sticky bit is
* minimal. * minimal.
......
...@@ -1321,7 +1321,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) ...@@ -1321,7 +1321,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
if (!(flags & UMOUNT_NOFOLLOW)) if (!(flags & UMOUNT_NOFOLLOW))
lookup_flags |= LOOKUP_FOLLOW; lookup_flags |= LOOKUP_FOLLOW;
retval = user_path_umountat(AT_FDCWD, name, lookup_flags, &path); retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
if (retval) if (retval)
goto out; goto out;
mnt = real_mount(path.mnt); mnt = real_mount(path.mnt);
......
...@@ -71,7 +71,7 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc) ...@@ -71,7 +71,7 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
if (!grab_super_passive(sb)) if (!grab_super_passive(sb))
return -1; return -1;
if (sb->s_op && sb->s_op->nr_cached_objects) if (sb->s_op->nr_cached_objects)
fs_objects = sb->s_op->nr_cached_objects(sb); fs_objects = sb->s_op->nr_cached_objects(sb);
total_objects = sb->s_nr_dentry_unused + total_objects = sb->s_nr_dentry_unused +
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#define _LINUX_EVENTFD_H #define _LINUX_EVENTFD_H
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/file.h>
#include <linux/wait.h> #include <linux/wait.h>
/* /*
...@@ -26,6 +25,8 @@ ...@@ -26,6 +25,8 @@
#define EFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK) #define EFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK)
#define EFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS | EFD_SEMAPHORE) #define EFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS | EFD_SEMAPHORE)
struct file;
#ifdef CONFIG_EVENTFD #ifdef CONFIG_EVENTFD
struct file *eventfd_file_create(unsigned int count, int flags); struct file *eventfd_file_create(unsigned int count, int flags);
......
...@@ -58,7 +58,6 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; ...@@ -58,7 +58,6 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
extern int user_path_at(int, const char __user *, unsigned, struct path *); extern int user_path_at(int, const char __user *, unsigned, struct path *);
extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty); extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty);
extern int user_path_umountat(int, const char __user *, unsigned int, struct path *);
#define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path) #define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path)
#define user_lpath(name, path) user_path_at(AT_FDCWD, name, 0, path) #define user_lpath(name, path) user_path_at(AT_FDCWD, name, 0, path)
...@@ -71,8 +70,7 @@ extern struct dentry *kern_path_create(int, const char *, struct path *, unsigne ...@@ -71,8 +70,7 @@ extern struct dentry *kern_path_create(int, const char *, struct path *, unsigne
extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int); extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int);
extern void done_path_create(struct path *, struct dentry *); extern void done_path_create(struct path *, struct dentry *);
extern struct dentry *kern_path_locked(const char *, struct path *); extern struct dentry *kern_path_locked(const char *, struct path *);
extern int vfs_path_lookup(struct dentry *, struct vfsmount *, extern int kern_path_mountpoint(int, const char *, struct path *, unsigned int);
const char *, unsigned int, struct path *);
extern struct dentry *lookup_one_len(const char *, struct dentry *, int); extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/flex_array.h> /* used in cgroup_attach_task */ #include <linux/flex_array.h> /* used in cgroup_attach_task */
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/file.h>
#include <linux/atomic.h> #include <linux/atomic.h>
...@@ -4034,8 +4035,8 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css, ...@@ -4034,8 +4035,8 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css,
struct cgroup_event *event; struct cgroup_event *event;
struct cgroup_subsys_state *cfile_css; struct cgroup_subsys_state *cfile_css;
unsigned int efd, cfd; unsigned int efd, cfd;
struct file *efile; struct fd efile;
struct file *cfile; struct fd cfile;
char *endp; char *endp;
int ret; int ret;
...@@ -4058,31 +4059,31 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css, ...@@ -4058,31 +4059,31 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css,
init_waitqueue_func_entry(&event->wait, cgroup_event_wake); init_waitqueue_func_entry(&event->wait, cgroup_event_wake);
INIT_WORK(&event->remove, cgroup_event_remove); INIT_WORK(&event->remove, cgroup_event_remove);
efile = eventfd_fget(efd); efile = fdget(efd);
if (IS_ERR(efile)) { if (!efile.file) {
ret = PTR_ERR(efile); ret = -EBADF;
goto out_kfree; goto out_kfree;
} }
event->eventfd = eventfd_ctx_fileget(efile); event->eventfd = eventfd_ctx_fileget(efile.file);
if (IS_ERR(event->eventfd)) { if (IS_ERR(event->eventfd)) {
ret = PTR_ERR(event->eventfd); ret = PTR_ERR(event->eventfd);
goto out_put_efile; goto out_put_efile;
} }
cfile = fget(cfd); cfile = fdget(cfd);
if (!cfile) { if (!cfile.file) {
ret = -EBADF; ret = -EBADF;
goto out_put_eventfd; goto out_put_eventfd;
} }
/* the process need read permission on control file */ /* the process need read permission on control file */
/* AV: shouldn't we check that it's been opened for read instead? */ /* AV: shouldn't we check that it's been opened for read instead? */
ret = inode_permission(file_inode(cfile), MAY_READ); ret = inode_permission(file_inode(cfile.file), MAY_READ);
if (ret < 0) if (ret < 0)
goto out_put_cfile; goto out_put_cfile;
event->cft = __file_cft(cfile); event->cft = __file_cft(cfile.file);
if (IS_ERR(event->cft)) { if (IS_ERR(event->cft)) {
ret = PTR_ERR(event->cft); ret = PTR_ERR(event->cft);
goto out_put_cfile; goto out_put_cfile;
...@@ -4103,7 +4104,7 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css, ...@@ -4103,7 +4104,7 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css,
ret = -EINVAL; ret = -EINVAL;
event->css = cgroup_css(cgrp, event->cft->ss); event->css = cgroup_css(cgrp, event->cft->ss);
cfile_css = css_from_dir(cfile->f_dentry->d_parent, event->cft->ss); cfile_css = css_from_dir(cfile.file->f_dentry->d_parent, event->cft->ss);
if (event->css && event->css == cfile_css && css_tryget(event->css)) if (event->css && event->css == cfile_css && css_tryget(event->css))
ret = 0; ret = 0;
...@@ -4121,25 +4122,25 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css, ...@@ -4121,25 +4122,25 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css,
if (ret) if (ret)
goto out_put_css; goto out_put_css;
efile->f_op->poll(efile, &event->pt); efile.file->f_op->poll(efile.file, &event->pt);
spin_lock(&cgrp->event_list_lock); spin_lock(&cgrp->event_list_lock);
list_add(&event->list, &cgrp->event_list); list_add(&event->list, &cgrp->event_list);
spin_unlock(&cgrp->event_list_lock); spin_unlock(&cgrp->event_list_lock);
fput(cfile); fdput(cfile);
fput(efile); fdput(efile);
return 0; return 0;
out_put_css: out_put_css:
css_put(event->css); css_put(event->css);
out_put_cfile: out_put_cfile:
fput(cfile); fdput(cfile);
out_put_eventfd: out_put_eventfd:
eventfd_ctx_put(event->eventfd); eventfd_ctx_put(event->eventfd);
out_put_efile: out_put_efile:
fput(efile); fdput(efile);
out_kfree: out_kfree:
kfree(event); kfree(event);
......
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