1
2
3
4
5
6
7
8#include <linux/slab.h>
9#include <linux/file.h>
10#include <linux/init.h>
11
12
13static kmem_cache_t *filp_cache;
14
15
16struct files_stat_struct files_stat = {0, 0, NR_FILE};
17
18
19static struct file * free_filps = NULL;
20
21static void insert_file_free(struct file *file)
22{
23 if((file->f_next = free_filps) != NULL)
24 free_filps->f_pprev = &file->f_next;
25 free_filps = file;
26 file->f_pprev = &free_filps;
27 files_stat.nr_free_files++;
28}
29
30
31struct file *inuse_filps = NULL;
32
33static inline void put_inuse(struct file *file)
34{
35 if((file->f_next = inuse_filps) != NULL)
36 inuse_filps->f_pprev = &file->f_next;
37 inuse_filps = file;
38 file->f_pprev = &inuse_filps;
39}
40
41
42static inline void remove_filp(struct file *file)
43{
44 if(file->f_next)
45 file->f_next->f_pprev = file->f_pprev;
46 *file->f_pprev = file->f_next;
47}
48
49
50void __init file_table_init(void)
51{
52 filp_cache = kmem_cache_create("filp", sizeof(struct file),
53 0,
54 SLAB_HWCACHE_ALIGN, NULL, NULL);
55 if(!filp_cache)
56 panic("VFS: Cannot alloc filp SLAB cache.");
57
58
59
60
61
62}
63
64
65
66
67
68struct file * get_empty_filp(void)
69{
70 static int old_max = 0;
71 struct file * f;
72
73 if (files_stat.nr_free_files > NR_RESERVED_FILES) {
74 used_one:
75 f = free_filps;
76 remove_filp(f);
77 files_stat.nr_free_files--;
78 new_one:
79 memset(f, 0, sizeof(*f));
80 f->f_count = 1;
81 f->f_version = ++global_event;
82 f->f_uid = current->fsuid;
83 f->f_gid = current->fsgid;
84 put_inuse(f);
85 return f;
86 }
87
88
89
90 if (files_stat.nr_free_files && !current->euid)
91 goto used_one;
92
93
94
95 if (files_stat.nr_files < files_stat.max_files) {
96 f = kmem_cache_alloc(filp_cache, SLAB_KERNEL);
97 if (f) {
98 files_stat.nr_files++;
99 goto new_one;
100 }
101
102 printk("VFS: filp allocation failed\n");
103
104 } else if (files_stat.max_files > old_max) {
105 printk("VFS: file-max limit %d reached\n", files_stat.max_files);
106 old_max = files_stat.max_files;
107 }
108 return NULL;
109}
110
111
112
113
114
115
116int init_private_file(struct file *filp, struct dentry *dentry, int mode)
117{
118 memset(filp, 0, sizeof(*filp));
119 filp->f_mode = mode;
120 filp->f_count = 1;
121 filp->f_dentry = dentry;
122 filp->f_uid = current->fsuid;
123 filp->f_gid = current->fsgid;
124 filp->f_op = dentry->d_inode->i_op->default_file_ops;
125 if (filp->f_op->open)
126 return filp->f_op->open(dentry->d_inode, filp);
127 else
128 return 0;
129}
130
131void fput(struct file *file)
132{
133 int count = file->f_count-1;
134
135 if (!count) {
136 locks_remove_flock(file);
137 __fput(file);
138 file->f_count = 0;
139 remove_filp(file);
140 insert_file_free(file);
141 } else
142 file->f_count = count;
143}
144
145void put_filp(struct file *file)
146{
147 if(--file->f_count == 0) {
148 remove_filp(file);
149 insert_file_free(file);
150 }
151}
152