dquot: cleanup dquot drop routine
[safe/jmp/linux-2.6] / fs / ext4 / ialloc.c
index 427f830..ca8986e 100644 (file)
@@ -15,8 +15,6 @@
 #include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
-#include <linux/ext4_jbd2.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/quotaops.h>
 #include <linux/blkdev.h>
 #include <asm/byteorder.h>
 
+#include "ext4.h"
+#include "ext4_jbd2.h"
 #include "xattr.h"
 #include "acl.h"
 
+#include <trace/events/ext4.h>
+
 /*
  * ialloc.c contains the inodes allocation and deallocation routines
  */
  * the free blocks count in the block.
  */
 
+/*
+ * To avoid calling the atomic setbit hundreds or thousands of times, we only
+ * need to use it within a single byte (to ensure we get endianness right).
+ * We can use memset for the rest of the bitmap as there are no other users.
+ */
+void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
+{
+       int i;
+
+       if (start_bit >= end_bit)
+               return;
+
+       ext4_debug("mark end bits +%d through +%d used\n", start_bit, end_bit);
+       for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++)
+               ext4_set_bit(i, bitmap);
+       if (i < end_bit)
+               memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
+}
+
+/* Initializes an uninitialized inode bitmap */
+unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh,
+                               ext4_group_t block_group,
+                               struct ext4_group_desc *gdp)
+{
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+
+       J_ASSERT_BH(bh, buffer_locked(bh));
+
+       /* If checksum is bad mark all blocks and inodes use to prevent
+        * allocation, essentially implementing a per-group read-only flag. */
+       if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+               ext4_error(sb, __func__, "Checksum bad for group %u",
+                          block_group);
+               ext4_free_blks_set(sb, gdp, 0);
+               ext4_free_inodes_set(sb, gdp, 0);
+               ext4_itable_unused_set(sb, gdp, 0);
+               memset(bh->b_data, 0xff, sb->s_blocksize);
+               return 0;
+       }
+
+       memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);
+       mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8,
+                       bh->b_data);
+
+       return EXT4_INODES_PER_GROUP(sb);
+}
 
 /*
  * Read the inode allocation bitmap for a given block_group, reading
  * Return buffer_head of bitmap on success or NULL.
  */
 static struct buffer_head *
-read_inode_bitmap(struct super_block * sb, unsigned long block_group)
+ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
 {
        struct ext4_group_desc *desc;
        struct buffer_head *bh = NULL;
+       ext4_fsblk_t bitmap_blk;
 
        desc = ext4_get_group_desc(sb, block_group, NULL);
        if (!desc)
-               goto error_out;
+               return NULL;
+       bitmap_blk = ext4_inode_bitmap(sb, desc);
+       bh = sb_getblk(sb, bitmap_blk);
+       if (unlikely(!bh)) {
+               ext4_error(sb, __func__,
+                           "Cannot read inode bitmap - "
+                           "block_group = %u, inode_bitmap = %llu",
+                           block_group, bitmap_blk);
+               return NULL;
+       }
+       if (bitmap_uptodate(bh))
+               return bh;
 
-       bh = sb_bread(sb, ext4_inode_bitmap(sb, desc));
-       if (!bh)
-               ext4_error(sb, "read_inode_bitmap",
+       lock_buffer(bh);
+       if (bitmap_uptodate(bh)) {
+               unlock_buffer(bh);
+               return bh;
+       }
+       ext4_lock_group(sb, block_group);
+       if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
+               ext4_init_inode_bitmap(sb, bh, block_group, desc);
+               set_bitmap_uptodate(bh);
+               set_buffer_uptodate(bh);
+               ext4_unlock_group(sb, block_group);
+               unlock_buffer(bh);
+               return bh;
+       }
+       ext4_unlock_group(sb, block_group);
+       if (buffer_uptodate(bh)) {
+               /*
+                * if not uninit if bh is uptodate,
+                * bitmap is also uptodate
+                */
+               set_bitmap_uptodate(bh);
+               unlock_buffer(bh);
+               return bh;
+       }
+       /*
+        * submit the buffer_head for read. We can
+        * safely mark the bitmap as uptodate now.
+        * We do it here so the bitmap uptodate bit
+        * get set with buffer lock held.
+        */
+       set_bitmap_uptodate(bh);
+       if (bh_submit_read(bh) < 0) {
+               put_bh(bh);
+               ext4_error(sb, __func__,
                            "Cannot read inode bitmap - "
-                           "block_group = %lu, inode_bitmap = %llu",
-                           block_group, ext4_inode_bitmap(sb, desc));
-error_out:
+                           "block_group = %u, inode_bitmap = %llu",
+                           block_group, bitmap_blk);
+               return NULL;
+       }
        return bh;
 }
 
@@ -86,62 +178,64 @@ error_out:
  * though), and then we'd have two inodes sharing the
  * same inode number and space on the harddisk.
  */
