Commit f33d4d3f authored by Theodore Y. Ts'o's avatar Theodore Y. Ts'o Committed by Linus Torvalds

Fix and simplify port of Orlov allocator to ext3.

My ext3 port of the Orlov allocator was buggy; the block group 
descriptor counts for free inodes and directories were getting 
doubly decremented / incremented.  This patch fixes this, as well
as simplifying the code.
parent 7c4e5b98
...@@ -208,7 +208,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent) ...@@ -208,7 +208,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
int ngroups = EXT3_SB(sb)->s_groups_count; int ngroups = EXT3_SB(sb)->s_groups_count;
int avefreei = le32_to_cpu(es->s_free_inodes_count) / ngroups; int avefreei = le32_to_cpu(es->s_free_inodes_count) / ngroups;
struct ext3_group_desc *desc, *best_desc = NULL; struct ext3_group_desc *desc, *best_desc = NULL;
struct buffer_head *bh, *best_bh = NULL; struct buffer_head *bh;
int group, best_group = -1; int group, best_group = -1;
for (group = 0; group < ngroups; group++) { for (group = 0; group < ngroups; group++) {
...@@ -222,16 +222,8 @@ static int find_group_dir(struct super_block *sb, struct inode *parent) ...@@ -222,16 +222,8 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
le16_to_cpu(best_desc->bg_free_blocks_count))) { le16_to_cpu(best_desc->bg_free_blocks_count))) {
best_group = group; best_group = group;
best_desc = desc; best_desc = desc;
best_bh = bh;
} }
} }
if (!best_desc)
return -1;
best_desc->bg_free_inodes_count =
cpu_to_le16(le16_to_cpu(best_desc->bg_free_inodes_count) - 1);
best_desc->bg_used_dirs_count =
cpu_to_le16(le16_to_cpu(best_desc->bg_used_dirs_count) + 1);
mark_buffer_dirty(best_bh);
return best_group; return best_group;
} }
...@@ -281,8 +273,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) ...@@ -281,8 +273,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
if ((parent == sb->s_root->d_inode) || if ((parent == sb->s_root->d_inode) ||
(parent->i_flags & EXT3_TOPDIR_FL)) { (parent->i_flags & EXT3_TOPDIR_FL)) {
struct ext3_group_desc *best_desc = NULL;
struct buffer_head *best_bh = NULL;
int best_ndir = inodes_per_group; int best_ndir = inodes_per_group;
int best_group = -1; int best_group = -1;
...@@ -301,15 +291,9 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) ...@@ -301,15 +291,9 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
continue; continue;
best_group = group; best_group = group;
best_ndir = le16_to_cpu(desc->bg_used_dirs_count); best_ndir = le16_to_cpu(desc->bg_used_dirs_count);
best_desc = desc;
best_bh = bh;
}
if (best_group >= 0) {
desc = best_desc;
bh = best_bh;
group = best_group;
goto found;
} }
if (best_group >= 0)
return best_group;
goto fallback; goto fallback;
} }
...@@ -341,7 +325,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) ...@@ -341,7 +325,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
continue; continue;
if (le16_to_cpu(desc->bg_free_blocks_count) < min_blocks) if (le16_to_cpu(desc->bg_free_blocks_count) < min_blocks)
continue; continue;
goto found; return group;
} }
fallback: fallback:
...@@ -351,19 +335,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) ...@@ -351,19 +335,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
if (!desc || !desc->bg_free_inodes_count) if (!desc || !desc->bg_free_inodes_count)
continue; continue;
if (le16_to_cpu(desc->bg_free_inodes_count) >= avefreei) if (le16_to_cpu(desc->bg_free_inodes_count) >= avefreei)
goto found; return group;
} }
return -1; return -1;
found:
desc->bg_free_inodes_count =
cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) - 1);
desc->bg_used_dirs_count =
cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) + 1);
sbi->s_dir_count++;
mark_buffer_dirty(bh);
return group;
} }
static int find_group_other(struct super_block *sb, struct inode *parent) static int find_group_other(struct super_block *sb, struct inode *parent)
...@@ -380,7 +355,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent) ...@@ -380,7 +355,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
group = parent_group; group = parent_group;
desc = ext3_get_group_desc (sb, group, &bh); desc = ext3_get_group_desc (sb, group, &bh);
if (desc && le16_to_cpu(desc->bg_free_inodes_count)) if (desc && le16_to_cpu(desc->bg_free_inodes_count))
goto found; return group;
/* /*
* Use a quadratic hash to find a group with a * Use a quadratic hash to find a group with a
...@@ -392,7 +367,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent) ...@@ -392,7 +367,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
group -= ngroups; group -= ngroups;
desc = ext3_get_group_desc (sb, group, &bh); desc = ext3_get_group_desc (sb, group, &bh);
if (desc && le16_to_cpu(desc->bg_free_inodes_count)) if (desc && le16_to_cpu(desc->bg_free_inodes_count))
goto found; return group;
} }
/* /*
...@@ -404,16 +379,10 @@ static int find_group_other(struct super_block *sb, struct inode *parent) ...@@ -404,16 +379,10 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
group = 0; group = 0;
desc = ext3_get_group_desc (sb, group, &bh); desc = ext3_get_group_desc (sb, group, &bh);
if (desc && le16_to_cpu(desc->bg_free_inodes_count)) if (desc && le16_to_cpu(desc->bg_free_inodes_count))
goto found; return group;
} }
return -1; return -1;
found:
desc->bg_free_inodes_count =
cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) - 1);
mark_buffer_dirty(bh);
return group;
} }
/* /*
...@@ -521,9 +490,11 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode) ...@@ -521,9 +490,11 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
if (err) goto fail; if (err) goto fail;
gdp->bg_free_inodes_count = gdp->bg_free_inodes_count =
cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1); cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
if (S_ISDIR(mode)) if (S_ISDIR(mode)) {
gdp->bg_used_dirs_count = gdp->bg_used_dirs_count =
cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1); cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
EXT3_SB(sb)->s_dir_count++;
}
BUFFER_TRACE(bh2, "call ext3_journal_dirty_metadata"); BUFFER_TRACE(bh2, "call ext3_journal_dirty_metadata");
err = ext3_journal_dirty_metadata(handle, bh2); err = ext3_journal_dirty_metadata(handle, bh2);
if (err) goto fail; if (err) goto fail;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment