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 | |
| 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>
| -rw-r--r-- | fs/nilfs2/ioctl.c | 2 | ||||
| -rw-r--r-- | fs/nilfs2/segment.c | 2 | ||||
| -rw-r--r-- | fs/nilfs2/super.c | 58 |
3 files changed, 58 insertions, 4 deletions
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 338858fc907c..3e90f86d5bfe 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
| @@ -580,6 +580,8 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
| 580 | goto out_free; | 580 | goto out_free; |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | ||
| 584 | |||
| 583 | ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); | 585 | ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); |
| 584 | if (ret < 0) | 586 | if (ret < 0) |
| 585 | printk(KERN_ERR "NILFS: GC failed during preparation: " | 587 | printk(KERN_ERR "NILFS: GC failed during preparation: " |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 56350bf1f79f..172ad4257494 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
| @@ -191,6 +191,8 @@ int nilfs_transaction_begin(struct super_block *sb, | |||
| 191 | if (ret > 0) | 191 | if (ret > 0) |
| 192 | return 0; | 192 | return 0; |
| 193 | 193 | ||
| 194 | vfs_check_frozen(sb, SB_FREEZE_WRITE); | ||
| 195 | |||
| 194 | sbi = NILFS_SB(sb); | 196 | sbi = NILFS_SB(sb); |
| 195 | nilfs = sbi->s_nilfs; | 197 | nilfs = sbi->s_nilfs; |
| 196 | down_read(&nilfs->ns_segctor_sem); | 198 | down_read(&nilfs->ns_segctor_sem); |
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; |
