- Reorganize locking scheme to batch two atomic operation in to one. - Fix possible undefined pointer deference. - Even if group descriptor stats aren't assessable we have to update inode bitmaps. Signed-off-by: Dmitry Monakhov <dmonakhov@xxxxxxxxxx> --- fs/ext3/ialloc.c | 62 +++++++++++++++++++++++++++-------------------------- 1 files changed, 32 insertions(+), 30 deletions(-) diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index ef9008b..8352a68 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -98,7 +98,7 @@ void ext3_free_inode (handle_t *handle, struct inode * inode) struct ext3_group_desc * gdp; struct ext3_super_block * es; struct ext3_sb_info *sbi; - int fatal = 0, err; + int fatal = 0, err, cleared = 0; if (atomic_read(&inode->i_count) > 1) { printk ("ext3_free_inode: inode has count=%d\n", @@ -150,38 +150,40 @@ void ext3_free_inode (handle_t *handle, struct inode * inode) if (fatal) goto error_return; - /* Ok, now we can actually update the inode bitmaps.. */ - if (!ext3_clear_bit_atomic(sb_bgl_lock(sbi, block_group), - bit, bitmap_bh->b_data)) - ext3_error (sb, "ext3_free_inode", - "bit already cleared for inode %lu", ino); - else { - gdp = ext3_get_group_desc (sb, block_group, &bh2); - + fatal = -ESRCH; + gdp = ext3_get_group_desc (sb, block_group, &bh2); + if (gdp) { BUFFER_TRACE(bh2, "get_write_access"); fatal = ext3_journal_get_write_access(handle, bh2); - if (fatal) goto error_return; - - if (gdp) { - spin_lock(sb_bgl_lock(sbi, block_group)); - le16_add_cpu(&gdp->bg_free_inodes_count, 1); - if (is_directory) - 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) - percpu_counter_dec(&sbi->s_dirs_counter); - - } - BUFFER_TRACE(bh2, "call ext3_journal_dirty_metadata"); - err = ext3_journal_dirty_metadata(handle, bh2); - if (!fatal) fatal = err; } - BUFFER_TRACE(bitmap_bh, "call ext3_journal_dirty_metadata"); - err = ext3_journal_dirty_metadata(handle, bitmap_bh); - if (!fatal) - fatal = err; + spin_lock(sb_bgl_lock(sbi, block_group)); + if (fatal) { + /* Skip group descriptor update, update only inode bitmaps */ + cleared = ext3_clear_bit(bit, bitmap_bh->b_data); + spin_unlock(sb_bgl_lock(sbi, block_group)); + goto out; + } + /* Ok, now we can actually update the inode bitmaps.. */ + cleared = ext3_clear_bit(bit, bitmap_bh->b_data); + if (!cleared) { + spin_unlock(sb_bgl_lock(sbi, block_group)); + goto out; + } + le16_add_cpu(&gdp->bg_free_inodes_count, 1); + if (is_directory) + 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) + percpu_counter_dec(&sbi->s_dirs_counter); + BUFFER_TRACE(bh2, "call ext3_journal_dirty_metadata"); + err = ext3_journal_dirty_metadata(handle, bh2); +out: + if (cleared) { + BUFFER_TRACE(bitmap_bh, "call ext3_journal_dirty_metadata"); + fatal = ext3_journal_dirty_metadata(handle, bitmap_bh); + } error_return: brelse(bitmap_bh); ext3_std_error(sb, fatal); -- 1.6.6.1 -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html