-void ext4_free_inode (handle_t *handle, struct inode * inode)
+void ext4_free_inode(handle_t *handle, struct inode *inode)
 {
-       struct super_block * sb = inode->i_sb;
+       struct super_block *sb = inode->i_sb;
        int is_directory;
        unsigned long ino;
        struct buffer_head *bitmap_bh = NULL;
        struct buffer_head *bh2;
-       unsigned long block_group;
+       ext4_group_t block_group;
        unsigned long bit;
-       struct ext4_group_desc * gdp;
-       struct ext4_super_block * es;
+       struct ext4_group_desc *gdp;
+       struct ext4_super_block *es;
        struct ext4_sb_info *sbi;
-       int fatal = 0, err;
+       int fatal = 0, err, count, cleared;
 
        if (atomic_read(&inode->i_count) > 1) {
-               printk ("ext4_free_inode: inode has count=%d\n",
-                                       atomic_read(&inode->i_count));
+               printk(KERN_ERR "ext4_free_inode: inode has count=%d\n",
+                      atomic_read(&inode->i_count));
                return;
        }
        if (inode->i_nlink) {
-               printk ("ext4_free_inode: inode has nlink=%d\n",
-                       inode->i_nlink);
+               printk(KERN_ERR "ext4_free_inode: inode has nlink=%d\n",
+                      inode->i_nlink);
                return;
        }
        if (!sb) {
-               printk("ext4_free_inode: inode on nonexistent device\n");
+               printk(KERN_ERR "ext4_free_inode: inode on "
+                      "nonexistent device\n");
                return;
        }
        sbi = EXT4_SB(sb);
 
        ino = inode->i_ino;
-       ext4_debug ("freeing inode %lu\n", ino);
+       ext4_debug("freeing inode %lu\n", ino);
+       trace_ext4_free_inode(inode);
 
        /*
         * Note: we must free any quota before locking the superblock,
         * as writing the quota to disk may need the lock as well.
         */
-       DQUOT_INIT(inode);
+       vfs_dq_init(inode);
        ext4_xattr_delete_inode(handle, inode);
-       DQUOT_FREE_INODE(inode);
-       DQUOT_DROP(inode);
+       dquot_free_inode(inode);
+       dquot_drop(inode);
 
        is_directory = S_ISDIR(inode->i_mode);
 
        /* Do this BEFORE marking the inode not in use or returning an error */
-       clear_inode (inode);
+       clear_inode(inode);
 
        es = EXT4_SB(sb)->s_es;
        if (ino < EXT4_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
-               ext4_error (sb, "ext4_free_inode",
-                           "reserved or nonexistent inode %lu", ino);
+               ext4_error(sb, "ext4_free_inode",
+                          "reserved or nonexistent inode %lu", ino);
                goto error_return;
        }
        block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
        bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
-       bitmap_bh = read_inode_bitmap(sb, block_group);
+       bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
        if (!bitmap_bh)
                goto error_return;
 
@@ -151,36 +245,53 @@ void ext4_free_inode (handle_t *handle, struct inode * inode)
                goto error_return;
 
        /* Ok, now we can actually update the inode bitmaps.. */
-       if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
-                                       bit, bitmap_bh->b_data))
-               ext4_error (sb, "ext4_free_inode",
-                             "bit already cleared for inode %lu", ino);
+       cleared = ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group),
+                                       bit, bitmap_bh->b_data);
+       if (!cleared)
+               ext4_error(sb, "ext4_free_inode",
+                          "bit already cleared for inode %lu", ino);
        else {
-               gdp = ext4_get_group_desc (sb, block_group, &bh2);
+               gdp = ext4_get_group_desc(sb, block_group, &bh2);
 
                BUFFER_TRACE(bh2, "get_write_access");
                fatal = ext4_journal_get_write_access(handle, bh2);
                if (fatal) goto error_return;
 
                if (gdp) {
-                       spin_lock(sb_bgl_lock(sbi, block_group));
-                       gdp->bg_free_inodes_count = cpu_to_le16(
-                               le16_to_cpu(gdp->bg_free_inodes_count) + 1);
-                       if (is_directory)
-                               gdp->bg_used_dirs_count = cpu_to_le16(
-                                 le16_to_cpu(gdp->bg_used_dirs_count) - 1);
-                       spin_unlock(sb_bgl_lock(sbi, block_group));
+                       ext4_lock_group(sb, block_group);
+                       count = ext4_free_inodes_count(sb, gdp) + 1;
+                       ext4_free_inodes_set(sb, gdp, count);
+                       if (is_directory) {
+                               count = ext4_used_dirs_count(sb, gdp) - 1;
+                               ext4_used_dirs_set(sb, gdp, count);
+                               if (sbi->s_log_groups_per_flex) {
+                                       ext4_group_t f;
+
+                                       f = ext4_flex_group(sbi, block_group);
+                                       atomic_dec(&sbi->s_flex_groups[f].free_inodes);
+                               }
+
+                       }
+                       gdp->bg_checksum = ext4_group_desc_csum(sbi,
+                                                       block_group, gdp);
+                       ext4_unlock_group(sb, block_group);
                        percpu_counter_inc(&sbi->s_freeinodes_counter);
                        if (is_directory)
                                percpu_counter_dec(&sbi->s_dirs_counter);
 
+                       if (sbi->s_log_groups_per_flex) {
+                               ext4_group_t f;
+
+                               f = ext4_flex_group(sbi, block_group);
+                               atomic_inc(&sbi->s_flex_groups[f].free_inodes);
+                       }
                }
-               BUFFER_TRACE(bh2, "call ext4_journal_dirty_metadata");
-               err = ext4_journal_dirty_metadata(handle, bh2);
+               BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
+               err = ext4_handle_dirty_metadata(handle, NULL, bh2);
                if (!fatal) fatal = err;
        }
-       BUFFER_TRACE(bitmap_bh, "call ext4_journal_dirty_metadata");
-       err = ext4_journal_dirty_metadata(handle, bitmap_bh);
+       BUFFER_TRACE(bitmap_bh, "call ext4_handle_dirty_metadata");
+       err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
        if (!fatal)
                fatal = err;
        sb->s_dirt = 1;
@@ -199,31 +310,142 @@ error_return:
  * For other inodes, search forward from the parent directory\'s block
  * group to find a free inode.
  */
