diff options
| -rw-r--r-- | fs/configfs/dir.c | 5 | ||||
| -rw-r--r-- | fs/file_table.c | 60 | ||||
| -rw-r--r-- | fs/hugetlbfs/inode.c | 22 | ||||
| -rw-r--r-- | include/linux/file.h | 9 | ||||
| -rw-r--r-- | ipc/shm.c | 13 | ||||
| -rw-r--r-- | mm/shmem.c | 7 | ||||
| -rw-r--r-- | mm/tiny-shmem.c | 19 | ||||
| -rw-r--r-- | net/socket.c | 18 |
8 files changed, 104 insertions, 49 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 2f436d4f1d6d..50ed691098bc 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
| @@ -142,7 +142,7 @@ static int init_dir(struct inode * inode) | |||
| 142 | return 0; | 142 | return 0; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | static int init_file(struct inode * inode) | 145 | static int configfs_init_file(struct inode * inode) |
| 146 | { | 146 | { |
| 147 | inode->i_size = PAGE_SIZE; | 147 | inode->i_size = PAGE_SIZE; |
| 148 | inode->i_fop = &configfs_file_operations; | 148 | inode->i_fop = &configfs_file_operations; |
| @@ -283,7 +283,8 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den | |||
| 283 | 283 | ||
| 284 | dentry->d_fsdata = configfs_get(sd); | 284 | dentry->d_fsdata = configfs_get(sd); |
| 285 | sd->s_dentry = dentry; | 285 | sd->s_dentry = dentry; |
| 286 | error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, init_file); | 286 | error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, |
| 287 | configfs_init_file); | ||
| 287 | if (error) { | 288 | if (error) { |
| 288 | configfs_put(sd); | 289 | configfs_put(sd); |
| 289 | return error; | 290 | return error; |
diff --git a/fs/file_table.c b/fs/file_table.c index ce3f39a4798a..3176fefc92e1 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
| @@ -137,6 +137,66 @@ fail: | |||
| 137 | 137 | ||
| 138 | EXPORT_SYMBOL(get_empty_filp); | 138 | EXPORT_SYMBOL(get_empty_filp); |
| 139 | 139 | ||
| 140 | /** | ||
| 141 | * alloc_file - allocate and initialize a 'struct file' | ||
| 142 | * @mnt: the vfsmount on which the file will reside | ||
| 143 | * @dentry: the dentry representing the new file | ||
| 144 | * @mode: the mode with which the new file will be opened | ||
| 145 | * @fop: the 'struct file_operations' for the new file | ||
| 146 | * | ||
| 147 | * Use this instead of get_empty_filp() to get a new | ||
| 148 | * 'struct file'. Do so because of the same initialization | ||
| 149 | * pitfalls reasons listed for init_file(). This is a | ||
| 150 | * preferred interface to using init_file(). | ||
| 151 | * | ||
| 152 | * If all the callers of init_file() are eliminated, its | ||
| 153 | * code should be moved into this function. | ||
| 154 | */ | ||
| 155 | struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry, | ||
| 156 | mode_t mode, const struct file_operations *fop) | ||
| 157 | { | ||
| 158 | struct file *file; | ||
| 159 | struct path; | ||
| 160 | |||
| 161 | file = get_empty_filp(); | ||
| 162 | if (!file) | ||
| 163 | return NULL; | ||
| 164 | |||
| 165 | init_file(file, mnt, dentry, mode, fop); | ||
| 166 | return file; | ||
| 167 | } | ||
| 168 | EXPORT_SYMBOL(alloc_file); | ||
| 169 | |||
| 170 | /** | ||
| 171 | * init_file - initialize a 'struct file' | ||
| 172 | * @file: the already allocated 'struct file' to initialized | ||
| 173 | * @mnt: the vfsmount on which the file resides | ||
| 174 | * @dentry: the dentry representing this file | ||
| 175 | * @mode: the mode the file is opened with | ||
| 176 | * @fop: the 'struct file_operations' for this file | ||
| 177 | * | ||
| 178 | * Use this instead of setting the members directly. Doing so | ||
| 179 | * avoids making mistakes like forgetting the mntget() or | ||
| 180 | * forgetting to take a write on the mnt. | ||
| 181 | * | ||
| 182 | * Note: This is a crappy interface. It is here to make | ||
| 183 | * merging with the existing users of get_empty_filp() | ||
| 184 | * who have complex failure logic easier. All users | ||
| 185 | * of this should be moving to alloc_file(). | ||
| 186 | */ | ||
| 187 | int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry, | ||
| 188 | mode_t mode, const struct file_operations *fop) | ||
| 189 | { | ||
| 190 | int error = 0; | ||
| 191 | file->f_path.dentry = dentry; | ||
| 192 | file->f_path.mnt = mntget(mnt); | ||
| 193 | file->f_mapping = dentry->d_inode->i_mapping; | ||
| 194 | file->f_mode = mode; | ||
| 195 | file->f_op = fop; | ||
| 196 | return error; | ||
| 197 | } | ||
| 198 | EXPORT_SYMBOL(init_file); | ||
| 199 | |||
| 140 | void fastcall fput(struct file *file) | 200 | void fastcall fput(struct file *file) |
| 141 | { | 201 | { |
| 142 | if (atomic_dec_and_test(&file->f_count)) | 202 | if (atomic_dec_and_test(&file->f_count)) |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 0f5df73dbb73..12aca8ed605f 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
| @@ -933,16 +933,11 @@ struct file *hugetlb_file_setup(const char *name, size_t size) | |||
| 933 | if (!dentry) | 933 | if (!dentry) |
| 934 | goto out_shm_unlock; | 934 | goto out_shm_unlock; |
| 935 | 935 | ||
| 936 | error = -ENFILE; | ||
| 937 | file = get_empty_filp(); | ||
| 938 | if (!file) | ||
| 939 | goto out_dentry; | ||
| 940 | |||
| 941 | error = -ENOSPC; | 936 | error = -ENOSPC; |
| 942 | inode = hugetlbfs_get_inode(root->d_sb, current->fsuid, | 937 | inode = hugetlbfs_get_inode(root->d_sb, current->fsuid, |
| 943 | current->fsgid, S_IFREG | S_IRWXUGO, 0); | 938 | current->fsgid, S_IFREG | S_IRWXUGO, 0); |
| 944 | if (!inode) | 939 | if (!inode) |
| 945 | goto out_file; | 940 | goto out_dentry; |
| 946 | 941 | ||
| 947 | error = -ENOMEM; | 942 | error = -ENOMEM; |
| 948 | if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT)) | 943 | if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT)) |
| @@ -951,17 +946,18 @@ struct file *hugetlb_file_setup(const char *name, size_t size) | |||
| 951 | d_instantiate(dentry, inode); | 946 | d_instantiate(dentry, inode); |
| 952 | inode->i_size = size; | 947 | inode->i_size = size; |
| 953 | inode->i_nlink = 0; | 948 | inode->i_nlink = 0; |
| 954 | file->f_path.mnt = mntget(hugetlbfs_vfsmount); | 949 | |
| 955 | file->f_path.dentry = dentry; | 950 | error = -ENFILE; |
| 956 | file->f_mapping = inode->i_mapping; | 951 | file = alloc_file(hugetlbfs_vfsmount, dentry, |
| 957 | file->f_op = &hugetlbfs_file_operations; | 952 | FMODE_WRITE | FMODE_READ, |
| 958 | file->f_mode = FMODE_WRITE | FMODE_READ; | 953 | &hugetlbfs_file_operations); |
| 954 | if (!file) | ||
| 955 | goto out_inode; | ||
| 956 | |||
| 959 | return file; | 957 | return file; |
| 960 | 958 | ||
| 961 | out_inode: | 959 | out_inode: |
| 962 | iput(inode); | 960 | iput(inode); |
| 963 | out_file: | ||
| 964 | put_filp(file); | ||
| 965 | out_dentry: | 961 | out_dentry: |
| 966 | dput(dentry); | 962 | dput(dentry); |
| 967 | out_shm_unlock: | 963 | out_shm_unlock: |
diff --git a/include/linux/file.h b/include/linux/file.h index 0114fbc78061..56023c74e9fd 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
| @@ -62,6 +62,15 @@ extern struct kmem_cache *filp_cachep; | |||
| 62 | extern void FASTCALL(__fput(struct file *)); | 62 | extern void FASTCALL(__fput(struct file *)); |
| 63 | extern void FASTCALL(fput(struct file *)); | 63 | extern void FASTCALL(fput(struct file *)); |
| 64 | 64 | ||
| 65 | struct file_operations; | ||
| 66 | struct vfsmount; | ||
| 67 | struct dentry; | ||
| 68 | extern int init_file(struct file *, struct vfsmount *mnt, | ||
| 69 | struct dentry *dentry, mode_t mode, | ||
| 70 | const struct file_operations *fop); | ||
| 71 | extern struct file *alloc_file(struct vfsmount *, struct dentry *dentry, | ||
| 72 | mode_t mode, const struct file_operations *fop); | ||
| 73 | |||
| 65 | static inline void fput_light(struct file *file, int fput_needed) | 74 | static inline void fput_light(struct file *file, int fput_needed) |
| 66 | { | 75 | { |
| 67 | if (unlikely(fput_needed)) | 76 | if (unlikely(fput_needed)) |
| @@ -907,7 +907,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
| 907 | goto out_unlock; | 907 | goto out_unlock; |
| 908 | 908 | ||
| 909 | path.dentry = dget(shp->shm_file->f_path.dentry); | 909 | path.dentry = dget(shp->shm_file->f_path.dentry); |
| 910 | path.mnt = mntget(shp->shm_file->f_path.mnt); | 910 | path.mnt = shp->shm_file->f_path.mnt; |
| 911 | shp->shm_nattch++; | 911 | shp->shm_nattch++; |
| 912 | size = i_size_read(path.dentry->d_inode); | 912 | size = i_size_read(path.dentry->d_inode); |
| 913 | shm_unlock(shp); | 913 | shm_unlock(shp); |
| @@ -915,18 +915,16 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
| 915 | err = -ENOMEM; | 915 | err = -ENOMEM; |
| 916 | sfd = kzalloc(sizeof(*sfd), GFP_KERNEL); | 916 | sfd = kzalloc(sizeof(*sfd), GFP_KERNEL); |
| 917 | if (!sfd) | 917 | if (!sfd) |
| 918 | goto out_put_path; | 918 | goto out_put_dentry; |
| 919 | 919 | ||
| 920 | err = -ENOMEM; | 920 | err = -ENOMEM; |
| 921 | file = get_empty_filp(); | 921 | |
| 922 | file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); | ||
| 922 | if (!file) | 923 | if (!file) |
| 923 | goto out_free; | 924 | goto out_free; |
| 924 | 925 | ||
| 925 | file->f_op = &shm_file_operations; | ||
| 926 | file->private_data = sfd; | 926 | file->private_data = sfd; |
| 927 | file->f_path = path; | ||
| 928 | file->f_mapping = shp->shm_file->f_mapping; | 927 | file->f_mapping = shp->shm_file->f_mapping; |
| 929 | file->f_mode = f_mode; | ||
| 930 | sfd->id = shp->id; | 928 | sfd->id = shp->id; |
| 931 | sfd->ns = get_ipc_ns(ns); | 929 | sfd->ns = get_ipc_ns(ns); |
| 932 | sfd->file = shp->shm_file; | 930 | sfd->file = shp->shm_file; |
| @@ -977,9 +975,8 @@ out_unlock: | |||
| 977 | 975 | ||
| 978 | out_free: | 976 | out_free: |
| 979 | kfree(sfd); | 977 | kfree(sfd); |
| 980 | out_put_path: | 978 | out_put_dentry: |
| 981 | dput(path.dentry); | 979 | dput(path.dentry); |
| 982 | mntput(path.mnt); | ||
| 983 | goto out_nattch; | 980 | goto out_nattch; |
| 984 | } | 981 | } |
| 985 | 982 | ||
diff --git a/mm/shmem.c b/mm/shmem.c index 6fa20a84daa0..289dbb0a6fd6 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
| @@ -2543,11 +2543,8 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) | |||
| 2543 | d_instantiate(dentry, inode); | 2543 | d_instantiate(dentry, inode); |
| 2544 | inode->i_size = size; | 2544 | inode->i_size = size; |
| 2545 | inode->i_nlink = 0; /* It is unlinked */ | 2545 | inode->i_nlink = 0; /* It is unlinked */ |
| 2546 | file->f_path.mnt = mntget(shm_mnt); | 2546 | init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ, |
| 2547 | file->f_path.dentry = dentry; | 2547 | &shmem_file_operations); |
| 2548 | file->f_mapping = inode->i_mapping; | ||
| 2549 | file->f_op = &shmem_file_operations; | ||
| 2550 | file->f_mode = FMODE_WRITE | FMODE_READ; | ||
| 2551 | return file; | 2548 | return file; |
| 2552 | 2549 | ||
| 2553 | close_file: | 2550 | close_file: |
diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c index 8803471593fd..d436a9c82db7 100644 --- a/mm/tiny-shmem.c +++ b/mm/tiny-shmem.c | |||
| @@ -66,24 +66,19 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) | |||
| 66 | if (!dentry) | 66 | if (!dentry) |
| 67 | goto put_memory; | 67 | goto put_memory; |
| 68 | 68 | ||
| 69 | error = -ENFILE; | ||
| 70 | file = get_empty_filp(); | ||
| 71 | if (!file) | ||
| 72 | goto put_dentry; | ||
| 73 | |||
| 74 | error = -ENOSPC; | 69 | error = -ENOSPC; |
| 75 | inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0); | 70 | inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0); |
| 76 | if (!inode) | 71 | if (!inode) |
| 77 | goto close_file; | 72 | goto put_dentry; |
| 78 | 73 | ||
| 79 | d_instantiate(dentry, inode); | 74 | d_instantiate(dentry, inode); |
| 80 | inode->i_nlink = 0; /* It is unlinked */ | 75 | error = -ENFILE; |
| 76 | file = alloc_file(shm_mnt, dentry, FMODE_WRITE | FMODE_READ, | ||
| 77 | &ramfs_file_operations); | ||
| 78 | if (!file) | ||
| 79 | goto put_dentry; | ||
| 81 | 80 | ||
| 82 | file->f_path.mnt = mntget(shm_mnt); | 81 | inode->i_nlink = 0; /* It is unlinked */ |
| 83 | file->f_path.dentry = dentry; | ||
| 84 | file->f_mapping = inode->i_mapping; | ||
| 85 | file->f_op = &ramfs_file_operations; | ||
| 86 | file->f_mode = FMODE_WRITE | FMODE_READ; | ||
| 87 | 82 | ||
| 88 | /* notify everyone as to the change of file size */ | 83 | /* notify everyone as to the change of file size */ |
| 89 | error = do_truncate(dentry, size, 0, file); | 84 | error = do_truncate(dentry, size, 0, file); |
diff --git a/net/socket.c b/net/socket.c index 3cd96fe8191d..540013ea8620 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -364,26 +364,26 @@ static int sock_alloc_fd(struct file **filep) | |||
| 364 | 364 | ||
| 365 | static int sock_attach_fd(struct socket *sock, struct file *file) | 365 | static int sock_attach_fd(struct socket *sock, struct file *file) |
| 366 | { | 366 | { |
| 367 | struct dentry *dentry; | ||
| 367 | struct qstr name = { .name = "" }; | 368 | struct qstr name = { .name = "" }; |
| 368 | 369 | ||
| 369 | file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); | 370 | dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); |
| 370 | if (unlikely(!file->f_path.dentry)) | 371 | if (unlikely(!dentry)) |
| 371 | return -ENOMEM; | 372 | return -ENOMEM; |
| 372 | 373 | ||
| 373 | file->f_path.dentry->d_op = &sockfs_dentry_operations; | 374 | dentry->d_op = &sockfs_dentry_operations; |
| 374 | /* | 375 | /* |
| 375 | * We dont want to push this dentry into global dentry hash table. | 376 | * We dont want to push this dentry into global dentry hash table. |
| 376 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED | 377 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED |
| 377 | * This permits a working /proc/$pid/fd/XXX on sockets | 378 | * This permits a working /proc/$pid/fd/XXX on sockets |
| 378 | */ | 379 | */ |
| 379 | file->f_path.dentry->d_flags &= ~DCACHE_UNHASHED; | 380 | dentry->d_flags &= ~DCACHE_UNHASHED; |
| 380 | d_instantiate(file->f_path.dentry, SOCK_INODE(sock)); | 381 | d_instantiate(dentry, SOCK_INODE(sock)); |
| 381 | file->f_path.mnt = mntget(sock_mnt); | ||
| 382 | file->f_mapping = file->f_path.dentry->d_inode->i_mapping; | ||
| 383 | 382 | ||
| 384 | sock->file = file; | 383 | sock->file = file; |
| 385 | file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; | 384 | init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE, |
| 386 | file->f_mode = FMODE_READ | FMODE_WRITE; | 385 | &socket_file_ops); |
| 386 | SOCK_INODE(sock)->i_fop = &socket_file_ops; | ||
| 387 | file->f_flags = O_RDWR; | 387 | file->f_flags = O_RDWR; |
| 388 | file->f_pos = 0; | 388 | file->f_pos = 0; |
| 389 | file->private_data = sock; | 389 | file->private_data = sock; |
