aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-09-20 05:19:06 -0400
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-10-22 20:24:39 -0400
commit5beb6e0b2008386571fd342d0a4a14f5c8c0baf8 (patch)
treeb5b86e48c3fe5041ce495ca9bee2e5f93f788293 /fs
parentc05dbfc2609993ccc067879579e2a7726e12b3f1 (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')
-rw-r--r--fs/nilfs2/ioctl.c2
-rw-r--r--fs/nilfs2/segment.c2
-rw-r--r--fs/nilfs2/super.c58
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;
73struct kmem_cache *nilfs_segbuf_cachep; 73struct kmem_cache *nilfs_segbuf_cachep;
74struct kmem_cache *nilfs_btree_path_cache; 74struct kmem_cache *nilfs_btree_path_cache;
75 75
76static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount);
76static int nilfs_remount(struct super_block *sb, int *flags, char *data); 77static int nilfs_remount(struct super_block *sb, int *flags, char *data);
77 78
78static void nilfs_set_error(struct nilfs_sb_info *sbi) 79static 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
443static 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
459static 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
442static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) 473static 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
629static int nilfs_setup_super(struct nilfs_sb_info *sbi) 662static 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
695skip_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;