Commit 5beb6e0b authored by Ryusuke Konishi's avatar Ryusuke Konishi

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: default avatarRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
parent c05dbfc2
...@@ -580,6 +580,8 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, ...@@ -580,6 +580,8 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
goto out_free; goto out_free;
} }
vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]);
if (ret < 0) if (ret < 0)
printk(KERN_ERR "NILFS: GC failed during preparation: " printk(KERN_ERR "NILFS: GC failed during preparation: "
......
...@@ -191,6 +191,8 @@ int nilfs_transaction_begin(struct super_block *sb, ...@@ -191,6 +191,8 @@ int nilfs_transaction_begin(struct super_block *sb,
if (ret > 0) if (ret > 0)
return 0; return 0;
vfs_check_frozen(sb, SB_FREEZE_WRITE);
sbi = NILFS_SB(sb); sbi = NILFS_SB(sb);
nilfs = sbi->s_nilfs; nilfs = sbi->s_nilfs;
down_read(&nilfs->ns_segctor_sem); down_read(&nilfs->ns_segctor_sem);
......
...@@ -73,6 +73,7 @@ struct kmem_cache *nilfs_transaction_cachep; ...@@ -73,6 +73,7 @@ struct kmem_cache *nilfs_transaction_cachep;
struct kmem_cache *nilfs_segbuf_cachep; struct kmem_cache *nilfs_segbuf_cachep;
struct kmem_cache *nilfs_btree_path_cache; struct kmem_cache *nilfs_btree_path_cache;
static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount);
static int nilfs_remount(struct super_block *sb, int *flags, char *data); static int nilfs_remount(struct super_block *sb, int *flags, char *data);
static void nilfs_set_error(struct nilfs_sb_info *sbi) 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,6 +440,36 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
return err; return err;
} }
static int nilfs_freeze(struct super_block *sb)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs;
int err;
if (sb->s_flags & MS_RDONLY)
return 0;
/* Mark super block clean */
down_write(&nilfs->ns_sem);
err = nilfs_cleanup_super(sbi);
up_write(&nilfs->ns_sem);
return err;
}
static int nilfs_unfreeze(struct super_block *sb)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs;
if (sb->s_flags & MS_RDONLY)
return 0;
down_write(&nilfs->ns_sem);
nilfs_setup_super(sbi, false);
up_write(&nilfs->ns_sem);
return 0;
}
static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct super_block *sb = dentry->d_sb; struct super_block *sb = dentry->d_sb;
...@@ -523,6 +554,8 @@ static const struct super_operations nilfs_sops = { ...@@ -523,6 +554,8 @@ static const struct super_operations nilfs_sops = {
.put_super = nilfs_put_super, .put_super = nilfs_put_super,
/* .write_super = nilfs_write_super, */ /* .write_super = nilfs_write_super, */
.sync_fs = nilfs_sync_fs, .sync_fs = nilfs_sync_fs,
.freeze_fs = nilfs_freeze,
.unfreeze_fs = nilfs_unfreeze,
/* .write_super_lockfs */ /* .write_super_lockfs */
/* .unlockfs */ /* .unlockfs */
.statfs = nilfs_statfs, .statfs = nilfs_statfs,
...@@ -626,7 +659,7 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi, ...@@ -626,7 +659,7 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi,
NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER;
} }
static int nilfs_setup_super(struct nilfs_sb_info *sbi) static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount)
{ {
struct the_nilfs *nilfs = sbi->s_nilfs; struct the_nilfs *nilfs = sbi->s_nilfs;
struct nilfs_super_block **sbp; struct nilfs_super_block **sbp;
...@@ -638,6 +671,9 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) ...@@ -638,6 +671,9 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi)
if (!sbp) if (!sbp)
return -EIO; return -EIO;
if (!is_mount)
goto skip_mount_setup;
max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count); max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count);
mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); mnt_count = le16_to_cpu(sbp[0]->s_mnt_count);
...@@ -654,9 +690,11 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) ...@@ -654,9 +690,11 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi)
sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT);
sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1); sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1);
sbp[0]->s_mtime = cpu_to_le64(get_seconds());
skip_mount_setup:
sbp[0]->s_state = sbp[0]->s_state =
cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS); cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS);
sbp[0]->s_mtime = cpu_to_le64(get_seconds());
/* synchronize sbp[1] with sbp[0] */ /* synchronize sbp[1] with sbp[0] */
memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); memcpy(sbp[1], sbp[0], nilfs->ns_sbsize);
return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); 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,7 +976,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
nilfs_setup_super(sbi); nilfs_setup_super(sbi, true);
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
} }
...@@ -1034,7 +1072,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1034,7 +1072,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
goto restore_opts; goto restore_opts;
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
nilfs_setup_super(sbi); nilfs_setup_super(sbi, true);
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
} }
out: out:
...@@ -1132,7 +1170,19 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, ...@@ -1132,7 +1170,19 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
goto failed; goto failed;
} }
/*
* once the super is inserted into the list by sget, s_umount
* will protect the lockfs code from trying to start a snapshot
* while we are mounting
*/
mutex_lock(&sd.bdev->bd_fsfreeze_mutex);
if (sd.bdev->bd_fsfreeze_count > 0) {
mutex_unlock(&sd.bdev->bd_fsfreeze_mutex);
err = -EBUSY;
goto failed;
}
s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev); s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev);
mutex_unlock(&sd.bdev->bd_fsfreeze_mutex);
if (IS_ERR(s)) { if (IS_ERR(s)) {
err = PTR_ERR(s); err = PTR_ERR(s);
goto failed; goto failed;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment