diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/file_table.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'fs/file_table.c')
-rw-r--r-- | fs/file_table.c | 85 |
1 files changed, 66 insertions, 19 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index a04bdd81c11c..01e4c1e8e6b6 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -60,7 +60,7 @@ static inline void file_free(struct file *f) | |||
60 | /* | 60 | /* |
61 | * Return the total number of open files in the system | 61 | * Return the total number of open files in the system |
62 | */ | 62 | */ |
63 | static int get_nr_files(void) | 63 | static long get_nr_files(void) |
64 | { | 64 | { |
65 | return percpu_counter_read_positive(&nr_files); | 65 | return percpu_counter_read_positive(&nr_files); |
66 | } | 66 | } |
@@ -68,7 +68,7 @@ static int get_nr_files(void) | |||
68 | /* | 68 | /* |
69 | * Return the maximum number of open files in the system | 69 | * Return the maximum number of open files in the system |
70 | */ | 70 | */ |
71 | int get_max_files(void) | 71 | unsigned long get_max_files(void) |
72 | { | 72 | { |
73 | return files_stat.max_files; | 73 | return files_stat.max_files; |
74 | } | 74 | } |
@@ -82,7 +82,7 @@ int proc_nr_files(ctl_table *table, int write, | |||
82 | void __user *buffer, size_t *lenp, loff_t *ppos) | 82 | void __user *buffer, size_t *lenp, loff_t *ppos) |
83 | { | 83 | { |
84 | files_stat.nr_files = get_nr_files(); | 84 | files_stat.nr_files = get_nr_files(); |
85 | return proc_dointvec(table, write, buffer, lenp, ppos); | 85 | return proc_doulongvec_minmax(table, write, buffer, lenp, ppos); |
86 | } | 86 | } |
87 | #else | 87 | #else |
88 | int proc_nr_files(ctl_table *table, int write, | 88 | int proc_nr_files(ctl_table *table, int write, |
@@ -105,7 +105,7 @@ int proc_nr_files(ctl_table *table, int write, | |||
105 | struct file *get_empty_filp(void) | 105 | struct file *get_empty_filp(void) |
106 | { | 106 | { |
107 | const struct cred *cred = current_cred(); | 107 | const struct cred *cred = current_cred(); |
108 | static int old_max; | 108 | static long old_max; |
109 | struct file * f; | 109 | struct file * f; |
110 | 110 | ||
111 | /* | 111 | /* |
@@ -125,13 +125,13 @@ struct file *get_empty_filp(void) | |||
125 | goto fail; | 125 | goto fail; |
126 | 126 | ||
127 | percpu_counter_inc(&nr_files); | 127 | percpu_counter_inc(&nr_files); |
128 | f->f_cred = get_cred(cred); | ||
128 | if (security_file_alloc(f)) | 129 | if (security_file_alloc(f)) |
129 | goto fail_sec; | 130 | goto fail_sec; |
130 | 131 | ||
131 | INIT_LIST_HEAD(&f->f_u.fu_list); | 132 | INIT_LIST_HEAD(&f->f_u.fu_list); |
132 | atomic_long_set(&f->f_count, 1); | 133 | atomic_long_set(&f->f_count, 1); |
133 | rwlock_init(&f->f_owner.lock); | 134 | rwlock_init(&f->f_owner.lock); |
134 | f->f_cred = get_cred(cred); | ||
135 | spin_lock_init(&f->f_lock); | 135 | spin_lock_init(&f->f_lock); |
136 | eventpoll_init_file(f); | 136 | eventpoll_init_file(f); |
137 | /* f->f_version: 0 */ | 137 | /* f->f_version: 0 */ |
@@ -140,8 +140,7 @@ struct file *get_empty_filp(void) | |||
140 | over: | 140 | over: |
141 | /* Ran out of filps - report that */ | 141 | /* Ran out of filps - report that */ |
142 | if (get_nr_files() > old_max) { | 142 | if (get_nr_files() > old_max) { |
143 | printk(KERN_INFO "VFS: file-max limit %d reached\n", | 143 | pr_info("VFS: file-max limit %lu reached\n", get_max_files()); |
144 | get_max_files()); | ||
145 | old_max = get_nr_files(); | 144 | old_max = get_nr_files(); |
146 | } | 145 | } |
147 | goto fail; | 146 | goto fail; |
@@ -191,7 +190,8 @@ struct file *alloc_file(struct path *path, fmode_t mode, | |||
191 | file_take_write(file); | 190 | file_take_write(file); |
192 | WARN_ON(mnt_clone_write(path->mnt)); | 191 | WARN_ON(mnt_clone_write(path->mnt)); |
193 | } | 192 | } |
194 | ima_counts_get(file); | 193 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) |
194 | i_readcount_inc(path->dentry->d_inode); | ||
195 | return file; | 195 | return file; |
196 | } | 196 | } |
197 | EXPORT_SYMBOL(alloc_file); | 197 | EXPORT_SYMBOL(alloc_file); |
@@ -247,11 +247,15 @@ static void __fput(struct file *file) | |||
247 | file->f_op->release(inode, file); | 247 | file->f_op->release(inode, file); |
248 | security_file_free(file); | 248 | security_file_free(file); |
249 | ima_file_free(file); | 249 | ima_file_free(file); |
250 | if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL)) | 250 | if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL && |
251 | !(file->f_mode & FMODE_PATH))) { | ||
251 | cdev_put(inode->i_cdev); | 252 | cdev_put(inode->i_cdev); |
253 | } | ||
252 | fops_put(file->f_op); | 254 | fops_put(file->f_op); |
253 | put_pid(file->f_owner.pid); | 255 | put_pid(file->f_owner.pid); |
254 | file_sb_list_del(file); | 256 | file_sb_list_del(file); |
257 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | ||
258 | i_readcount_dec(inode); | ||
255 | if (file->f_mode & FMODE_WRITE) | 259 | if (file->f_mode & FMODE_WRITE) |
256 | drop_file_write_access(file); | 260 | drop_file_write_access(file); |
257 | file->f_path.dentry = NULL; | 261 | file->f_path.dentry = NULL; |
@@ -277,11 +281,10 @@ struct file *fget(unsigned int fd) | |||
277 | rcu_read_lock(); | 281 | rcu_read_lock(); |
278 | file = fcheck_files(files, fd); | 282 | file = fcheck_files(files, fd); |
279 | if (file) { | 283 | if (file) { |
280 | if (!atomic_long_inc_not_zero(&file->f_count)) { | 284 | /* File object ref couldn't be taken */ |
281 | /* File object ref couldn't be taken */ | 285 | if (file->f_mode & FMODE_PATH || |
282 | rcu_read_unlock(); | 286 | !atomic_long_inc_not_zero(&file->f_count)) |
283 | return NULL; | 287 | file = NULL; |
284 | } | ||
285 | } | 288 | } |
286 | rcu_read_unlock(); | 289 | rcu_read_unlock(); |
287 | 290 | ||
@@ -290,6 +293,25 @@ struct file *fget(unsigned int fd) | |||
290 | 293 | ||
291 | EXPORT_SYMBOL(fget); | 294 | EXPORT_SYMBOL(fget); |
292 | 295 | ||
296 | struct file *fget_raw(unsigned int fd) | ||
297 | { | ||
298 | struct file *file; | ||
299 | struct files_struct *files = current->files; | ||
300 | |||
301 | rcu_read_lock(); | ||
302 | file = fcheck_files(files, fd); | ||
303 | if (file) { | ||
304 | /* File object ref couldn't be taken */ | ||
305 | if (!atomic_long_inc_not_zero(&file->f_count)) | ||
306 | file = NULL; | ||
307 | } | ||
308 | rcu_read_unlock(); | ||
309 | |||
310 | return file; | ||
311 | } | ||
312 | |||
313 | EXPORT_SYMBOL(fget_raw); | ||
314 | |||
293 | /* | 315 | /* |
294 | * Lightweight file lookup - no refcnt increment if fd table isn't shared. | 316 | * Lightweight file lookup - no refcnt increment if fd table isn't shared. |
295 | * | 317 | * |
@@ -312,7 +334,34 @@ struct file *fget_light(unsigned int fd, int *fput_needed) | |||
312 | struct files_struct *files = current->files; | 334 | struct files_struct *files = current->files; |
313 | 335 | ||
314 | *fput_needed = 0; | 336 | *fput_needed = 0; |
315 | if (likely((atomic_read(&files->count) == 1))) { | 337 | if (atomic_read(&files->count) == 1) { |
338 | file = fcheck_files(files, fd); | ||
339 | if (file && (file->f_mode & FMODE_PATH)) | ||
340 | file = NULL; | ||
341 | } else { | ||
342 | rcu_read_lock(); | ||
343 | file = fcheck_files(files, fd); | ||
344 | if (file) { | ||
345 | if (!(file->f_mode & FMODE_PATH) && | ||
346 | atomic_long_inc_not_zero(&file->f_count)) | ||
347 | *fput_needed = 1; | ||
348 | else | ||
349 | /* Didn't get the reference, someone's freed */ | ||
350 | file = NULL; | ||
351 | } | ||
352 | rcu_read_unlock(); | ||
353 | } | ||
354 | |||
355 | return file; | ||
356 | } | ||
357 | |||
358 | struct file *fget_raw_light(unsigned int fd, int *fput_needed) | ||
359 | { | ||
360 | struct file *file; | ||
361 | struct files_struct *files = current->files; | ||
362 | |||
363 | *fput_needed = 0; | ||
364 | if (atomic_read(&files->count) == 1) { | ||
316 | file = fcheck_files(files, fd); | 365 | file = fcheck_files(files, fd); |
317 | } else { | 366 | } else { |
318 | rcu_read_lock(); | 367 | rcu_read_lock(); |
@@ -487,7 +536,7 @@ retry: | |||
487 | 536 | ||
488 | void __init files_init(unsigned long mempages) | 537 | void __init files_init(unsigned long mempages) |
489 | { | 538 | { |
490 | int n; | 539 | unsigned long n; |
491 | 540 | ||
492 | filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, | 541 | filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, |
493 | SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); | 542 | SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); |
@@ -498,9 +547,7 @@ void __init files_init(unsigned long mempages) | |||
498 | */ | 547 | */ |
499 | 548 | ||
500 | n = (mempages * (PAGE_SIZE / 1024)) / 10; | 549 | n = (mempages * (PAGE_SIZE / 1024)) / 10; |
501 | files_stat.max_files = n; | 550 | files_stat.max_files = max_t(unsigned long, n, NR_FILE); |
502 | if (files_stat.max_files < NR_FILE) | ||
503 | files_stat.max_files = NR_FILE; | ||
504 | files_defer_init(); | 551 | files_defer_init(); |
505 | lg_lock_init(files_lglock); | 552 | lg_lock_init(files_lglock); |
506 | percpu_counter_init(&nr_files, 0); | 553 | percpu_counter_init(&nr_files, 0); |