diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2009-08-08 16:52:35 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-12-16 12:16:42 -0500 |
commit | 2c48b9c45579a9b5e3e74694eebf3d2451f3dbd3 (patch) | |
tree | cecbf786ae0650368a8136bdd90910e05d9b95c3 | |
parent | a95161aaa801c18c52b2e7cf3d6b4b141c00a20a (diff) |
switch alloc_file() to passing struct path
... and have the caller grab both mnt and dentry; kill
leak in infiniband, while we are at it.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | arch/ia64/kernel/perfmon.c | 15 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 9 | ||||
-rw-r--r-- | fs/anon_inodes.c | 18 | ||||
-rw-r--r-- | fs/file_table.c | 13 | ||||
-rw-r--r-- | fs/hugetlbfs/inode.c | 15 | ||||
-rw-r--r-- | fs/notify/inotify/inotify_user.c | 8 | ||||
-rw-r--r-- | fs/pipe.c | 17 | ||||
-rw-r--r-- | include/linux/file.h | 5 | ||||
-rw-r--r-- | ipc/shm.c | 10 | ||||
-rw-r--r-- | mm/shmem.c | 14 | ||||
-rw-r--r-- | net/socket.c | 17 |
11 files changed, 78 insertions, 63 deletions
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 599b233bef75..5246285a95fb 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c | |||
@@ -2200,7 +2200,7 @@ pfm_alloc_file(pfm_context_t *ctx) | |||
2200 | { | 2200 | { |
2201 | struct file *file; | 2201 | struct file *file; |
2202 | struct inode *inode; | 2202 | struct inode *inode; |
2203 | struct dentry *dentry; | 2203 | struct path path; |
2204 | char name[32]; | 2204 | char name[32]; |
2205 | struct qstr this; | 2205 | struct qstr this; |
2206 | 2206 | ||
@@ -2225,18 +2225,19 @@ pfm_alloc_file(pfm_context_t *ctx) | |||
2225 | /* | 2225 | /* |
2226 | * allocate a new dcache entry | 2226 | * allocate a new dcache entry |
2227 | */ | 2227 | */ |
2228 | dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this); | 2228 | path.dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this); |
2229 | if (!dentry) { | 2229 | if (!path.dentry) { |
2230 | iput(inode); | 2230 | iput(inode); |
2231 | return ERR_PTR(-ENOMEM); | 2231 | return ERR_PTR(-ENOMEM); |
2232 | } | 2232 | } |
2233 | path.mnt = mntget(pfmfs_mnt); | ||
2233 | 2234 | ||
2234 | dentry->d_op = &pfmfs_dentry_operations; | 2235 | path.dentry->d_op = &pfmfs_dentry_operations; |
2235 | d_add(dentry, inode); | 2236 | d_add(path.dentry, inode); |
2236 | 2237 | ||
2237 | file = alloc_file(pfmfs_mnt, dentry, FMODE_READ, &pfm_file_ops); | 2238 | file = alloc_file(&path, FMODE_READ, &pfm_file_ops); |
2238 | if (!file) { | 2239 | if (!file) { |
2239 | dput(dentry); | 2240 | path_put(&path); |
2240 | return ERR_PTR(-ENFILE); | 2241 | return ERR_PTR(-ENFILE); |
2241 | } | 2242 | } |
2242 | 2243 | ||
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index aec0fbdfe7f0..5f284ffd430e 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
@@ -492,6 +492,7 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file, | |||
492 | int is_async, int *fd) | 492 | int is_async, int *fd) |
493 | { | 493 | { |
494 | struct ib_uverbs_event_file *ev_file; | 494 | struct ib_uverbs_event_file *ev_file; |
495 | struct path path; | ||
495 | struct file *filp; | 496 | struct file *filp; |
496 | int ret; | 497 | int ret; |
497 | 498 | ||
@@ -519,8 +520,10 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file, | |||
519 | * system call on a uverbs file, which will already have a | 520 | * system call on a uverbs file, which will already have a |
520 | * module reference. | 521 | * module reference. |
521 | */ | 522 | */ |
522 | filp = alloc_file(uverbs_event_mnt, dget(uverbs_event_mnt->mnt_root), | 523 | path.mnt = uverbs_event_mnt; |
523 | FMODE_READ, fops_get(&uverbs_event_fops)); | 524 | path.dentry = uverbs_event_mnt->mnt_root; |
525 | path_get(&path); | ||
526 | filp = alloc_file(&path, FMODE_READ, fops_get(&uverbs_event_fops)); | ||
524 | if (!filp) { | 527 | if (!filp) { |
525 | ret = -ENFILE; | 528 | ret = -ENFILE; |
526 | goto err_fd; | 529 | goto err_fd; |
@@ -531,6 +534,8 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file, | |||
531 | return filp; | 534 | return filp; |
532 | 535 | ||
533 | err_fd: | 536 | err_fd: |
537 | fops_put(&uverbs_event_fops); | ||
538 | path_put(&path); | ||
534 | put_unused_fd(*fd); | 539 | put_unused_fd(*fd); |
535 | 540 | ||
536 | err: | 541 | err: |
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 2ca7a7cafdbf..94f5110c4655 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c | |||
@@ -88,7 +88,7 @@ struct file *anon_inode_getfile(const char *name, | |||
88 | void *priv, int flags) | 88 | void *priv, int flags) |
89 | { | 89 | { |
90 | struct qstr this; | 90 | struct qstr this; |
91 | struct dentry *dentry; | 91 | struct path path; |
92 | struct file *file; | 92 | struct file *file; |
93 | int error; | 93 | int error; |
94 | 94 | ||
@@ -106,10 +106,11 @@ struct file *anon_inode_getfile(const char *name, | |||
106 | this.name = name; | 106 | this.name = name; |
107 | this.len = strlen(name); | 107 | this.len = strlen(name); |
108 | this.hash = 0; | 108 | this.hash = 0; |
109 | dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this); | 109 | path.dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this); |
110 | if (!dentry) | 110 | if (!path.dentry) |
111 | goto err_module; | 111 | goto err_module; |
112 | 112 | ||
113 | path.mnt = mntget(anon_inode_mnt); | ||
113 | /* | 114 | /* |
114 | * We know the anon_inode inode count is always greater than zero, | 115 | * We know the anon_inode inode count is always greater than zero, |
115 | * so we can avoid doing an igrab() and we can use an open-coded | 116 | * so we can avoid doing an igrab() and we can use an open-coded |
@@ -117,14 +118,13 @@ struct file *anon_inode_getfile(const char *name, | |||
117 | */ | 118 | */ |
118 | atomic_inc(&anon_inode_inode->i_count); | 119 | atomic_inc(&anon_inode_inode->i_count); |
119 | 120 | ||
120 | dentry->d_op = &anon_inodefs_dentry_operations; | 121 | path.dentry->d_op = &anon_inodefs_dentry_operations; |
121 | /* Do not publish this dentry inside the global dentry hash table */ | 122 | /* Do not publish this dentry inside the global dentry hash table */ |
122 | dentry->d_flags &= ~DCACHE_UNHASHED; | 123 | path.dentry->d_flags &= ~DCACHE_UNHASHED; |
123 | d_instantiate(dentry, anon_inode_inode); | 124 | d_instantiate(path.dentry, anon_inode_inode); |
124 | 125 | ||
125 | error = -ENFILE; | 126 | error = -ENFILE; |
126 | file = alloc_file(anon_inode_mnt, dentry, | 127 | file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops); |
127 | FMODE_READ | FMODE_WRITE, fops); | ||
128 | if (!file) | 128 | if (!file) |
129 | goto err_dput; | 129 | goto err_dput; |
130 | file->f_mapping = anon_inode_inode->i_mapping; | 130 | file->f_mapping = anon_inode_inode->i_mapping; |
@@ -137,7 +137,7 @@ struct file *anon_inode_getfile(const char *name, | |||
137 | return file; | 137 | return file; |
138 | 138 | ||
139 | err_dput: | 139 | err_dput: |
140 | dput(dentry); | 140 | path_put(&path); |
141 | err_module: | 141 | err_module: |
142 | module_put(fops->owner); | 142 | module_put(fops->owner); |
143 | return ERR_PTR(error); | 143 | return ERR_PTR(error); |
diff --git a/fs/file_table.c b/fs/file_table.c index 602a9ee3023a..163cd28314e0 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -162,8 +162,8 @@ fail: | |||
162 | * If all the callers of init_file() are eliminated, its | 162 | * If all the callers of init_file() are eliminated, its |
163 | * code should be moved into this function. | 163 | * code should be moved into this function. |
164 | */ | 164 | */ |
165 | struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry, | 165 | struct file *alloc_file(struct path *path, fmode_t mode, |
166 | fmode_t mode, const struct file_operations *fop) | 166 | const struct file_operations *fop) |
167 | { | 167 | { |
168 | struct file *file; | 168 | struct file *file; |
169 | 169 | ||
@@ -171,9 +171,8 @@ struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry, | |||
171 | if (!file) | 171 | if (!file) |
172 | return NULL; | 172 | return NULL; |
173 | 173 | ||
174 | file->f_path.dentry = dentry; | 174 | file->f_path = *path; |
175 | file->f_path.mnt = mntget(mnt); | 175 | file->f_mapping = path->dentry->d_inode->i_mapping; |
176 | file->f_mapping = dentry->d_inode->i_mapping; | ||
177 | file->f_mode = mode; | 176 | file->f_mode = mode; |
178 | file->f_op = fop; | 177 | file->f_op = fop; |
179 | 178 | ||
@@ -183,10 +182,10 @@ struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry, | |||
183 | * visible. We do this for consistency, and so | 182 | * visible. We do this for consistency, and so |
184 | * that we can do debugging checks at __fput() | 183 | * that we can do debugging checks at __fput() |
185 | */ | 184 | */ |
186 | if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) { | 185 | if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) { |
187 | int error = 0; | 186 | int error = 0; |
188 | file_take_write(file); | 187 | file_take_write(file); |
189 | error = mnt_clone_write(mnt); | 188 | error = mnt_clone_write(path->mnt); |
190 | WARN_ON(error); | 189 | WARN_ON(error); |
191 | } | 190 | } |
192 | return file; | 191 | return file; |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 87a1258953b8..6bd41525cd71 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -922,7 +922,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, | |||
922 | int error = -ENOMEM; | 922 | int error = -ENOMEM; |
923 | struct file *file; | 923 | struct file *file; |
924 | struct inode *inode; | 924 | struct inode *inode; |
925 | struct dentry *dentry, *root; | 925 | struct path path; |
926 | struct dentry *root; | ||
926 | struct qstr quick_string; | 927 | struct qstr quick_string; |
927 | 928 | ||
928 | *user = NULL; | 929 | *user = NULL; |
@@ -944,10 +945,11 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, | |||
944 | quick_string.name = name; | 945 | quick_string.name = name; |
945 | quick_string.len = strlen(quick_string.name); | 946 | quick_string.len = strlen(quick_string.name); |
946 | quick_string.hash = 0; | 947 | quick_string.hash = 0; |
947 | dentry = d_alloc(root, &quick_string); | 948 | path.dentry = d_alloc(root, &quick_string); |
948 | if (!dentry) | 949 | if (!path.dentry) |
949 | goto out_shm_unlock; | 950 | goto out_shm_unlock; |
950 | 951 | ||
952 | path.mnt = mntget(hugetlbfs_vfsmount); | ||
951 | error = -ENOSPC; | 953 | error = -ENOSPC; |
952 | inode = hugetlbfs_get_inode(root->d_sb, current_fsuid(), | 954 | inode = hugetlbfs_get_inode(root->d_sb, current_fsuid(), |
953 | current_fsgid(), S_IFREG | S_IRWXUGO, 0); | 955 | current_fsgid(), S_IFREG | S_IRWXUGO, 0); |
@@ -960,13 +962,12 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, | |||
960 | acctflag)) | 962 | acctflag)) |
961 | goto out_inode; | 963 | goto out_inode; |
962 | 964 | ||
963 | d_instantiate(dentry, inode); | 965 | d_instantiate(path.dentry, inode); |
964 | inode->i_size = size; | 966 | inode->i_size = size; |
965 | inode->i_nlink = 0; | 967 | inode->i_nlink = 0; |
966 | 968 | ||
967 | error = -ENFILE; | 969 | error = -ENFILE; |
968 | file = alloc_file(hugetlbfs_vfsmount, dentry, | 970 | file = alloc_file(&path, FMODE_WRITE | FMODE_READ, |
969 | FMODE_WRITE | FMODE_READ, | ||
970 | &hugetlbfs_file_operations); | 971 | &hugetlbfs_file_operations); |
971 | if (!file) | 972 | if (!file) |
972 | goto out_dentry; /* inode is already attached */ | 973 | goto out_dentry; /* inode is already attached */ |
@@ -977,7 +978,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, | |||
977 | out_inode: | 978 | out_inode: |
978 | iput(inode); | 979 | iput(inode); |
979 | out_dentry: | 980 | out_dentry: |
980 | dput(dentry); | 981 | path_put(&path); |
981 | out_shm_unlock: | 982 | out_shm_unlock: |
982 | if (*user) { | 983 | if (*user) { |
983 | user_shm_unlock(size, *user); | 984 | user_shm_unlock(size, *user); |
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 9e4f90042eaf..8271cf05c957 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
@@ -646,6 +646,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags) | |||
646 | struct fsnotify_group *group; | 646 | struct fsnotify_group *group; |
647 | struct user_struct *user; | 647 | struct user_struct *user; |
648 | struct file *filp; | 648 | struct file *filp; |
649 | struct path path; | ||
649 | int fd, ret; | 650 | int fd, ret; |
650 | 651 | ||
651 | /* Check the IN_* constants for consistency. */ | 652 | /* Check the IN_* constants for consistency. */ |
@@ -675,8 +676,10 @@ SYSCALL_DEFINE1(inotify_init1, int, flags) | |||
675 | 676 | ||
676 | atomic_inc(&user->inotify_devs); | 677 | atomic_inc(&user->inotify_devs); |
677 | 678 | ||
678 | filp = alloc_file(inotify_mnt, dget(inotify_mnt->mnt_root), | 679 | path.mnt = inotify_mnt; |
679 | FMODE_READ, &inotify_fops); | 680 | path.dentry = inotify_mnt->mnt_root; |
681 | path_get(&path); | ||
682 | filp = alloc_file(&path, FMODE_READ, &inotify_fops); | ||
680 | if (!filp) | 683 | if (!filp) |
681 | goto Enfile; | 684 | goto Enfile; |
682 | 685 | ||
@@ -689,6 +692,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags) | |||
689 | 692 | ||
690 | Enfile: | 693 | Enfile: |
691 | ret = -ENFILE; | 694 | ret = -ENFILE; |
695 | path_put(&path); | ||
692 | atomic_dec(&user->inotify_devs); | 696 | atomic_dec(&user->inotify_devs); |
693 | out_free_uid: | 697 | out_free_uid: |
694 | free_uid(user); | 698 | free_uid(user); |
@@ -974,7 +974,7 @@ struct file *create_write_pipe(int flags) | |||
974 | int err; | 974 | int err; |
975 | struct inode *inode; | 975 | struct inode *inode; |
976 | struct file *f; | 976 | struct file *f; |
977 | struct dentry *dentry; | 977 | struct path path; |
978 | struct qstr name = { .name = "" }; | 978 | struct qstr name = { .name = "" }; |
979 | 979 | ||
980 | err = -ENFILE; | 980 | err = -ENFILE; |
@@ -983,21 +983,22 @@ struct file *create_write_pipe(int flags) | |||
983 | goto err; | 983 | goto err; |
984 | 984 | ||
985 | err = -ENOMEM; | 985 | err = -ENOMEM; |
986 | dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name); | 986 | path.dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name); |
987 | if (!dentry) | 987 | if (!path.dentry) |
988 | goto err_inode; | 988 | goto err_inode; |
989 | path.mnt = mntget(pipe_mnt); | ||
989 | 990 | ||
990 | dentry->d_op = &pipefs_dentry_operations; | 991 | path.dentry->d_op = &pipefs_dentry_operations; |
991 | /* | 992 | /* |
992 | * We dont want to publish this dentry into global dentry hash table. | 993 | * We dont want to publish this dentry into global dentry hash table. |
993 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED | 994 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED |
994 | * This permits a working /proc/$pid/fd/XXX on pipes | 995 | * This permits a working /proc/$pid/fd/XXX on pipes |
995 | */ | 996 | */ |
996 | dentry->d_flags &= ~DCACHE_UNHASHED; | 997 | path.dentry->d_flags &= ~DCACHE_UNHASHED; |
997 | d_instantiate(dentry, inode); | 998 | d_instantiate(path.dentry, inode); |
998 | 999 | ||
999 | err = -ENFILE; | 1000 | err = -ENFILE; |
1000 | f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipefifo_fops); | 1001 | f = alloc_file(&path, FMODE_WRITE, &write_pipefifo_fops); |
1001 | if (!f) | 1002 | if (!f) |
1002 | goto err_dentry; | 1003 | goto err_dentry; |
1003 | f->f_mapping = inode->i_mapping; | 1004 | f->f_mapping = inode->i_mapping; |
@@ -1009,7 +1010,7 @@ struct file *create_write_pipe(int flags) | |||
1009 | 1010 | ||
1010 | err_dentry: | 1011 | err_dentry: |
1011 | free_pipe_info(inode); | 1012 | free_pipe_info(inode); |
1012 | dput(dentry); | 1013 | path_put(&path); |
1013 | return ERR_PTR(err); | 1014 | return ERR_PTR(err); |
1014 | 1015 | ||
1015 | err_inode: | 1016 | err_inode: |
diff --git a/include/linux/file.h b/include/linux/file.h index 6a8d3612eb2a..5555508fd517 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
@@ -18,8 +18,9 @@ extern void drop_file_write_access(struct file *file); | |||
18 | struct file_operations; | 18 | struct file_operations; |
19 | struct vfsmount; | 19 | struct vfsmount; |
20 | struct dentry; | 20 | struct dentry; |
21 | extern struct file *alloc_file(struct vfsmount *, struct dentry *dentry, | 21 | struct path; |
22 | fmode_t mode, const struct file_operations *fop); | 22 | extern struct file *alloc_file(struct path *, fmode_t mode, |
23 | const struct file_operations *fop); | ||
23 | 24 | ||
24 | static inline void fput_light(struct file *file, int fput_needed) | 25 | static inline void fput_light(struct file *file, int fput_needed) |
25 | { | 26 | { |
@@ -878,8 +878,8 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
878 | if (err) | 878 | if (err) |
879 | goto out_unlock; | 879 | goto out_unlock; |
880 | 880 | ||
881 | path.dentry = dget(shp->shm_file->f_path.dentry); | 881 | path = shp->shm_file->f_path; |
882 | path.mnt = shp->shm_file->f_path.mnt; | 882 | path_get(&path); |
883 | shp->shm_nattch++; | 883 | shp->shm_nattch++; |
884 | size = i_size_read(path.dentry->d_inode); | 884 | size = i_size_read(path.dentry->d_inode); |
885 | shm_unlock(shp); | 885 | shm_unlock(shp); |
@@ -889,8 +889,8 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
889 | if (!sfd) | 889 | if (!sfd) |
890 | goto out_put_dentry; | 890 | goto out_put_dentry; |
891 | 891 | ||
892 | file = alloc_file(path.mnt, path.dentry, f_mode, | 892 | file = alloc_file(&path, f_mode, |
893 | is_file_hugepages(shp->shm_file) ? | 893 | is_file_hugepages(shp->shm_file) ? |
894 | &shm_file_operations_huge : | 894 | &shm_file_operations_huge : |
895 | &shm_file_operations); | 895 | &shm_file_operations); |
896 | if (!file) | 896 | if (!file) |
@@ -950,7 +950,7 @@ out_unlock: | |||
950 | out_free: | 950 | out_free: |
951 | kfree(sfd); | 951 | kfree(sfd); |
952 | out_put_dentry: | 952 | out_put_dentry: |
953 | dput(path.dentry); | 953 | path_put(&path); |
954 | goto out_nattch; | 954 | goto out_nattch; |
955 | } | 955 | } |
956 | 956 | ||
diff --git a/mm/shmem.c b/mm/shmem.c index ef8f47473c5a..d2ec7f029ff4 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -2626,7 +2626,8 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags | |||
2626 | int error; | 2626 | int error; |
2627 | struct file *file; | 2627 | struct file *file; |
2628 | struct inode *inode; | 2628 | struct inode *inode; |
2629 | struct dentry *dentry, *root; | 2629 | struct path path; |
2630 | struct dentry *root; | ||
2630 | struct qstr this; | 2631 | struct qstr this; |
2631 | 2632 | ||
2632 | if (IS_ERR(shm_mnt)) | 2633 | if (IS_ERR(shm_mnt)) |
@@ -2643,16 +2644,17 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags | |||
2643 | this.len = strlen(name); | 2644 | this.len = strlen(name); |
2644 | this.hash = 0; /* will go */ | 2645 | this.hash = 0; /* will go */ |
2645 | root = shm_mnt->mnt_root; | 2646 | root = shm_mnt->mnt_root; |
2646 | dentry = d_alloc(root, &this); | 2647 | path.dentry = d_alloc(root, &this); |
2647 | if (!dentry) | 2648 | if (!path.dentry) |
2648 | goto put_memory; | 2649 | goto put_memory; |
2650 | path.mnt = mntget(shm_mnt); | ||
2649 | 2651 | ||
2650 | error = -ENOSPC; | 2652 | error = -ENOSPC; |
2651 | inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, flags); | 2653 | inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, flags); |
2652 | if (!inode) | 2654 | if (!inode) |
2653 | goto put_dentry; | 2655 | goto put_dentry; |
2654 | 2656 | ||
2655 | d_instantiate(dentry, inode); | 2657 | d_instantiate(path.dentry, inode); |
2656 | inode->i_size = size; | 2658 | inode->i_size = size; |
2657 | inode->i_nlink = 0; /* It is unlinked */ | 2659 | inode->i_nlink = 0; /* It is unlinked */ |
2658 | #ifndef CONFIG_MMU | 2660 | #ifndef CONFIG_MMU |
@@ -2662,7 +2664,7 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags | |||
2662 | #endif | 2664 | #endif |
2663 | 2665 | ||
2664 | error = -ENFILE; | 2666 | error = -ENFILE; |
2665 | file = alloc_file(shm_mnt, dentry, FMODE_WRITE | FMODE_READ, | 2667 | file = alloc_file(&path, FMODE_WRITE | FMODE_READ, |
2666 | &shmem_file_operations); | 2668 | &shmem_file_operations); |
2667 | if (!file) | 2669 | if (!file) |
2668 | goto put_dentry; | 2670 | goto put_dentry; |
@@ -2671,7 +2673,7 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags | |||
2671 | return file; | 2673 | return file; |
2672 | 2674 | ||
2673 | put_dentry: | 2675 | put_dentry: |
2674 | dput(dentry); | 2676 | path_put(&path); |
2675 | put_memory: | 2677 | put_memory: |
2676 | shmem_unacct_size(flags, size); | 2678 | shmem_unacct_size(flags, size); |
2677 | return ERR_PTR(error); | 2679 | return ERR_PTR(error); |
diff --git a/net/socket.c b/net/socket.c index eaaba3510e81..dbfdfa96d29b 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -358,7 +358,7 @@ static const struct dentry_operations sockfs_dentry_operations = { | |||
358 | static int sock_alloc_file(struct socket *sock, struct file **f, int flags) | 358 | static int sock_alloc_file(struct socket *sock, struct file **f, int flags) |
359 | { | 359 | { |
360 | struct qstr name = { .name = "" }; | 360 | struct qstr name = { .name = "" }; |
361 | struct dentry *dentry; | 361 | struct path path; |
362 | struct file *file; | 362 | struct file *file; |
363 | int fd; | 363 | int fd; |
364 | 364 | ||
@@ -366,28 +366,29 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags) | |||
366 | if (unlikely(fd < 0)) | 366 | if (unlikely(fd < 0)) |
367 | return fd; | 367 | return fd; |
368 | 368 | ||
369 | dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); | 369 | path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); |
370 | if (unlikely(!dentry)) { | 370 | if (unlikely(!path.dentry)) { |
371 | put_unused_fd(fd); | 371 | put_unused_fd(fd); |
372 | return -ENOMEM; | 372 | return -ENOMEM; |
373 | } | 373 | } |
374 | path.mnt = mntget(sock_mnt); | ||
374 | 375 | ||
375 | dentry->d_op = &sockfs_dentry_operations; | 376 | path.dentry->d_op = &sockfs_dentry_operations; |
376 | /* | 377 | /* |
377 | * We dont want to push this dentry into global dentry hash table. | 378 | * We dont want to push this dentry into global dentry hash table. |
378 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED | 379 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED |
379 | * This permits a working /proc/$pid/fd/XXX on sockets | 380 | * This permits a working /proc/$pid/fd/XXX on sockets |
380 | */ | 381 | */ |
381 | dentry->d_flags &= ~DCACHE_UNHASHED; | 382 | path.dentry->d_flags &= ~DCACHE_UNHASHED; |
382 | d_instantiate(dentry, SOCK_INODE(sock)); | 383 | d_instantiate(path.dentry, SOCK_INODE(sock)); |
383 | SOCK_INODE(sock)->i_fop = &socket_file_ops; | 384 | SOCK_INODE(sock)->i_fop = &socket_file_ops; |
384 | 385 | ||
385 | file = alloc_file(sock_mnt, dentry, FMODE_READ | FMODE_WRITE, | 386 | file = alloc_file(&path, FMODE_READ | FMODE_WRITE, |
386 | &socket_file_ops); | 387 | &socket_file_ops); |
387 | if (unlikely(!file)) { | 388 | if (unlikely(!file)) { |
388 | /* drop dentry, keep inode */ | 389 | /* drop dentry, keep inode */ |
389 | atomic_inc(&path.dentry->d_inode->i_count); | 390 | atomic_inc(&path.dentry->d_inode->i_count); |
390 | dput(dentry); | 391 | path_put(&path); |
391 | put_unused_fd(fd); | 392 | put_unused_fd(fd); |
392 | return -ENFILE; | 393 | return -ENFILE; |
393 | } | 394 | } |