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/iobuf.h>
15
16
17struct files_stat_struct files_stat = {0, 0, NR_FILE};
18
19
20static LIST_HEAD(anon_list);
21
22static LIST_HEAD(free_list);
23
24spinlock_t files_lock = SPIN_LOCK_UNLOCKED;
25
26
27
28
29
30
31
32struct file * get_empty_filp(void)
33{
34 static int old_max = 0;
35 struct file * f;
36
37 file_list_lock();
38 if (files_stat.nr_free_files > NR_RESERVED_FILES) {
39 used_one:
40 f = list_entry(free_list.next, struct file, f_list);
41 list_del(&f->f_list);
42 files_stat.nr_free_files--;
43 new_one:
44 memset(f, 0, sizeof(*f));
45 atomic_set(&f->f_count,1);
46 f->f_version = ++event;
47 f->f_uid = current->fsuid;
48 f->f_gid = current->fsgid;
49 list_add(&f->f_list, &anon_list);
50 file_list_unlock();
51 return f;
52 }
53
54
55
56 if (files_stat.nr_free_files && !current->euid)
57 goto used_one;
58
59
60
61 if (files_stat.nr_files < files_stat.max_files) {
62 file_list_unlock();
63 f = kmem_cache_alloc(filp_cachep, SLAB_KERNEL);
64 file_list_lock();
65 if (f) {
66 files_stat.nr_files++;
67 goto new_one;
68 }
69
70 printk(KERN_WARNING "VFS: filp allocation failed\n");
71
72 } else if (files_stat.max_files > old_max) {
73 printk(KERN_INFO "VFS: file-max limit %d reached\n", files_stat.max_files);
74 old_max = files_stat.max_files;
75 }
76 file_list_unlock();
77 return NULL;
78}
79
80
81
82
83
84
85int init_private_file(struct file *filp, struct dentry *dentry, int mode)
86{
87 memset(filp, 0, sizeof(*filp));
88 filp->f_mode = mode;
89 atomic_set(&filp->f_count, 1);
90 filp->f_dentry = dentry;
91 filp->f_uid = current->fsuid;
92 filp->f_gid = current->fsgid;
93 filp->f_op = dentry->d_inode->i_fop;
94 if (filp->f_op->open)
95 return filp->f_op->open(dentry->d_inode, filp);
96 else
97 return 0;
98}
99
100void fput(struct file * file)
101{
102 struct dentry * dentry = file->f_dentry;
103 struct vfsmount * mnt = file->f_vfsmnt;
104 struct inode * inode = dentry->d_inode;
105
106 if (atomic_dec_and_test(&file->f_count)) {
107 locks_remove_flock(file);
108
109 if (file->f_iobuf)
110 free_kiovec(1, &file->f_iobuf);
111
112 if (file->f_op && file->f_op->release)
113 file->f_op->release(inode, file);
114 fops_put(file->f_op);
115 if (file->f_mode & FMODE_WRITE)
116 put_write_access(inode);
117 file_list_lock();
118 file->f_dentry = NULL;
119 file->f_vfsmnt = NULL;
120 list_del(&file->f_list);
121 list_add(&file->f_list, &free_list);
122 files_stat.nr_free_files++;
123 file_list_unlock();
124 dput(dentry);
125 mntput(mnt);
126 }
127}
128
129struct file * fget(unsigned int fd)
130{
131 struct file * file;
132 struct files_struct *files = current->files;
133
134 read_lock(&files->file_lock);
135 file = fcheck(fd);
136 if (file)
137 get_file(file);
138 read_unlock(&files->file_lock);
139 return file;
140}
141
142
143
144void put_filp(struct file *file)
145{
146 if(atomic_dec_and_test(&file->f_count)) {
147 file_list_lock();
148 list_del(&file->f_list);
149 list_add(&file->f_list, &free_list);
150 files_stat.nr_free_files++;
151 file_list_unlock();
152 }
153}
154
155void file_move(struct file *file, struct list_head *list)
156{
157 if (!list)
158 return;
159 file_list_lock();
160 list_del(&file->f_list);
161 list_add(&file->f_list, list);
162 file_list_unlock();
163}
164
165int fs_may_remount_ro(struct super_block *sb)
166{
167 struct list_head *p;
168
169
170 file_list_lock();
171 for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
172 struct file *file = list_entry(p, struct file, f_list);
173 struct inode *inode = file->f_dentry->d_inode;
174
175
176 if (inode->i_nlink == 0)
177 goto too_bad;
178
179
180 if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE))
181 goto too_bad;
182 }
183 file_list_unlock();
184 return 1;
185too_bad:
186 file_list_unlock();
187 return 0;
188}
189
190void __init files_init(unsigned long mempages)
191{
192 int n;
193
194
195
196
197 n = (mempages * (PAGE_SIZE / 1024)) / 10;
198 files_stat.max_files = n;
199 if (files_stat.max_files < NR_FILE)
200 files_stat.max_files = NR_FILE;
201}
202
203