aboutsummaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c69
1 files changed, 54 insertions, 15 deletions
diff --git a/fs/super.c b/fs/super.c
index 938119ab8dcb..8819e3a7ff20 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -54,7 +54,22 @@ static struct super_block *alloc_super(struct file_system_type *type)
54 s = NULL; 54 s = NULL;
55 goto out; 55 goto out;
56 } 56 }
57#ifdef CONFIG_SMP
58 s->s_files = alloc_percpu(struct list_head);
59 if (!s->s_files) {
60 security_sb_free(s);
61 kfree(s);
62 s = NULL;
63 goto out;
64 } else {
65 int i;
66
67 for_each_possible_cpu(i)
68 INIT_LIST_HEAD(per_cpu_ptr(s->s_files, i));
69 }
70#else
57 INIT_LIST_HEAD(&s->s_files); 71 INIT_LIST_HEAD(&s->s_files);
72#endif
58 INIT_LIST_HEAD(&s->s_instances); 73 INIT_LIST_HEAD(&s->s_instances);
59 INIT_HLIST_HEAD(&s->s_anon); 74 INIT_HLIST_HEAD(&s->s_anon);
60 INIT_LIST_HEAD(&s->s_inodes); 75 INIT_LIST_HEAD(&s->s_inodes);
@@ -108,6 +123,9 @@ out:
108 */ 123 */
109static inline void destroy_super(struct super_block *s) 124static inline void destroy_super(struct super_block *s)
110{ 125{
126#ifdef CONFIG_SMP
127 free_percpu(s->s_files);
128#endif
111 security_sb_free(s); 129 security_sb_free(s);
112 kfree(s->s_subtype); 130 kfree(s->s_subtype);
113 kfree(s->s_options); 131 kfree(s->s_options);
@@ -305,8 +323,13 @@ retry:
305 if (s) { 323 if (s) {
306 up_write(&s->s_umount); 324 up_write(&s->s_umount);
307 destroy_super(s); 325 destroy_super(s);
326 s = NULL;
308 } 327 }
309 down_write(&old->s_umount); 328 down_write(&old->s_umount);
329 if (unlikely(!(old->s_flags & MS_BORN))) {
330 deactivate_locked_super(old);
331 goto retry;
332 }
310 return old; 333 return old;
311 } 334 }
312 } 335 }
@@ -358,10 +381,10 @@ EXPORT_SYMBOL(drop_super);
358 */ 381 */
359void sync_supers(void) 382void sync_supers(void)
360{ 383{
361 struct super_block *sb, *n; 384 struct super_block *sb, *p = NULL;
362 385
363 spin_lock(&sb_lock); 386 spin_lock(&sb_lock);
364 list_for_each_entry_safe(sb, n, &super_blocks, s_list) { 387 list_for_each_entry(sb, &super_blocks, s_list) {
365 if (list_empty(&sb->s_instances)) 388 if (list_empty(&sb->s_instances))
366 continue; 389 continue;
367 if (sb->s_op->write_super && sb->s_dirt) { 390 if (sb->s_op->write_super && sb->s_dirt) {
@@ -374,11 +397,13 @@ void sync_supers(void)
374 up_read(&sb->s_umount); 397 up_read(&sb->s_umount);
375 398
376 spin_lock(&sb_lock); 399 spin_lock(&sb_lock);
377 /* lock was dropped, must reset next */ 400 if (p)
378 list_safe_reset_next(sb, n, s_list); 401 __put_super(p);
379 __put_super(sb); 402 p = sb;
380 } 403 }
381 } 404 }
405 if (p)
406 __put_super(p);
382 spin_unlock(&sb_lock); 407 spin_unlock(&sb_lock);
383} 408}
384 409
@@ -392,10 +417,10 @@ void sync_supers(void)
392 */ 417 */
393void iterate_supers(void (*f)(struct super_block *, void *), void *arg) 418void iterate_supers(void (*f)(struct super_block *, void *), void *arg)
394{ 419{
395 struct super_block *sb, *n; 420 struct super_block *sb, *p = NULL;
396 421
397 spin_lock(&sb_lock); 422 spin_lock(&sb_lock);
398 list_for_each_entry_safe(sb, n, &super_blocks, s_list) { 423 list_for_each_entry(sb, &super_blocks, s_list) {
399 if (list_empty(&sb->s_instances)) 424 if (list_empty(&sb->s_instances))
400 continue; 425 continue;
401 sb->s_count++; 426 sb->s_count++;
@@ -407,10 +432,12 @@ void iterate_supers(void (*f)(struct super_block *, void *), void *arg)
407 up_read(&sb->s_umount); 432 up_read(&sb->s_umount);
408 433
409 spin_lock(&sb_lock); 434 spin_lock(&sb_lock);
410 /* lock was dropped, must reset next */ 435 if (p)
411 list_safe_reset_next(sb, n, s_list); 436 __put_super(p);
412 __put_super(sb); 437 p = sb;
413 } 438 }
439 if (p)
440 __put_super(p);
414 spin_unlock(&sb_lock); 441 spin_unlock(&sb_lock);
415} 442}
416 443
@@ -572,10 +599,10 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
572 599
573static void do_emergency_remount(struct work_struct *work) 600static void do_emergency_remount(struct work_struct *work)
574{ 601{
575 struct super_block *sb, *n; 602 struct super_block *sb, *p = NULL;
576 603
577 spin_lock(&sb_lock); 604 spin_lock(&sb_lock);
578 list_for_each_entry_safe(sb, n, &super_blocks, s_list) { 605 list_for_each_entry(sb, &super_blocks, s_list) {
579 if (list_empty(&sb->s_instances)) 606 if (list_empty(&sb->s_instances))
580 continue; 607 continue;
581 sb->s_count++; 608 sb->s_count++;
@@ -589,10 +616,12 @@ static void do_emergency_remount(struct work_struct *work)
589 } 616 }
590 up_write(&sb->s_umount); 617 up_write(&sb->s_umount);
591 spin_lock(&sb_lock); 618 spin_lock(&sb_lock);
592 /* lock was dropped, must reset next */ 619 if (p)
593 list_safe_reset_next(sb, n, s_list); 620 __put_super(p);
594 __put_super(sb); 621 p = sb;
595 } 622 }
623 if (p)
624 __put_super(p);
596 spin_unlock(&sb_lock); 625 spin_unlock(&sb_lock);
597 kfree(work); 626 kfree(work);
598 printk("Emergency Remount complete\n"); 627 printk("Emergency Remount complete\n");
@@ -773,7 +802,16 @@ int get_sb_bdev(struct file_system_type *fs_type,
773 goto error_bdev; 802 goto error_bdev;
774 } 803 }
775 804
805 /*
806 * s_umount nests inside bd_mutex during
807 * __invalidate_device(). close_bdev_exclusive()
808 * acquires bd_mutex and can't be called under
809 * s_umount. Drop s_umount temporarily. This is safe
810 * as we're holding an active reference.
811 */
812 up_write(&s->s_umount);
776 close_bdev_exclusive(bdev, mode); 813 close_bdev_exclusive(bdev, mode);
814 down_write(&s->s_umount);
777 } else { 815 } else {
778 char b[BDEVNAME_SIZE]; 816 char b[BDEVNAME_SIZE];
779 817
@@ -909,6 +947,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
909 goto out_free_secdata; 947 goto out_free_secdata;
910 BUG_ON(!mnt->mnt_sb); 948 BUG_ON(!mnt->mnt_sb);
911 WARN_ON(!mnt->mnt_sb->s_bdi); 949 WARN_ON(!mnt->mnt_sb->s_bdi);
950 mnt->mnt_sb->s_flags |= MS_BORN;
912 951
913 error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); 952 error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
914 if (error) 953 if (error)