diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-09-20 05:19:06 -0400 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-10-22 20:24:39 -0400 |
commit | 5beb6e0b2008386571fd342d0a4a14f5c8c0baf8 (patch) | |
tree | b5b86e48c3fe5041ce495ca9bee2e5f93f788293 /fs/nilfs2/super.c | |
parent | c05dbfc2609993ccc067879579e2a7726e12b3f1 (diff) |
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>
Diffstat (limited to 'fs/nilfs2/super.c')
-rw-r--r-- | fs/nilfs2/super.c | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index a1cd444103ff..92e8c769584c 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -73,6 +73,7 @@ struct kmem_cache *nilfs_transaction_cachep; | |||
73 | struct kmem_cache *nilfs_segbuf_cachep; | 73 | struct kmem_cache *nilfs_segbuf_cachep; |
74 | struct kmem_cache *nilfs_btree_path_cache; | 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 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); | 77 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); |
77 | 78 | ||
78 | static void nilfs_set_error(struct nilfs_sb_info *sbi) | 79 | static void nilfs_set_error(struct nilfs_sb_info *sbi) |
@@ -439,6 +440,36 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, | |||
439 | return err; | 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 | static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 473 | static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
443 | { | 474 | { |
444 | struct super_block *sb = dentry->d_sb; | 475 | struct super_block *sb = dentry->d_sb; |
@@ -523,6 +554,8 @@ static const struct super_operations nilfs_sops = { | |||
523 | .put_super = nilfs_put_super, | 554 | .put_super = nilfs_put_super, |
524 | /* .write_super = nilfs_write_super, */ | 555 | /* .write_super = nilfs_write_super, */ |
525 | .sync_fs = nilfs_sync_fs, | 556 | .sync_fs = nilfs_sync_fs, |
557 | .freeze_fs = nilfs_freeze, | ||
558 | .unfreeze_fs = nilfs_unfreeze, | ||
526 | /* .write_super_lockfs */ | 559 | /* .write_super_lockfs */ |
527 | /* .unlockfs */ | 560 | /* .unlockfs */ |
528 | .statfs = nilfs_statfs, | 561 | .statfs = nilfs_statfs, |
@@ -626,7 +659,7 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi, | |||
626 | NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; | 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 | struct the_nilfs *nilfs = sbi->s_nilfs; | 664 | struct the_nilfs *nilfs = sbi->s_nilfs; |
632 | struct nilfs_super_block **sbp; | 665 | struct nilfs_super_block **sbp; |
@@ -638,6 +671,9 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) | |||
638 | if (!sbp) | 671 | if (!sbp) |
639 | return -EIO; | 672 | return -EIO; |
640 | 673 | ||
674 | if (!is_mount) | ||
675 | goto skip_mount_setup; | ||
676 | |||
641 | max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count); | 677 | max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count); |
642 | mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); | 678 | mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); |
643 | 679 | ||
@@ -654,9 +690,11 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) | |||
654 | sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); | 690 | sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); |
655 | 691 | ||
656 | sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1); | 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 | sbp[0]->s_state = | 696 | sbp[0]->s_state = |
658 | cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS); | 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 | /* synchronize sbp[1] with sbp[0] */ | 698 | /* synchronize sbp[1] with sbp[0] */ |
661 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | 699 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); |
662 | return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); | 700 | return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); |
@@ -938,7 +976,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) | |||
938 | 976 | ||
939 | if (!(sb->s_flags & MS_RDONLY)) { | 977 | if (!(sb->s_flags & MS_RDONLY)) { |
940 | down_write(&nilfs->ns_sem); | 978 | down_write(&nilfs->ns_sem); |
941 | nilfs_setup_super(sbi); | 979 | nilfs_setup_super(sbi, true); |
942 | up_write(&nilfs->ns_sem); | 980 | up_write(&nilfs->ns_sem); |
943 | } | 981 | } |
944 | 982 | ||
@@ -1034,7 +1072,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
1034 | goto restore_opts; | 1072 | goto restore_opts; |
1035 | 1073 | ||
1036 | down_write(&nilfs->ns_sem); | 1074 | down_write(&nilfs->ns_sem); |
1037 | nilfs_setup_super(sbi); | 1075 | nilfs_setup_super(sbi, true); |
1038 | up_write(&nilfs->ns_sem); | 1076 | up_write(&nilfs->ns_sem); |
1039 | } | 1077 | } |
1040 | out: | 1078 | out: |
@@ -1132,7 +1170,19 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1132 | goto failed; | 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 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev); | 1184 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev); |
1185 | mutex_unlock(&sd.bdev->bd_fsfreeze_mutex); | ||
1136 | if (IS_ERR(s)) { | 1186 | if (IS_ERR(s)) { |
1137 | err = PTR_ERR(s); | 1187 | err = PTR_ERR(s); |
1138 | goto failed; | 1188 | goto failed; |