diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 70 |
1 files changed, 45 insertions, 25 deletions
diff --git a/fs/super.c b/fs/super.c index afd0f1ad45e0..de41e1e46f09 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -136,12 +136,13 @@ static struct super_block *alloc_super(struct file_system_type *type) | |||
136 | INIT_LIST_HEAD(&s->s_files); | 136 | INIT_LIST_HEAD(&s->s_files); |
137 | #endif | 137 | #endif |
138 | s->s_bdi = &default_backing_dev_info; | 138 | s->s_bdi = &default_backing_dev_info; |
139 | INIT_LIST_HEAD(&s->s_instances); | 139 | INIT_HLIST_NODE(&s->s_instances); |
140 | INIT_HLIST_BL_HEAD(&s->s_anon); | 140 | INIT_HLIST_BL_HEAD(&s->s_anon); |
141 | INIT_LIST_HEAD(&s->s_inodes); | 141 | INIT_LIST_HEAD(&s->s_inodes); |
142 | INIT_LIST_HEAD(&s->s_dentry_lru); | 142 | INIT_LIST_HEAD(&s->s_dentry_lru); |
143 | INIT_LIST_HEAD(&s->s_inode_lru); | 143 | INIT_LIST_HEAD(&s->s_inode_lru); |
144 | spin_lock_init(&s->s_inode_lru_lock); | 144 | spin_lock_init(&s->s_inode_lru_lock); |
145 | INIT_LIST_HEAD(&s->s_mounts); | ||
145 | init_rwsem(&s->s_umount); | 146 | init_rwsem(&s->s_umount); |
146 | mutex_init(&s->s_lock); | 147 | mutex_init(&s->s_lock); |
147 | lockdep_set_class(&s->s_umount, &type->s_umount_key); | 148 | lockdep_set_class(&s->s_umount, &type->s_umount_key); |
@@ -200,6 +201,7 @@ static inline void destroy_super(struct super_block *s) | |||
200 | free_percpu(s->s_files); | 201 | free_percpu(s->s_files); |
201 | #endif | 202 | #endif |
202 | security_sb_free(s); | 203 | security_sb_free(s); |
204 | WARN_ON(!list_empty(&s->s_mounts)); | ||
203 | kfree(s->s_subtype); | 205 | kfree(s->s_subtype); |
204 | kfree(s->s_options); | 206 | kfree(s->s_options); |
205 | kfree(s); | 207 | kfree(s); |
@@ -210,7 +212,7 @@ static inline void destroy_super(struct super_block *s) | |||
210 | /* | 212 | /* |
211 | * Drop a superblock's refcount. The caller must hold sb_lock. | 213 | * Drop a superblock's refcount. The caller must hold sb_lock. |
212 | */ | 214 | */ |
213 | void __put_super(struct super_block *sb) | 215 | static void __put_super(struct super_block *sb) |
214 | { | 216 | { |
215 | if (!--sb->s_count) { | 217 | if (!--sb->s_count) { |
216 | list_del_init(&sb->s_list); | 218 | list_del_init(&sb->s_list); |
@@ -225,7 +227,7 @@ void __put_super(struct super_block *sb) | |||
225 | * Drops a temporary reference, frees superblock if there's no | 227 | * Drops a temporary reference, frees superblock if there's no |
226 | * references left. | 228 | * references left. |
227 | */ | 229 | */ |
228 | void put_super(struct super_block *sb) | 230 | static void put_super(struct super_block *sb) |
229 | { | 231 | { |
230 | spin_lock(&sb_lock); | 232 | spin_lock(&sb_lock); |
231 | __put_super(sb); | 233 | __put_super(sb); |
@@ -328,7 +330,7 @@ static int grab_super(struct super_block *s) __releases(sb_lock) | |||
328 | bool grab_super_passive(struct super_block *sb) | 330 | bool grab_super_passive(struct super_block *sb) |
329 | { | 331 | { |
330 | spin_lock(&sb_lock); | 332 | spin_lock(&sb_lock); |
331 | if (list_empty(&sb->s_instances)) { | 333 | if (hlist_unhashed(&sb->s_instances)) { |
332 | spin_unlock(&sb_lock); | 334 | spin_unlock(&sb_lock); |
333 | return false; | 335 | return false; |
334 | } | 336 | } |
@@ -337,7 +339,7 @@ bool grab_super_passive(struct super_block *sb) | |||
337 | spin_unlock(&sb_lock); | 339 | spin_unlock(&sb_lock); |
338 | 340 | ||
339 | if (down_read_trylock(&sb->s_umount)) { | 341 | if (down_read_trylock(&sb->s_umount)) { |
340 | if (sb->s_root) | 342 | if (sb->s_root && (sb->s_flags & MS_BORN)) |
341 | return true; | 343 | return true; |
342 | up_read(&sb->s_umount); | 344 | up_read(&sb->s_umount); |
343 | } | 345 | } |
@@ -400,7 +402,7 @@ void generic_shutdown_super(struct super_block *sb) | |||
400 | } | 402 | } |
401 | spin_lock(&sb_lock); | 403 | spin_lock(&sb_lock); |
402 | /* should be initialized for __put_super_and_need_restart() */ | 404 | /* should be initialized for __put_super_and_need_restart() */ |
403 | list_del_init(&sb->s_instances); | 405 | hlist_del_init(&sb->s_instances); |
404 | spin_unlock(&sb_lock); | 406 | spin_unlock(&sb_lock); |
405 | up_write(&sb->s_umount); | 407 | up_write(&sb->s_umount); |
406 | } | 408 | } |
@@ -420,13 +422,14 @@ struct super_block *sget(struct file_system_type *type, | |||
420 | void *data) | 422 | void *data) |
421 | { | 423 | { |
422 | struct super_block *s = NULL; | 424 | struct super_block *s = NULL; |
425 | struct hlist_node *node; | ||
423 | struct super_block *old; | 426 | struct super_block *old; |
424 | int err; | 427 | int err; |
425 | 428 | ||
426 | retry: | 429 | retry: |
427 | spin_lock(&sb_lock); | 430 | spin_lock(&sb_lock); |
428 | if (test) { | 431 | if (test) { |
429 | list_for_each_entry(old, &type->fs_supers, s_instances) { | 432 | hlist_for_each_entry(old, node, &type->fs_supers, s_instances) { |
430 | if (!test(old, data)) | 433 | if (!test(old, data)) |
431 | continue; | 434 | continue; |
432 | if (!grab_super(old)) | 435 | if (!grab_super(old)) |
@@ -462,7 +465,7 @@ retry: | |||
462 | s->s_type = type; | 465 | s->s_type = type; |
463 | strlcpy(s->s_id, type->name, sizeof(s->s_id)); | 466 | strlcpy(s->s_id, type->name, sizeof(s->s_id)); |
464 | list_add_tail(&s->s_list, &super_blocks); | 467 | list_add_tail(&s->s_list, &super_blocks); |
465 | list_add(&s->s_instances, &type->fs_supers); | 468 | hlist_add_head(&s->s_instances, &type->fs_supers); |
466 | spin_unlock(&sb_lock); | 469 | spin_unlock(&sb_lock); |
467 | get_filesystem(type); | 470 | get_filesystem(type); |
468 | register_shrinker(&s->s_shrink); | 471 | register_shrinker(&s->s_shrink); |
@@ -497,14 +500,14 @@ void sync_supers(void) | |||
497 | 500 | ||
498 | spin_lock(&sb_lock); | 501 | spin_lock(&sb_lock); |
499 | list_for_each_entry(sb, &super_blocks, s_list) { | 502 | list_for_each_entry(sb, &super_blocks, s_list) { |
500 | if (list_empty(&sb->s_instances)) | 503 | if (hlist_unhashed(&sb->s_instances)) |
501 | continue; | 504 | continue; |
502 | if (sb->s_op->write_super && sb->s_dirt) { | 505 | if (sb->s_op->write_super && sb->s_dirt) { |
503 | sb->s_count++; | 506 | sb->s_count++; |
504 | spin_unlock(&sb_lock); | 507 | spin_unlock(&sb_lock); |
505 | 508 | ||
506 | down_read(&sb->s_umount); | 509 | down_read(&sb->s_umount); |
507 | if (sb->s_root && sb->s_dirt) | 510 | if (sb->s_root && sb->s_dirt && (sb->s_flags & MS_BORN)) |
508 | sb->s_op->write_super(sb); | 511 | sb->s_op->write_super(sb); |
509 | up_read(&sb->s_umount); | 512 | up_read(&sb->s_umount); |
510 | 513 | ||
@@ -533,13 +536,13 @@ void iterate_supers(void (*f)(struct super_block *, void *), void *arg) | |||
533 | 536 | ||
534 | spin_lock(&sb_lock); | 537 | spin_lock(&sb_lock); |
535 | list_for_each_entry(sb, &super_blocks, s_list) { | 538 | list_for_each_entry(sb, &super_blocks, s_list) { |
536 | if (list_empty(&sb->s_instances)) | 539 | if (hlist_unhashed(&sb->s_instances)) |
537 | continue; | 540 | continue; |
538 | sb->s_count++; | 541 | sb->s_count++; |
539 | spin_unlock(&sb_lock); | 542 | spin_unlock(&sb_lock); |
540 | 543 | ||
541 | down_read(&sb->s_umount); | 544 | down_read(&sb->s_umount); |
542 | if (sb->s_root) | 545 | if (sb->s_root && (sb->s_flags & MS_BORN)) |
543 | f(sb, arg); | 546 | f(sb, arg); |
544 | up_read(&sb->s_umount); | 547 | up_read(&sb->s_umount); |
545 | 548 | ||
@@ -566,14 +569,15 @@ void iterate_supers_type(struct file_system_type *type, | |||
566 | void (*f)(struct super_block *, void *), void *arg) | 569 | void (*f)(struct super_block *, void *), void *arg) |
567 | { | 570 | { |
568 | struct super_block *sb, *p = NULL; | 571 | struct super_block *sb, *p = NULL; |
572 | struct hlist_node *node; | ||
569 | 573 | ||
570 | spin_lock(&sb_lock); | 574 | spin_lock(&sb_lock); |
571 | list_for_each_entry(sb, &type->fs_supers, s_instances) { | 575 | hlist_for_each_entry(sb, node, &type->fs_supers, s_instances) { |
572 | sb->s_count++; | 576 | sb->s_count++; |
573 | spin_unlock(&sb_lock); | 577 | spin_unlock(&sb_lock); |
574 | 578 | ||
575 | down_read(&sb->s_umount); | 579 | down_read(&sb->s_umount); |
576 | if (sb->s_root) | 580 | if (sb->s_root && (sb->s_flags & MS_BORN)) |
577 | f(sb, arg); | 581 | f(sb, arg); |
578 | up_read(&sb->s_umount); | 582 | up_read(&sb->s_umount); |
579 | 583 | ||
@@ -607,14 +611,14 @@ struct super_block *get_super(struct block_device *bdev) | |||
607 | spin_lock(&sb_lock); | 611 | spin_lock(&sb_lock); |
608 | rescan: | 612 | rescan: |
609 | list_for_each_entry(sb, &super_blocks, s_list) { | 613 | list_for_each_entry(sb, &super_blocks, s_list) { |
610 | if (list_empty(&sb->s_instances)) | 614 | if (hlist_unhashed(&sb->s_instances)) |
611 | continue; | 615 | continue; |
612 | if (sb->s_bdev == bdev) { | 616 | if (sb->s_bdev == bdev) { |
613 | sb->s_count++; | 617 | sb->s_count++; |
614 | spin_unlock(&sb_lock); | 618 | spin_unlock(&sb_lock); |
615 | down_read(&sb->s_umount); | 619 | down_read(&sb->s_umount); |
616 | /* still alive? */ | 620 | /* still alive? */ |
617 | if (sb->s_root) | 621 | if (sb->s_root && (sb->s_flags & MS_BORN)) |
618 | return sb; | 622 | return sb; |
619 | up_read(&sb->s_umount); | 623 | up_read(&sb->s_umount); |
620 | /* nope, got unmounted */ | 624 | /* nope, got unmounted */ |
@@ -647,7 +651,7 @@ struct super_block *get_active_super(struct block_device *bdev) | |||
647 | restart: | 651 | restart: |
648 | spin_lock(&sb_lock); | 652 | spin_lock(&sb_lock); |
649 | list_for_each_entry(sb, &super_blocks, s_list) { | 653 | list_for_each_entry(sb, &super_blocks, s_list) { |
650 | if (list_empty(&sb->s_instances)) | 654 | if (hlist_unhashed(&sb->s_instances)) |
651 | continue; | 655 | continue; |
652 | if (sb->s_bdev == bdev) { | 656 | if (sb->s_bdev == bdev) { |
653 | if (grab_super(sb)) /* drops sb_lock */ | 657 | if (grab_super(sb)) /* drops sb_lock */ |
@@ -667,14 +671,14 @@ struct super_block *user_get_super(dev_t dev) | |||
667 | spin_lock(&sb_lock); | 671 | spin_lock(&sb_lock); |
668 | rescan: | 672 | rescan: |
669 | list_for_each_entry(sb, &super_blocks, s_list) { | 673 | list_for_each_entry(sb, &super_blocks, s_list) { |
670 | if (list_empty(&sb->s_instances)) | 674 | if (hlist_unhashed(&sb->s_instances)) |
671 | continue; | 675 | continue; |
672 | if (sb->s_dev == dev) { | 676 | if (sb->s_dev == dev) { |
673 | sb->s_count++; | 677 | sb->s_count++; |
674 | spin_unlock(&sb_lock); | 678 | spin_unlock(&sb_lock); |
675 | down_read(&sb->s_umount); | 679 | down_read(&sb->s_umount); |
676 | /* still alive? */ | 680 | /* still alive? */ |
677 | if (sb->s_root) | 681 | if (sb->s_root && (sb->s_flags & MS_BORN)) |
678 | return sb; | 682 | return sb; |
679 | up_read(&sb->s_umount); | 683 | up_read(&sb->s_umount); |
680 | /* nope, got unmounted */ | 684 | /* nope, got unmounted */ |
@@ -719,23 +723,29 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
719 | /* If we are remounting RDONLY and current sb is read/write, | 723 | /* If we are remounting RDONLY and current sb is read/write, |
720 | make sure there are no rw files opened */ | 724 | make sure there are no rw files opened */ |
721 | if (remount_ro) { | 725 | if (remount_ro) { |
722 | if (force) | 726 | if (force) { |
723 | mark_files_ro(sb); | 727 | mark_files_ro(sb); |
724 | else if (!fs_may_remount_ro(sb)) | 728 | } else { |
725 | return -EBUSY; | 729 | retval = sb_prepare_remount_readonly(sb); |
730 | if (retval) | ||
731 | return retval; | ||
732 | } | ||
726 | } | 733 | } |
727 | 734 | ||
728 | if (sb->s_op->remount_fs) { | 735 | if (sb->s_op->remount_fs) { |
729 | retval = sb->s_op->remount_fs(sb, &flags, data); | 736 | retval = sb->s_op->remount_fs(sb, &flags, data); |
730 | if (retval) { | 737 | if (retval) { |
731 | if (!force) | 738 | if (!force) |
732 | return retval; | 739 | goto cancel_readonly; |
733 | /* If forced remount, go ahead despite any errors */ | 740 | /* If forced remount, go ahead despite any errors */ |
734 | WARN(1, "forced remount of a %s fs returned %i\n", | 741 | WARN(1, "forced remount of a %s fs returned %i\n", |
735 | sb->s_type->name, retval); | 742 | sb->s_type->name, retval); |
736 | } | 743 | } |
737 | } | 744 | } |
738 | sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); | 745 | sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); |
746 | /* Needs to be ordered wrt mnt_is_readonly() */ | ||
747 | smp_wmb(); | ||
748 | sb->s_readonly_remount = 0; | ||
739 | 749 | ||
740 | /* | 750 | /* |
741 | * Some filesystems modify their metadata via some other path than the | 751 | * Some filesystems modify their metadata via some other path than the |
@@ -748,6 +758,10 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
748 | if (remount_ro && sb->s_bdev) | 758 | if (remount_ro && sb->s_bdev) |
749 | invalidate_bdev(sb->s_bdev); | 759 | invalidate_bdev(sb->s_bdev); |
750 | return 0; | 760 | return 0; |
761 | |||
762 | cancel_readonly: | ||
763 | sb->s_readonly_remount = 0; | ||
764 | return retval; | ||
751 | } | 765 | } |
752 | 766 | ||
753 | static void do_emergency_remount(struct work_struct *work) | 767 | static void do_emergency_remount(struct work_struct *work) |
@@ -756,12 +770,13 @@ static void do_emergency_remount(struct work_struct *work) | |||
756 | 770 | ||
757 | spin_lock(&sb_lock); | 771 | spin_lock(&sb_lock); |
758 | list_for_each_entry(sb, &super_blocks, s_list) { | 772 | list_for_each_entry(sb, &super_blocks, s_list) { |
759 | if (list_empty(&sb->s_instances)) | 773 | if (hlist_unhashed(&sb->s_instances)) |
760 | continue; | 774 | continue; |
761 | sb->s_count++; | 775 | sb->s_count++; |
762 | spin_unlock(&sb_lock); | 776 | spin_unlock(&sb_lock); |
763 | down_write(&sb->s_umount); | 777 | down_write(&sb->s_umount); |
764 | if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY)) { | 778 | if (sb->s_root && sb->s_bdev && (sb->s_flags & MS_BORN) && |
779 | !(sb->s_flags & MS_RDONLY)) { | ||
765 | /* | 780 | /* |
766 | * What lock protects sb->s_flags?? | 781 | * What lock protects sb->s_flags?? |
767 | */ | 782 | */ |
@@ -1144,6 +1159,11 @@ int freeze_super(struct super_block *sb) | |||
1144 | return -EBUSY; | 1159 | return -EBUSY; |
1145 | } | 1160 | } |
1146 | 1161 | ||
1162 | if (!(sb->s_flags & MS_BORN)) { | ||
1163 | up_write(&sb->s_umount); | ||
1164 | return 0; /* sic - it's "nothing to do" */ | ||
1165 | } | ||
1166 | |||
1147 | if (sb->s_flags & MS_RDONLY) { | 1167 | if (sb->s_flags & MS_RDONLY) { |
1148 | sb->s_frozen = SB_FREEZE_TRANS; | 1168 | sb->s_frozen = SB_FREEZE_TRANS; |
1149 | smp_wmb(); | 1169 | smp_wmb(); |