-static int find_group_dir(struct super_block *sb, struct inode *parent)
+static int find_group_dir(struct super_block *sb, struct inode *parent,
+                               ext4_group_t *best_group)
 {
-       int ngroups = EXT4_SB(sb)->s_groups_count;
+       ext4_group_t ngroups = ext4_get_groups_count(sb);
        unsigned int freei, avefreei;
        struct ext4_group_desc *desc, *best_desc = NULL;
-       struct buffer_head *bh;
-       int group, best_group = -1;
+       ext4_group_t group;
+       int ret = -1;
 
        freei = percpu_counter_read_positive(&EXT4_SB(sb)->s_freeinodes_counter);
        avefreei = freei / ngroups;
 
        for (group = 0; group < ngroups; group++) {
-               desc = ext4_get_group_desc (sb, group, &bh);
-               if (!desc || !desc->bg_free_inodes_count)
+               desc = ext4_get_group_desc(sb, group, NULL);
+               if (!desc || !ext4_free_inodes_count(sb, desc))
                        continue;
-               if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
+               if (ext4_free_inodes_count(sb, desc) < avefreei)
                        continue;
                if (!best_desc ||
-                   (le16_to_cpu(desc->bg_free_blocks_count) >
-                    le16_to_cpu(best_desc->bg_free_blocks_count))) {
-                       best_group = group;
+                   (ext4_free_blks_count(sb, desc) >
+                    ext4_free_blks_count(sb, best_desc))) {
+                       *best_group = group;
                        best_desc = desc;
+                       ret = 0;
+               }
+       }
+       return ret;
+}
+
+#define free_block_ratio 10
+
+static int find_group_flex(struct super_block *sb, struct inode *parent,
+                          ext4_group_t *best_group)
+{
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       struct ext4_group_desc *desc;
+       struct flex_groups *flex_group = sbi->s_flex_groups;
+       ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
+       ext4_group_t parent_fbg_group = ext4_flex_group(sbi, parent_group);
+       ext4_group_t ngroups = ext4_get_groups_count(sb);
+       int flex_size = ext4_flex_bg_size(sbi);
+       ext4_group_t best_flex = parent_fbg_group;
+       int blocks_per_flex = sbi->s_blocks_per_group * flex_size;
+       int flexbg_free_blocks;
+       int flex_freeb_ratio;
+       ext4_group_t n_fbg_groups;
+       ext4_group_t i;
+
+       n_fbg_groups = (ngroups + flex_size - 1) >>
+               sbi->s_log_groups_per_flex;
+
+find_close_to_parent:
+       flexbg_free_blocks = atomic_read(&flex_group[best_flex].free_blocks);
+       flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
+       if (atomic_read(&flex_group[best_flex].free_inodes) &&
+           flex_freeb_ratio > free_block_ratio)
+               goto found_flexbg;
+
+       if (best_flex && best_flex == parent_fbg_group) {
+               best_flex--;
+               goto find_close_to_parent;
+       }
+
+       for (i = 0; i < n_fbg_groups; i++) {
+               if (i == parent_fbg_group || i == parent_fbg_group - 1)
+                       continue;
+
+               flexbg_free_blocks = atomic_read(&flex_group[i].free_blocks);
+               flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
+
+               if (flex_freeb_ratio > free_block_ratio &&
+                   (atomic_read(&flex_group[i].free_inodes))) {
+                       best_flex = i;
+                       goto found_flexbg;
+               }
+
+               if ((atomic_read(&flex_group[best_flex].free_inodes) == 0) ||
+                   ((atomic_read(&flex_group[i].free_blocks) >
+                     atomic_read(&flex_group[best_flex].free_blocks)) &&
+                    atomic_read(&flex_group[i].free_inodes)))
+                       best_flex = i;
+       }
+
+       if (!atomic_read(&flex_group[best_flex].free_inodes) ||
+           !atomic_read(&flex_group[best_flex].free_blocks))
+               return -1;
+
+found_flexbg:
+       for (i = best_flex * flex_size; i < ngroups &&
+                    i < (best_flex + 1) * flex_size; i++) {
+               desc = ext4_get_group_desc(sb, i, NULL);
+               if (ext4_free_inodes_count(sb, desc)) {
+                       *best_group = i;
+                       goto out;
                }
        }
-       return best_group;
+
+       return -1;
+out:
+       return 0;
+}
+
+struct orlov_stats {
+       __u32 free_inodes;
+       __u32 free_blocks;
+       __u32 used_dirs;
+};
+
+/*
+ * Helper function for Orlov's allocator; returns critical information
+ * for a particular block group or flex_bg.  If flex_size is 1, then g
+ * is a block group number; otherwise it is flex_bg number.
+ */
+void get_orlov_stats(struct super_block *sb, ext4_group_t g,
+                      int flex_size, struct orlov_stats *stats)
+{
+       struct ext4_group_desc *desc;
+       struct flex_groups *flex_group = EXT4_SB(sb)->s_flex_groups;
+
+       if (flex_size > 1) {
+               stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
+               stats->free_blocks = atomic_read(&flex_group[g].free_blocks);
+               stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
+               return;
+       }
+
+       desc = ext4_get_group_desc(sb, g, NULL);
+       if (desc) {
+               stats->free_inodes = ext4_free_inodes_count(sb, desc);
+               stats->free_blocks = ext4_free_blks_count(sb, desc);
+               stats->used_dirs = ext4_used_dirs_count(sb, desc);
+       } else {
+               stats->free_inodes = 0;
+               stats->free_blocks = 0;
+               stats->used_dirs = 0;
+       }
 }
 
 /*
@@ -241,35 +463,37 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
  * it has too many directories already (max_dirs) or
  * it has too few free inodes left (min_inodes) or
  * it has too few free blocks left (min_blocks) or
- * it's already running too large debt (max_debt).
- * Parent's group is prefered, if it doesn't satisfy these
+ * Parent's group is preferred, if it doesn't satisfy these
  * conditions we search cyclically through the rest. If none
  * of the groups look good we just look for a group with more
  * free inodes than average (starting at parent's group).
- *
- * Debt is incremented each time we allocate a directory and decremented
- * when we allocate an inode, within 0--255.
  */
 
