Commit 5beb6e0b2008386571fd342d0a4a14f5c8c0baf8
1 parent
c05dbfc260
Exists in
master
and in
7 other branches
nilfs2: add bdev freeze/thaw support
Nilfs hasn't supported the freeze/thaw feature because it didn't work due to the peculiar design that multiple super block instances could be allocated for a device. This limitation was removed by the patch "nilfs2: do not allocate multiple super block instances for a device". So now this adds the freeze/thaw support to nilfs. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Showing 3 changed files with 58 additions and 4 deletions Side-by-side Diff
fs/nilfs2/ioctl.c
fs/nilfs2/segment.c
fs/nilfs2/super.c
... | ... | @@ -73,6 +73,7 @@ |
73 | 73 | struct kmem_cache *nilfs_segbuf_cachep; |
74 | 74 | struct kmem_cache *nilfs_btree_path_cache; |
75 | 75 | |
76 | +static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount); | |
76 | 77 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); |
77 | 78 | |
78 | 79 | static void nilfs_set_error(struct nilfs_sb_info *sbi) |
... | ... | @@ -439,6 +440,36 @@ |
439 | 440 | return err; |
440 | 441 | } |
441 | 442 | |
443 | +static int nilfs_freeze(struct super_block *sb) | |
444 | +{ | |
445 | + struct nilfs_sb_info *sbi = NILFS_SB(sb); | |
446 | + struct the_nilfs *nilfs = sbi->s_nilfs; | |
447 | + int err; | |
448 | + | |
449 | + if (sb->s_flags & MS_RDONLY) | |
450 | + return 0; | |
451 | + | |
452 | + /* Mark super block clean */ | |
453 | + down_write(&nilfs->ns_sem); | |
454 | + err = nilfs_cleanup_super(sbi); | |
455 | + up_write(&nilfs->ns_sem); | |
456 | + return err; | |
457 | +} | |
458 | + | |
459 | +static int nilfs_unfreeze(struct super_block *sb) | |
460 | +{ | |
461 | + struct nilfs_sb_info *sbi = NILFS_SB(sb); | |
462 | + struct the_nilfs *nilfs = sbi->s_nilfs; | |
463 | + | |
464 | + if (sb->s_flags & MS_RDONLY) | |
465 | + return 0; | |
466 | + | |
467 | + down_write(&nilfs->ns_sem); | |
468 | + nilfs_setup_super(sbi, false); | |
469 | + up_write(&nilfs->ns_sem); | |
470 | + return 0; | |
471 | +} | |
472 | + | |
442 | 473 | static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
443 | 474 | { |
444 | 475 | struct super_block *sb = dentry->d_sb; |
... | ... | @@ -523,6 +554,8 @@ |
523 | 554 | .put_super = nilfs_put_super, |
524 | 555 | /* .write_super = nilfs_write_super, */ |
525 | 556 | .sync_fs = nilfs_sync_fs, |
557 | + .freeze_fs = nilfs_freeze, | |
558 | + .unfreeze_fs = nilfs_unfreeze, | |
526 | 559 | /* .write_super_lockfs */ |
527 | 560 | /* .unlockfs */ |
528 | 561 | .statfs = nilfs_statfs, |
... | ... | @@ -626,7 +659,7 @@ |
626 | 659 | NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; |
627 | 660 | } |
628 | 661 | |
629 | -static int nilfs_setup_super(struct nilfs_sb_info *sbi) | |
662 | +static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount) | |
630 | 663 | { |
631 | 664 | struct the_nilfs *nilfs = sbi->s_nilfs; |
632 | 665 | struct nilfs_super_block **sbp; |
... | ... | @@ -638,6 +671,9 @@ |
638 | 671 | if (!sbp) |
639 | 672 | return -EIO; |
640 | 673 | |
674 | + if (!is_mount) | |
675 | + goto skip_mount_setup; | |
676 | + | |
641 | 677 | max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count); |
642 | 678 | mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); |
643 | 679 | |
644 | 680 | |
... | ... | @@ -654,9 +690,11 @@ |
654 | 690 | sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); |
655 | 691 | |
656 | 692 | sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1); |
693 | + sbp[0]->s_mtime = cpu_to_le64(get_seconds()); | |
694 | + | |
695 | +skip_mount_setup: | |
657 | 696 | sbp[0]->s_state = |
658 | 697 | cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS); |
659 | - sbp[0]->s_mtime = cpu_to_le64(get_seconds()); | |
660 | 698 | /* synchronize sbp[1] with sbp[0] */ |
661 | 699 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); |
662 | 700 | return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); |
... | ... | @@ -938,7 +976,7 @@ |
938 | 976 | |
939 | 977 | if (!(sb->s_flags & MS_RDONLY)) { |
940 | 978 | down_write(&nilfs->ns_sem); |
941 | - nilfs_setup_super(sbi); | |
979 | + nilfs_setup_super(sbi, true); | |
942 | 980 | up_write(&nilfs->ns_sem); |
943 | 981 | } |
944 | 982 | |
... | ... | @@ -1034,7 +1072,7 @@ |
1034 | 1072 | goto restore_opts; |
1035 | 1073 | |
1036 | 1074 | down_write(&nilfs->ns_sem); |
1037 | - nilfs_setup_super(sbi); | |
1075 | + nilfs_setup_super(sbi, true); | |
1038 | 1076 | up_write(&nilfs->ns_sem); |
1039 | 1077 | } |
1040 | 1078 | out: |
1041 | 1079 | |
... | ... | @@ -1132,7 +1170,19 @@ |
1132 | 1170 | goto failed; |
1133 | 1171 | } |
1134 | 1172 | |
1173 | + /* | |
1174 | + * once the super is inserted into the list by sget, s_umount | |
1175 | + * will protect the lockfs code from trying to start a snapshot | |
1176 | + * while we are mounting | |
1177 | + */ | |
1178 | + mutex_lock(&sd.bdev->bd_fsfreeze_mutex); | |
1179 | + if (sd.bdev->bd_fsfreeze_count > 0) { | |
1180 | + mutex_unlock(&sd.bdev->bd_fsfreeze_mutex); | |
1181 | + err = -EBUSY; | |
1182 | + goto failed; | |
1183 | + } | |
1135 | 1184 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev); |
1185 | + mutex_unlock(&sd.bdev->bd_fsfreeze_mutex); | |
1136 | 1186 | if (IS_ERR(s)) { |
1137 | 1187 | err = PTR_ERR(s); |
1138 | 1188 | goto failed; |