diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-12 15:28:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-12 15:28:32 -0400 |
commit | 7214dd4ea9048d2031e14fc552980cecd6573a9e (patch) | |
tree | 18c9ba52d252d29fcfe7d73d9c78205b285f91d0 /fs | |
parent | 19e8a2f875a56009c0ce30389964aca452a85510 (diff) | |
parent | 08fdc8a0138afaf324296a342f32ad26ec465e43 (diff) |
Merge branch 'work.thaw' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs thaw updates from Al Viro:
"An ancient series that has fallen through the cracks in the previous
cycle"
* 'work.thaw' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
buffer.c: call thaw_super during emergency thaw
vfs: factor sb iteration out of do_emergency_remount
Diffstat (limited to 'fs')
-rw-r--r-- | fs/buffer.c | 25 | ||||
-rw-r--r-- | fs/super.c | 105 |
2 files changed, 79 insertions, 51 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index f3491074b035..249b83fafe48 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -494,35 +494,12 @@ repeat: | |||
494 | return err; | 494 | return err; |
495 | } | 495 | } |
496 | 496 | ||
497 | static void do_thaw_one(struct super_block *sb, void *unused) | 497 | void emergency_thaw_bdev(struct super_block *sb) |
498 | { | 498 | { |
499 | while (sb->s_bdev && !thaw_bdev(sb->s_bdev, sb)) | 499 | while (sb->s_bdev && !thaw_bdev(sb->s_bdev, sb)) |
500 | printk(KERN_WARNING "Emergency Thaw on %pg\n", sb->s_bdev); | 500 | printk(KERN_WARNING "Emergency Thaw on %pg\n", sb->s_bdev); |
501 | } | 501 | } |
502 | 502 | ||
503 | static void do_thaw_all(struct work_struct *work) | ||
504 | { | ||
505 | iterate_supers(do_thaw_one, NULL); | ||
506 | kfree(work); | ||
507 | printk(KERN_WARNING "Emergency Thaw complete\n"); | ||
508 | } | ||
509 | |||
510 | /** | ||
511 | * emergency_thaw_all -- forcibly thaw every frozen filesystem | ||
512 | * | ||
513 | * Used for emergency unfreeze of all filesystems via SysRq | ||
514 | */ | ||
515 | void emergency_thaw_all(void) | ||
516 | { | ||
517 | struct work_struct *work; | ||
518 | |||
519 | work = kmalloc(sizeof(*work), GFP_ATOMIC); | ||
520 | if (work) { | ||
521 | INIT_WORK(work, do_thaw_all); | ||
522 | schedule_work(work); | ||
523 | } | ||
524 | } | ||
525 | |||
526 | /** | 503 | /** |
527 | * sync_mapping_buffers - write out & wait upon a mapping's "associated" buffers | 504 | * sync_mapping_buffers - write out & wait upon a mapping's "associated" buffers |
528 | * @mapping: the mapping which wants those buffers written | 505 | * @mapping: the mapping which wants those buffers written |
diff --git a/fs/super.c b/fs/super.c index 672538ca9831..5fa9a8d8d865 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/user_namespace.h> | 37 | #include <linux/user_namespace.h> |
38 | #include "internal.h" | 38 | #include "internal.h" |
39 | 39 | ||
40 | static int thaw_super_locked(struct super_block *sb); | ||
40 | 41 | ||
41 | static LIST_HEAD(super_blocks); | 42 | static LIST_HEAD(super_blocks); |
42 | static DEFINE_SPINLOCK(sb_lock); | 43 | static DEFINE_SPINLOCK(sb_lock); |
@@ -574,6 +575,28 @@ void drop_super_exclusive(struct super_block *sb) | |||
574 | } | 575 | } |
575 | EXPORT_SYMBOL(drop_super_exclusive); | 576 | EXPORT_SYMBOL(drop_super_exclusive); |
576 | 577 | ||
578 | static void __iterate_supers(void (*f)(struct super_block *)) | ||
579 | { | ||
580 | struct super_block *sb, *p = NULL; | ||
581 | |||
582 | spin_lock(&sb_lock); | ||
583 | list_for_each_entry(sb, &super_blocks, s_list) { | ||
584 | if (hlist_unhashed(&sb->s_instances)) | ||
585 | continue; | ||
586 | sb->s_count++; | ||
587 | spin_unlock(&sb_lock); | ||
588 | |||
589 | f(sb); | ||
590 | |||
591 | spin_lock(&sb_lock); | ||
592 | if (p) | ||
593 | __put_super(p); | ||
594 | p = sb; | ||
595 | } | ||
596 | if (p) | ||
597 | __put_super(p); | ||
598 | spin_unlock(&sb_lock); | ||
599 | } | ||
577 | /** | 600 | /** |
578 | * iterate_supers - call function for all active superblocks | 601 | * iterate_supers - call function for all active superblocks |
579 | * @f: function to call | 602 | * @f: function to call |
@@ -881,33 +904,22 @@ cancel_readonly: | |||
881 | return retval; | 904 | return retval; |
882 | } | 905 | } |
883 | 906 | ||
884 | static void do_emergency_remount(struct work_struct *work) | 907 | static void do_emergency_remount_callback(struct super_block *sb) |
885 | { | 908 | { |
886 | struct super_block *sb, *p = NULL; | 909 | down_write(&sb->s_umount); |
887 | 910 | if (sb->s_root && sb->s_bdev && (sb->s_flags & SB_BORN) && | |
888 | spin_lock(&sb_lock); | 911 | !sb_rdonly(sb)) { |
889 | list_for_each_entry(sb, &super_blocks, s_list) { | 912 | /* |
890 | if (hlist_unhashed(&sb->s_instances)) | 913 | * What lock protects sb->s_flags?? |
891 | continue; | 914 | */ |
892 | sb->s_count++; | 915 | do_remount_sb(sb, SB_RDONLY, NULL, 1); |
893 | spin_unlock(&sb_lock); | ||
894 | down_write(&sb->s_umount); | ||
895 | if (sb->s_root && sb->s_bdev && (sb->s_flags & SB_BORN) && | ||
896 | !sb_rdonly(sb)) { | ||
897 | /* | ||
898 | * What lock protects sb->s_flags?? | ||
899 | */ | ||
900 | do_remount_sb(sb, SB_RDONLY, NULL, 1); | ||
901 | } | ||
902 | up_write(&sb->s_umount); | ||
903 | spin_lock(&sb_lock); | ||
904 | if (p) | ||
905 | __put_super(p); | ||
906 | p = sb; | ||
907 | } | 916 | } |
908 | if (p) | 917 | up_write(&sb->s_umount); |
909 | __put_super(p); | 918 | } |
910 | spin_unlock(&sb_lock); | 919 | |
920 | static void do_emergency_remount(struct work_struct *work) | ||
921 | { | ||
922 | __iterate_supers(do_emergency_remount_callback); | ||
911 | kfree(work); | 923 | kfree(work); |
912 | printk("Emergency Remount complete\n"); | 924 | printk("Emergency Remount complete\n"); |
913 | } | 925 | } |
@@ -923,6 +935,40 @@ void emergency_remount(void) | |||
923 | } | 935 | } |
924 | } | 936 | } |
925 | 937 | ||
938 | static void do_thaw_all_callback(struct super_block *sb) | ||
939 | { | ||
940 | down_write(&sb->s_umount); | ||
941 | if (sb->s_root && sb->s_flags & MS_BORN) { | ||
942 | emergency_thaw_bdev(sb); | ||
943 | thaw_super_locked(sb); | ||
944 | } else { | ||
945 | up_write(&sb->s_umount); | ||
946 | } | ||
947 | } | ||
948 | |||
949 | static void do_thaw_all(struct work_struct *work) | ||
950 | { | ||
951 | __iterate_supers(do_thaw_all_callback); | ||
952 | kfree(work); | ||
953 | printk(KERN_WARNING "Emergency Thaw complete\n"); | ||
954 | } | ||
955 | |||
956 | /** | ||
957 | * emergency_thaw_all -- forcibly thaw every frozen filesystem | ||
958 | * | ||
959 | * Used for emergency unfreeze of all filesystems via SysRq | ||
960 | */ | ||
961 | void emergency_thaw_all(void) | ||
962 | { | ||
963 | struct work_struct *work; | ||
964 | |||
965 | work = kmalloc(sizeof(*work), GFP_ATOMIC); | ||
966 | if (work) { | ||
967 | INIT_WORK(work, do_thaw_all); | ||
968 | schedule_work(work); | ||
969 | } | ||
970 | } | ||
971 | |||
926 | /* | 972 | /* |
927 | * Unnamed block devices are dummy devices used by virtual | 973 | * Unnamed block devices are dummy devices used by virtual |
928 | * filesystems which don't use real block-devices. -- jrs | 974 | * filesystems which don't use real block-devices. -- jrs |
@@ -1492,11 +1538,10 @@ EXPORT_SYMBOL(freeze_super); | |||
1492 | * | 1538 | * |
1493 | * Unlocks the filesystem and marks it writeable again after freeze_super(). | 1539 | * Unlocks the filesystem and marks it writeable again after freeze_super(). |
1494 | */ | 1540 | */ |
1495 | int thaw_super(struct super_block *sb) | 1541 | static int thaw_super_locked(struct super_block *sb) |
1496 | { | 1542 | { |
1497 | int error; | 1543 | int error; |
1498 | 1544 | ||
1499 | down_write(&sb->s_umount); | ||
1500 | if (sb->s_writers.frozen != SB_FREEZE_COMPLETE) { | 1545 | if (sb->s_writers.frozen != SB_FREEZE_COMPLETE) { |
1501 | up_write(&sb->s_umount); | 1546 | up_write(&sb->s_umount); |
1502 | return -EINVAL; | 1547 | return -EINVAL; |
@@ -1527,4 +1572,10 @@ out: | |||
1527 | deactivate_locked_super(sb); | 1572 | deactivate_locked_super(sb); |
1528 | return 0; | 1573 | return 0; |
1529 | } | 1574 | } |
1575 | |||
1576 | int thaw_super(struct super_block *sb) | ||
1577 | { | ||
1578 | down_write(&sb->s_umount); | ||
1579 | return thaw_super_locked(sb); | ||
1580 | } | ||
1530 | EXPORT_SYMBOL(thaw_super); | 1581 | EXPORT_SYMBOL(thaw_super); |