Whamcloud - gitweb
land b1_5 onto HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-ialloc-2.4.21-suse2.patch
1 Index: linux-2.4.21-suse2/fs/ext3/ialloc.c
2 ===================================================================
3 --- linux-2.4.21-suse2.orig/fs/ext3/ialloc.c    2005-08-04 09:14:23.000000000 -0600
4 +++ linux-2.4.21-suse2/fs/ext3/ialloc.c 2005-08-04 09:17:49.000000000 -0600
5 @@ -328,19 +328,140 @@
6   * directories already is chosen.
7   *
8   * For other inodes, search forward from the parent directory's block
9 - * group to find a free inode.
10 + * group to find a free inode in a group with some free blocks.
11   */
12 +static int find_group_dir(struct super_block *sb, const struct inode *parent,
13 +                         struct ext3_group_desc **best_desc,
14 +                         struct buffer_head **best_bh)
15 +{
16 +       struct ext3_sb_info *sbi = EXT3_SB(sb);
17 +       int ngroups = sbi->s_groups_count;
18 +       int avefreei;
19 +       struct ext3_group_desc *desc;
20 +       struct buffer_head *bh;
21 +       int group, best_group = -1, ndir_best = 999999999;
22 +
23 +       *best_desc = NULL;
24 +       *best_bh = NULL;
25 +
26 +       avefreei = le32_to_cpu(sbi->s_es->s_free_inodes_count) / ngroups;
27 +
28 +       for (group = 0; group < ngroups; group++) {
29 +               desc = ext3_get_group_desc(sb, group, &bh);
30 +               if (!desc || !desc->bg_free_inodes_count)
31 +                       continue;
32 +               if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
33 +                       continue;
34 +               if (le16_to_cpu(desc->bg_used_dirs_count) > ndir_best)
35 +                       continue;
36 +               if (!*best_desc ||
37 +                   (le16_to_cpu(desc->bg_free_blocks_count) >
38 +                    le16_to_cpu((*best_desc)->bg_free_blocks_count))) {
39 +                       *best_bh = bh;
40 +                       *best_desc = desc;
41 +                       best_group = group;
42 +                       ndir_best = le16_to_cpu(desc->bg_used_dirs_count);
43 +               }
44 +       }
45 +
46 +       return best_group;
47 +}
48 +
49 +static int find_group_other(struct super_block *sb, const struct inode *parent,
50 +                           struct ext3_group_desc **best_desc,
51 +                           struct buffer_head **best_bh)
52 +{
53 +       struct ext3_sb_info *sbi = EXT3_SB(sb);
54 +       int parent_group = EXT3_I(parent)->i_block_group;
55 +       int ngroups = sbi->s_groups_count;
56 +       int avefreeb;
57 +       struct ext3_group_desc *desc;
58 +       struct buffer_head *bh;
59 +       int group, i, best_group = -1;
60 +
61 +       *best_desc = NULL;
62 +       *best_bh = NULL;
63 +
64 +       /*
65 +        * Try to place the inode in its parent directory
66 +        */
67 +       group = parent_group;
68 +       desc = ext3_get_group_desc (sb, group, &bh);
69 +       if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
70 +           le16_to_cpu(desc->bg_free_blocks_count)) {
71 +               *best_desc = desc;
72 +               *best_bh = bh;
73 +               return group;
74 +       }
75 +
76 +       /*
77 +        * We're going to place this inode in a different blockgroup from its
78 +        * parent.  We want to cause files in a common directory to all land in
79 +        * the same blockgroup if it has space.  But we want files which are
80 +        * in a different directory which shares a blockgroup with our parent
81 +        * to land in a different blockgroup.
82 +        *
83 +        * So add our directory's i_ino into the starting point for the hash.
84 +        */
85 +       group = (group + parent->i_ino) % ngroups;
86 +
87 +       avefreeb = le32_to_cpu(sbi->s_es->s_free_blocks_count) /
88 +               sbi->s_groups_count / ngroups;
89 +
90 +       /*
91 +        * Use a quadratic hash to find a group with a free inode and some free
92 +        * blocks.
93 +        */
94 +       for (i = 1; i < ngroups; i <<= 1) {
95 +               group += i;
96 +               if (group >= ngroups)
97 +                       group -= ngroups;
98 +               desc = ext3_get_group_desc(sb, group, &bh);
99 +               if (!desc || !desc->bg_free_inodes_count)
100 +                       continue;
101 +               if (le16_to_cpu(desc->bg_free_blocks_count) > avefreeb) {
102 +                       *best_bh = bh;
103 +                       *best_desc = desc;
104 +                       return group;
105 +               }
106 +       }
107 +
108 +       /*
109 +        * That failed: try linear search for a group with free inodes and
110 +        * preferrably free blocks, returning as soon as we find a good one.
111 +        */
112 +       group = sbi->s_last_group;
113 +       for (i = 0; i < ngroups; i++) {
114 +               if (++group >= ngroups)
115 +                       group = 0;
116 +               desc = ext3_get_group_desc(sb, group, &bh);
117 +               if (!desc || !desc->bg_free_inodes_count)
118 +                       continue;
119 +               if (!*best_desc ||
120 +                   (le16_to_cpu(desc->bg_free_blocks_count) >
121 +                    le16_to_cpu((*best_desc)->bg_free_blocks_count))) {
122 +                       *best_bh = bh;
123 +                       *best_desc = desc;
124 +                       best_group = group;
125 +                       if (le16_to_cpu(desc->bg_free_blocks_count) >= avefreeb)
126 +                               break;
127 +               }
128 +       }
129 +       sbi->s_last_group = best_group;
130 +
131 +       return best_group;
132 +}
133 +
134  struct inode * ext3_new_inode(handle_t *handle, const struct inode * dir,
135                               int mode, unsigned long goal)
136  {
137         struct super_block * sb;
138         struct buffer_head * bh;
139         struct buffer_head * bh2;
140 -       int i, j, avefreei;
141 +       int i, j;
142         struct inode * inode;
143         int bitmap_nr;
144         struct ext3_group_desc * gdp;
145 -       struct ext3_group_desc * tmp;
146         struct ext3_super_block * es;
147         struct ext3_iloc iloc;
148         int err = 0;
149 @@ -392,72 +513,10 @@
150         }
151  
152  repeat:
153 -       gdp = NULL;
154 -       i = 0;
155 -
156 -       if (S_ISDIR(mode)) {
157 -               avefreei = le32_to_cpu(es->s_free_inodes_count) /
158 -                       sb->u.ext3_sb.s_groups_count;
159 -               if (!gdp) {
160 -                       for (j = 0; j < sb->u.ext3_sb.s_groups_count; j++) {
161 -                               struct buffer_head *temp_buffer;
162 -                               tmp = ext3_get_group_desc (sb, j, &temp_buffer);
163 -                               if (tmp &&
164 -                                   le16_to_cpu(tmp->bg_free_inodes_count) &&
165 -                                   le16_to_cpu(tmp->bg_free_inodes_count) >=
166 -                                                       avefreei) {
167 -                                       if (!gdp || (le16_to_cpu(tmp->bg_free_blocks_count) >
168 -                                               le16_to_cpu(gdp->bg_free_blocks_count))) {
169 -                                               i = j;
170 -                                               gdp = tmp;
171 -                                               bh2 = temp_buffer;
172 -                                       }
173 -                               }
174 -                       }
175 -               }
176 -       } else {
177 -               /*
178 -                * Try to place the inode in its parent directory
179 -                */
180 -               i = dir->u.ext3_i.i_block_group;
181 -               tmp = ext3_get_group_desc (sb, i, &bh2);
182 -               if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
183 -                       gdp = tmp;
184 -               else
185 -               {
186 -                       /*
187 -                        * Use a quadratic hash to find a group with a
188 -                        * free inode
189 -                        */
190 -                       for (j = 1; j < sb->u.ext3_sb.s_groups_count; j <<= 1) {
191 -                               i += j;
192 -                               if (i >= sb->u.ext3_sb.s_groups_count)
193 -                                       i -= sb->u.ext3_sb.s_groups_count;
194 -                               tmp = ext3_get_group_desc (sb, i, &bh2);
195 -                               if (tmp &&
196 -                                   le16_to_cpu(tmp->bg_free_inodes_count)) {
197 -                                       gdp = tmp;
198 -                                       break;
199 -                               }
200 -                       }
201 -               }
202 -               if (!gdp) {
203 -                       /*
204 -                        * That failed: try linear search for a free inode
205 -                        */
206 -                       i = dir->u.ext3_i.i_block_group + 1;
207 -                       for (j = 2; j < sb->u.ext3_sb.s_groups_count; j++) {
208 -                               if (++i >= sb->u.ext3_sb.s_groups_count)
209 -                                       i = 0;
210 -                               tmp = ext3_get_group_desc (sb, i, &bh2);
211 -                               if (tmp &&
212 -                                   le16_to_cpu(tmp->bg_free_inodes_count)) {
213 -                                       gdp = tmp;
214 -                                       break;
215 -                               }
216 -                       }
217 -               }
218 -       }
219 +       if (S_ISDIR(mode))
220 +               i = find_group_dir(sb, dir, &gdp, &bh2);
221 +       else
222 +               i = find_group_other(sb, dir, &gdp, &bh2);
223  
224         err = -ENOSPC;
225         if (!gdp)
226 Index: linux-2.4.21-suse2/include/linux/ext3_fs_sb.h
227 ===================================================================
228 --- linux-2.4.21-suse2.orig/include/linux/ext3_fs_sb.h  2005-08-04 09:14:21.000000000 -0600
229 +++ linux-2.4.21-suse2/include/linux/ext3_fs_sb.h       2005-08-04 09:19:32.000000000 -0600
230 @@ -45,6 +45,7 @@
231         unsigned long s_gdb_count;      /* Number of group descriptor blocks */
232         unsigned long s_desc_per_block; /* Number of group descriptors per block */
233         unsigned long s_groups_count;   /* Number of groups in the fs */
234 +       unsigned long s_last_group;     /* Last group used for inode allocation */
235         struct buffer_head * s_sbh;     /* Buffer containing the super block */
236         struct ext3_super_block * s_es; /* Pointer to the super block in the buffer */
237         struct buffer_head ** s_group_desc;