diff --git a/fs/inotify.c b/fs/inotify.c index 54757be888b679d231e278851921997f8fcfca01..a87926584cd284c9aa1d94230cc2a659dc2d86db 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -62,8 +62,8 @@ int inotify_max_queued_events; * Lifetimes of the three main data structures--inotify_device, inode, and * inotify_watch--are managed by reference count. * - * inotify_device: Lifetime is from open until release. Additional references - * can bump the count via get_inotify_dev() and drop the count via + * inotify_device: Lifetime is from inotify_init() until release. Additional + * references can bump the count via get_inotify_dev() and drop the count via * put_inotify_dev(). * * inotify_watch: Lifetime is from create_watch() to destory_watch(). @@ -75,7 +75,7 @@ int inotify_max_queued_events; */ /* - * struct inotify_device - represents an open instance of an inotify device + * struct inotify_device - represents an inotify instance * * This structure is protected by the semaphore 'sem'. */ @@ -371,7 +371,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd) /* you can only watch an inode if you have read permissions on it */ error = permission(nd->dentry->d_inode, MAY_READ, NULL); if (error) - path_release (nd); + path_release(nd); return error; } @@ -387,7 +387,8 @@ static struct inotify_watch *create_watch(struct inotify_device *dev, struct inotify_watch *watch; int ret; - if (atomic_read(&dev->user->inotify_watches) >= inotify_max_user_watches) + if (atomic_read(&dev->user->inotify_watches) >= + inotify_max_user_watches) return ERR_PTR(-ENOSPC); watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL); @@ -783,15 +784,14 @@ static int inotify_release(struct inode *ignored, struct file *file) inotify_dev_event_dequeue(dev); up(&dev->sem); - /* free this device: the put matching the get in inotify_open() */ + /* free this device: the put matching the get in inotify_init() */ put_inotify_dev(dev); return 0; } /* - * inotify_ignore - handle the INOTIFY_IGNORE ioctl, asking that a given wd be - * removed from the device. + * inotify_ignore - remove a given wd from this inotify instance. * * Can sleep. */ @@ -856,15 +856,12 @@ asmlinkage long sys_inotify_init(void) { struct inotify_device *dev; struct user_struct *user; - int ret = -ENOTTY; - int fd; - struct file *filp; + struct file *filp; + int fd, ret; fd = get_unused_fd(); - if (fd < 0) { - ret = fd; - goto out; - } + if (fd < 0) + return fd; filp = get_empty_filp(); if (!filp) { @@ -872,16 +869,11 @@ asmlinkage long sys_inotify_init(void) ret = -ENFILE; goto out; } - filp->f_op = &inotify_fops; - filp->f_vfsmnt = mntget(inotify_mnt); - filp->f_dentry = dget(inotify_mnt->mnt_root); - filp->f_mapping = filp->f_dentry->d_inode->i_mapping; - filp->f_mode = FMODE_READ; - filp->f_flags = O_RDONLY; user = get_uid(current->user); - if (unlikely(atomic_read(&user->inotify_devs) >= inotify_max_user_instances)) { + if (unlikely(atomic_read(&user->inotify_devs) >= + inotify_max_user_instances)) { ret = -EMFILE; goto out_err; } @@ -892,6 +884,14 @@ asmlinkage long sys_inotify_init(void) goto out_err; } + filp->f_op = &inotify_fops; + filp->f_vfsmnt = mntget(inotify_mnt); + filp->f_dentry = dget(inotify_mnt->mnt_root); + filp->f_mapping = filp->f_dentry->d_inode->i_mapping; + filp->f_mode = FMODE_READ; + filp->f_flags = O_RDONLY; + filp->private_data = dev; + idr_init(&dev->idr); INIT_LIST_HEAD(&dev->events); INIT_LIST_HEAD(&dev->watches); @@ -905,9 +905,8 @@ asmlinkage long sys_inotify_init(void) get_inotify_dev(dev); atomic_inc(&user->inotify_devs); + fd_install(fd, filp); - filp->private_data = dev; - fd_install (fd, filp); return fd; out_err: put_unused_fd (fd); @@ -917,7 +916,7 @@ asmlinkage long sys_inotify_init(void) return ret; } -asmlinkage long sys_inotify_add_watch(int fd, const char *path, u32 mask) +asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) { struct inotify_watch *watch, *old; struct inode *inode; @@ -930,21 +929,20 @@ asmlinkage long sys_inotify_add_watch(int fd, const char *path, u32 mask) if (!filp) return -EBADF; - dev = filp->private_data; - - ret = find_inode((const char __user*) path, &nd); - if (ret) + ret = find_inode(path, &nd); + if (unlikely(ret)) goto fput_and_out; - /* Held in place by reference in nd */ + /* inode held in place by reference to nd; dev by fget on fd */ inode = nd.dentry->d_inode; + dev = filp->private_data; down(&inode->inotify_sem); down(&dev->sem); /* don't let user-space set invalid bits: we don't want flags set */ mask &= IN_ALL_EVENTS; - if (!mask) { + if (unlikely(!mask)) { ret = -EINVAL; goto out; } @@ -1009,11 +1007,11 @@ static struct file_system_type inotify_fs_type = { }; /* - * inotify_init - Our initialization function. Note that we cannnot return + * inotify_setup - Our initialization function. Note that we cannnot return * error because we have compiled-in VFS hooks. So an (unlikely) failure here * must result in panic(). */ -static int __init inotify_init(void) +static int __init inotify_setup(void) { register_filesystem(&inotify_fs_type); inotify_mnt = kern_mount(&inotify_fs_type); @@ -1034,4 +1032,4 @@ static int __init inotify_init(void) return 0; } -module_init(inotify_init); +module_init(inotify_setup);