diff options
author | Zhonghua Guo <guozhonghua@h3c.com> | 2014-04-03 17:47:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-03 19:20:55 -0400 |
commit | a35ad97cd48cfab45f4ee5eb0e6f5787a05cab25 (patch) | |
tree | e94ba401f7bcaba9924972ac71c09f465fb50302 /fs/ocfs2 | |
parent | c8d888d9f1469806c339218fc342817eb3b628a8 (diff) |
ocfs2: fix deadlock risk when kmalloc failed in dlm_query_region_handler
In dlm_query_region_handler(), once kmalloc failed, it will unlock
dlm_domain_lock without lock first, then deadlock happens.
Signed-off-by: Zhonghua Guo <guozhonghua@h3c.com>
Signed-off-by: Joseph Qi <joseph.qi@huawei.com>
Reviewed-by: Srinivas Eeda <srinivas.eeda@oracle.com>
Tested-by: Joseph Qi <joseph.qi@huawei.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/dlm/dlmdomain.c | 21 |
1 files changed, 9 insertions, 12 deletions
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 1307a8cff8db..c973690dc0bc 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
@@ -1123,7 +1123,6 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len, | |||
1123 | struct dlm_ctxt *dlm = NULL; | 1123 | struct dlm_ctxt *dlm = NULL; |
1124 | char *local = NULL; | 1124 | char *local = NULL; |
1125 | int status = 0; | 1125 | int status = 0; |
1126 | int locked = 0; | ||
1127 | 1126 | ||
1128 | qr = (struct dlm_query_region *) msg->buf; | 1127 | qr = (struct dlm_query_region *) msg->buf; |
1129 | 1128 | ||
@@ -1132,10 +1131,8 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len, | |||
1132 | 1131 | ||
1133 | /* buffer used in dlm_mast_regions() */ | 1132 | /* buffer used in dlm_mast_regions() */ |
1134 | local = kmalloc(sizeof(qr->qr_regions), GFP_KERNEL); | 1133 | local = kmalloc(sizeof(qr->qr_regions), GFP_KERNEL); |
1135 | if (!local) { | 1134 | if (!local) |
1136 | status = -ENOMEM; | 1135 | return -ENOMEM; |
1137 | goto bail; | ||
1138 | } | ||
1139 | 1136 | ||
1140 | status = -EINVAL; | 1137 | status = -EINVAL; |
1141 | 1138 | ||
@@ -1144,16 +1141,15 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len, | |||
1144 | if (!dlm) { | 1141 | if (!dlm) { |
1145 | mlog(ML_ERROR, "Node %d queried hb regions on domain %s " | 1142 | mlog(ML_ERROR, "Node %d queried hb regions on domain %s " |
1146 | "before join domain\n", qr->qr_node, qr->qr_domain); | 1143 | "before join domain\n", qr->qr_node, qr->qr_domain); |
1147 | goto bail; | 1144 | goto out_domain_lock; |
1148 | } | 1145 | } |
1149 | 1146 | ||
1150 | spin_lock(&dlm->spinlock); | 1147 | spin_lock(&dlm->spinlock); |
1151 | locked = 1; | ||
1152 | if (dlm->joining_node != qr->qr_node) { | 1148 | if (dlm->joining_node != qr->qr_node) { |
1153 | mlog(ML_ERROR, "Node %d queried hb regions on domain %s " | 1149 | mlog(ML_ERROR, "Node %d queried hb regions on domain %s " |
1154 | "but joining node is %d\n", qr->qr_node, qr->qr_domain, | 1150 | "but joining node is %d\n", qr->qr_node, qr->qr_domain, |
1155 | dlm->joining_node); | 1151 | dlm->joining_node); |
1156 | goto bail; | 1152 | goto out_dlm_lock; |
1157 | } | 1153 | } |
1158 | 1154 | ||
1159 | /* Support for global heartbeat was added in 1.1 */ | 1155 | /* Support for global heartbeat was added in 1.1 */ |
@@ -1163,14 +1159,15 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len, | |||
1163 | "but active dlm protocol is %d.%d\n", qr->qr_node, | 1159 | "but active dlm protocol is %d.%d\n", qr->qr_node, |
1164 | qr->qr_domain, dlm->dlm_locking_proto.pv_major, | 1160 | qr->qr_domain, dlm->dlm_locking_proto.pv_major, |
1165 | dlm->dlm_locking_proto.pv_minor); | 1161 | dlm->dlm_locking_proto.pv_minor); |
1166 | goto bail; | 1162 | goto out_dlm_lock; |
1167 | } | 1163 | } |
1168 | 1164 | ||
1169 | status = dlm_match_regions(dlm, qr, local, sizeof(qr->qr_regions)); | 1165 | status = dlm_match_regions(dlm, qr, local, sizeof(qr->qr_regions)); |
1170 | 1166 | ||
1171 | bail: | 1167 | out_dlm_lock: |
1172 | if (locked) | 1168 | spin_unlock(&dlm->spinlock); |
1173 | spin_unlock(&dlm->spinlock); | 1169 | |
1170 | out_domain_lock: | ||
1174 | spin_unlock(&dlm_domain_lock); | 1171 | spin_unlock(&dlm_domain_lock); |
1175 | 1172 | ||
1176 | kfree(local); | 1173 | kfree(local); |