Merge branch 'master' into for_paulus
[linux-drm-fsl-dcu.git] / fs / ext4 / super.c
index b91dffd7a0312ad2cba35b8fb50b9a1a8d4a3982..61c4718e4a5391239191e2043c3a6a3e56e0f0c9 100644 (file)
@@ -63,40 +63,52 @@ static void ext4_write_super (struct super_block * sb);
 static void ext4_write_super_lockfs(struct super_block *sb);
 
 
-ext4_fsblk_t ext4_block_bitmap(struct ext4_group_desc *bg)
+ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
+                              struct ext4_group_desc *bg)
 {
        return le32_to_cpu(bg->bg_block_bitmap) |
-               ((ext4_fsblk_t)le16_to_cpu(bg->bg_block_bitmap_hi) << 32);
+               (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
+                (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
 }
 
-ext4_fsblk_t ext4_inode_bitmap(struct ext4_group_desc *bg)
+ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
+                              struct ext4_group_desc *bg)
 {
        return le32_to_cpu(bg->bg_inode_bitmap) |
-               ((ext4_fsblk_t)le16_to_cpu(bg->bg_inode_bitmap_hi) << 32);
+               (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
+                (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
 }
 
-ext4_fsblk_t ext4_inode_table(struct ext4_group_desc *bg)
+ext4_fsblk_t ext4_inode_table(struct super_block *sb,
+                             struct ext4_group_desc *bg)
 {
        return le32_to_cpu(bg->bg_inode_table) |
-               ((ext4_fsblk_t)le16_to_cpu(bg->bg_inode_table_hi) << 32);
+               (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
+                (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
 }
 
-void ext4_block_bitmap_set(struct ext4_group_desc *bg, ext4_fsblk_t blk)
+void ext4_block_bitmap_set(struct super_block *sb,
+                          struct ext4_group_desc *bg, ext4_fsblk_t blk)
 {
        bg->bg_block_bitmap = cpu_to_le32((u32)blk);
-       bg->bg_block_bitmap_hi = cpu_to_le16(blk >> 32);
+       if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
+               bg->bg_block_bitmap_hi = cpu_to_le32(blk >> 32);
 }
 
-void ext4_inode_bitmap_set(struct ext4_group_desc *bg, ext4_fsblk_t blk)
+void ext4_inode_bitmap_set(struct super_block *sb,
+                          struct ext4_group_desc *bg, ext4_fsblk_t blk)
 {
        bg->bg_inode_bitmap  = cpu_to_le32((u32)blk);
-       bg->bg_inode_bitmap_hi = cpu_to_le16(blk >> 32);
+       if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
+               bg->bg_inode_bitmap_hi = cpu_to_le32(blk >> 32);
 }
 
-void ext4_inode_table_set(struct ext4_group_desc *bg, ext4_fsblk_t blk)
+void ext4_inode_table_set(struct super_block *sb,
+                         struct ext4_group_desc *bg, ext4_fsblk_t blk)
 {
        bg->bg_inode_table = cpu_to_le32((u32)blk);
-       bg->bg_inode_table_hi = cpu_to_le16(blk >> 32);
+       if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
+               bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);
 }
 
 /*
@@ -474,7 +486,7 @@ static void ext4_put_super (struct super_block * sb)
        return;
 }
 
-static kmem_cache_t *ext4_inode_cachep;
+static struct kmem_cache *ext4_inode_cachep;
 
 /*
  * Called inside transaction, so use GFP_NOFS
@@ -483,7 +495,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 {
        struct ext4_inode_info *ei;
 
-       ei = kmem_cache_alloc(ext4_inode_cachep, SLAB_NOFS);
+       ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS);
        if (!ei)
                return NULL;
 #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
@@ -501,7 +513,7 @@ static void ext4_destroy_inode(struct inode *inode)
        kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
 
@@ -678,7 +690,7 @@ static struct quotactl_ops ext4_qctl_operations = {
 };
 #endif
 
-static struct super_operations ext4_sops = {
+static const struct super_operations ext4_sops = {
        .alloc_inode    = ext4_alloc_inode,
        .destroy_inode  = ext4_destroy_inode,
        .read_inode     = ext4_read_inode,
@@ -1179,9 +1191,10 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
                        "running e2fsck is recommended\n");
 #if 0
                /* @@@ We _will_ want to clear the valid bit if we find
-                   inconsistencies, to force a fsck at reboot.  But for
-                   a plain journaled filesystem we can keep it set as
-                   valid forever! :) */
+                * inconsistencies, to force a fsck at reboot.  But for
+                * a plain journaled filesystem we can keep it set as
+                * valid forever! :)
+                */
        es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT4_VALID_FS);
 #endif
        if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
@@ -1239,36 +1252,37 @@ static int ext4_check_descriptors (struct super_block * sb)
                if ((i % EXT4_DESC_PER_BLOCK(sb)) == 0)
                        gdp = (struct ext4_group_desc *)
                                        sbi->s_group_desc[desc_block++]->b_data;
-               block_bitmap = ext4_block_bitmap(gdp);
+               block_bitmap = ext4_block_bitmap(sb, gdp);
                if (block_bitmap < first_block || block_bitmap > last_block)
                {
                        ext4_error (sb, "ext4_check_descriptors",
                                    "Block bitmap for group %d"
-                                   " not in group (block "E3FSBLK")!",
+                                   " not in group (block %llu)!",
                                    i, block_bitmap);
                        return 0;
                }
-               inode_bitmap = ext4_inode_bitmap(gdp);
+               inode_bitmap = ext4_inode_bitmap(sb, gdp);
                if (inode_bitmap < first_block || inode_bitmap > last_block)
                {
                        ext4_error (sb, "ext4_check_descriptors",
                                    "Inode bitmap for group %d"
-                                   " not in group (block "E3FSBLK")!",
+                                   " not in group (block %llu)!",
                                    i, inode_bitmap);
                        return 0;
                }
-               inode_table = ext4_inode_table(gdp);
+               inode_table = ext4_inode_table(sb, gdp);
                if (inode_table < first_block ||
                    inode_table + sbi->s_itb_per_group > last_block)
                {
                        ext4_error (sb, "ext4_check_descriptors",
                                    "Inode table for group %d"
-                                   " not in group (block "E3FSBLK")!",
+                                   " not in group (block %llu)!",
                                    i, inode_table);
                        return 0;
                }
                first_block += EXT4_BLOCKS_PER_GROUP(sb);
-               gdp++;
+               gdp = (struct ext4_group_desc *)
+                       ((__u8 *)gdp + EXT4_DESC_SIZE(sb));
        }
 
        ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
@@ -1307,6 +1321,12 @@ static void ext4_orphan_cleanup (struct super_block * sb,
                return;
        }
 
+       if (bdev_read_only(sb->s_bdev)) {
+               printk(KERN_ERR "EXT4-fs: write access "
+                       "unavailable, skipping orphan cleanup.\n");
+               return;
+       }
+
        if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
                if (es->s_last_orphan)
                        jbd_debug(1, "Errors on filesystem, "
@@ -1410,8 +1430,7 @@ static loff_t ext4_max_size(int bits)
 }
 
 static ext4_fsblk_t descriptor_loc(struct super_block *sb,
-                                   ext4_fsblk_t logic_sb_block,
-                                   int nr)
+                               ext4_fsblk_t logical_sb_block, int nr)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        unsigned long bg, first_meta_bg;
@@ -1421,7 +1440,7 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb,
 
        if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
            nr < first_meta_bg)
