diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/inotify.c | 66 |
1 files changed, 32 insertions, 34 deletions
diff --git a/fs/inotify.c b/fs/inotify.c index 54757be888b6..a87926584cd2 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
@@ -62,8 +62,8 @@ int inotify_max_queued_events; | |||
62 | * Lifetimes of the three main data structures--inotify_device, inode, and | 62 | * Lifetimes of the three main data structures--inotify_device, inode, and |
63 | * inotify_watch--are managed by reference count. | 63 | * inotify_watch--are managed by reference count. |
64 | * | 64 | * |
65 | * inotify_device: Lifetime is from open until release. Additional references | 65 | * inotify_device: Lifetime is from inotify_init() until release. Additional |
66 | * can bump the count via get_inotify_dev() and drop the count via | 66 | * references can bump the count via get_inotify_dev() and drop the count via |
67 | * put_inotify_dev(). | 67 | * put_inotify_dev(). |
68 | * | 68 | * |
69 | * inotify_watch: Lifetime is from create_watch() to destory_watch(). | 69 | * inotify_watch: Lifetime is from create_watch() to destory_watch(). |
@@ -75,7 +75,7 @@ int inotify_max_queued_events; | |||
75 | */ | 75 | */ |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * struct inotify_device - represents an open instance of an inotify device | 78 | * struct inotify_device - represents an inotify instance |
79 | * | 79 | * |
80 | * This structure is protected by the semaphore 'sem'. | 80 | * This structure is protected by the semaphore 'sem'. |
81 | */ | 81 | */ |
@@ -371,7 +371,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd) | |||
371 | /* you can only watch an inode if you have read permissions on it */ | 371 | /* you can only watch an inode if you have read permissions on it */ |
372 | error = permission(nd->dentry->d_inode, MAY_READ, NULL); | 372 | error = permission(nd->dentry->d_inode, MAY_READ, NULL); |
373 | if (error) | 373 | if (error) |
374 | path_release (nd); | 374 | path_release(nd); |
375 | return error; | 375 | return error; |
376 | } | 376 | } |
377 | 377 | ||
@@ -387,7 +387,8 @@ static struct inotify_watch *create_watch(struct inotify_device *dev, | |||
387 | struct inotify_watch *watch; | 387 | struct inotify_watch *watch; |
388 | int ret; | 388 | int ret; |
389 | 389 | ||
390 | if (atomic_read(&dev->user->inotify_watches) >= inotify_max_user_watches) | 390 | if (atomic_read(&dev->user->inotify_watches) >= |
391 | inotify_max_user_watches) | ||
391 | return ERR_PTR(-ENOSPC); | 392 | return ERR_PTR(-ENOSPC); |
392 | 393 | ||
393 | watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL); | 394 | watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL); |
@@ -783,15 +784,14 @@ static int inotify_release(struct inode *ignored, struct file *file) | |||
783 | inotify_dev_event_dequeue(dev); | 784 | inotify_dev_event_dequeue(dev); |
784 | up(&dev->sem); | 785 | up(&dev->sem); |
785 | 786 | ||
786 | /* free this device: the put matching the get in inotify_open() */ | 787 | /* free this device: the put matching the get in inotify_init() */ |
787 | put_inotify_dev(dev); | 788 | put_inotify_dev(dev); |
788 | 789 | ||
789 | return 0; | 790 | return 0; |
790 | } | 791 | } |
791 | 792 | ||
792 | /* | 793 | /* |
793 | * inotify_ignore - handle the INOTIFY_IGNORE ioctl, asking that a given wd be | 794 | * inotify_ignore - remove a given wd from this inotify instance. |
794 | * removed from the device. | ||
795 | * | 795 | * |
796 | * Can sleep. | 796 | * Can sleep. |
797 | */ | 797 | */ |
@@ -856,15 +856,12 @@ asmlinkage long sys_inotify_init(void) | |||
856 | { | 856 | { |
857 | struct inotify_device *dev; | 857 | struct inotify_device *dev; |
858 | struct user_struct *user; | 858 | struct user_struct *user; |
859 | int ret = -ENOTTY; | 859 | struct file *filp; |
860 | int fd; | 860 | int fd, ret; |
861 | struct file *filp; | ||
862 | 861 | ||
863 | fd = get_unused_fd(); | 862 | fd = get_unused_fd(); |
864 | if (fd < 0) { | 863 | if (fd < 0) |
865 | ret = fd; | 864 | return fd; |
866 | goto out; | ||
867 | } | ||
868 | 865 | ||
869 | filp = get_empty_filp(); | 866 | filp = get_empty_filp(); |
870 | if (!filp) { | 867 | if (!filp) { |
@@ -872,16 +869,11 @@ asmlinkage long sys_inotify_init(void) | |||
872 | ret = -ENFILE; | 869 | ret = -ENFILE; |
873 | goto out; | 870 | goto out; |
874 | } | 871 | } |
875 | filp->f_op = &inotify_fops; | ||
876 | filp->f_vfsmnt = mntget(inotify_mnt); | ||
877 | filp->f_dentry = dget(inotify_mnt->mnt_root); | ||
878 | filp->f_mapping = filp->f_dentry->d_inode->i_mapping; | ||
879 | filp->f_mode = FMODE_READ; | ||
880 | filp->f_flags = O_RDONLY; | ||
881 | 872 | ||
882 | user = get_uid(current->user); | 873 | user = get_uid(current->user); |
883 | 874 | ||
884 | if (unlikely(atomic_read(&user->inotify_devs) >= inotify_max_user_instances)) { | 875 | if (unlikely(atomic_read(&user->inotify_devs) >= |
876 | inotify_max_user_instances)) { | ||
885 | ret = -EMFILE; | 877 | ret = -EMFILE; |
886 | goto out_err; | 878 | goto out_err; |
887 | } | 879 | } |
@@ -892,6 +884,14 @@ asmlinkage long sys_inotify_init(void) | |||
892 | goto out_err; | 884 | goto out_err; |
893 | } | 885 | } |
894 | 886 | ||
887 | filp->f_op = &inotify_fops; | ||
888 | filp->f_vfsmnt = mntget(inotify_mnt); | ||
889 | filp->f_dentry = dget(inotify_mnt->mnt_root); | ||
890 | filp->f_mapping = filp->f_dentry->d_inode->i_mapping; | ||
891 | filp->f_mode = FMODE_READ; | ||
892 | filp->f_flags = O_RDONLY; | ||
893 | filp->private_data = dev; | ||
894 | |||
895 | idr_init(&dev->idr); | 895 | idr_init(&dev->idr); |
896 | INIT_LIST_HEAD(&dev->events); | 896 | INIT_LIST_HEAD(&dev->events); |
897 | INIT_LIST_HEAD(&dev->watches); | 897 | INIT_LIST_HEAD(&dev->watches); |
@@ -905,9 +905,8 @@ asmlinkage long sys_inotify_init(void) | |||
905 | 905 | ||
906 | get_inotify_dev(dev); | 906 | get_inotify_dev(dev); |
907 | atomic_inc(&user->inotify_devs); | 907 | atomic_inc(&user->inotify_devs); |
908 | fd_install(fd, filp); | ||
908 | 909 | ||
909 | filp->private_data = dev; | ||
910 | fd_install (fd, filp); | ||
911 | return fd; | 910 | return fd; |
912 | out_err: | 911 | out_err: |
913 | put_unused_fd (fd); | 912 | put_unused_fd (fd); |
@@ -917,7 +916,7 @@ out: | |||
917 | return ret; | 916 | return ret; |
918 | } | 917 | } |
919 | 918 | ||
920 | asmlinkage long sys_inotify_add_watch(int fd, const char *path, u32 mask) | 919 | asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) |
921 | { | 920 | { |
922 | struct inotify_watch *watch, *old; | 921 | struct inotify_watch *watch, *old; |
923 | struct inode *inode; | 922 | struct inode *inode; |
@@ -930,21 +929,20 @@ asmlinkage long sys_inotify_add_watch(int fd, const char *path, u32 mask) | |||
930 | if (!filp) | 929 | if (!filp) |
931 | return -EBADF; | 930 | return -EBADF; |
932 | 931 | ||
933 | dev = filp->private_data; | 932 | ret = find_inode(path, &nd); |
934 | 933 | if (unlikely(ret)) | |
935 | ret = find_inode((const char __user*) path, &nd); | ||
936 | if (ret) | ||
937 | goto fput_and_out; | 934 | goto fput_and_out; |
938 | 935 | ||
939 | /* Held in place by reference in nd */ | 936 | /* inode held in place by reference to nd; dev by fget on fd */ |
940 | inode = nd.dentry->d_inode; | 937 | inode = nd.dentry->d_inode; |
938 | dev = filp->private_data; | ||
941 | 939 | ||
942 | down(&inode->inotify_sem); | 940 | down(&inode->inotify_sem); |
943 | down(&dev->sem); | 941 | down(&dev->sem); |
944 | 942 | ||
945 | /* don't let user-space set invalid bits: we don't want flags set */ | 943 | /* don't let user-space set invalid bits: we don't want flags set */ |
946 | mask &= IN_ALL_EVENTS; | 944 | mask &= IN_ALL_EVENTS; |
947 | if (!mask) { | 945 | if (unlikely(!mask)) { |
948 | ret = -EINVAL; | 946 | ret = -EINVAL; |
949 | goto out; | 947 | goto out; |
950 | } | 948 | } |
@@ -1009,11 +1007,11 @@ static struct file_system_type inotify_fs_type = { | |||
1009 | }; | 1007 | }; |
1010 | 1008 | ||
1011 | /* | 1009 | /* |
1012 | * inotify_init - Our initialization function. Note that we cannnot return | 1010 | * inotify_setup - Our initialization function. Note that we cannnot return |
1013 | * error because we have compiled-in VFS hooks. So an (unlikely) failure here | 1011 | * error because we have compiled-in VFS hooks. So an (unlikely) failure here |
1014 | * must result in panic(). | 1012 | * must result in panic(). |
1015 | */ | 1013 | */ |
1016 | static int __init inotify_init(void) | 1014 | static int __init inotify_setup(void) |
1017 | { | 1015 | { |
1018 | register_filesystem(&inotify_fs_type); | 1016 | register_filesystem(&inotify_fs_type); |
1019 | inotify_mnt = kern_mount(&inotify_fs_type); | 1017 | inotify_mnt = kern_mount(&inotify_fs_type); |
@@ -1034,4 +1032,4 @@ static int __init inotify_init(void) | |||
1034 | return 0; | 1032 | return 0; |
1035 | } | 1033 | } |
1036 | 1034 | ||
1037 | module_init(inotify_init); | 1035 | module_init(inotify_setup); |