1
2
3
4
5
6
7
8#include <linux/string.h>
9#include <linux/slab.h>
10#include <linux/file.h>
11#include <linux/init.h>
12#include <linux/module.h>
13#include <linux/smp_lock.h>
14#include <linux/fs.h>
15#include <linux/security.h>
16#include <linux/eventpoll.h>
17#include <linux/mount.h>
18#include <linux/cdev.h>
19
20
21struct files_stat_struct files_stat = {
22 .max_files = NR_FILE
23};
24
25EXPORT_SYMBOL(files_stat);
26
27
28spinlock_t __cacheline_aligned_in_smp files_lock = SPIN_LOCK_UNLOCKED;
29
30EXPORT_SYMBOL(files_lock);
31
32static spinlock_t filp_count_lock = SPIN_LOCK_UNLOCKED;
33
34
35
36
37
38void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags)
39{
40 if ((cflags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
41 SLAB_CTOR_CONSTRUCTOR) {
42 unsigned long flags;
43 spin_lock_irqsave(&filp_count_lock, flags);
44 files_stat.nr_files++;
45 spin_unlock_irqrestore(&filp_count_lock, flags);
46 }
47}
48
49void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags)
50{
51 unsigned long flags;
52 spin_lock_irqsave(&filp_count_lock, flags);
53 files_stat.nr_files--;
54 spin_unlock_irqrestore(&filp_count_lock, flags);
55}
56
57static inline void file_free(struct file *f)
58{
59 kmem_cache_free(filp_cachep, f);
60}
61
62
63
64
65
66struct file *get_empty_filp(void)
67{
68static int old_max;
69 struct file * f;
70
71
72
73
74 if (files_stat.nr_files < files_stat.max_files ||
75 capable(CAP_SYS_ADMIN)) {
76 f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
77 if (f) {
78 memset(f, 0, sizeof(*f));
79 if (security_file_alloc(f)) {
80 file_free(f);
81 goto fail;
82 }
83 eventpoll_init_file(f);
84 atomic_set(&f->f_count, 1);
85 f->f_uid = current->fsuid;
86 f->f_gid = current->fsgid;
87 f->f_owner.lock = RW_LOCK_UNLOCKED;
88
89 INIT_LIST_HEAD(&f->f_list);
90 return f;
91 }
92 }
93
94
95 if (files_stat.max_files >= old_max) {
96 printk(KERN_INFO "VFS: file-max limit %d reached\n",
97 files_stat.max_files);
98 old_max = files_stat.max_files;
99 } else {
100
101 printk(KERN_WARNING "VFS: filp allocation failed\n");
102 }
103fail:
104 return NULL;
105}
106
107EXPORT_SYMBOL(get_empty_filp);
108
109
110
111
112
113
114int open_private_file(struct file *filp, struct dentry *dentry, int flags)
115{
116 int error;
117 memset(filp, 0, sizeof(*filp));
118 eventpoll_init_file(filp);
119 filp->f_flags = flags;
120 filp->f_mode = (flags+1) & O_ACCMODE;
121 atomic_set(&filp->f_count, 1);
122 filp->f_dentry = dentry;
123 filp->f_uid = current->fsuid;
124 filp->f_gid = current->fsgid;
125 filp->f_op = dentry->d_inode->i_fop;
126 INIT_LIST_HEAD(&filp->f_list);
127 error = security_file_alloc(filp);
128 if (!error)
129 if (filp->f_op && filp->f_op->open) {
130 error = filp->f_op->open(dentry->d_inode, filp);
131 if (error)
132 security_file_free(filp);
133 }
134 return error;
135}
136
137EXPORT_SYMBOL(open_private_file);
138
139
140
141
142
143void close_private_file(struct file *file)
144{
145 struct inode * inode = file->f_dentry->d_inode;
146
147 if (file->f_op && file->f_op->release)
148 file->f_op->release(inode, file);
149 security_file_free(file);
150}
151
152EXPORT_SYMBOL(close_private_file);
153
154void fput(struct file *file)
155{
156 if (atomic_dec_and_test(&file->f_count))
157 __fput(file);
158}
159
160EXPORT_SYMBOL(fput);
161
162
163
164
165void __fput(struct file *file)
166{
167 struct dentry *dentry = file->f_dentry;
168 struct vfsmount *mnt = file->f_vfsmnt;
169 struct inode *inode = dentry->d_inode;
170
171
172
173
174
175 eventpoll_release(file);
176 locks_remove_flock(file);
177
178 if (file->f_op && file->f_op->release)
179 file->f_op->release(inode, file);
180 security_file_free(file);
181 if (unlikely(inode->i_cdev != NULL))
182 cdev_put(inode->i_cdev);
183 fops_put(file->f_op);
184 if (file->f_mode & FMODE_WRITE)
185 put_write_access(inode);
186 file_kill(file);
187 file->f_dentry = NULL;
188 file->f_vfsmnt = NULL;
189 file_free(file);
190 dput(dentry);
191 mntput(mnt);
192}
193
194struct file *fget(unsigned int fd)
195{
196 struct file *file;
197 struct files_struct *files = current->files;
198
199 spin_lock(&files->file_lock);
200 file = fcheck(fd);
201 if (file)
202 get_file(file);
203 spin_unlock(&files->file_lock);
204 return file;
205}
206
207EXPORT_SYMBOL(fget);
208
209
210
211
212
213
214
215
216struct file *fget_light(unsigned int fd, int *fput_needed)
217{
218 struct file *file;
219 struct files_struct *files = current->files;
220
221 *fput_needed = 0;
222 if (likely((atomic_read(&files->count) == 1))) {
223 file = fcheck(fd);
224 } else {
225 spin_lock(&files->file_lock);
226 file = fcheck(fd);
227 if (file) {
228 get_file(file);
229 *fput_needed = 1;
230 }
231 spin_unlock(&files->file_lock);
232 }
233 return file;
234}
235
236
237void put_filp(struct file *file)
238{
239 if (atomic_dec_and_test(&file->f_count)) {
240 security_file_free(file);
241 file_kill(file);
242 file_free(file);
243 }
244}
245
246EXPORT_SYMBOL(put_filp);
247
248void file_move(struct file *file, struct list_head *list)
249{
250 if (!list)
251 return;
252 file_list_lock();
253 list_move(&file->f_list, list);
254 file_list_unlock();
255}
256
257void file_kill(struct file *file)
258{
259 if (!list_empty(&file->f_list)) {
260 file_list_lock();
261 list_del_init(&file->f_list);
262 file_list_unlock();
263 }
264}
265
266int fs_may_remount_ro(struct super_block *sb)
267{
268 struct list_head *p;
269
270
271 file_list_lock();
272 list_for_each(p, &sb->s_files) {
273 struct file *file = list_entry(p, struct file, f_list);
274 struct inode *inode = file->f_dentry->d_inode;
275
276
277 if (inode->i_nlink == 0)
278 goto too_bad;
279
280
281 if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE))
282 goto too_bad;
283 }
284 file_list_unlock();
285 return 1;
286too_bad:
287 file_list_unlock();
288 return 0;
289}
290
291void __init files_init(unsigned long mempages)
292{
293 int n;
294
295
296
297
298 n = (mempages * (PAGE_SIZE / 1024)) / 10;
299 files_stat.max_files = n;
300 if (files_stat.max_files < NR_FILE)
301 files_stat.max_files = NR_FILE;
302}
303