-               return (logic_sb_block + nr + 1);
+               return logical_sb_block + nr + 1;
        bg = sbi->s_desc_per_block * nr;
        if (ext4_bg_has_super(sb, bg))
                has_super = 1;
@@ -1436,7 +1455,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        struct ext4_sb_info *sbi;
        ext4_fsblk_t block;
        ext4_fsblk_t sb_block = get_sb_block(&data);
-       ext4_fsblk_t logic_sb_block;
+       ext4_fsblk_t logical_sb_block;
        unsigned long offset = 0;
        unsigned int journal_inum = 0;
        unsigned long journal_devnum = 0;
@@ -1471,13 +1490,13 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
         * block sizes.  We need to calculate the offset from buffer start.
         */
        if (blocksize != EXT4_MIN_BLOCK_SIZE) {
-               logic_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
-               offset = sector_div(logic_sb_block, blocksize);
+               logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
+               offset = do_div(logical_sb_block, blocksize);
        } else {
-               logic_sb_block = sb_block;
+               logical_sb_block = sb_block;
        }
 
-       if (!(bh = sb_bread(sb, logic_sb_block))) {
+       if (!(bh = sb_bread(sb, logical_sb_block))) {
                printk (KERN_ERR "EXT4-fs: unable to read superblock\n");
                goto out_fail;
        }
@@ -1499,10 +1518,14 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                set_opt(sbi->s_mount_opt, GRPID);
        if (def_mount_opts & EXT4_DEFM_UID16)
                set_opt(sbi->s_mount_opt, NO_UID32);
+#ifdef CONFIG_EXT4DEV_FS_XATTR
        if (def_mount_opts & EXT4_DEFM_XATTR_USER)
                set_opt(sbi->s_mount_opt, XATTR_USER);
+#endif
+#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
        if (def_mount_opts & EXT4_DEFM_ACL)
                set_opt(sbi->s_mount_opt, POSIX_ACL);
+#endif
        if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)
                sbi->s_mount_opt |= EXT4_MOUNT_JOURNAL_DATA;
        else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)
