Whamcloud - gitweb
LU-162 Export ext4_discard_preallocations for ldiskfs
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ext4-discard-prealloc-after-failed.patch
1
2 [PATCH] discard an inode's preallocated blocks after failed allocation
3 Date:   Tue, 30 Nov 2010 15:22:38 -0800 (PST)
4 From:   jiayingz@google.com (Jiaying Zhang)
5
6 We have seen kernel crashes caused by the BUG_ON in
7 ext4_mb_return_to_preallocation() that checks whether the inode's
8 i_prealloc_list is empty. As I understand, the assumption is that
9 when ext4_mb_return_to_preallocation() is called from ext4_free_blocks(),
10 the inode's preallocation list should have been already discarded.
11 However, although we call ext4_discard_preallocations() during ext4
12 truncate, we don't always call that function in various failure
13 cases before calling ext4_free_blocks(). So it is likely to hit this
14 BUG_ON with disk errors or corrupted fs etc.
15
16 To fix the problem, the following patch adds ext4_discard_preallocation()
17 before ext4_free_blocks() in failed allocation cases. This will discard
18 any preallocated block extent attached to the inode, but I think it is
19 probably what we should be doing with failed allocation.
20
21 I am also curious whether we can drop the ext4_mb_return_to_preallocation()
22 call from ext4_free_blocks(). From the comments above that function, it
23 seems to intent to discard the specified blocks only but all it is currently
24 doing is the BUG_ON check on whether the inode's preallocation list is empty.
25 Is there any plan to extend this function later?
26
27
28 ext4: discard an inode's preallocated blocks after failed allocation so that
29 we won't hit on the BUG_ON check in ext4_mb_return_to_preallocation() later.
30
31 Signed-off-by: Jiaying Zhang <jiayingz@google.com>
32
33 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
34 index 29a4adf..2164df6 100644
35 --- a/fs/ext4/extents.c
36 +++ b/fs/ext4/extents.c
37 @@ -1056,6 +1056,7 @@ cleanup:
38        }
39
40        if (err) {
41 +               ext4_discard_preallocations(inode);
42                /* free all allocated blocks in error case */
43                for (i = 0; i < depth; i++) {
44                        if (!ablocks[i])
45 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
46 index 4f4362c..456cb4a 100644
47 --- a/fs/ext4/inode.c
48 +++ b/fs/ext4/inode.c
49 @@ -690,6 +690,7 @@ allocated:
50        *err = 0;
51        return ret;
52  failed_out:
53 +       ext4_discard_preallocations(inode);
54        for (i = 0; i < index; i++)
55                ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0);
56        return ret;
57 @@ -787,6 +788,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
58        return err;
59  failed:
60        /* Allocation failed, free what we already allocated */
61 +       ext4_discard_preallocations(inode);
62        for (i = 1; i <= n ; i++) {
63                 BUFFER_TRACE(branch[i].bh, "call jbd2_journal_forget");
64                 ext4_journal_forget(handle, branch[i].bh);
65 @@ -878,6 +880,7 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
66        return err;
67
68  err_out:
69 +       ext4_discard_preallocations(inode);
70        for (i = 1; i <= num; i++) {
71                /*
72                 * branch[i].bh is newly allocated, so there is no
73 --
74 To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
75 the body of a message to majordomo@vger.kernel.org
76 More majordomo info at  http://vger.kernel.org/majordomo-info.html