-#define INODE_COST 64
-#define BLOCK_COST 256
-
-static int find_group_orlov(struct super_block *sb, struct inode *parent)
+static int find_group_orlov(struct super_block *sb, struct inode *parent,
+                           ext4_group_t *group, int mode,
+                           const struct qstr *qstr)
 {
-       int parent_group = EXT4_I(parent)->i_block_group;
+       ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       struct ext4_super_block *es = sbi->s_es;
-       int ngroups = sbi->s_groups_count;
+       ext4_group_t real_ngroups = ext4_get_groups_count(sb);
        int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
        unsigned int freei, avefreei;
        ext4_fsblk_t freeb, avefreeb;
-       ext4_fsblk_t blocks_per_dir;
        unsigned int ndirs;
-       int max_debt, max_dirs, min_inodes;
+       int max_dirs, min_inodes;
        ext4_grpblk_t min_blocks;
-       int group = -1, i;
+       ext4_group_t i, grp, g, ngroups;
        struct ext4_group_desc *desc;
-       struct buffer_head *bh;
+       struct orlov_stats stats;
+       int flex_size = ext4_flex_bg_size(sbi);
+       struct dx_hash_info hinfo;
+
+       ngroups = real_ngroups;
+       if (flex_size > 1) {
+               ngroups = (real_ngroups + flex_size - 1) >>
+                       sbi->s_log_groups_per_flex;
+               parent_group >>= sbi->s_log_groups_per_flex;
+       }
 
        freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
        avefreei = freei / ngroups;
@@ -278,70 +502,104 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
        do_div(avefreeb, ngroups);
        ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
 
-       if ((parent == sb->s_root->d_inode) ||
-           (EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL)) {
+       if (S_ISDIR(mode) &&
+           ((parent == sb->s_root->d_inode) ||
+            (EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL))) {
                int best_ndir = inodes_per_group;
-               int best_group = -1;
-
-               get_random_bytes(&group, sizeof(group));
-               parent_group = (unsigned)group % ngroups;
+               int ret = -1;
+
+               if (qstr) {
+                       hinfo.hash_version = DX_HASH_HALF_MD4;
+                       hinfo.seed = sbi->s_hash_seed;
+                       ext4fs_dirhash(qstr->name, qstr->len, &hinfo);
+                       grp = hinfo.hash;
+               } else
+                       get_random_bytes(&grp, sizeof(grp));
+               parent_group = (unsigned)grp % ngroups;
                for (i = 0; i < ngroups; i++) {
-                       group = (parent_group + i) % ngroups;
-                       desc = ext4_get_group_desc (sb, group, &bh);
-                       if (!desc || !desc->bg_free_inodes_count)
+                       g = (parent_group + i) % ngroups;
+                       get_orlov_stats(sb, g, flex_size, &stats);
+                       if (!stats.free_inodes)
                                continue;
-                       if (le16_to_cpu(desc->bg_used_dirs_count) >= best_ndir)
+                       if (stats.used_dirs >= best_ndir)
                                continue;
-                       if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
+                       if (stats.free_inodes < avefreei)
                                continue;
-                       if (le16_to_cpu(desc->bg_free_blocks_count) < avefreeb)
+                       if (stats.free_blocks < avefreeb)
                                continue;
-                       best_group = group;
-                       best_ndir = le16_to_cpu(desc->bg_used_dirs_count);
+                       grp = g;
+                       ret = 0;
+                       best_ndir = stats.used_dirs;
+               }
+               if (ret)
+                       goto fallback;
+       found_flex_bg:
+               if (flex_size == 1) {
+                       *group = grp;
+                       return 0;
+               }
+
+               /*
+                * We pack inodes at the beginning of the flexgroup's
+                * inode tables.  Block allocation decisions will do
+                * something similar, although regular files will
+                * start at 2nd block group of the flexgroup.  See
+                * ext4_ext_find_goal() and ext4_find_near().
+                */
+               grp *= flex_size;
+               for (i = 0; i < flex_size; i++) {
+                       if (grp+i >= real_ngroups)
+                               break;
+                       desc = ext4_get_group_desc(sb, grp+i, NULL);
+                       if (desc && ext4_free_inodes_count(sb, desc)) {
+                               *group = grp+i;
+                               return 0;
+                       }
                }
-               if (best_group >= 0)
-                       return best_group;
                goto fallback;
        }
 
-       blocks_per_dir = ext4_blocks_count(es) - freeb;
-       do_div(blocks_per_dir, ndirs);
-
        max_dirs = ndirs / ngroups + inodes_per_group / 16;
-       min_inodes = avefreei - inodes_per_group / 4;
-       min_blocks = avefreeb - EXT4_BLOCKS_PER_GROUP(sb) / 4;
-
-       max_debt = EXT4_BLOCKS_PER_GROUP(sb);
-       max_debt /= max_t(int, blocks_per_dir, BLOCK_COST);
-       if (max_debt * INODE_COST > inodes_per_group)
-               max_debt = inodes_per_group / INODE_COST;
-       if (max_debt > 255)
-               max_debt = 255;
-       if (max_debt == 0)
-               max_debt = 1;
+       min_inodes = avefreei - inodes_per_group*flex_size / 4;
+       if (min_inodes < 1)
+               min_inodes = 1;
+       min_blocks = avefreeb - EXT4_BLOCKS_PER_GROUP(sb)*flex_size / 4;
+
+       /*
+        * Start looking in the flex group where we last allocated an
+        * inode for this parent directory
+        */
+       if (EXT4_I(parent)->i_last_alloc_group != ~0) {
+               parent_group = EXT4_I(parent)->i_last_alloc_group;
+               if (flex_size > 1)
+                       parent_group >>= sbi->s_log_groups_per_flex;
+       }
 
        for (i = 0; i < ngroups; i++) {
-               group = (parent_group + i) % ngroups;
-               desc = ext4_get_group_desc (sb, group, &bh);
-               if (!desc || !desc->bg_free_inodes_count)
-                       continue;
-               if (le16_to_cpu(desc->bg_used_dirs_count) >= max_dirs)
+               grp = (parent_group + i) % ngroups;
+               get_orlov_stats(sb, grp, flex_size, &stats);
+               if (stats.used_dirs >= max_dirs)
                        continue;
-               if (le16_to_cpu(desc->bg_free_inodes_count) < min_inodes)
+               if (stats.free_inodes < min_inodes)
                        continue;
-               if (le16_to_cpu(desc->bg_free_blocks_count) < min_blocks)
+               if (stats.free_blocks < min_blocks)
                        continue;
-               return group;
+               goto found_flex_bg;
        }
 
 fallback:
+       ngroups = real_ngroups;
+       avefreei = freei / ngroups;
+fallback_retry:
+       parent_group = EXT4_I(parent)->i_block_group;
        for (i = 0; i < ngroups; i++) {
-               group = (parent_group + i) % ngroups;
-               desc = ext4_get_group_desc (sb, group, &bh);
-               if (!desc || !desc->bg_free_inodes_count)
-                       continue;
-               if (le16_to_cpu(desc->bg_free_inodes_count) >= avefreei)
-                       return group;
+               grp = (parent_group + i) % ngroups;
+               desc = ext4_get_group_desc(sb, grp, NULL);
+               if (desc && ext4_free_inodes_count(sb, desc) &&
+                   ext4_free_inodes_count(sb, desc) >= avefreei) {
+                       *group = grp;
+                       return 0;
+               }
        }
 
        if (avefreei) {
@@ -350,28 +608,66 @@ fallback:
                 * filesystems the above test can fail to find any blockgroups
                 */
                avefreei = 0;
-               goto fallback;
+               goto fallback_retry;
        }
 
        return -1;
 }
 
-static int find_group_other(struct super_block *sb, struct inode *parent)
+static int find_group_other(struct super_block *sb, struct inode *parent,
+                           ext4_group_t *group, int mode)
 {
-       int parent_group = EXT4_I(parent)->i_block_group;
-       int ngroups = EXT4_SB(sb)->s_groups_count;
+       ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
+       ext4_group_t i, last, ngroups = ext4_get_groups_count(sb);
        struct ext4_group_desc *desc;
-       struct buffer_head *bh;
-       int group, i;
+       int flex_size = ext4_flex_bg_size(EXT4_SB(sb));
+
+       /*
+        * Try to place the inode is the same flex group as its
+        * parent.  If we can't find space, use the Orlov algorithm to
+        * find another flex group, and store that information in the
+        * parent directory's inode information so that use that flex
+        * group for future allocations.
+        */
+       if (flex_size > 1) {
+               int retry = 0;
+
+       try_again:
+               parent_group &= ~(flex_size-1);
+               last = parent_group + flex_size;
+               if (last > ngroups)
+                       last = ngroups;
+               for  (i = parent_group; i < last; i++) {
+                       desc = ext4_get_group_desc(sb, i, NULL);
+                       if (desc && ext4_free_inodes_count(sb, desc)) {
+                               *group = i;
+                               return 0;
+                       }
+               }
+               if (!retry && EXT4_I(parent)->i_last_alloc_group != ~0) {
+                       retry = 1;
+                       parent_group = EXT4_I(parent)->i_last_alloc_group;
+                       goto try_again;
+               }
+               /*
+                * If this didn't work, use the Orlov search algorithm
+                * to find a new flex group; we pass in the mode to
+                * avoid the topdir algorithms.
+                */
+               *group = parent_group + flex_size;
+               if (*group > ngroups)
+                       *group = 0;
+               return find_group_orlov(sb, parent, group, mode, 0);
+       }
 
        /*
         * Try to place the inode in its parent directory
         */
-       group = parent_group;
-       desc = ext4_get_group_desc (sb, group, &bh);
-       if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
-                       le16_to_cpu(desc->bg_free_blocks_count))
-               return group;
+       *group = parent_group;
+       desc = ext4_get_group_desc(sb, *group, NULL);
+       if (desc && ext4_free_inodes_count(sb, desc) &&
+                       ext4_free_blks_count(sb, desc))
+               return 0;
 
        /*
         * We're going to place this inode in a different blockgroup from its
@@ -382,39 +678,117 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
         *
         * So add our directory's i_ino into the starting point for the hash.
         */
-       group = (group + parent->i_ino) % ngroups;
+       *group = (*group + parent->i_ino) % ngroups;
 
        /*
         * Use a quadratic hash to find a group with a free inode and some free
         * blocks.
         */
        for (i = 1; i < ngroups; i <<= 1) {
-               group += i;
-               if (group >= ngroups)
-                       group -= ngroups;
-               desc = ext4_get_group_desc (sb, group, &bh);
-               if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
-                               le16_to_cpu(desc->bg_free_blocks_count))
-                       return group;
+               *group += i;
+               if (*group >= ngroups)
+                       *group -= ngroups;
+               desc = ext4_get_group_desc(sb, *group, NULL);
+               if (desc && ext4_free_inodes_count(sb, desc) &&
+                               ext4_free_blks_count(sb, desc))
+                       return 0;
        }
 
        /*
         * That failed: try linear search for a free inode, even if that group
         * has no free blocks.
         */
-       group = parent_group;
+       *group = parent_group;
        for (i = 0; i < ngroups; i++) {
-               if (++group >= ngroups)
-                       group = 0;
-               desc = ext4_get_group_desc (sb, group, &bh);
-               if (desc && le16_to_cpu(desc->bg_free_inodes_count))
-                       return group;
+               if (++*group >= ngroups)
+                       *group = 0;
+               desc = ext4_get_group_desc(sb, *group, NULL);
+               if (desc && ext4_free_inodes_count(sb, desc))
+                       return 0;
        }
 
        return -1;
 }
 
 /*
+ * claim the inode from the inode bitmap. If the group
+ * is uninit we need to take the groups's ext4_group_lock
+ * and clear the uninit flag. The inode bitmap update
+ * and group desc uninit flag clear should be done
+ * after holding ext4_group_lock so that ext4_read_inode_bitmap
+ * doesn't race with the ext4_claim_inode
+ */
+static int ext4_claim_inode(struct super_block *sb,
+                       struct buffer_head *inode_bitmap_bh,
+                       unsigned long ino, ext4_group_t group, int mode)
+{
+       int free = 0, retval = 0, count;
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL);
+
+       ext4_lock_group(sb, group);
+       if (ext4_set_bit(ino, inode_bitmap_bh->b_data)) {
+               /* not a free inode */
+               retval = 1;
+               goto err_ret;
+       }
+       ino++;
+       if ((group == 0 && ino < EXT4_FIRST_INO(sb)) ||
+                       ino > EXT4_INODES_PER_GROUP(sb)) {
+               ext4_unlock_group(sb, group);
+               ext4_error(sb, __func__,
+                          "reserved inode or inode > inodes count - "
+                          "block_group = %u, inode=%lu", group,
+                          ino + group * EXT4_INODES_PER_GROUP(sb));
+               return 1;
+       }
+       /* If we didn't allocate from within the initialized part of the inode
+        * table then we need to initialize up to this inode. */
+       if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+
+               if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
+                       gdp->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT);
+                       /* When marking the block group with
+                        * ~EXT4_BG_INODE_UNINIT we don't want to depend
+                        * on the value of bg_itable_unused even though
+                        * mke2fs could have initialized the same for us.
+                        * Instead we calculated the value below
+                        */
+
+                       free = 0;
+               } else {
+                       free = EXT4_INODES_PER_GROUP(sb) -
+                               ext4_itable_unused_count(sb, gdp);
+               }
+
+               /*
+                * Check the relative inode number against the last used
+                * relative inode number in this group. if it is greater
+                * we need to  update the bg_itable_unused count
+                *
+                */
+               if (ino > free)
+                       ext4_itable_unused_set(sb, gdp,
+                                       (EXT4_INODES_PER_GROUP(sb) - ino));
+       }
+       count = ext4_free_inodes_count(sb, gdp) - 1;
+       ext4_free_inodes_set(sb, gdp, count);
+       if (S_ISDIR(mode)) {
+               count = ext4_used_dirs_count(sb, gdp) + 1;
+               ext4_used_dirs_set(sb, gdp, count);
+               if (sbi->s_log_groups_per_flex) {
+                       ext4_group_t f = ext4_flex_group(sbi, group);
+
+                       atomic_inc(&sbi->s_flex_groups[f].free_inodes);
+               }
+       }
+       gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
+err_ret:
+       ext4_unlock_group(sb, group);
+       return retval;
+}
+
+/*
  * There are two policies for allocating an inode.  If the new inode is
  * a directory, then a forward search is made for a block group with both
  * free space and a low directory-to-inode ratio; if that fails, then of
@@ -424,83 +798,123 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
  * For other inodes, search forward from the parent directory's block
  * group to find a free inode.
  */
-struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
+struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
+                            const struct qstr *qstr, __u32 goal)
 {
        struct super_block *sb;
-       struct buffer_head *bitmap_bh = NULL;
-       struct buffer_head *bh2;
-       int group;
+       struct buffer_head *inode_bitmap_bh = NULL;
+       struct buffer_head *group_desc_bh;
+       ext4_group_t ngroups, group = 0;
        unsigned long ino = 0;
-       struct inode * inode;
-       struct ext4_group_desc * gdp = NULL;
-       struct ext4_super_block * es;
+       struct inode *inode;
+       struct ext4_group_desc *gdp = NULL;
        struct ext4_inode_info *ei;
        struct ext4_sb_info *sbi;
-       int err = 0;
+       int ret2, err = 0;
        struct inode *ret;
-       int i;
+       ext4_group_t i;
+       int free = 0;
+       static int once = 1;
+       ext4_group_t flex_group;
 
        /* Cannot create files in a deleted directory */
        if (!dir || !dir->i_nlink)
                return ERR_PTR(-EPERM);
 
        sb = dir->i_sb;
+       ngroups = ext4_get_groups_count(sb);
+       trace_ext4_request_inode(dir, mode);
        inode = new_inode(sb);
        if (!inode)
                return ERR_PTR(-ENOMEM);
        ei = EXT4_I(inode);
-
        sbi = EXT4_SB(sb);
-       es = sbi->s_es;
+
+       if (!goal)
+               goal = sbi->s_inode_goal;
+
+       if (goal && goal <= le32_to_cpu(sbi->s_es->s_inodes_count)) {
+               group = (goal - 1) / EXT4_INODES_PER_GROUP(sb);
+               ino = (goal - 1) % EXT4_INODES_PER_GROUP(sb);
+               ret2 = 0;
+               goto got_group;
+       }
+
+       if (sbi->s_log_groups_per_flex && test_opt(sb, OLDALLOC)) {
+               ret2 = find_group_flex(sb, dir, &group);
+               if (ret2 == -1) {
+                       ret2 = find_group_other(sb, dir, &group, mode);
+                       if (ret2 == 0 && once) {
+                               once = 0;
+                               printk(KERN_NOTICE "ext4: find_group_flex "
+                                      "failed, fallback succeeded dir %lu\n",
+                                      dir->i_ino);
+                       }
+               }
+               goto got_group;
+       }
+
        if (S_ISDIR(mode)) {
-               if (test_opt (sb, OLDALLOC))
-                       group = find_group_dir(sb, dir);
+               if (test_opt(sb, OLDALLOC))
+                       ret2 = find_group_dir(sb, dir, &group);
                else
-                       group = find_group_orlov(sb, dir);
+                       ret2 = find_group_orlov(sb, dir, &group, mode, qstr);
        } else
-               group = find_group_other(sb, dir);
+               ret2 = find_group_other(sb, dir, &group, mode);
 
+got_group:
+       EXT4_I(dir)->i_last_alloc_group = group;
        err = -ENOSPC;
-       if (group == -1)
+       if (ret2 == -1)
                goto out;
 
-       for (i = 0; i < sbi->s_groups_count; i++) {
+       for (i = 0; i < ngroups; i++, ino = 0) {
                err = -EIO;
 
-               gdp = ext4_get_group_desc(sb, group, &bh2);
+               gdp = ext4_get_group_desc(sb, group, &group_desc_bh);
                if (!gdp)
                        goto fail;
 
-               brelse(bitmap_bh);
-               bitmap_bh = read_inode_bitmap(sb, group);
-               if (!bitmap_bh)
+               brelse(inode_bitmap_bh);
+               inode_bitmap_bh = ext4_read_inode_bitmap(sb, group);
+               if (!inode_bitmap_bh)
                        goto fail;
 
-               ino = 0;
-
 repeat_in_this_group:
                ino = ext4_find_next_zero_bit((unsigned long *)
-                               bitmap_bh->b_data, EXT4_INODES_PER_GROUP(sb), ino);
+                                             inode_bitmap_bh->b_data,
+                                             EXT4_INODES_PER_GROUP(sb), ino);
+
                if (ino < EXT4_INODES_PER_GROUP(sb)) {
 
-                       BUFFER_TRACE(bitmap_bh, "get_write_access");
-                       err = ext4_journal_get_write_access(handle, bitmap_bh);
+                       BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
+                       err = ext4_journal_get_write_access(handle,
+                                                           inode_bitmap_bh);
                        if (err)
                                goto fail;
 
-                       if (!ext4_set_bit_atomic(sb_bgl_lock(sbi, group),
-                                               ino, bitmap_bh->b_data)) {
+                       BUFFER_TRACE(group_desc_bh, "get_write_access");
+                       err = ext4_journal_get_write_access(handle,
+                                                               group_desc_bh);
+                       if (err)
+                               goto fail;
+                       if (!ext4_claim_inode(sb, inode_bitmap_bh,
+                                               ino, group, mode)) {
                                /* we won it */
-                               BUFFER_TRACE(bitmap_bh,
-                                       "call ext4_journal_dirty_metadata");
-                               err = ext4_journal_dirty_metadata(handle,
-                                                               bitmap_bh);
+                               BUFFER_TRACE(inode_bitmap_bh,
+                                       "call ext4_handle_dirty_metadata");
+                               err = ext4_handle_dirty_metadata(handle,
+                                                                inode,
+                                                       inode_bitmap_bh);
                                if (err)
                                        goto fail;
+                               /* zero bit is inode number 1*/
+                               ino++;
                                goto got;
                        }
                        /* we lost it */
-                       jbd2_journal_release_buffer(handle, bitmap_bh);
+                       ext4_handle_release_buffer(handle, inode_bitmap_bh);
+                       ext4_handle_release_buffer(handle, group_desc_bh);
 
                        if (++ino < EXT4_INODES_PER_GROUP(sb))
                                goto repeat_in_this_group;
@@ -513,54 +927,76 @@ repeat_in_this_group:
                 * group descriptor metadata has not yet been updated.
                 * So we just go onto the next blockgroup.
                 */
-               if (++group == sbi->s_groups_count)
+               if (++group == ngroups)
                        group = 0;
        }
        err = -ENOSPC;
        goto out;
 
 got:
-       ino += group * EXT4_INODES_PER_GROUP(sb) + 1;
-       if (ino < EXT4_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
-               ext4_error (sb, "ext4_new_inode",
-                           "reserved inode or inode > inodes count - "
-                           "block_group = %d, inode=%lu", group, ino);
-               err = -EIO;
-               goto fail;
-       }
+       /* We may have to initialize the block bitmap if it isn't already */
+       if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
+           gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+               struct buffer_head *block_bitmap_bh;
+
+               block_bitmap_bh = ext4_read_block_bitmap(sb, group);
+               BUFFER_TRACE(block_bitmap_bh, "get block bitmap access");
+               err = ext4_journal_get_write_access(handle, block_bitmap_bh);
+               if (err) {
+                       brelse(block_bitmap_bh);
+                       goto fail;
+               }
 
-       BUFFER_TRACE(bh2, "get_write_access");
-       err = ext4_journal_get_write_access(handle, bh2);
-       if (err) goto fail;
-       spin_lock(sb_bgl_lock(sbi, group));
-       gdp->bg_free_inodes_count =
-               cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
-       if (S_ISDIR(mode)) {
-               gdp->bg_used_dirs_count =
-                       cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
+               free = 0;
+               ext4_lock_group(sb, group);
+               /* recheck and clear flag under lock if we still need to */
+               if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+                       free = ext4_free_blocks_after_init(sb, group, gdp);
+                       gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+                       ext4_free_blks_set(sb, gdp, free);
+                       gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
+                                                               gdp);
+               }
+               ext4_unlock_group(sb, group);
+
+               /* Don't need to dirty bitmap block if we didn't change it */
+               if (free) {
+                       BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
+                       err = ext4_handle_dirty_metadata(handle,
+                                                       NULL, block_bitmap_bh);
+               }
+
+               brelse(block_bitmap_bh);
+               if (err)
+                       goto fail;
        }
-       spin_unlock(sb_bgl_lock(sbi, group));
-       BUFFER_TRACE(bh2, "call ext4_journal_dirty_metadata");
-       err = ext4_journal_dirty_metadata(handle, bh2);
-       if (err) goto fail;
+       BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata");
+       err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh);
+       if (err)
+               goto fail;
 
        percpu_counter_dec(&sbi->s_freeinodes_counter);
        if (S_ISDIR(mode))
                percpu_counter_inc(&sbi->s_dirs_counter);
        sb->s_dirt = 1;
 