@@ -1514,6 +1537,8 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                set_opt(sbi->s_mount_opt, ERRORS_PANIC);
        else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_RO)
                set_opt(sbi->s_mount_opt, ERRORS_RO);
+       else
+               set_opt(sbi->s_mount_opt, ERRORS_CONT);
 
        sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
        sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
@@ -1577,9 +1602,9 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
 
                brelse (bh);
                sb_set_blocksize(sb, blocksize);
-               logic_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
-               offset = sector_div(logic_sb_block, blocksize);
-               bh = sb_bread(sb, logic_sb_block);
+               logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
+               offset = do_div(logical_sb_block, blocksize);
+               bh = sb_bread(sb, logical_sb_block);
                if (!bh) {
                        printk(KERN_ERR
                               "EXT4-fs: Can't read superblock on 2nd try.\n");
@@ -1619,7 +1644,18 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                       sbi->s_frag_size, blocksize);
                goto failed_mount;
        }
-       sbi->s_frags_per_block = 1;
+       sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
+       if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) {
+               if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
+                   sbi->s_desc_size > EXT4_MAX_DESC_SIZE ||
+                   sbi->s_desc_size & (sbi->s_desc_size - 1)) {
+                       printk(KERN_ERR
+                              "EXT4-fs: unsupported descriptor size %lu\n",
+                              sbi->s_desc_size);
+                       goto failed_mount;
+               }
+       } else
+               sbi->s_desc_size = EXT4_MIN_DESC_SIZE;
        sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
        sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
        sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
@@ -1630,7 +1666,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                goto cantfind_ext4;
        sbi->s_itb_per_group = sbi->s_inodes_per_group /
                                        sbi->s_inodes_per_block;
-       sbi->s_desc_per_block = blocksize / sizeof(struct ext4_group_desc);
+       sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb);
        sbi->s_sbh = bh;
        sbi->s_mount_state = le16_to_cpu(es->s_state);
        sbi->s_addr_per_block_bits = log2(EXT4_ADDR_PER_BLOCK(sb));
@@ -1687,7 +1723,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        bgl_lock_init(&sbi->s_blockgroup_lock);
 
        for (i = 0; i < db_count; i++) {
-               block = descriptor_loc(sb, logic_sb_block, i);
+               block = descriptor_loc(sb, logical_sb_block, i);
                sbi->s_group_desc[i] = sb_bread(sb, block);
                if (!sbi->s_group_desc[i]) {
                        printk (KERN_ERR "EXT4-fs: "
@@ -1766,8 +1802,9 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        switch (test_opt(sb, DATA_FLAGS)) {
        case 0:
                /* No mode set, assume a default based on the journal
-                   capabilities: ORDERED_DATA if the journal can
-                   cope, else JOURNAL_DATA */
+                * capabilities: ORDERED_DATA if the journal can
+                * cope, else JOURNAL_DATA
+                */
                if (jbd2_journal_check_available_features
                    (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE))
                        set_opt(sbi->s_mount_opt, ORDERED_DATA);
@@ -2386,6 +2423,22 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
                                err = -EROFS;
                                goto restore_opts;
                        }
+
+                       /*
+                        * If we have an unprocessed orphan list hanging
+                        * around from a previously readonly bdev mount,
+                        * require a full umount/remount for now.
+                        */
+                       if (es->s_last_orphan) {
+                               printk(KERN_WARNING "EXT4-fs: %s: couldn't "
+                                      "remount RDWR because of unprocessed "
+                                      "orphan inode list.  Please "
+                                      "umount/remount instead.\n",
+                                      sb->s_id);
+                               err = -EINVAL;
+                               goto restore_opts;
+                       }
+
                        /*
                         * Mounting a RDONLY partition read-write, so reread
                         * and store the current valid flag.  (It may have
@@ -2433,6 +2486,7 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
        struct ext4_super_block *es = sbi->s_es;
        ext4_fsblk_t overhead;
        int i;
+       u64 fsid;
 
        if (test_opt (sb, MINIX_DF))
                overhead = 0;
@@ -2479,6 +2533,10 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
        buf->f_files = le32_to_cpu(es->s_inodes_count);
        buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
        buf->f_namelen = EXT4_NAME_LEN;
+       fsid = le64_to_cpup((void *)es->s_uuid) ^
+              le64_to_cpup((void *)es->s_uuid + sizeof(u64));
+       buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
+       buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
        return 0;
 }
 
@@ -2777,7 +2835,7 @@ static int __init init_ext4_fs(void)
        err = init_inodecache();
        if (err)
                goto out1;
-        err = register_filesystem(&ext4dev_fs_type);
+       err = register_filesystem(&ext4dev_fs_type);
        if (err)
                goto out;
        return 0;