diff options
Diffstat (limited to 'fs/file_table.c')
-rw-r--r-- | fs/file_table.c | 65 |
1 files changed, 62 insertions, 3 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index d17fd691b83..3176fefc92e 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -98,16 +98,15 @@ struct file *get_empty_filp(void) | |||
98 | * percpu_counters are inaccurate. Do an expensive check before | 98 | * percpu_counters are inaccurate. Do an expensive check before |
99 | * we go and fail. | 99 | * we go and fail. |
100 | */ | 100 | */ |
101 | if (percpu_counter_sum(&nr_files) >= files_stat.max_files) | 101 | if (percpu_counter_sum_positive(&nr_files) >= files_stat.max_files) |
102 | goto over; | 102 | goto over; |
103 | } | 103 | } |
104 | 104 | ||
105 | f = kmem_cache_alloc(filp_cachep, GFP_KERNEL); | 105 | f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL); |
106 | if (f == NULL) | 106 | if (f == NULL) |
107 | goto fail; | 107 | goto fail; |
108 | 108 | ||
109 | percpu_counter_inc(&nr_files); | 109 | percpu_counter_inc(&nr_files); |
110 | memset(f, 0, sizeof(*f)); | ||
111 | if (security_file_alloc(f)) | 110 | if (security_file_alloc(f)) |
112 | goto fail_sec; | 111 | goto fail_sec; |
113 | 112 | ||
@@ -138,6 +137,66 @@ fail: | |||
138 | 137 | ||
139 | EXPORT_SYMBOL(get_empty_filp); | 138 | EXPORT_SYMBOL(get_empty_filp); |
140 | 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 | |||
141 | void fastcall fput(struct file *file) | 200 | void fastcall fput(struct file *file) |
142 | { | 201 | { |
143 | if (atomic_dec_and_test(&file->f_count)) | 202 | if (atomic_dec_and_test(&file->f_count)) |