aboutsummaryrefslogtreecommitdiffstats
path: root/fs/file_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/file_table.c')
-rw-r--r--fs/file_table.c171
1 files changed, 119 insertions, 52 deletions
diff --git a/fs/file_table.c b/fs/file_table.c
index 32d12b78bac8..a7c231786a9a 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -22,6 +22,7 @@
22#include <linux/sysctl.h> 22#include <linux/sysctl.h>
23#include <linux/percpu_counter.h> 23#include <linux/percpu_counter.h>
24#include <linux/ima.h> 24#include <linux/ima.h>
25#include <linux/percpu.h>
25 26
26#include <asm/atomic.h> 27#include <asm/atomic.h>
27 28
@@ -32,8 +33,7 @@ struct files_stat_struct files_stat = {
32 .max_files = NR_FILE 33 .max_files = NR_FILE
33}; 34};
34 35
35/* public. Not pretty! */ 36static DEFINE_PER_CPU(spinlock_t, files_cpulock);
36__cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock);
37 37
38/* SLAB cache for file structures */ 38/* SLAB cache for file structures */
39static struct kmem_cache *filp_cachep __read_mostly; 39static struct kmem_cache *filp_cachep __read_mostly;
@@ -258,7 +258,7 @@ void __fput(struct file *file)
258 cdev_put(inode->i_cdev); 258 cdev_put(inode->i_cdev);
259 fops_put(file->f_op); 259 fops_put(file->f_op);
260 put_pid(file->f_owner.pid); 260 put_pid(file->f_owner.pid);
261 file_kill(file); 261 file_sb_list_del(file);
262 if (file->f_mode & FMODE_WRITE) 262 if (file->f_mode & FMODE_WRITE)
263 drop_file_write_access(file); 263 drop_file_write_access(file);
264 file->f_path.dentry = NULL; 264 file->f_path.dentry = NULL;
@@ -320,55 +320,112 @@ struct file *fget_light(unsigned int fd, int *fput_needed)
320 return file; 320 return file;
321} 321}
322 322
323
324void put_filp(struct file *file) 323void put_filp(struct file *file)
325{ 324{
326 if (atomic_long_dec_and_test(&file->f_count)) { 325 if (atomic_long_dec_and_test(&file->f_count)) {
327 security_file_free(file); 326 security_file_free(file);
328 file_kill(file); 327 file_sb_list_del(file);
329 file_free(file); 328 file_free(file);
330 } 329 }
331} 330}
332 331
333void file_move(struct file *file, struct list_head *list) 332void file_sb_list_add(struct file *file, struct super_block *sb)
334{ 333{
335 if (!list) 334 spinlock_t *lock;
336 return; 335 struct list_head *list;
337 file_list_lock(); 336#ifdef CONFIG_SMP
338 list_move(&file->f_u.fu_list, list); 337 int cpu;
339 file_list_unlock(); 338#endif
339
340 lock = &get_cpu_var(files_cpulock);
341#ifdef CONFIG_SMP
342 cpu = smp_processor_id();
343 list = per_cpu_ptr(sb->s_files, cpu);
344 file->f_sb_list_cpu = cpu;
345#else
346 list = &sb->s_files;
347#endif
348 put_cpu_var(files_cpulock);
349 spin_lock(lock);
350 BUG_ON(!list_empty(&file->f_u.fu_list));
351 list_add(&file->f_u.fu_list, list);
352 spin_unlock(lock);
340} 353}
341 354
342void file_kill(struct file *file) 355void file_sb_list_del(struct file *file)
343{ 356{
344 if (!list_empty(&file->f_u.fu_list)) { 357 if (!list_empty(&file->f_u.fu_list)) {
345 file_list_lock(); 358 spinlock_t *lock;
359
360#ifdef CONFIG_SMP
361 lock = &per_cpu(files_cpulock, file->f_sb_list_cpu);
362#else
363 lock = &__get_cpu_var(files_cpulock);
364#endif
365 spin_lock(lock);
346 list_del_init(&file->f_u.fu_list); 366 list_del_init(&file->f_u.fu_list);
347 file_list_unlock(); 367 spin_unlock(lock);
368 }
369}
370
371static void file_list_lock_all(void)
372{
373 int i;
374 int nr = 0;
375
376 for_each_possible_cpu(i) {
377 spinlock_t *lock;
378
379 lock = &per_cpu(files_cpulock, i);
380 spin_lock_nested(lock, nr);
381 nr++;
382 }
383}
384
385static void file_list_unlock_all(void)
386{
387 int i;
388
389 for_each_possible_cpu(i) {
390 spinlock_t *lock;
391
392 lock = &per_cpu(files_cpulock, i);
393 spin_unlock(lock);
348 } 394 }
349} 395}
350 396
351int fs_may_remount_ro(struct super_block *sb) 397int fs_may_remount_ro(struct super_block *sb)
352{ 398{
353 struct file *file; 399 int i;
354 400
355 /* Check that no files are currently opened for writing. */ 401 /* Check that no files are currently opened for writing. */
356 file_list_lock(); 402 file_list_lock_all();
357 list_for_each_entry(file, &sb->s_files, f_u.fu_list) { 403 for_each_possible_cpu(i) {
358 struct inode *inode = file->f_path.dentry->d_inode; 404 struct file *file;
405 struct list_head *list;
406
407#ifdef CONFIG_SMP
408 list = per_cpu_ptr(sb->s_files, i);
409#else
410 list = &sb->s_files;
411#endif
412 list_for_each_entry(file, list, f_u.fu_list) {
413 struct inode *inode = file->f_path.dentry->d_inode;
359 414
360 /* File with pending delete? */ 415 /* File with pending delete? */
361 if (inode->i_nlink == 0) 416 if (inode->i_nlink == 0)
362 goto too_bad; 417 goto too_bad;
363 418
364 /* Writeable file? */ 419 /* Writeable file? */
365 if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)) 420 if (S_ISREG(inode->i_mode) &&
366 goto too_bad; 421 (file->f_mode & FMODE_WRITE))
422 goto too_bad;
423 }
367 } 424 }
368 file_list_unlock(); 425 file_list_unlock_all();
369 return 1; /* Tis' cool bro. */ 426 return 1; /* Tis' cool bro. */
370too_bad: 427too_bad:
371 file_list_unlock(); 428 file_list_unlock_all();
372 return 0; 429 return 0;
373} 430}
374 431
@@ -381,40 +438,48 @@ too_bad:
381 */ 438 */
382void mark_files_ro(struct super_block *sb) 439void mark_files_ro(struct super_block *sb)
383{ 440{
384 struct file *f; 441 int i;
385 442
386retry: 443retry:
387 file_list_lock(); 444 file_list_lock_all();
388 list_for_each_entry(f, &sb->s_files, f_u.fu_list) { 445 for_each_possible_cpu(i) {
389 struct vfsmount *mnt; 446 struct file *f;
390 if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) 447 struct list_head *list;
391 continue; 448
392 if (!file_count(f)) 449#ifdef CONFIG_SMP
393 continue; 450 list = per_cpu_ptr(sb->s_files, i);
394 if (!(f->f_mode & FMODE_WRITE)) 451#else
395 continue; 452 list = &sb->s_files;
396 spin_lock(&f->f_lock); 453#endif
397 f->f_mode &= ~FMODE_WRITE; 454 list_for_each_entry(f, list, f_u.fu_list) {
398 spin_unlock(&f->f_lock); 455 struct vfsmount *mnt;
399 if (file_check_writeable(f) != 0) 456 if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
400 continue; 457 continue;
401 file_release_write(f); 458 if (!file_count(f))
402 mnt = mntget(f->f_path.mnt); 459 continue;
403 file_list_unlock(); 460 if (!(f->f_mode & FMODE_WRITE))
404 /* 461 continue;
405 * This can sleep, so we can't hold 462 spin_lock(&f->f_lock);
406 * the file_list_lock() spinlock. 463 f->f_mode &= ~FMODE_WRITE;
407 */ 464 spin_unlock(&f->f_lock);
408 mnt_drop_write(mnt); 465 if (file_check_writeable(f) != 0)
409 mntput(mnt); 466 continue;
410 goto retry; 467 file_release_write(f);
468 mnt = mntget(f->f_path.mnt);
469 /* This can sleep, so we can't hold the spinlock. */
470 file_list_unlock_all();
471 mnt_drop_write(mnt);
472 mntput(mnt);
473 goto retry;
474 }
411 } 475 }
412 file_list_unlock(); 476 file_list_unlock_all();
413} 477}
414 478
415void __init files_init(unsigned long mempages) 479void __init files_init(unsigned long mempages)
416{ 480{
417 int n; 481 int n;
482 int i;
418 483
419 filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, 484 filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
420 SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); 485 SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
@@ -429,5 +494,7 @@ void __init files_init(unsigned long mempages)
429 if (files_stat.max_files < NR_FILE) 494 if (files_stat.max_files < NR_FILE)
430 files_stat.max_files = NR_FILE; 495 files_stat.max_files = NR_FILE;
431 files_defer_init(); 496 files_defer_init();
497 for_each_possible_cpu(i)
498 spin_lock_init(&per_cpu(files_cpulock, i));
432 percpu_counter_init(&nr_files, 0); 499 percpu_counter_init(&nr_files, 0);
433} 500}