]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Jan Kara <jack@suse.cz> |
2 | Subject: ocfs2: Fix possible deadlock in quota recovery | |
3 | Patch-mainline: 2.6.31 | |
4 | ||
5 | In ocfs2_finish_quota_recovery() we acquired global quota file lock and started | |
6 | recovering local quota file. During this process we need to get quota | |
7 | structures, which calls ocfs2_dquot_acquire() which gets global quota file lock | |
8 | again. This second lock can block in case some other node has requested the | |
9 | quota file lock in the mean time. Fix the problem by moving quota file locking | |
10 | down into the function where it is really needed. Then dqget() or dqput() | |
11 | won't be called with the lock held. | |
12 | ||
13 | Signed-off-by: Jan Kara <jack@suse.cz> | |
14 | --- | |
15 | fs/ocfs2/quota_local.c | 16 +++++++++------- | |
16 | 1 files changed, 9 insertions(+), 7 deletions(-) | |
17 | ||
18 | Index: linux-2.6.27-SLE11_BRANCH/fs/ocfs2/quota_local.c | |
19 | =================================================================== | |
20 | --- linux-2.6.27-SLE11_BRANCH.orig/fs/ocfs2/quota_local.c 2009-07-16 13:16:27.000000000 +0200 | |
21 | +++ linux-2.6.27-SLE11_BRANCH/fs/ocfs2/quota_local.c 2009-07-16 13:20:05.000000000 +0200 | |
22 | @@ -438,10 +438,6 @@ | |
23 | ||
24 | mlog_entry("ino=%lu type=%u", (unsigned long)lqinode->i_ino, type); | |
25 | ||
26 | - status = ocfs2_lock_global_qf(oinfo, 1); | |
27 | - if (status < 0) | |
28 | - goto out; | |
29 | - | |
30 | list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) { | |
31 | chunk = rchunk->rc_chunk; | |
32 | hbh = ocfs2_bread(lqinode, ol_quota_chunk_block(sb, chunk), | |
33 | @@ -471,12 +467,18 @@ | |
34 | type); | |
35 | goto out_put_bh; | |
36 | } | |
37 | + status = ocfs2_lock_global_qf(oinfo, 1); | |
38 | + if (status < 0) { | |
39 | + mlog_errno(status); | |
40 | + goto out_put_dquot; | |
41 | + } | |
42 | + | |
43 | handle = ocfs2_start_trans(OCFS2_SB(sb), | |
44 | OCFS2_QSYNC_CREDITS); | |
45 | if (IS_ERR(handle)) { | |
46 | status = PTR_ERR(handle); | |
47 | mlog_errno(status); | |
48 | - goto out_put_dquot; | |
49 | + goto out_drop_lock; | |
50 | } | |
51 | mutex_lock(&sb_dqopt(sb)->dqio_mutex); | |
52 | spin_lock(&dq_data_lock); | |
53 | @@ -514,6 +516,8 @@ | |
54 | out_commit: | |
55 | mutex_unlock(&sb_dqopt(sb)->dqio_mutex); | |
56 | ocfs2_commit_trans(OCFS2_SB(sb), handle); | |
57 | +out_drop_lock: | |
58 | + ocfs2_unlock_global_qf(oinfo, 1); | |
59 | out_put_dquot: | |
60 | dqput(dquot); | |
61 | out_put_bh: | |
62 | @@ -528,8 +532,6 @@ | |
63 | if (status < 0) | |
64 | break; | |
65 | } | |
66 | - ocfs2_unlock_global_qf(oinfo, 1); | |
67 | -out: | |
68 | if (status < 0) | |
69 | free_recovery_list(&(rec->r_list[type])); | |
70 | mlog_exit(status); |