"(NILFS)");
MODULE_LICENSE("GPL");
-struct kmem_cache *nilfs_inode_cachep;
+static struct kmem_cache *nilfs_inode_cachep;
struct kmem_cache *nilfs_transaction_cachep;
struct kmem_cache *nilfs_segbuf_cachep;
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 void nilfs_set_error(struct nilfs_sb_info *sbi)
retry:
set_buffer_dirty(nilfs->ns_sbh[0]);
-
if (nilfs_test_opt(sbi, BARRIER)) {
err = __sync_dirty_buffer(nilfs->ns_sbh[0],
- WRITE_SYNC | WRITE_BARRIER);
- if (err == -EOPNOTSUPP) {
- nilfs_warning(sbi->s_super, __func__,
- "barrier-based sync failed. "
- "disabling barriers\n");
- nilfs_clear_opt(sbi, BARRIER);
- goto retry;
- }
+ WRITE_SYNC | WRITE_FLUSH_FUA);
} else {
err = sync_dirty_buffer(nilfs->ns_sbh[0]);
}
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)
{
struct super_block *sb = dentry->d_sb;
.put_super = nilfs_put_super,
/* .write_super = nilfs_write_super, */
.sync_fs = nilfs_sync_fs,
+ .freeze_fs = nilfs_freeze,
+ .unfreeze_fs = nilfs_unfreeze,
/* .write_super_lockfs */
/* .unlockfs */
.statfs = nilfs_statfs,
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 nilfs_super_block **sbp;
if (!sbp)
return -EIO;
+ if (!is_mount)
+ goto skip_mount_setup;
+
max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count);
mnt_count = le16_to_cpu(sbp[0]->s_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_mtime = cpu_to_le64(get_seconds());
+
+skip_mount_setup:
sbp[0]->s_state =
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] */
memcpy(sbp[1], sbp[0], nilfs->ns_sbsize);
return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL);
struct the_nilfs *nilfs;
struct nilfs_sb_info *sbi;
struct nilfs_root *fsroot;
+ struct backing_dev_info *bdi;
__u64 cno;
int err;
sb->s_export_op = &nilfs_export_ops;
sb->s_root = NULL;
sb->s_time_gran = 1;
- sb->s_bdi = nilfs->ns_bdi;
+
+ bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
+ sb->s_bdi = bdi ? : &default_backing_dev_info;
err = load_nilfs(nilfs, sbi);
if (err)
if (!(sb->s_flags & MS_RDONLY)) {
down_write(&nilfs->ns_sem);
- nilfs_setup_super(sbi);
+ nilfs_setup_super(sbi, true);
up_write(&nilfs->ns_sem);
}
goto restore_opts;
down_write(&nilfs->ns_sem);
- nilfs_setup_super(sbi);
+ nilfs_setup_super(sbi, true);
up_write(&nilfs->ns_sem);
}
out:
return (void *)s->s_bdev == data;
}
-static int
-nilfs_get_sb(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *data, struct vfsmount *mnt)
+static struct dentry *
+nilfs_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data)
{
struct nilfs_super_data sd;
struct super_block *s;
sd.bdev = open_bdev_exclusive(dev_name, mode, fs_type);
if (IS_ERR(sd.bdev))
- return PTR_ERR(sd.bdev);
+ return ERR_CAST(sd.bdev);
sd.cno = 0;
sd.flags = flags;
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);
+ mutex_unlock(&sd.bdev->bd_fsfreeze_mutex);
if (IS_ERR(s)) {
err = PTR_ERR(s);
goto failed;
if (!s_new)
close_bdev_exclusive(sd.bdev, mode);
- mnt->mnt_sb = s;
- mnt->mnt_root = root_dentry;
- return 0;
+ return root_dentry;
failed_super:
deactivate_locked_super(s);
failed:
if (!s_new)
close_bdev_exclusive(sd.bdev, mode);
- return err;
+ return ERR_PTR(err);
}
struct file_system_type nilfs_fs_type = {
.owner = THIS_MODULE,
.name = "nilfs2",
- .get_sb = nilfs_get_sb,
+ .mount = nilfs_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};