[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Wed, 14 Apr 2010 15:23:03 +0400
From: Dmitry Monakhov <dmonakhov@...nvz.org>
To: linux-ext4@...r.kernel.org
Cc: jack@...e.cz, Dmitry Monakhov <dmonakhov@...nvz.org>
Subject: [PATCH 1/2] ext3: fix inode bitmaps manipulation in free_inode
- 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@...nvz.org>
---
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@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists