Whamcloud - gitweb
b=17569
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ext4-ialloc-2.6-rhel5.patch
1 Index: linux-2.6.18.i386/fs/ext4/ialloc.c
2 ===================================================================
3 --- linux-2.6.18.i386.orig/fs/ext4/ialloc.c
4 +++ linux-2.6.18.i386/fs/ext4/ialloc.c
5 @@ -509,12 +509,16 @@ fallback:
6  }
7  
8  static int find_group_other(struct super_block *sb, struct inode *parent,
9 -                               ext4_group_t *group)
10 +                           ext4_group_t *group, int mode)
11  {
12 +       struct ext4_sb_info *sbi = EXT4_SB(sb);
13         ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
14 -       ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
15 +       ext4_group_t ngroups = sbi->s_groups_count;
16         struct ext4_group_desc *desc;
17         ext4_group_t i;
18 +       int best_group = -1;
19 +       ext4_fsblk_t avefreeb, freeb;
20 +       int best_group_freeb = 0;
21  
22         /*
23          * Try to place the inode in its parent directory
24 @@ -522,8 +526,10 @@ static int find_group_other(struct super
25         *group = parent_group;
26         desc = ext4_get_group_desc(sb, *group, NULL);
27         if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
28 -                       le16_to_cpu(desc->bg_free_blocks_count))
29 +           (!S_ISREG(mode) || le16_to_cpu(desc->bg_free_blocks_count)))
30                 return 0;
31 +       avefreeb = ext4_free_blocks_count(sbi->s_es);
32 +       do_div(avefreeb, ngroups);
33  
34         /*
35          * We're going to place this inode in a different blockgroup from its
36 @@ -537,33 +543,49 @@ static int find_group_other(struct super
37         *group = (*group + parent->i_ino) % ngroups;
38  
39         /*
40 -        * Use a quadratic hash to find a group with a free inode and some free
41 -        * blocks.
42 +        * Use a quadratic hash to find a group with a free inode and
43 +        * average number of free blocks.
44          */
45         for (i = 1; i < ngroups; i <<= 1) {
46                 *group += i;
47                 if (*group >= ngroups)
48                         *group -= ngroups;
49                 desc = ext4_get_group_desc(sb, *group, NULL);
50 -               if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
51 -                               le16_to_cpu(desc->bg_free_blocks_count))
52 +               if (!desc || !desc->bg_free_inodes_count)
53 +                       continue;
54 +               if (!S_ISREG(mode))
55 +                       return 0;
56 +               if (le16_to_cpu(desc->bg_free_blocks_count) >= avefreeb)
57                         return 0;
58         }
59  
60         /*
61 -        * That failed: try linear search for a free inode, even if that group
62 -        * has no free blocks.
63 +        * That failed: start from last group used to allocate inode
64 +        * try linear search for a free inode and prefereably
65 +        * free blocks.
66          */
67 -       *group = parent_group;
68 +       *group = sbi->s_last_alloc_group;
69 +       if (*group == -1)
70 +               *group = parent_group;
71 +
72         for (i = 0; i < ngroups; i++) {
73                 if (++*group >= ngroups)
74                         *group = 0;
75                 desc = ext4_get_group_desc(sb, *group, NULL);
76 -               if (desc && le16_to_cpu(desc->bg_free_inodes_count))
77 -                       return 0;
78 +               if (!desc || !desc->bg_free_inodes_count)
79 +                       continue;
80 +               freeb = le16_to_cpu(desc->bg_free_blocks_count);
81 +               if (freeb > best_group_freeb) {
82 +                       best_group_freeb = freeb;
83 +                       best_group = *group;
84 +                       if (freeb >= avefreeb || !S_ISREG(mode))
85 +                               break;
86 +               }
87         }
88  
89 -       return -1;
90 +       sbi->s_last_alloc_group = best_group;
91 +       *group = best_group;
92 +       return 0;
93  }
94  
95  /*
96 @@ -656,7 +678,7 @@ continue_allocation:
97                 else
98                         ret2 = find_group_orlov(sb, dir, &group);
99         } else
100 -               ret2 = find_group_other(sb, dir, &group);
101 +               ret2 = find_group_other(sb, dir, &group, mode);
102  
103  got_group:
104         err = -ENOSPC;
105 Index: linux-2.6.18.i386/fs/ext4/super.c
106 ===================================================================
107 --- linux-2.6.18.i386.orig/fs/ext4/super.c
108 +++ linux-2.6.18.i386/fs/ext4/super.c
109 @@ -2190,6 +2190,7 @@ static int ext4_fill_super(struct super_
110  
111         bgl_lock_init(&sbi->s_blockgroup_lock);
112  
113 +       sbi->s_last_alloc_group = -1;
114         for (i = 0; i < db_count; i++) {
115                 block = descriptor_loc(sb, logical_sb_block, i);
116                 sbi->s_group_desc[i] = sb_bread(sb, block);
117 Index: linux-2.6.18.i386/fs/ext4/ext4_sb.h
118 ===================================================================
119 --- linux-2.6.18.i386.orig/fs/ext4/ext4_sb.h
120 +++ linux-2.6.18.i386/fs/ext4/ext4_sb.h
121 @@ -60,6 +60,8 @@ struct ext4_sb_info {
122         struct percpu_counter s_freeinodes_counter;
123         struct percpu_counter s_dirs_counter;
124         struct blockgroup_lock s_blockgroup_lock;
125 +       /* Last group used to allocate inode */
126 +       int s_last_alloc_group;
127  
128         /* root of the per fs reservation window tree */
129         spinlock_t s_rsv_window_lock;