]> Pileus Git - ~andy/linux/blobdiff - fs/logfs/super.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide-2.6
[~andy/linux] / fs / logfs / super.c
index 94d80f7ee7c220d8535a699077a1322d219fbc88..b60bfac3263c71d688532ef5d434e04220d87aa2 100644 (file)
@@ -11,6 +11,7 @@
  */
 #include "logfs.h"
 #include <linux/bio.h>
+#include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/statfs.h>
 #include <linux/buffer_head.h>
@@ -277,7 +278,7 @@ static int logfs_recover_sb(struct super_block *sb)
        }
        if (valid0 && valid1 && ds_cmp(ds0, ds1)) {
                printk(KERN_INFO"Superblocks don't match - fixing.\n");
-               return write_one_sb(sb, super->s_devops->find_last_sb);
+               return logfs_write_sb(sb);
        }
        /* If neither is valid now, something's wrong.  Didn't we properly
         * check them before?!? */
@@ -289,6 +290,10 @@ static int logfs_make_writeable(struct super_block *sb)
 {
        int err;
 
+       err = logfs_open_segfile(sb);
+       if (err)
+               return err;
+
        /* Repair any broken superblock copies */
        err = logfs_recover_sb(sb);
        if (err)
@@ -299,10 +304,6 @@ static int logfs_make_writeable(struct super_block *sb)
        if (err)
                return err;
 
-       err = logfs_open_segfile(sb);
-       if (err)
-               return err;
-
        /* Do one GC pass before any data gets dirtied */
        logfs_gc_pass(sb);
 
@@ -328,7 +329,7 @@ static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt)
 
        sb->s_root = d_alloc_root(rootdir);
        if (!sb->s_root)
-               goto fail;
+               goto fail2;
 
        super->s_erase_page = alloc_pages(GFP_KERNEL, 0);
        if (!super->s_erase_page)
@@ -440,7 +441,7 @@ static int __logfs_read_sb(struct super_block *sb)
        return 0;
 }
 
-static int logfs_read_sb(struct super_block *sb)
+static int logfs_read_sb(struct super_block *sb, int read_only)
 {
        struct logfs_super *super = logfs_super(sb);
        int ret;
@@ -460,6 +461,12 @@ static int logfs_read_sb(struct super_block *sb)
        if (ret)
                return ret;
 
+       if (super->s_feature_incompat & ~LOGFS_FEATURES_INCOMPAT)
+               return -EIO;
+       if ((super->s_feature_ro_compat & ~LOGFS_FEATURES_RO_COMPAT) &&
+                       !read_only)
+               return -EIO;
+
        mutex_init(&super->s_dirop_mutex);
        mutex_init(&super->s_object_alias_mutex);
        INIT_LIST_HEAD(&super->s_freeing_list);
@@ -490,7 +497,7 @@ static void logfs_kill_sb(struct super_block *sb)
        log_super("LogFS: Start unmounting\n");
        /* Alias entries slow down mount, so evict as many as possible */
        sync_filesystem(sb);
-       logfs_write_anchor(super->s_master_inode);
+       logfs_write_anchor(sb);
 
        /*
         * From this point on alias entries are simply dropped - and any
@@ -555,7 +562,7 @@ int logfs_get_sb_device(struct file_system_type *type, int flags,
        sb->s_op        = &logfs_super_operations;
        sb->s_flags     = flags | MS_NOATIME;
 
-       err = logfs_read_sb(sb);
+       err = logfs_read_sb(sb, sb->s_flags & MS_RDONLY);
        if (err)
                goto err1;
 
@@ -566,8 +573,7 @@ int logfs_get_sb_device(struct file_system_type *type, int flags,
        return 0;
 
 err1:
-       up_write(&sb->s_umount);
-       deactivate_super(sb);
+       deactivate_locked_super(sb);
        return err;
 err0:
        kfree(super);