aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dlm
diff options
context:
space:
mode:
authorpiaojun <piaojun@huawei.com>2016-08-02 17:02:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-08-02 17:31:41 -0400
commit309e91911daede6adde0364f489e69909c3f6894 (patch)
tree287184133ed121eba278f5acedb57e62d1576e22 /fs/ocfs2/dlm
parent86b652b93adb57d8fed8edd532ed2eb8a791950d (diff)
ocfs2/dlm: solve a BUG when deref failed in dlm_drop_lockres_ref
We found a BUG situation that lockres is migrated during deref described below. To solve the BUG, we could purge lockres directly when other node says I did not have a ref. Additionally, we'd better purge lockres if master goes down, as no one will response deref done. Node 1 Node 2(old master) Node3(new master) dlm_purge_lockres send deref to N2 leave domain migrate lockres to N3 finish migration send do assert master to N1 receive do assert msg form N3, but can not find lockres because DROPPING_REF is set, so the owner is still N2. receive deref from N1 and response -EINVAL because lockres is migrated BUG when receive -EINVAL in dlm_drop_lockres_ref Fixes: 842b90b62461d ("ocfs2/dlm: return in progress if master can not clear the refmap bit right now") Link: http://lkml.kernel.org/r/57845103.3070406@huawei.com Signed-off-by: Jun Piao <piaojun@huawei.com> Reviewed-by: Joseph Qi <joseph.qi@huawei.com> Reviewed-by: Jiufei Xue <xuejiufei@huawei.com> Reviewed-by: Mark Fasheh <mfasheh@suse.de> Cc: Joel Becker <jlbec@evilplan.org> Cc: Junxiao Bi <junxiao.bi@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2/dlm')
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c9
-rw-r--r--fs/ocfs2/dlm/dlmthread.c13
2 files changed, 17 insertions, 5 deletions
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 525dc06468c4..553d220df406 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -2276,9 +2276,12 @@ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
2276 mlog(ML_ERROR, "%s: res %.*s, DEREF to node %u got %d\n", 2276 mlog(ML_ERROR, "%s: res %.*s, DEREF to node %u got %d\n",
2277 dlm->name, namelen, lockname, res->owner, r); 2277 dlm->name, namelen, lockname, res->owner, r);
2278 dlm_print_one_lock_resource(res); 2278 dlm_print_one_lock_resource(res);
2279 BUG(); 2279 if (r == -ENOMEM)
2280 } 2280 BUG();
2281 return ret ? ret : r; 2281 } else
2282 ret = r;
2283
2284 return ret;
2282} 2285}
2283 2286
2284int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data, 2287int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c
index 68d239ba0c63..ce397229acc0 100644
--- a/fs/ocfs2/dlm/dlmthread.c
+++ b/fs/ocfs2/dlm/dlmthread.c
@@ -175,6 +175,15 @@ static void dlm_purge_lockres(struct dlm_ctxt *dlm,
175 res->lockname.len, res->lockname.name, master); 175 res->lockname.len, res->lockname.name, master);
176 176
177 if (!master) { 177 if (!master) {
178 if (res->state & DLM_LOCK_RES_DROPPING_REF) {
179 mlog(ML_NOTICE, "%s: res %.*s already in "
180 "DLM_LOCK_RES_DROPPING_REF state\n",
181 dlm->name, res->lockname.len,
182 res->lockname.name);
183 spin_unlock(&res->spinlock);
184 return;
185 }
186
178 res->state |= DLM_LOCK_RES_DROPPING_REF; 187 res->state |= DLM_LOCK_RES_DROPPING_REF;
179 /* drop spinlock... retake below */ 188 /* drop spinlock... retake below */
180 spin_unlock(&res->spinlock); 189 spin_unlock(&res->spinlock);
@@ -203,8 +212,8 @@ static void dlm_purge_lockres(struct dlm_ctxt *dlm,
203 dlm->purge_count--; 212 dlm->purge_count--;
204 } 213 }
205 214
206 if (!master && ret != 0) { 215 if (!master && ret == DLM_DEREF_RESPONSE_INPROG) {
207 mlog(0, "%s: deref %.*s in progress or master goes down\n", 216 mlog(0, "%s: deref %.*s in progress\n",
208 dlm->name, res->lockname.len, res->lockname.name); 217 dlm->name, res->lockname.len, res->lockname.name);
209 spin_unlock(&res->spinlock); 218 spin_unlock(&res->spinlock);
210 return; 219 return;