X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=fs%2Fext3%2Fialloc.c;h=4f4020c54683acbc2969e01e531b8e117ef6a005;hb=635440c0235537a3f0a90ed5b6f8cd8a5da862de;hp=e45dbd65173624c10796655baa0566c98ece4f29;hpb=a77c64c1a641950626181b4857abb701d8f38ccc;p=linux-2.6-omap-h63xx.git diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index e45dbd65173..4f4020c5468 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -164,11 +164,9 @@ void ext3_free_inode (handle_t *handle, struct inode * inode) if (gdp) { spin_lock(sb_bgl_lock(sbi, block_group)); - gdp->bg_free_inodes_count = cpu_to_le16( - le16_to_cpu(gdp->bg_free_inodes_count) + 1); + le16_add_cpu(&gdp->bg_free_inodes_count, 1); if (is_directory) - gdp->bg_used_dirs_count = cpu_to_le16( - le16_to_cpu(gdp->bg_used_dirs_count) - 1); + le16_add_cpu(&gdp->bg_used_dirs_count, -1); spin_unlock(sb_bgl_lock(sbi, block_group)); percpu_counter_inc(&sbi->s_freeinodes_counter); if (is_directory) @@ -204,14 +202,13 @@ static int find_group_dir(struct super_block *sb, struct inode *parent) int ngroups = EXT3_SB(sb)->s_groups_count; unsigned int freei, avefreei; struct ext3_group_desc *desc, *best_desc = NULL; - struct buffer_head *bh; int group, best_group = -1; freei = percpu_counter_read_positive(&EXT3_SB(sb)->s_freeinodes_counter); avefreei = freei / ngroups; for (group = 0; group < ngroups; group++) { - desc = ext3_get_group_desc (sb, group, &bh); + desc = ext3_get_group_desc (sb, group, NULL); if (!desc || !desc->bg_free_inodes_count) continue; if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei) @@ -269,7 +266,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) ext3_grpblk_t min_blocks; int group = -1, i; struct ext3_group_desc *desc; - struct buffer_head *bh; freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); avefreei = freei / ngroups; @@ -286,7 +282,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) parent_group = (unsigned)group % ngroups; for (i = 0; i < ngroups; i++) { group = (parent_group + i) % ngroups; - desc = ext3_get_group_desc (sb, group, &bh); + desc = ext3_get_group_desc (sb, group, NULL); if (!desc || !desc->bg_free_inodes_count) continue; if (le16_to_cpu(desc->bg_used_dirs_count) >= best_ndir) @@ -319,7 +315,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) for (i = 0; i < ngroups; i++) { group = (parent_group + i) % ngroups; - desc = ext3_get_group_desc (sb, group, &bh); + desc = ext3_get_group_desc (sb, group, NULL); if (!desc || !desc->bg_free_inodes_count) continue; if (le16_to_cpu(desc->bg_used_dirs_count) >= max_dirs) @@ -334,7 +330,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) fallback: for (i = 0; i < ngroups; i++) { group = (parent_group + i) % ngroups; - desc = ext3_get_group_desc (sb, group, &bh); + desc = ext3_get_group_desc (sb, group, NULL); if (!desc || !desc->bg_free_inodes_count) continue; if (le16_to_cpu(desc->bg_free_inodes_count) >= avefreei) @@ -358,14 +354,13 @@ static int find_group_other(struct super_block *sb, struct inode *parent) int parent_group = EXT3_I(parent)->i_block_group; int ngroups = EXT3_SB(sb)->s_groups_count; struct ext3_group_desc *desc; - struct buffer_head *bh; int group, i; /* * Try to place the inode in its parent directory */ group = parent_group; - desc = ext3_get_group_desc (sb, group, &bh); + desc = ext3_get_group_desc (sb, group, NULL); if (desc && le16_to_cpu(desc->bg_free_inodes_count) && le16_to_cpu(desc->bg_free_blocks_count)) return group; @@ -389,7 +384,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent) group += i; if (group >= ngroups) group -= ngroups; - desc = ext3_get_group_desc (sb, group, &bh); + desc = ext3_get_group_desc (sb, group, NULL); if (desc && le16_to_cpu(desc->bg_free_inodes_count) && le16_to_cpu(desc->bg_free_blocks_count)) return group; @@ -403,7 +398,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent) for (i = 0; i < ngroups; i++) { if (++group >= ngroups) group = 0; - desc = ext3_get_group_desc (sb, group, &bh); + desc = ext3_get_group_desc (sb, group, NULL); if (desc && le16_to_cpu(desc->bg_free_inodes_count)) return group; } @@ -530,11 +525,9 @@ got: err = ext3_journal_get_write_access(handle, bh2); if (err) goto fail; spin_lock(sb_bgl_lock(sbi, group)); - gdp->bg_free_inodes_count = - cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1); + le16_add_cpu(&gdp->bg_free_inodes_count, -1); if (S_ISDIR(mode)) { - gdp->bg_used_dirs_count = - cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1); + le16_add_cpu(&gdp->bg_used_dirs_count, 1); } spin_unlock(sb_bgl_lock(sbi, group)); BUFFER_TRACE(bh2, "call ext3_journal_dirty_metadata"); @@ -645,14 +638,15 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino) unsigned long max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count); unsigned long block_group; int bit; - struct buffer_head *bitmap_bh = NULL; + struct buffer_head *bitmap_bh; struct inode *inode = NULL; + long err = -EIO; /* Error cases - e2fsck has already cleaned up for us */ if (ino > max_ino) { ext3_warning(sb, __FUNCTION__, "bad orphan ino %lu! e2fsck was run?", ino); - goto out; + goto error; } block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb); @@ -661,38 +655,49 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino) if (!bitmap_bh) { ext3_warning(sb, __FUNCTION__, "inode bitmap error for orphan %lu", ino); - goto out; + goto error; } /* Having the inode bit set should be a 100% indicator that this * is a valid orphan (no e2fsck run on fs). Orphans also include * inodes that were being truncated, so we can't check i_nlink==0. */ - if (!ext3_test_bit(bit, bitmap_bh->b_data) || - !(inode = iget(sb, ino)) || is_bad_inode(inode) || - NEXT_ORPHAN(inode) > max_ino) { - ext3_warning(sb, __FUNCTION__, - "bad orphan inode %lu! e2fsck was run?", ino); - printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n", - bit, (unsigned long long)bitmap_bh->b_blocknr, - ext3_test_bit(bit, bitmap_bh->b_data)); - printk(KERN_NOTICE "inode=%p\n", inode); - if (inode) { - printk(KERN_NOTICE "is_bad_inode(inode)=%d\n", - is_bad_inode(inode)); - printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", - NEXT_ORPHAN(inode)); - printk(KERN_NOTICE "max_ino=%lu\n", max_ino); - } + if (!ext3_test_bit(bit, bitmap_bh->b_data)) + goto bad_orphan; + + inode = ext3_iget(sb, ino); + if (IS_ERR(inode)) + goto iget_failed; + + if (NEXT_ORPHAN(inode) > max_ino) + goto bad_orphan; + brelse(bitmap_bh); + return inode; + +iget_failed: + err = PTR_ERR(inode); + inode = NULL; +bad_orphan: + ext3_warning(sb, __FUNCTION__, + "bad orphan inode %lu! e2fsck was run?", ino); + printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n", + bit, (unsigned long long)bitmap_bh->b_blocknr, + ext3_test_bit(bit, bitmap_bh->b_data)); + printk(KERN_NOTICE "inode=%p\n", inode); + if (inode) { + printk(KERN_NOTICE "is_bad_inode(inode)=%d\n", + is_bad_inode(inode)); + printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", + NEXT_ORPHAN(inode)); + printk(KERN_NOTICE "max_ino=%lu\n", max_ino); /* Avoid freeing blocks if we got a bad deleted inode */ - if (inode && inode->i_nlink == 0) + if (inode->i_nlink == 0) inode->i_blocks = 0; iput(inode); - inode = NULL; } -out: brelse(bitmap_bh); - return inode; +error: + return ERR_PTR(err); } unsigned long ext3_count_free_inodes (struct super_block * sb)