]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - fs/nilfs2/super.c
Merge branch 'for-2637/i2c-all' of git://git.fluff.org/bjdooks/linux
[net-next-2.6.git] / fs / nilfs2 / super.c
index a1cd444103ffca8c3fe61662951ec4b16d474bbc..f804d41ec9d3b2e253972beed4ecda1fc2daf2b9 100644 (file)
@@ -68,11 +68,12 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem "
                   "(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)
@@ -179,17 +180,9 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag)
 
  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]);
        }
@@ -439,6 +432,36 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
        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;
@@ -523,6 +546,8 @@ static const struct super_operations nilfs_sops = {
        .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,
@@ -626,7 +651,7 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi,
                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;
@@ -638,6 +663,9 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi)
        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);
 
@@ -654,9 +682,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_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);
@@ -872,6 +902,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
        struct the_nilfs *nilfs;
        struct nilfs_sb_info *sbi;
        struct nilfs_root *fsroot;
+       struct backing_dev_info *bdi;
        __u64 cno;
        int err;
 
@@ -910,7 +941,9 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
        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)
@@ -938,7 +971,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
 
        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);
        }
 
@@ -1034,7 +1067,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
                        goto restore_opts;
 
                down_write(&nilfs->ns_sem);
-               nilfs_setup_super(sbi);
+               nilfs_setup_super(sbi, true);
                up_write(&nilfs->ns_sem);
        }
  out:
@@ -1108,9 +1141,9 @@ static int nilfs_test_bdev_super(struct super_block *s, void *data)
        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;
@@ -1123,7 +1156,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
 
        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;
@@ -1132,7 +1165,19 @@ nilfs_get_sb(struct file_system_type *fs_type, int 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;
@@ -1190,9 +1235,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
        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);
@@ -1200,13 +1243,13 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
  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,
 };