]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - 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
1 From ae42cce7e825bdc82a8e9c30a87c342d1e364e57 Mon Sep 17 00:00:00 2001
2 From: Dmitry Monakhov <dmonakhov@openvz.org>
3 Date: Sun, 30 May 2010 22:49:54 -0400
4 Subject: ext4: clean up inode bitmaps manipulation in ext4_free_inode
5
6 commit 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
16 Note: this commit has been observed to fix fs corruption problems
17 under heavy fs load
18
19 Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
20 Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
21 Signed-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);