]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.32.17/0040-ext4-clean-up-inode-bitmaps-manipulation-in-ext4_fre.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.32.17 / 0040-ext4-clean-up-inode-bitmaps-manipulation-in-ext4_fre.patch
CommitLineData
7d777456
GKH
1From ae42cce7e825bdc82a8e9c30a87c342d1e364e57 Mon Sep 17 00:00:00 2001
2From: Dmitry Monakhov <dmonakhov@openvz.org>
3Date: Sun, 30 May 2010 22:49:54 -0400
4Subject: ext4: clean up inode bitmaps manipulation in ext4_free_inode
5
6commit d17413c08cd2b1dd2bf2cfdbb0f7b736b2b2b15c upstrea (as of v2..34-git13)
7
8- Reorganize locking scheme to batch two atomic operation in to one.
9 This also allow us to state what healthy group must obey following rule
10 ext4_free_inodes_count(sb, gdp) == ext4_count_free(inode_bitmap, NUM);
11- Fix possible undefined pointer dereference.
12- Even if group descriptor stats aren't accessible we have to update
13 inode bitmaps.
14- Move non-group members update out of group_lock.
15
16Note: this commit has been observed to fix fs corruption problems
17under heavy fs load
18
19Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
20Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
21Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
22---
23 fs/ext4/ialloc.c | 85 +++++++++++++++++++++++++------------------------------
24 1 file changed, 39 insertions(+), 46 deletions(-)
25
26--- a/fs/ext4/ialloc.c
27+++ b/fs/ext4/ialloc.c
28@@ -244,57 +244,50 @@ void ext4_free_inode(handle_t *handle, s
29 if (fatal)
30 goto error_return;
31
32- /* Ok, now we can actually update the inode bitmaps.. */
33- cleared = ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group),
34- bit, bitmap_bh->b_data);
35- if (!cleared)
36- ext4_error(sb, "ext4_free_inode",
37- "bit already cleared for inode %lu", ino);
38- else {
39- gdp = ext4_get_group_desc(sb, block_group, &bh2);
40-
41+ fatal = -ESRCH;
42+ gdp = ext4_get_group_desc(sb, block_group, &bh2);
43+ if (gdp) {
44 BUFFER_TRACE(bh2, "get_write_access");
45 fatal = ext4_journal_get_write_access(handle, bh2);
46- if (fatal) goto error_return;
47-
48- if (gdp) {
49- ext4_lock_group(sb, block_group);
50- count = ext4_free_inodes_count(sb, gdp) + 1;
51- ext4_free_inodes_set(sb, gdp, count);
52- if (is_directory) {
53- count = ext4_used_dirs_count(sb, gdp) - 1;
54- ext4_used_dirs_set(sb, gdp, count);
55- if (sbi->s_log_groups_per_flex) {
56- ext4_group_t f;
57-
58- f = ext4_flex_group(sbi, block_group);
59- atomic_dec(&sbi->s_flex_groups[f].used_dirs);
60- }
61-
62- }
63- gdp->bg_checksum = ext4_group_desc_csum(sbi,
64- block_group, gdp);
65- ext4_unlock_group(sb, block_group);
66- percpu_counter_inc(&sbi->s_freeinodes_counter);
67- if (is_directory)
68- percpu_counter_dec(&sbi->s_dirs_counter);
69+ }
70+ ext4_lock_group(sb, block_group);
71+ cleared = ext4_clear_bit(bit, bitmap_bh->b_data);
72+ if (fatal || !cleared) {
73+ ext4_unlock_group(sb, block_group);
74+ goto out;
75+ }
76
77- if (sbi->s_log_groups_per_flex) {
78- ext4_group_t f;
79+ count = ext4_free_inodes_count(sb, gdp) + 1;
80+ ext4_free_inodes_set(sb, gdp, count);
81+ if (is_directory) {
82+ count = ext4_used_dirs_count(sb, gdp) - 1;
83+ ext4_used_dirs_set(sb, gdp, count);
84+ percpu_counter_dec(&sbi->s_dirs_counter);
85+ }
86+ gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
87+ ext4_unlock_group(sb, block_group);
88
89- f = ext4_flex_group(sbi, block_group);
90- atomic_inc(&sbi->s_flex_groups[f].free_inodes);
91- }
92- }
93- BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
94- err = ext4_handle_dirty_metadata(handle, NULL, bh2);
95- if (!fatal) fatal = err;
96+ percpu_counter_inc(&sbi->s_freeinodes_counter);
97+ if (sbi->s_log_groups_per_flex) {
98+ ext4_group_t f = ext4_flex_group(sbi, block_group);
99+
100+ atomic_inc(&sbi->s_flex_groups[f].free_inodes);
101+ if (is_directory)
102+ atomic_dec(&sbi->s_flex_groups[f].used_dirs);
103 }
104- BUFFER_TRACE(bitmap_bh, "call ext4_handle_dirty_metadata");
105- err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
106- if (!fatal)
107- fatal = err;
108- sb->s_dirt = 1;
109+ BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
110+ fatal = ext4_handle_dirty_metadata(handle, NULL, bh2);
111+out:
112+ if (cleared) {
113+ BUFFER_TRACE(bitmap_bh, "call ext4_handle_dirty_metadata");
114+ err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
115+ if (!fatal)
116+ fatal = err;
117+ sb->s_dirt = 1;
118+ } else
119+ ext4_error(sb, "ext4_free_inode",
120+ "bit already cleared for inode %lu", ino);
121+
122 error_return:
123 brelse(bitmap_bh);
124 ext4_std_error(sb, fatal);