diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-04 11:06:42 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-11-09 00:16:20 -0500 |
commit | eee5cc2702929fd41cce28058dc6d6717f723f87 (patch) | |
tree | d405e2302511adec7d25024679b8ac2cbd95d608 /fs | |
parent | 8b61e74ffc6310e1d35a9b51c8463093851f8bcf (diff) |
get rid of s_files and files_lock
The only thing we need it for is alt-sysrq-r (emergency remount r/o)
and these days we can do just as well without going through the
list of files.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/file_table.c | 125 | ||||
-rw-r--r-- | fs/internal.h | 3 | ||||
-rw-r--r-- | fs/open.c | 2 | ||||
-rw-r--r-- | fs/super.c | 15 |
4 files changed, 2 insertions, 143 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index e61e5529fa9d..23b6dca03ba0 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -36,8 +36,6 @@ struct files_stat_struct files_stat = { | |||
36 | .max_files = NR_FILE | 36 | .max_files = NR_FILE |
37 | }; | 37 | }; |
38 | 38 | ||
39 | DEFINE_STATIC_LGLOCK(files_lglock); | ||
40 | |||
41 | /* SLAB cache for file structures */ | 39 | /* SLAB cache for file structures */ |
42 | static struct kmem_cache *filp_cachep __read_mostly; | 40 | static struct kmem_cache *filp_cachep __read_mostly; |
43 | 41 | ||
@@ -134,7 +132,6 @@ struct file *get_empty_filp(void) | |||
134 | return ERR_PTR(error); | 132 | return ERR_PTR(error); |
135 | } | 133 | } |
136 | 134 | ||
137 | INIT_LIST_HEAD(&f->f_u.fu_list); | ||
138 | atomic_long_set(&f->f_count, 1); | 135 | atomic_long_set(&f->f_count, 1); |
139 | rwlock_init(&f->f_owner.lock); | 136 | rwlock_init(&f->f_owner.lock); |
140 | spin_lock_init(&f->f_lock); | 137 | spin_lock_init(&f->f_lock); |
@@ -304,7 +301,6 @@ void fput(struct file *file) | |||
304 | if (atomic_long_dec_and_test(&file->f_count)) { | 301 | if (atomic_long_dec_and_test(&file->f_count)) { |
305 | struct task_struct *task = current; | 302 | struct task_struct *task = current; |
306 | 303 | ||
307 | file_sb_list_del(file); | ||
308 | if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) { | 304 | if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) { |
309 | init_task_work(&file->f_u.fu_rcuhead, ____fput); | 305 | init_task_work(&file->f_u.fu_rcuhead, ____fput); |
310 | if (!task_work_add(task, &file->f_u.fu_rcuhead, true)) | 306 | if (!task_work_add(task, &file->f_u.fu_rcuhead, true)) |
@@ -333,7 +329,6 @@ void __fput_sync(struct file *file) | |||
333 | { | 329 | { |
334 | if (atomic_long_dec_and_test(&file->f_count)) { | 330 | if (atomic_long_dec_and_test(&file->f_count)) { |
335 | struct task_struct *task = current; | 331 | struct task_struct *task = current; |
336 | file_sb_list_del(file); | ||
337 | BUG_ON(!(task->flags & PF_KTHREAD)); | 332 | BUG_ON(!(task->flags & PF_KTHREAD)); |
338 | __fput(file); | 333 | __fput(file); |
339 | } | 334 | } |
@@ -345,129 +340,10 @@ void put_filp(struct file *file) | |||
345 | { | 340 | { |
346 | if (atomic_long_dec_and_test(&file->f_count)) { | 341 | if (atomic_long_dec_and_test(&file->f_count)) { |
347 | security_file_free(file); | 342 | security_file_free(file); |
348 | file_sb_list_del(file); | ||
349 | file_free(file); | 343 | file_free(file); |
350 | } | 344 | } |
351 | } | 345 | } |
352 | 346 | ||
353 | static inline int file_list_cpu(struct file *file) | ||
354 | { | ||
355 | #ifdef CONFIG_SMP | ||
356 | return file->f_sb_list_cpu; | ||
357 | #else | ||
358 | return smp_processor_id(); | ||
359 | #endif | ||
360 | } | ||
361 | |||
362 | /* helper for file_sb_list_add to reduce ifdefs */ | ||
363 | static inline void __file_sb_list_add(struct file *file, struct super_block *sb) | ||
364 | { | ||
365 | struct list_head *list; | ||
366 | #ifdef CONFIG_SMP | ||
367 | int cpu; | ||
368 | cpu = smp_processor_id(); | ||
369 | file->f_sb_list_cpu = cpu; | ||
370 | list = per_cpu_ptr(sb->s_files, cpu); | ||
371 | #else | ||
372 | list = &sb->s_files; | ||
373 | #endif | ||
374 | list_add(&file->f_u.fu_list, list); | ||
375 | } | ||
376 | |||
377 | /** | ||
378 | * file_sb_list_add - add a file to the sb's file list | ||
379 | * @file: file to add | ||
380 | * @sb: sb to add it to | ||
381 | * | ||
382 | * Use this function to associate a file with the superblock of the inode it | ||
383 | * refers to. | ||
384 | */ | ||
385 | void file_sb_list_add(struct file *file, struct super_block *sb) | ||
386 | { | ||
387 | if (likely(!(file->f_mode & FMODE_WRITE))) | ||
388 | return; | ||
389 | if (!S_ISREG(file_inode(file)->i_mode)) | ||
390 | return; | ||
391 | lg_local_lock(&files_lglock); | ||
392 | __file_sb_list_add(file, sb); | ||
393 | lg_local_unlock(&files_lglock); | ||
394 | } | ||
395 | |||
396 | /** | ||
397 | * file_sb_list_del - remove a file from the sb's file list | ||
398 | * @file: file to remove | ||
399 | * @sb: sb to remove it from | ||
400 | * | ||
401 | * Use this function to remove a file from its superblock. | ||
402 | */ | ||
403 | void file_sb_list_del(struct file *file) | ||
404 | { | ||
405 | if (!list_empty(&file->f_u.fu_list)) { | ||
406 | lg_local_lock_cpu(&files_lglock, file_list_cpu(file)); | ||
407 | list_del_init(&file->f_u.fu_list); | ||
408 | lg_local_unlock_cpu(&files_lglock, file_list_cpu(file)); | ||
409 | } | ||
410 | } | ||
411 | |||
412 | #ifdef CONFIG_SMP | ||
413 | |||
414 | /* | ||
415 | * These macros iterate all files on all CPUs for a given superblock. | ||
416 | * files_lglock must be held globally. | ||
417 | */ | ||
418 | #define do_file_list_for_each_entry(__sb, __file) \ | ||
419 | { \ | ||
420 | int i; \ | ||
421 | for_each_possible_cpu(i) { \ | ||
422 | struct list_head *list; \ | ||
423 | list = per_cpu_ptr((__sb)->s_files, i); \ | ||
424 | list_for_each_entry((__file), list, f_u.fu_list) | ||
425 | |||
426 | #define while_file_list_for_each_entry \ | ||
427 | } \ | ||
428 | } | ||
429 | |||
430 | #else | ||
431 | |||
432 | #define do_file_list_for_each_entry(__sb, __file) \ | ||
433 | { \ | ||
434 | struct list_head *list; \ | ||
435 | list = &(sb)->s_files; \ | ||
436 | list_for_each_entry((__file), list, f_u.fu_list) | ||
437 | |||
438 | #define while_file_list_for_each_entry \ | ||
439 | } | ||
440 | |||
441 | #endif | ||
442 | |||
443 | /** | ||
444 | * mark_files_ro - mark all files read-only | ||
445 | * @sb: superblock in question | ||
446 | * | ||
447 | * All files are marked read-only. We don't care about pending | ||
448 | * delete files so this should be used in 'force' mode only. | ||
449 | */ | ||
450 | void mark_files_ro(struct super_block *sb) | ||
451 | { | ||
452 | struct file *f; | ||
453 | |||
454 | lg_global_lock(&files_lglock); | ||
455 | do_file_list_for_each_entry(sb, f) { | ||
456 | if (!file_count(f)) | ||
457 | continue; | ||
458 | if (!(f->f_mode & FMODE_WRITE)) | ||
459 | continue; | ||
460 | spin_lock(&f->f_lock); | ||
461 | f->f_mode &= ~FMODE_WRITE; | ||
462 | spin_unlock(&f->f_lock); | ||
463 | if (file_check_writeable(f) != 0) | ||
464 | continue; | ||
465 | __mnt_drop_write(f->f_path.mnt); | ||
466 | file_release_write(f); | ||
467 | } while_file_list_for_each_entry; | ||
468 | lg_global_unlock(&files_lglock); | ||
469 | } | ||
470 | |||
471 | void __init files_init(unsigned long mempages) | 347 | void __init files_init(unsigned long mempages) |
472 | { | 348 | { |
473 | unsigned long n; | 349 | unsigned long n; |
@@ -483,6 +359,5 @@ void __init files_init(unsigned long mempages) | |||
483 | n = (mempages * (PAGE_SIZE / 1024)) / 10; | 359 | n = (mempages * (PAGE_SIZE / 1024)) / 10; |
484 | files_stat.max_files = max_t(unsigned long, n, NR_FILE); | 360 | files_stat.max_files = max_t(unsigned long, n, NR_FILE); |
485 | files_defer_init(); | 361 | files_defer_init(); |
486 | lg_lock_init(&files_lglock, "files_lglock"); | ||
487 | percpu_counter_init(&nr_files, 0); | 362 | percpu_counter_init(&nr_files, 0); |
488 | } | 363 | } |
diff --git a/fs/internal.h b/fs/internal.h index 4a11e75ce14d..465742407466 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -73,9 +73,6 @@ extern void chroot_fs_refs(const struct path *, const struct path *); | |||
73 | /* | 73 | /* |
74 | * file_table.c | 74 | * file_table.c |
75 | */ | 75 | */ |
76 | extern void file_sb_list_add(struct file *f, struct super_block *sb); | ||
77 | extern void file_sb_list_del(struct file *f); | ||
78 | extern void mark_files_ro(struct super_block *); | ||
79 | extern struct file *get_empty_filp(void); | 76 | extern struct file *get_empty_filp(void); |
80 | 77 | ||
81 | /* | 78 | /* |
@@ -685,7 +685,6 @@ static int do_dentry_open(struct file *f, | |||
685 | } | 685 | } |
686 | 686 | ||
687 | f->f_mapping = inode->i_mapping; | 687 | f->f_mapping = inode->i_mapping; |
688 | file_sb_list_add(f, inode->i_sb); | ||
689 | 688 | ||
690 | if (unlikely(f->f_mode & FMODE_PATH)) { | 689 | if (unlikely(f->f_mode & FMODE_PATH)) { |
691 | f->f_op = &empty_fops; | 690 | f->f_op = &empty_fops; |
@@ -724,7 +723,6 @@ static int do_dentry_open(struct file *f, | |||
724 | 723 | ||
725 | cleanup_all: | 724 | cleanup_all: |
726 | fops_put(f->f_op); | 725 | fops_put(f->f_op); |
727 | file_sb_list_del(f); | ||
728 | if (f->f_mode & FMODE_WRITE) { | 726 | if (f->f_mode & FMODE_WRITE) { |
729 | put_write_access(inode); | 727 | put_write_access(inode); |
730 | if (!special_file(inode->i_mode)) { | 728 | if (!special_file(inode->i_mode)) { |
diff --git a/fs/super.c b/fs/super.c index 743bb7118053..e5f6c2cfac38 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -140,9 +140,6 @@ static void destroy_super(struct super_block *s) | |||
140 | int i; | 140 | int i; |
141 | list_lru_destroy(&s->s_dentry_lru); | 141 | list_lru_destroy(&s->s_dentry_lru); |
142 | list_lru_destroy(&s->s_inode_lru); | 142 | list_lru_destroy(&s->s_inode_lru); |
143 | #ifdef CONFIG_SMP | ||
144 | free_percpu(s->s_files); | ||
145 | #endif | ||
146 | for (i = 0; i < SB_FREEZE_LEVELS; i++) | 143 | for (i = 0; i < SB_FREEZE_LEVELS; i++) |
147 | percpu_counter_destroy(&s->s_writers.counter[i]); | 144 | percpu_counter_destroy(&s->s_writers.counter[i]); |
148 | security_sb_free(s); | 145 | security_sb_free(s); |
@@ -172,15 +169,6 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
172 | if (security_sb_alloc(s)) | 169 | if (security_sb_alloc(s)) |
173 | goto fail; | 170 | goto fail; |
174 | 171 | ||
175 | #ifdef CONFIG_SMP | ||
176 | s->s_files = alloc_percpu(struct list_head); | ||
177 | if (!s->s_files) | ||
178 | goto fail; | ||
179 | for_each_possible_cpu(i) | ||
180 | INIT_LIST_HEAD(per_cpu_ptr(s->s_files, i)); | ||
181 | #else | ||
182 | INIT_LIST_HEAD(&s->s_files); | ||
183 | #endif | ||
184 | for (i = 0; i < SB_FREEZE_LEVELS; i++) { | 172 | for (i = 0; i < SB_FREEZE_LEVELS; i++) { |
185 | if (percpu_counter_init(&s->s_writers.counter[i], 0) < 0) | 173 | if (percpu_counter_init(&s->s_writers.counter[i], 0) < 0) |
186 | goto fail; | 174 | goto fail; |
@@ -722,7 +710,8 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
722 | make sure there are no rw files opened */ | 710 | make sure there are no rw files opened */ |
723 | if (remount_ro) { | 711 | if (remount_ro) { |
724 | if (force) { | 712 | if (force) { |
725 | mark_files_ro(sb); | 713 | sb->s_readonly_remount = 1; |
714 | smp_wmb(); | ||
726 | } else { | 715 | } else { |
727 | retval = sb_prepare_remount_readonly(sb); | 716 | retval = sb_prepare_remount_readonly(sb); |
728 | if (retval) | 717 | if (retval) |