Index: linux-2.6.27.21-0.1/fs/ext4/ialloc.c =================================================================== --- linux-2.6.27.21-0.1.orig/fs/ext4/ialloc.c 2009-07-07 14:47:04.000000000 +0530 +++ linux-2.6.27.21-0.1/fs/ext4/ialloc.c 2009-07-07 15:04:02.000000000 +0530 @@ -953,6 +953,36 @@ return ERR_PTR(err); } +unsigned long ext4_find_reverse(struct super_block *sb) +{ + struct ext4_group_desc *desc; + struct buffer_head *bitmap_bh = NULL; + int group; + unsigned long ino, offset; + + for (offset = (EXT4_INODES_PER_GROUP(sb) >> 1); offset >= 0; + offset >>= 1) { + for (group = EXT4_SB(sb)->s_groups_count - 1; group >= 0; + --group) { + desc = ext4_get_group_desc(sb, group, NULL); + if (ext4_free_inodes_count(sb, desc) == 0) + continue; + + bitmap_bh = ext4_read_inode_bitmap(sb, group); + if (!bitmap_bh) + continue; + + ino = ext4_find_next_zero_bit((unsigned long *) + bitmap_bh->b_data, + EXT4_INODES_PER_GROUP(sb), offset); + if (ino < EXT4_INODES_PER_GROUP(sb)) + return (group * EXT4_INODES_PER_GROUP(sb) + + ino + 1); + } + } + return 0; +} + /* Verify that we are loading a valid orphan from disk */ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) { Index: linux-2.6.27.21-0.1/fs/ext4/namei.c =================================================================== --- linux-2.6.27.21-0.1.orig/fs/ext4/namei.c 2009-07-07 14:47:05.000000000 +0530 +++ linux-2.6.27.21-0.1/fs/ext4/namei.c 2009-07-07 15:04:21.000000000 +0530 @@ -161,6 +161,12 @@ u32 ldp_magic; }; +/* Only use the least 3 bits of ldp_flags for goal policy */ +typedef enum { + DP_GOAL_POLICY = 0, + DP_LASTGROUP_REVERSE = 1, +} dp_policy_t; + static inline ext4_lblk_t dx_get_block(struct dx_entry *entry); static void dx_set_block(struct dx_entry *entry, ext4_lblk_t value); static inline unsigned dx_get_hash(struct dx_entry *entry); @@ -1771,8 +1777,14 @@ if (dentry->d_fsdata != NULL) { struct lvfs_dentry_params *param = dentry->d_fsdata; - if (param->ldp_magic == LVFS_DENTRY_PARAM_MAGIC) - inum = param->ldp_inum; + if (param->ldp_magic == LVFS_DENTRY_PARAM_MAGIC) { + if ((dp_policy_t)(param->ldp_flags & 0x7) == + DP_LASTGROUP_REVERSE) + inum = ext4_find_reverse(sb); + else /* DP_GOAL_POLICY */ + inum = param->ldp_inum; + } + } return inum; } Index: linux-2.6.27.21-0.1/fs/ext4/ext4.h =================================================================== --- linux-2.6.27.21-0.1.orig/fs/ext4/ext4.h 2009-07-07 14:47:22.000000000 +0530 +++ linux-2.6.27.21-0.1/fs/ext4/ext4.h 2009-07-07 15:04:02.000000000 +0530 @@ -1101,6 +1101,7 @@ EXT4_SB(dir->i_sb)->s_inode_goal); } extern void ext4_free_inode(handle_t *, struct inode *); +extern unsigned long ext4_find_reverse(struct super_block *); extern struct inode * ext4_orphan_get(struct super_block *, unsigned long); extern unsigned long ext4_count_free_inodes(struct super_block *); extern unsigned long ext4_count_dirs(struct super_block *);