Blame view
fs/file_table.c
6.71 KB
1da177e4c
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* * linux/fs/file_table.c * * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) */ #include <linux/string.h> #include <linux/slab.h> #include <linux/file.h> #include <linux/init.h> #include <linux/module.h> #include <linux/smp_lock.h> #include <linux/fs.h> #include <linux/security.h> #include <linux/eventpoll.h> |
ab2af1f50
|
17 |
#include <linux/rcupdate.h> |
1da177e4c
|
18 |
#include <linux/mount.h> |
16f7e0fe2
|
19 |
#include <linux/capability.h> |
1da177e4c
|
20 |
#include <linux/cdev.h> |
0eeca2830
|
21 |
#include <linux/fsnotify.h> |
529bf6be5
|
22 23 24 25 |
#include <linux/sysctl.h> #include <linux/percpu_counter.h> #include <asm/atomic.h> |
1da177e4c
|
26 27 28 29 30 |
/* sysctl tunables... */ struct files_stat_struct files_stat = { .max_files = NR_FILE }; |
1da177e4c
|
31 |
/* public. Not pretty! */ |
529bf6be5
|
32 |
__cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock); |
1da177e4c
|
33 |
|
529bf6be5
|
34 |
static struct percpu_counter nr_files __cacheline_aligned_in_smp; |
1da177e4c
|
35 |
|
529bf6be5
|
36 |
static inline void file_free_rcu(struct rcu_head *head) |
1da177e4c
|
37 |
{ |
529bf6be5
|
38 39 |
struct file *f = container_of(head, struct file, f_u.fu_rcuhead); kmem_cache_free(filp_cachep, f); |
1da177e4c
|
40 |
} |
529bf6be5
|
41 |
static inline void file_free(struct file *f) |
1da177e4c
|
42 |
{ |
529bf6be5
|
43 44 |
percpu_counter_dec(&nr_files); call_rcu(&f->f_u.fu_rcuhead, file_free_rcu); |
1da177e4c
|
45 |
} |
529bf6be5
|
46 47 48 49 |
/* * Return the total number of open files in the system */ static int get_nr_files(void) |
1da177e4c
|
50 |
{ |
529bf6be5
|
51 |
return percpu_counter_read_positive(&nr_files); |
1da177e4c
|
52 |
} |
529bf6be5
|
53 54 55 56 |
/* * Return the maximum number of open files in the system */ int get_max_files(void) |
ab2af1f50
|
57 |
{ |
529bf6be5
|
58 |
return files_stat.max_files; |
ab2af1f50
|
59 |
} |
529bf6be5
|
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
EXPORT_SYMBOL_GPL(get_max_files); /* * Handle nr_files sysctl */ #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS) int proc_nr_files(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) { files_stat.nr_files = get_nr_files(); return proc_dointvec(table, write, filp, buffer, lenp, ppos); } #else int proc_nr_files(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } #endif |
ab2af1f50
|
79 |
|
1da177e4c
|
80 81 82 83 84 85 |
/* Find an unused file structure and return a pointer to it. * Returns NULL, if there are no more free file structures or * we run out of memory. */ struct file *get_empty_filp(void) { |
5a6b7951b
|
86 |
struct task_struct *tsk; |
af4d2ecbf
|
87 |
static int old_max; |
1da177e4c
|
88 89 90 91 92 |
struct file * f; /* * Privileged users can go above max_files */ |
529bf6be5
|
93 94 95 96 97 98 99 100 |
if (get_nr_files() >= files_stat.max_files && !capable(CAP_SYS_ADMIN)) { /* * percpu_counters are inaccurate. Do an expensive check before * we go and fail. */ if (percpu_counter_sum(&nr_files) >= files_stat.max_files) goto over; } |
af4d2ecbf
|
101 102 103 104 |
f = kmem_cache_alloc(filp_cachep, GFP_KERNEL); if (f == NULL) goto fail; |
529bf6be5
|
105 |
percpu_counter_inc(&nr_files); |
af4d2ecbf
|
106 107 108 |
memset(f, 0, sizeof(*f)); if (security_file_alloc(f)) goto fail_sec; |
1da177e4c
|
109 |
|
5a6b7951b
|
110 111 |
tsk = current; INIT_LIST_HEAD(&f->f_u.fu_list); |
af4d2ecbf
|
112 |
atomic_set(&f->f_count, 1); |
af4d2ecbf
|
113 |
rwlock_init(&f->f_owner.lock); |
5a6b7951b
|
114 115 116 |
f->f_uid = tsk->fsuid; f->f_gid = tsk->fsgid; eventpoll_init_file(f); |
af4d2ecbf
|
117 |
/* f->f_version: 0 */ |
af4d2ecbf
|
118 119 120 |
return f; over: |
1da177e4c
|
121 |
/* Ran out of filps - report that */ |
529bf6be5
|
122 |
if (get_nr_files() > old_max) { |
1da177e4c
|
123 124 |
printk(KERN_INFO "VFS: file-max limit %d reached ", |
529bf6be5
|
125 126 |
get_max_files()); old_max = get_nr_files(); |
1da177e4c
|
127 |
} |
af4d2ecbf
|
128 129 130 131 |
goto fail; fail_sec: file_free(f); |
1da177e4c
|
132 133 134 135 136 137 138 139 |
fail: return NULL; } EXPORT_SYMBOL(get_empty_filp); void fastcall fput(struct file *file) { |
095975da2
|
140 |
if (atomic_dec_and_test(&file->f_count)) |
1da177e4c
|
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
__fput(file); } EXPORT_SYMBOL(fput); /* __fput is called from task context when aio completion releases the last * last use of a struct file *. Do not use otherwise. */ void fastcall __fput(struct file *file) { struct dentry *dentry = file->f_dentry; struct vfsmount *mnt = file->f_vfsmnt; struct inode *inode = dentry->d_inode; might_sleep(); |
0eeca2830
|
156 157 |
fsnotify_close(file); |
1da177e4c
|
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
/* * The function eventpoll_release() should be the first called * in the file cleanup chain. */ eventpoll_release(file); locks_remove_flock(file); if (file->f_op && file->f_op->release) file->f_op->release(inode, file); security_file_free(file); if (unlikely(inode->i_cdev != NULL)) cdev_put(inode->i_cdev); fops_put(file->f_op); if (file->f_mode & FMODE_WRITE) put_write_access(inode); file_kill(file); file->f_dentry = NULL; file->f_vfsmnt = NULL; file_free(file); dput(dentry); mntput(mnt); } struct file fastcall *fget(unsigned int fd) { struct file *file; struct files_struct *files = current->files; |
ab2af1f50
|
185 |
rcu_read_lock(); |
1da177e4c
|
186 |
file = fcheck_files(files, fd); |
ab2af1f50
|
187 |
if (file) { |
095975da2
|
188 |
if (!atomic_inc_not_zero(&file->f_count)) { |
ab2af1f50
|
189 190 191 192 193 194 |
/* File object ref couldn't be taken */ rcu_read_unlock(); return NULL; } } rcu_read_unlock(); |
1da177e4c
|
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
return file; } EXPORT_SYMBOL(fget); /* * Lightweight file lookup - no refcnt increment if fd table isn't shared. * You can use this only if it is guranteed that the current task already * holds a refcnt to that file. That check has to be done at fget() only * and a flag is returned to be passed to the corresponding fput_light(). * There must not be a cloning between an fget_light/fput_light pair. */ struct file fastcall *fget_light(unsigned int fd, int *fput_needed) { struct file *file; struct files_struct *files = current->files; *fput_needed = 0; if (likely((atomic_read(&files->count) == 1))) { file = fcheck_files(files, fd); } else { |
ab2af1f50
|
216 |
rcu_read_lock(); |
1da177e4c
|
217 218 |
file = fcheck_files(files, fd); if (file) { |
095975da2
|
219 |
if (atomic_inc_not_zero(&file->f_count)) |
ab2af1f50
|
220 221 222 223 |
*fput_needed = 1; else /* Didn't get the reference, someone's freed */ file = NULL; |
1da177e4c
|
224 |
} |
ab2af1f50
|
225 |
rcu_read_unlock(); |
1da177e4c
|
226 |
} |
ab2af1f50
|
227 |
|
1da177e4c
|
228 229 230 231 232 233 |
return file; } void put_filp(struct file *file) { |
095975da2
|
234 |
if (atomic_dec_and_test(&file->f_count)) { |
1da177e4c
|
235 236 237 238 239 240 241 242 243 244 245 |
security_file_free(file); file_kill(file); file_free(file); } } void file_move(struct file *file, struct list_head *list) { if (!list) return; file_list_lock(); |
2f5120166
|
246 |
list_move(&file->f_u.fu_list, list); |
1da177e4c
|
247 248 249 250 251 |
file_list_unlock(); } void file_kill(struct file *file) { |
2f5120166
|
252 |
if (!list_empty(&file->f_u.fu_list)) { |
1da177e4c
|
253 |
file_list_lock(); |
2f5120166
|
254 |
list_del_init(&file->f_u.fu_list); |
1da177e4c
|
255 256 257 258 259 260 261 262 263 264 265 |
file_list_unlock(); } } int fs_may_remount_ro(struct super_block *sb) { struct list_head *p; /* Check that no files are currently opened for writing. */ file_list_lock(); list_for_each(p, &sb->s_files) { |
2f5120166
|
266 |
struct file *file = list_entry(p, struct file, f_u.fu_list); |
1da177e4c
|
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
struct inode *inode = file->f_dentry->d_inode; /* File with pending delete? */ if (inode->i_nlink == 0) goto too_bad; /* Writeable file? */ if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)) goto too_bad; } file_list_unlock(); return 1; /* Tis' cool bro. */ too_bad: file_list_unlock(); return 0; } void __init files_init(unsigned long mempages) { int n; /* One file with associated inode and dcache is very roughly 1K. * Per default don't use more than 10% of our memory for files. */ n = (mempages * (PAGE_SIZE / 1024)) / 10; files_stat.max_files = n; if (files_stat.max_files < NR_FILE) files_stat.max_files = NR_FILE; |
ab2af1f50
|
295 |
files_defer_init(); |
0216bfcff
|
296 |
percpu_counter_init(&nr_files, 0); |
1da177e4c
|
297 |
} |