]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/ext4/super.c
Merge branch 'linux-2.6'
[mv-sheeva.git] / fs / ext4 / super.c
index 64fc7f1117344e66dabe080fc25ae0b8cfd7b6e1..055a0cd0168e5029ee87bb3ce8c55153fae3b171 100644 (file)
@@ -503,6 +503,7 @@ static void ext4_put_super (struct super_block * sb)
        struct ext4_super_block *es = sbi->s_es;
        int i;
 
+       ext4_mb_release(sb);
        ext4_ext_release(sb);
        ext4_xattr_put_super(sb);
        jbd2_journal_destroy(sbi->s_journal);
@@ -569,6 +570,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        ei->i_block_alloc_info = NULL;
        ei->vfs_inode.i_version = 1;
        memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
+       INIT_LIST_HEAD(&ei->i_prealloc_list);
+       spin_lock_init(&ei->i_prealloc_lock);
        return &ei->vfs_inode;
 }
 
@@ -733,9 +736,13 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
                seq_puts(seq, ",nobh");
        if (!test_opt(sb, EXTENTS))
                seq_puts(seq, ",noextents");
+       if (!test_opt(sb, MBALLOC))
+               seq_puts(seq, ",nomballoc");
        if (test_opt(sb, I_VERSION))
                seq_puts(seq, ",i_version");
 
+       if (sbi->s_stripe)
+               seq_printf(seq, ",stripe=%lu", sbi->s_stripe);
        /*
         * journal mode get enabled in different ways
         * So just print the value even if we didn't specify it
@@ -881,6 +888,7 @@ enum {
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
        Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
        Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version,
+       Opt_mballoc, Opt_nomballoc, Opt_stripe,
 };
 
 static match_table_t tokens = {
@@ -935,6 +943,9 @@ static match_table_t tokens = {
        {Opt_extents, "extents"},
        {Opt_noextents, "noextents"},
        {Opt_i_version, "i_version"},
+       {Opt_mballoc, "mballoc"},
+       {Opt_nomballoc, "nomballoc"},
+       {Opt_stripe, "stripe=%u"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
 };
@@ -1284,6 +1295,19 @@ clear_qf_name:
                        set_opt(sbi->s_mount_opt, I_VERSION);
                        sb->s_flags |= MS_I_VERSION;
                        break;
+               case Opt_mballoc:
+                       set_opt(sbi->s_mount_opt, MBALLOC);
+                       break;
+               case Opt_nomballoc:
+                       clear_opt(sbi->s_mount_opt, MBALLOC);
+                       break;
+               case Opt_stripe:
+                       if (match_int(&args[0], &option))
+                               return 0;
+                       if (option < 0)
+                               return 0;
+                       sbi->s_stripe = option;
+                       break;
                default:
                        printk (KERN_ERR
                                "EXT4-fs: Unrecognized mount option \"%s\" "
@@ -1742,6 +1766,34 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb,
        return (has_super + ext4_group_first_block_no(sb, bg));
 }
 
+/**
+ * ext4_get_stripe_size: Get the stripe size.
+ * @sbi: In memory super block info
+ *
+ * If we have specified it via mount option, then
+ * use the mount option value. If the value specified at mount time is
+ * greater than the blocks per group use the super block value.
+ * If the super block value is greater than blocks per group return 0.
+ * Allocator needs it be less than blocks per group.
+ *
+ */
+static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi)
+{
+       unsigned long stride = le16_to_cpu(sbi->s_es->s_raid_stride);
+       unsigned long stripe_width =
+                       le32_to_cpu(sbi->s_es->s_raid_stripe_width);
+
+       if (sbi->s_stripe && sbi->s_stripe <= sbi->s_blocks_per_group)
+               return sbi->s_stripe;
+
+       if (stripe_width <= sbi->s_blocks_per_group)
+               return stripe_width;
+
+       if (stride <= sbi->s_blocks_per_group)
+               return stride;
+
+       return 0;
+}
 
 static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                                __releases(kernel_sem)
@@ -1760,7 +1812,6 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        unsigned long def_mount_opts;
        struct inode *root;
        int blocksize;
-       int hblock;
        int db_count;
        int i;
        int needs_recovery;
@@ -1855,6 +1906,11 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
         * User -o noextents to turn it off
         */
        set_opt(sbi->s_mount_opt, EXTENTS);
+       /*
+        * turn on mballoc feature by default in ext4 filesystem
+        * User -o nomballoc to turn it off
+        */
+       set_opt(sbi->s_mount_opt, MBALLOC);
 
        if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
                            NULL, 0))
@@ -1912,20 +1968,16 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
-       hblock = bdev_hardsect_size(sb->s_bdev);
        if (sb->s_blocksize != blocksize) {
-               /*
-                * Make sure the blocksize for the filesystem is larger
-                * than the hardware sectorsize for the machine.
-                */
-               if (blocksize < hblock) {
-                       printk(KERN_ERR "EXT4-fs: blocksize %d too small for "
-                              "device blocksize %d.\n", blocksize, hblock);
+
+               /* Validate the filesystem blocksize */
+               if (!sb_set_blocksize(sb, blocksize)) {
+                       printk(KERN_ERR "EXT4-fs: bad block size %d.\n",
+                                       blocksize);
                        goto failed_mount;
                }
 
                brelse (bh);
-               sb_set_blocksize(sb, blocksize);
                logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
                offset = do_div(logical_sb_block, blocksize);
                bh = sb_bread(sb, logical_sb_block);
@@ -2091,6 +2143,8 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        sbi->s_rsv_window_head.rsv_goal_size = 0;
        ext4_rsv_window_add(sb, &sbi->s_rsv_window_head);
 
+       sbi->s_stripe = ext4_get_stripe_size(sbi);
+
        /*
         * set up enough so that it can read an inode
         */
@@ -2250,6 +2304,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                "writeback");
 
        ext4_ext_init(sb);
+       ext4_mb_init(sb, needs_recovery);
 
        lock_kernel();
        return 0;
@@ -3232,9 +3287,15 @@ static struct file_system_type ext4dev_fs_type = {
 
 static int __init init_ext4_fs(void)
 {
-       int err = init_ext4_xattr();
+       int err;
+
+       err = init_ext4_mballoc();
        if (err)
                return err;
+
+       err = init_ext4_xattr();
+       if (err)
+               goto out2;
        err = init_inodecache();
        if (err)
                goto out1;
@@ -3246,6 +3307,8 @@ out:
        destroy_inodecache();
 out1:
        exit_ext4_xattr();
+out2:
+       exit_ext4_mballoc();
        return err;
 }
 
@@ -3254,6 +3317,7 @@ static void __exit exit_ext4_fs(void)
        unregister_filesystem(&ext4dev_fs_type);
        destroy_inodecache();
        exit_ext4_xattr();
+       exit_ext4_mballoc();
 }
 
 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");