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
6 * directories already is chosen.
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.
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)
16 + struct ext3_sb_info *sbi = EXT3_SB(sb);
17 + int ngroups = sbi->s_groups_count;
19 + struct ext3_group_desc *desc;
20 + struct buffer_head *bh;
21 + int group, best_group = -1, ndir_best = 999999999;
26 + avefreei = le32_to_cpu(sbi->s_es->s_free_inodes_count) / ngroups;
28 + for (group = 0; group < ngroups; group++) {
29 + desc = ext3_get_group_desc(sb, group, &bh);
30 + if (!desc || !desc->bg_free_inodes_count)
32 + if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
34 + if (le16_to_cpu(desc->bg_used_dirs_count) > ndir_best)
37 + (le16_to_cpu(desc->bg_free_blocks_count) >
38 + le16_to_cpu((*best_desc)->bg_free_blocks_count))) {
42 + ndir_best = le16_to_cpu(desc->bg_used_dirs_count);
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)
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;
57 + struct ext3_group_desc *desc;
58 + struct buffer_head *bh;
59 + int group, i, best_group = -1;
65 + * Try to place the inode in its parent directory
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)) {
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.
83 + * So add our directory's i_ino into the starting point for the hash.
85 + group = (group + parent->i_ino) % ngroups;
87 + avefreeb = le32_to_cpu(sbi->s_es->s_free_blocks_count) /
88 + sbi->s_groups_count / ngroups;
91 + * Use a quadratic hash to find a group with a free inode and some free
94 + for (i = 1; i < ngroups; i <<= 1) {
96 + if (group >= ngroups)
98 + desc = ext3_get_group_desc(sb, group, &bh);
99 + if (!desc || !desc->bg_free_inodes_count)
101 + if (le16_to_cpu(desc->bg_free_blocks_count) > avefreeb) {
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.
112 + group = sbi->s_last_group;
113 + for (i = 0; i < ngroups; i++) {
114 + if (++group >= ngroups)
116 + desc = ext3_get_group_desc(sb, group, &bh);
117 + if (!desc || !desc->bg_free_inodes_count)
120 + (le16_to_cpu(desc->bg_free_blocks_count) >
121 + le16_to_cpu((*best_desc)->bg_free_blocks_count))) {
124 + best_group = group;
125 + if (le16_to_cpu(desc->bg_free_blocks_count) >= avefreeb)
129 + sbi->s_last_group = best_group;
134 struct inode * ext3_new_inode(handle_t *handle, const struct inode * dir,
135 int mode, unsigned long goal)
137 struct super_block * sb;
138 struct buffer_head * bh;
139 struct buffer_head * bh2;
140 - int i, j, avefreei;
142 struct inode * inode;
144 struct ext3_group_desc * gdp;
145 - struct ext3_group_desc * tmp;
146 struct ext3_super_block * es;
147 struct ext3_iloc iloc;
149 @@ -392,72 +513,10 @@
156 - if (S_ISDIR(mode)) {
157 - avefreei = le32_to_cpu(es->s_free_inodes_count) /
158 - sb->u.ext3_sb.s_groups_count;
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);
164 - le16_to_cpu(tmp->bg_free_inodes_count) &&
165 - le16_to_cpu(tmp->bg_free_inodes_count) >=
167 - if (!gdp || (le16_to_cpu(tmp->bg_free_blocks_count) >
168 - le16_to_cpu(gdp->bg_free_blocks_count))) {
178 - * Try to place the inode in its parent directory
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))
187 - * Use a quadratic hash to find a group with a
190 - for (j = 1; j < sb->u.ext3_sb.s_groups_count; j <<= 1) {
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);
196 - le16_to_cpu(tmp->bg_free_inodes_count)) {
204 - * That failed: try linear search for a free inode
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)
210 - tmp = ext3_get_group_desc (sb, i, &bh2);
212 - le16_to_cpu(tmp->bg_free_inodes_count)) {
220 + i = find_group_dir(sb, dir, &gdp, &bh2);
222 + i = find_group_other(sb, dir, &gdp, &bh2);
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
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;