This file is read-only and shows the number of
                kilobytes of data that have been written to this
                filesystem since it was mounted.
+
+What:          /sys/fs/ext4/<disk>/inode_goal
+Date:          June 2008
+Contact:       "Theodore Ts'o" <tytso@mit.edu>
+Description:
+               Tuning parameter which (if non-zero) controls the goal
+               inode used by the inode allocator in p0reference to
+               all other allocation hueristics.  This is intended for
+               debugging use only, and should be 0 on production
+               systems.
 
        int s_inode_size;
        int s_first_ino;
        unsigned int s_inode_readahead_blks;
+       unsigned int s_inode_goal;
        spinlock_t s_next_gen_lock;
        u32 s_next_generation;
        u32 s_hash_seed[4];
 
 /* ialloc.c */
 extern struct inode *ext4_new_inode(handle_t *, struct inode *, int,
-                                   const struct qstr *qstr);
+                                   const struct qstr *qstr, __u32 goal);
 extern void ext4_free_inode(handle_t *, struct inode *);
 extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
 extern unsigned long ext4_count_free_inodes(struct super_block *);
 
  * group to find a free inode.
  */
 struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
-                            const struct qstr *qstr)
+                            const struct qstr *qstr, __u32 goal)
 {
        struct super_block *sb;
        struct buffer_head *inode_bitmap_bh = NULL;
        ei = EXT4_I(inode);
        sbi = EXT4_SB(sb);
 
+       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) {
        if (ret2 == -1)
                goto out;
 
-       for (i = 0; i < ngroups; i++) {
+       for (i = 0; i < ngroups; i++, ino = 0) {
                err = -EIO;
 
                gdp = ext4_get_group_desc(sb, group, &group_desc_bh);
                if (!inode_bitmap_bh)
                        goto fail;
 
-               ino = 0;
-
 repeat_in_this_group:
                ino = ext4_find_next_zero_bit((unsigned long *)
                                              inode_bitmap_bh->b_data,
 
        struct inode *tmp_inode = NULL;
        struct list_blocks_struct lb;
        unsigned long max_entries;
+       __u32 goal;
 
        /*
         * If the filesystem does not support extents, or the inode
                retval = PTR_ERR(handle);
                return retval;
        }
+       goal = (((inode->i_ino - 1) / EXT4_INODES_PER_GROUP(inode->i_sb)) *
+               EXT4_INODES_PER_GROUP(inode->i_sb)) + 1;
        tmp_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode,
-                                  S_IFREG, 0);
+                                  S_IFREG, 0, goal);
        if (IS_ERR(tmp_inode)) {
                retval = -ENOMEM;
                ext4_journal_stop(handle);
 
        if (IS_DIRSYNC(dir))
                ext4_handle_sync(handle);
 
-       inode = ext4_new_inode(handle, dir, mode, &dentry->d_name);
+       inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0);
        err = PTR_ERR(inode);
        if (!IS_ERR(inode)) {
                inode->i_op = &ext4_file_inode_operations;
        if (IS_DIRSYNC(dir))
                ext4_handle_sync(handle);
 
-       inode = ext4_new_inode(handle, dir, mode, &dentry->d_name);
+       inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0);
        err = PTR_ERR(inode);
        if (!IS_ERR(inode)) {
                init_special_inode(inode, inode->i_mode, rdev);
        if (IS_DIRSYNC(dir))
                ext4_handle_sync(handle);
 
-       inode = ext4_new_inode(handle, dir, S_IFDIR | mode, &dentry->d_name);
+       inode = ext4_new_inode(handle, dir, S_IFDIR | mode,
+                              &dentry->d_name, 0);
        err = PTR_ERR(inode);
        if (IS_ERR(inode))
                goto out_stop;
        if (IS_DIRSYNC(dir))
                ext4_handle_sync(handle);
 
-       inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO, &dentry->d_name);
+       inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO,
+                              &dentry->d_name, 0);
        err = PTR_ERR(inode);
        if (IS_ERR(inode))
                goto out_stop;
 
 EXT4_RO_ATTR(lifetime_write_kbytes);
 EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
                 inode_readahead_blks_store, s_inode_readahead_blks);
+EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
 EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
 EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
 EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
        ATTR_LIST(session_write_kbytes),
        ATTR_LIST(lifetime_write_kbytes),
        ATTR_LIST(inode_readahead_blks),
+       ATTR_LIST(inode_goal),
        ATTR_LIST(mb_stats),
        ATTR_LIST(mb_max_to_scan),
        ATTR_LIST(mb_min_to_scan),