-       inode->i_uid = current->fsuid;
-       if (test_opt (sb, GRPID))
+       if (sbi->s_log_groups_per_flex) {
+               flex_group = ext4_flex_group(sbi, group);
+               atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes);
+       }
+
+       inode->i_uid = current_fsuid();
+       if (test_opt(sb, GRPID))
                inode->i_gid = dir->i_gid;
        else if (dir->i_mode & S_ISGID) {
                inode->i_gid = dir->i_gid;
                if (S_ISDIR(mode))
                        mode |= S_ISGID;
        } else
-               inode->i_gid = current->fsgid;
+               inode->i_gid = current_fsgid();
        inode->i_mode = mode;
 
-       inode->i_ino = ino;
+       inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
        /* This is the optimal IO size (for stat), not the fs block size */
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
@@ -570,27 +1006,25 @@ got:
        ei->i_dir_start_lookup = 0;
        ei->i_disksize = 0;
 
-       ei->i_flags = EXT4_I(dir)->i_flags & ~EXT4_INDEX_FL;
-       if (S_ISLNK(mode))
-               ei->i_flags &= ~(EXT4_IMMUTABLE_FL|EXT4_APPEND_FL);
-       /* dirsync only applies to directories */
-       if (!S_ISDIR(mode))
-               ei->i_flags &= ~EXT4_DIRSYNC_FL;
-#ifdef EXT4_FRAGMENTS
-       ei->i_faddr = 0;
-       ei->i_frag_no = 0;
-       ei->i_frag_size = 0;
-#endif
+       /*
+        * Don't inherit extent flag from directory, amongst others. We set
+        * extent flag on newly created directory and file only if -o extent
+        * mount option is specified
+        */
+       ei->i_flags =
+               ext4_mask_flags(mode, EXT4_I(dir)->i_flags & EXT4_FL_INHERITED);
        ei->i_file_acl = 0;
-       ei->i_dir_acl = 0;
        ei->i_dtime = 0;
-       ei->i_block_alloc_info = NULL;
        ei->i_block_group = group;
+       ei->i_last_alloc_group = ~0;
 
        ext4_set_inode_flags(inode);
        if (IS_DIRSYNC(inode))
-               handle->h_sync = 1;
-       insert_inode_hash(inode);
+               ext4_handle_sync(handle);
+       if (insert_inode_locked(inode) < 0) {
+               err = -EINVAL;
+               goto fail_drop;
+       }
        spin_lock(&sbi->s_next_gen_lock);
        inode->i_generation = sbi->s_next_generation++;
        spin_unlock(&sbi->s_next_gen_lock);
@@ -600,37 +1034,35 @@ got:
        ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
 
        ret = inode;
-       if(DQUOT_ALLOC_INODE(inode)) {
-               err = -EDQUOT;
+       vfs_dq_init(inode);
+       err = dquot_alloc_inode(inode);
+       if (err)
                goto fail_drop;
-       }
 
        err = ext4_init_acl(handle, inode, dir);
        if (err)
                goto fail_free_drop;
 
-       err = ext4_init_security(handle,inode, dir);
+       err = ext4_init_security(handle, inode, dir);
        if (err)
                goto fail_free_drop;
 
+       if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+               /* set extent flag only for directory, file and normal symlink*/
+               if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) {
+                       EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL;
+                       ext4_ext_tree_init(handle, inode);
+               }
+       }
+
        err = ext4_mark_inode_dirty(handle, inode);
        if (err) {
                ext4_std_error(sb, err);
                goto fail_free_drop;
        }
-       if (test_opt(sb, EXTENTS)) {
-               EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL;
-               ext4_ext_tree_init(handle, inode);
-               if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
-                       err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
-                       if (err) goto fail;
-                       EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS);
-                       BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "call ext4_journal_dirty_metadata");
-                       err = ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
-               }
-       }
 
        ext4_debug("allocating inode %lu\n", inode->i_ino);
+       trace_ext4_allocate_inode(inode, dir, mode);
        goto really_out;
 fail:
        ext4_std_error(sb, err);
@@ -638,18 +1070,19 @@ out:
        iput(inode);
        ret = ERR_PTR(err);
 really_out:
-       brelse(bitmap_bh);
+       brelse(inode_bitmap_bh);
        return ret;
 
 fail_free_drop:
-       DQUOT_FREE_INODE(inode);
+       dquot_free_inode(inode);
 
 fail_drop:
-       DQUOT_DROP(inode);
+       dquot_drop(inode);
        inode->i_flags |= S_NOQUOTA;
        inode->i_nlink = 0;
+       unlock_new_inode(inode);
        iput(inode);
-       brelse(bitmap_bh);
+       brelse(inode_bitmap_bh);
        return ERR_PTR(err);
 }
 
@@ -657,63 +1090,84 @@ fail_drop:
 struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
 {
        unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count);
-       unsigned long block_group;
+       ext4_group_t block_group;
        int bit;
