Whamcloud - gitweb
b=16893
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ext4-alloc-policy-2.6-rhel5.patch
diff --git a/ldiskfs/kernel_patches/patches/ext4-alloc-policy-2.6-rhel5.patch b/ldiskfs/kernel_patches/patches/ext4-alloc-policy-2.6-rhel5.patch
new file mode 100644 (file)
index 0000000..a1b8375
--- /dev/null
@@ -0,0 +1,101 @@
+Index: linux-2.6.18-128.1.6/fs/ext4/ialloc.c
+===================================================================
+--- linux-2.6.18-128.1.6.orig/fs/ext4/ialloc.c
++++ linux-2.6.18-128.1.6/fs/ext4/ialloc.c
+@@ -946,6 +946,36 @@ fail_drop:
+       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 (desc->bg_free_inodes_count == 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.18-128.1.6/fs/ext4/namei.c
+===================================================================
+--- linux-2.6.18-128.1.6.orig/fs/ext4/namei.c
++++ linux-2.6.18-128.1.6/fs/ext4/namei.c
+@@ -151,14 +151,24 @@ struct dx_map_entry
+       u16 size;
+ };
++/*
++ * dentry_param used by ext4_new_inode_wantedi()
++ */
+ #define LVFS_DENTRY_PARAM_MAGIC               20070216UL
+ struct lvfs_dentry_params
+ {
+-      unsigned long   p_inum;
+-      void        *p_ptr;
+-      u32          magic;
++      unsigned long   ldp_inum;
++      long            ldp_flags;
++      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);
+@@ -1762,8 +1772,13 @@ static struct inode * ext4_new_inode_wan
+       if (dentry->d_fsdata != NULL) {
+               struct lvfs_dentry_params *param = dentry->d_fsdata;
+-              if (param->magic == LVFS_DENTRY_PARAM_MAGIC)
+-                      inum = param->p_inum;
++              if (param->ldp_magic == LVFS_DENTRY_PARAM_MAGIC) {
++                      if ((dp_policy_t)(param->ldp_flags & 0x7) ==
++                          DP_LASTGROUP_REVERSE)
++                              inum = ext4_find_reverse(dir->i_sb);
++                        else /* DP_GOAL_POLICY */
++                              inum = param->ldp_inum;
++                }
+       }
+       return ext4_new_inode(handle, dir, mode, inum);
+ }
+Index: linux-2.6.18-128.1.6/fs/ext4/ext4.h
+===================================================================
+--- linux-2.6.18-128.1.6.orig/fs/ext4/ext4.h
++++ linux-2.6.18-128.1.6/fs/ext4/ext4.h
+@@ -1071,6 +1071,7 @@ extern int ext4fs_dirhash(const char *na
+ /* ialloc.c */
+ extern struct inode * ext4_new_inode (handle_t *, struct inode *, int,
+                                     unsigned long);
++extern unsigned long ext4_find_reverse(struct super_block *);
+ 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 *);