aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dlm/dlmdomain.c
diff options
context:
space:
mode:
authorKurt Hackel <kurt.hackel@oracle.com>2006-12-01 17:47:20 -0500
committerMark Fasheh <mark.fasheh@oracle.com>2007-02-07 14:53:07 -0500
commitba2bf2185121db74e075c703fbf986761733dd1d (patch)
treef7b90fa14db61fb6fc5d92d393b1d837e58a9faa /fs/ocfs2/dlm/dlmdomain.c
parent5331be090567d9335476f876b2d85427cd7c4426 (diff)
ocfs2_dlm: fix cluster-wide refcounting of lock resources
This was previously broken and migration of some locks had to be temporarily disabled. We use a new (and backward-incompatible) set of network messages to account for all references to a lock resources held across the cluster. once these are all freed, the master node may then free the lock resource memory once its local references are dropped. Signed-off-by: Kurt Hackel <kurt.hackel@oracle.com> Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2/dlm/dlmdomain.c')
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c117
1 files changed, 87 insertions, 30 deletions
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index f0b25f2dd205..3995de360264 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -125,10 +125,10 @@ void __dlm_insert_lockres(struct dlm_ctxt *dlm,
125 hlist_add_head(&res->hash_node, bucket); 125 hlist_add_head(&res->hash_node, bucket);
126} 126}
127 127
128struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm, 128struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm,
129 const char *name, 129 const char *name,
130 unsigned int len, 130 unsigned int len,
131 unsigned int hash) 131 unsigned int hash)
132{ 132{
133 struct hlist_head *bucket; 133 struct hlist_head *bucket;
134 struct hlist_node *list; 134 struct hlist_node *list;
@@ -154,6 +154,37 @@ struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm,
154 return NULL; 154 return NULL;
155} 155}
156 156
157/* intended to be called by functions which do not care about lock
158 * resources which are being purged (most net _handler functions).
159 * this will return NULL for any lock resource which is found but
160 * currently in the process of dropping its mastery reference.
161 * use __dlm_lookup_lockres_full when you need the lock resource
162 * regardless (e.g. dlm_get_lock_resource) */
163struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm,
164 const char *name,
165 unsigned int len,
166 unsigned int hash)
167{
168 struct dlm_lock_resource *res = NULL;
169
170 mlog_entry("%.*s\n", len, name);
171
172 assert_spin_locked(&dlm->spinlock);
173
174 res = __dlm_lookup_lockres_full(dlm, name, len, hash);
175 if (res) {
176 spin_lock(&res->spinlock);
177 if (res->state & DLM_LOCK_RES_DROPPING_REF) {
178 spin_unlock(&res->spinlock);
179 dlm_lockres_put(res);
180 return NULL;
181 }
182 spin_unlock(&res->spinlock);
183 }
184
185 return res;
186}
187
157struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm, 188struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm,
158 const char *name, 189 const char *name,
159 unsigned int len) 190 unsigned int len)
@@ -330,43 +361,60 @@ static void dlm_complete_dlm_shutdown(struct dlm_ctxt *dlm)
330 wake_up(&dlm_domain_events); 361 wake_up(&dlm_domain_events);
331} 362}
332 363
333static void dlm_migrate_all_locks(struct dlm_ctxt *dlm) 364static int dlm_migrate_all_locks(struct dlm_ctxt *dlm)
334{ 365{
335 int i; 366 int i, num, n, ret = 0;
336 struct dlm_lock_resource *res; 367 struct dlm_lock_resource *res;
368 struct hlist_node *iter;
369 struct hlist_head *bucket;
370 int dropped;
337 371
338 mlog(0, "Migrating locks from domain %s\n", dlm->name); 372 mlog(0, "Migrating locks from domain %s\n", dlm->name);
339restart: 373
374 num = 0;
340 spin_lock(&dlm->spinlock); 375 spin_lock(&dlm->spinlock);
341 for (i = 0; i < DLM_HASH_BUCKETS; i++) { 376 for (i = 0; i < DLM_HASH_BUCKETS; i++) {
342 while (!hlist_empty(dlm_lockres_hash(dlm, i))) { 377redo_bucket:
343 res = hlist_entry(dlm_lockres_hash(dlm, i)->first, 378 n = 0;
344 struct dlm_lock_resource, hash_node); 379 bucket = dlm_lockres_hash(dlm, i);
345 /* need reference when manually grabbing lockres */ 380 iter = bucket->first;
381 while (iter) {
382 n++;
383 res = hlist_entry(iter, struct dlm_lock_resource,
384 hash_node);
346 dlm_lockres_get(res); 385 dlm_lockres_get(res);
347 /* this should unhash the lockres 386 /* migrate, if necessary. this will drop the dlm
348 * and exit with dlm->spinlock */ 387 * spinlock and retake it if it does migration. */
349 mlog(0, "purging res=%p\n", res); 388 dropped = dlm_empty_lockres(dlm, res);
350 if (dlm_lockres_is_dirty(dlm, res)) { 389
351 /* HACK! this should absolutely go. 390 spin_lock(&res->spinlock);
352 * need to figure out why some empty 391 __dlm_lockres_calc_usage(dlm, res);
353 * lockreses are still marked dirty */ 392 iter = res->hash_node.next;
354 mlog(ML_ERROR, "lockres %.*s dirty!\n", 393 spin_unlock(&res->spinlock);
355 res->lockname.len, res->lockname.name); 394
356
357 spin_unlock(&dlm->spinlock);
358 dlm_kick_thread(dlm, res);
359 wait_event(dlm->ast_wq, !dlm_lockres_is_dirty(dlm, res));
360 dlm_lockres_put(res);
361 goto restart;
362 }
363 dlm_purge_lockres(dlm, res);
364 dlm_lockres_put(res); 395 dlm_lockres_put(res);
396
397 cond_resched_lock(&dlm->spinlock);
398
399 if (dropped)
400 goto redo_bucket;
365 } 401 }
402 num += n;
403 mlog(0, "%s: touched %d lockreses in bucket %d "
404 "(tot=%d)\n", dlm->name, n, i, num);
366 } 405 }
367 spin_unlock(&dlm->spinlock); 406 spin_unlock(&dlm->spinlock);
368 407 wake_up(&dlm->dlm_thread_wq);
408
409 /* let the dlm thread take care of purging, keep scanning until
410 * nothing remains in the hash */
411 if (num) {
412 mlog(0, "%s: %d lock resources in hash last pass\n",
413 dlm->name, num);
414 ret = -EAGAIN;
415 }
369 mlog(0, "DONE Migrating locks from domain %s\n", dlm->name); 416 mlog(0, "DONE Migrating locks from domain %s\n", dlm->name);
417 return ret;
370} 418}
371 419
372static int dlm_no_joining_node(struct dlm_ctxt *dlm) 420static int dlm_no_joining_node(struct dlm_ctxt *dlm)
@@ -571,7 +619,9 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm)
571 /* We changed dlm state, notify the thread */ 619 /* We changed dlm state, notify the thread */
572 dlm_kick_thread(dlm, NULL); 620 dlm_kick_thread(dlm, NULL);
573 621
574 dlm_migrate_all_locks(dlm); 622 while (dlm_migrate_all_locks(dlm)) {
623 mlog(0, "%s: more migration to do\n", dlm->name);
624 }
575 dlm_mark_domain_leaving(dlm); 625 dlm_mark_domain_leaving(dlm);
576 dlm_leave_domain(dlm); 626 dlm_leave_domain(dlm);
577 dlm_complete_dlm_shutdown(dlm); 627 dlm_complete_dlm_shutdown(dlm);
@@ -1082,6 +1132,13 @@ static int dlm_register_domain_handlers(struct dlm_ctxt *dlm)
1082 if (status) 1132 if (status)
1083 goto bail; 1133 goto bail;
1084 1134
1135 status = o2net_register_handler(DLM_DEREF_LOCKRES_MSG, dlm->key,
1136 sizeof(struct dlm_deref_lockres),
1137 dlm_deref_lockres_handler,
1138 dlm, &dlm->dlm_domain_handlers);
1139 if (status)
1140 goto bail;
1141
1085 status = o2net_register_handler(DLM_MIGRATE_REQUEST_MSG, dlm->key, 1142 status = o2net_register_handler(DLM_MIGRATE_REQUEST_MSG, dlm->key,
1086 sizeof(struct dlm_migrate_request), 1143 sizeof(struct dlm_migrate_request),
1087 dlm_migrate_request_handler, 1144 dlm_migrate_request_handler,