]>
Commit | Line | Data |
---|---|---|
505e0a06 GKH |
1 | From 209f7512d007980fd111a74a064d70a3656079cf Mon Sep 17 00:00:00 2001 |
2 | From: Joseph Qi <joseph.qi@huawei.com> | |
3 | Date: Thu, 6 Aug 2015 15:46:23 -0700 | |
4 | Subject: ocfs2: fix BUG in ocfs2_downconvert_thread_do_work() | |
5 | ||
6 | From: Joseph Qi <joseph.qi@huawei.com> | |
7 | ||
8 | commit 209f7512d007980fd111a74a064d70a3656079cf upstream. | |
9 | ||
10 | The "BUG_ON(list_empty(&osb->blocked_lock_list))" in | |
11 | ocfs2_downconvert_thread_do_work can be triggered in the following case: | |
12 | ||
13 | ocfs2dc has firstly saved osb->blocked_lock_count to local varibale | |
14 | processed, and then processes the dentry lockres. During the dentry | |
15 | put, it calls iput and then deletes rw, inode and open lockres from | |
16 | blocked list in ocfs2_mark_lockres_freeing. And this causes the | |
17 | variable `processed' to not reflect the number of blocked lockres to be | |
18 | processed, which triggers the BUG. | |
19 | ||
20 | Signed-off-by: Joseph Qi <joseph.qi@huawei.com> | |
21 | Cc: Mark Fasheh <mfasheh@suse.com> | |
22 | Cc: Joel Becker <jlbec@evilplan.org> | |
23 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
24 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
25 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
26 | ||
27 | --- | |
28 | fs/ocfs2/dlmglue.c | 10 +++++++--- | |
29 | 1 file changed, 7 insertions(+), 3 deletions(-) | |
30 | ||
31 | --- a/fs/ocfs2/dlmglue.c | |
32 | +++ b/fs/ocfs2/dlmglue.c | |
33 | @@ -3971,9 +3971,13 @@ static void ocfs2_downconvert_thread_do_ | |
34 | osb->dc_work_sequence = osb->dc_wake_sequence; | |
35 | ||
36 | processed = osb->blocked_lock_count; | |
37 | - while (processed) { | |
38 | - BUG_ON(list_empty(&osb->blocked_lock_list)); | |
39 | - | |
40 | + /* | |
41 | + * blocked lock processing in this loop might call iput which can | |
42 | + * remove items off osb->blocked_lock_list. Downconvert up to | |
43 | + * 'processed' number of locks, but stop short if we had some | |
44 | + * removed in ocfs2_mark_lockres_freeing when downconverting. | |
45 | + */ | |
46 | + while (processed && !list_empty(&osb->blocked_lock_list)) { | |
47 | lockres = list_entry(osb->blocked_lock_list.next, | |
48 | struct ocfs2_lock_res, l_blocked_list); | |
49 | list_del_init(&lockres->l_blocked_list); |