-       struct buffer_head *bitmap_bh = NULL;
+       struct buffer_head *bitmap_bh;
        struct inode *inode = NULL;
+       long err = -EIO;
 
        /* Error cases - e2fsck has already cleaned up for us */
        if (ino > max_ino) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "bad orphan ino %lu!  e2fsck was run?", ino);
-               goto out;
+               goto error;
        }
 
        block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
        bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
-       bitmap_bh = read_inode_bitmap(sb, block_group);
+       bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
        if (!bitmap_bh) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "inode bitmap error for orphan %lu", ino);
-               goto out;
+               goto error;
        }
 
        /* Having the inode bit set should be a 100% indicator that this
         * is a valid orphan (no e2fsck run on fs).  Orphans also include
         * inodes that were being truncated, so we can't check i_nlink==0.
         */
-       if (!ext4_test_bit(bit, bitmap_bh->b_data) ||
-                       !(inode = iget(sb, ino)) || is_bad_inode(inode) ||
-                       NEXT_ORPHAN(inode) > max_ino) {
-               ext4_warning(sb, __FUNCTION__,
-                            "bad orphan inode %lu!  e2fsck was run?", ino);
-               printk(KERN_NOTICE "ext4_test_bit(bit=%d, block=%llu) = %d\n",
-                      bit, (unsigned long long)bitmap_bh->b_blocknr,
-                      ext4_test_bit(bit, bitmap_bh->b_data));
-               printk(KERN_NOTICE "inode=%p\n", inode);
-               if (inode) {
-                       printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
-                              is_bad_inode(inode));
-                       printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
-                              NEXT_ORPHAN(inode));
-                       printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
-               }
+       if (!ext4_test_bit(bit, bitmap_bh->b_data))
+               goto bad_orphan;
+
+       inode = ext4_iget(sb, ino);
+       if (IS_ERR(inode))
+               goto iget_failed;
+
+       /*
+        * If the orphans has i_nlinks > 0 then it should be able to be
+        * truncated, otherwise it won't be removed from the orphan list
+        * during processing and an infinite loop will result.
+        */
+       if (inode->i_nlink && !ext4_can_truncate(inode))
+               goto bad_orphan;
+
+       if (NEXT_ORPHAN(inode) > max_ino)
+               goto bad_orphan;
+       brelse(bitmap_bh);
+       return inode;
+
+iget_failed:
+       err = PTR_ERR(inode);
+       inode = NULL;
+bad_orphan:
+       ext4_warning(sb, __func__,
+                    "bad orphan inode %lu!  e2fsck was run?", ino);
+       printk(KERN_NOTICE "ext4_test_bit(bit=%d, block=%llu) = %d\n",
+              bit, (unsigned long long)bitmap_bh->b_blocknr,
+              ext4_test_bit(bit, bitmap_bh->b_data));
+       printk(KERN_NOTICE "inode=%p\n", inode);
+       if (inode) {
+               printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
+                      is_bad_inode(inode));
+               printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
+                      NEXT_ORPHAN(inode));
+               printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
+               printk(KERN_NOTICE "i_nlink=%u\n", inode->i_nlink);
                /* Avoid freeing blocks if we got a bad deleted inode */
-               if (inode && inode->i_nlink == 0)
+               if (inode->i_nlink == 0)
                        inode->i_blocks = 0;
                iput(inode);
-               inode = NULL;
        }
-out:
        brelse(bitmap_bh);
-       return inode;
+error:
+       return ERR_PTR(err);
 }
 
-unsigned long ext4_count_free_inodes (struct super_block * sb)
+unsigned long ext4_count_free_inodes(struct super_block *sb)
 {
        unsigned long desc_count;
        struct ext4_group_desc *gdp;
-       int i;
+       ext4_group_t i, ngroups = ext4_get_groups_count(sb);
 #ifdef EXT4FS_DEBUG
        struct ext4_super_block *es;
        unsigned long bitmap_count, x;
@@ -723,32 +1177,33 @@ unsigned long ext4_count_free_inodes (struct super_block * sb)
        desc_count = 0;
        bitmap_count = 0;
        gdp = NULL;
-       for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
-               gdp = ext4_get_group_desc (sb, i, NULL);
+       for (i = 0; i < ngroups; i++) {
+               gdp = ext4_get_group_desc(sb, i, NULL);
                if (!gdp)
                        continue;
-               desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
+               desc_count += ext4_free_inodes_count(sb, gdp);
                brelse(bitmap_bh);
-               bitmap_bh = read_inode_bitmap(sb, i);
+               bitmap_bh = ext4_read_inode_bitmap(sb, i);
                if (!bitmap_bh)
                        continue;
 
                x = ext4_count_free(bitmap_bh, EXT4_INODES_PER_GROUP(sb) / 8);
-               printk("group %d: stored = %d, counted = %lu\n",
-                       i, le16_to_cpu(gdp->bg_free_inodes_count), x);
+               printk(KERN_DEBUG "group %lu: stored = %d, counted = %lu\n",
+                       (unsigned long) i, ext4_free_inodes_count(sb, gdp), x);
                bitmap_count += x;
        }
        brelse(bitmap_bh);
-       printk("ext4_count_free_inodes: stored = %u, computed = %lu, %lu\n",
-               le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
+       printk(KERN_DEBUG "ext4_count_free_inodes: "
+              "stored = %u, computed = %lu, %lu\n",
+              le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
        return desc_count;
 #else
        desc_count = 0;
-       for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
-               gdp = ext4_get_group_desc (sb, i, NULL);
+       for (i = 0; i < ngroups; i++) {
+               gdp = ext4_get_group_desc(sb, i, NULL);
                if (!gdp)
                        continue;
-               desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
+               desc_count += ext4_free_inodes_count(sb, gdp);
                cond_resched();
        }
        return desc_count;
@@ -756,17 +1211,16 @@ unsigned long ext4_count_free_inodes (struct super_block * sb)
 }
 
 /* Called at mount-time, super-block is locked */
-unsigned long ext4_count_dirs (struct super_block * sb)
+unsigned long ext4_count_dirs(struct super_block * sb)
 {
        unsigned long count = 0;
-       int i;
+       ext4_group_t i, ngroups = ext4_get_groups_count(sb);
 
-       for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
-               struct ext4_group_desc *gdp = ext4_get_group_desc (sb, i, NULL);
+       for (i = 0; i < ngroups; i++) {
+               struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
                if (!gdp)
                        continue;
-               count += le16_to_cpu(gdp->bg_used_dirs_count);
+               count += ext4_used_dirs_count(sb, gdp);
        }
        return count;
 }
-