diff options
author | David Teigland <teigland@redhat.com> | 2012-05-15 17:07:49 -0400 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2012-07-16 15:17:52 -0400 |
commit | 1d7c484eeb167fc374294e38ae402de4097c8611 (patch) | |
tree | 82ed8a279b8f399205a15951c50c22aea67d7323 /fs | |
parent | c04fecb4d9f7753e0cbff7edd03ec68f8721cdce (diff) |
dlm: use idr instead of list for recovered rsbs
When a large number of resources are being recovered,
a linear search of the recover_list takes a long time.
Use an idr in place of a list.
Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/dlm/dlm_internal.h | 3 | ||||
-rw-r--r-- | fs/dlm/lockspace.c | 3 | ||||
-rw-r--r-- | fs/dlm/rcom.c | 2 | ||||
-rw-r--r-- | fs/dlm/recover.c | 116 |
4 files changed, 101 insertions, 23 deletions
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 3093207a7684..a5f82d5b3946 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h | |||
@@ -288,6 +288,7 @@ struct dlm_rsb { | |||
288 | int res_nodeid; | 288 | int res_nodeid; |
289 | int res_master_nodeid; | 289 | int res_master_nodeid; |
290 | int res_dir_nodeid; | 290 | int res_dir_nodeid; |
291 | int res_id; /* for ls_recover_idr */ | ||
291 | uint32_t res_lvbseq; | 292 | uint32_t res_lvbseq; |
292 | uint32_t res_hash; | 293 | uint32_t res_hash; |
293 | uint32_t res_bucket; /* rsbtbl */ | 294 | uint32_t res_bucket; /* rsbtbl */ |
@@ -587,6 +588,8 @@ struct dlm_ls { | |||
587 | struct list_head ls_recover_list; | 588 | struct list_head ls_recover_list; |
588 | spinlock_t ls_recover_list_lock; | 589 | spinlock_t ls_recover_list_lock; |
589 | int ls_recover_list_count; | 590 | int ls_recover_list_count; |
591 | struct idr ls_recover_idr; | ||
592 | spinlock_t ls_recover_idr_lock; | ||
590 | wait_queue_head_t ls_wait_general; | 593 | wait_queue_head_t ls_wait_general; |
591 | struct mutex ls_clear_proc_locks; | 594 | struct mutex ls_clear_proc_locks; |
592 | 595 | ||
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 065bb75ed609..d4d3b3165c6c 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
@@ -565,6 +565,8 @@ static int new_lockspace(const char *name, const char *cluster, | |||
565 | 565 | ||
566 | INIT_LIST_HEAD(&ls->ls_recover_list); | 566 | INIT_LIST_HEAD(&ls->ls_recover_list); |
567 | spin_lock_init(&ls->ls_recover_list_lock); | 567 | spin_lock_init(&ls->ls_recover_list_lock); |
568 | idr_init(&ls->ls_recover_idr); | ||
569 | spin_lock_init(&ls->ls_recover_idr_lock); | ||
568 | ls->ls_recover_list_count = 0; | 570 | ls->ls_recover_list_count = 0; |
569 | ls->ls_local_handle = ls; | 571 | ls->ls_local_handle = ls; |
570 | init_waitqueue_head(&ls->ls_wait_general); | 572 | init_waitqueue_head(&ls->ls_wait_general); |
@@ -636,6 +638,7 @@ static int new_lockspace(const char *name, const char *cluster, | |||
636 | spin_lock(&lslist_lock); | 638 | spin_lock(&lslist_lock); |
637 | list_del(&ls->ls_list); | 639 | list_del(&ls->ls_list); |
638 | spin_unlock(&lslist_lock); | 640 | spin_unlock(&lslist_lock); |
641 | idr_destroy(&ls->ls_recover_idr); | ||
639 | kfree(ls->ls_recover_buf); | 642 | kfree(ls->ls_recover_buf); |
640 | out_lkbfree: | 643 | out_lkbfree: |
641 | idr_destroy(&ls->ls_lkbidr); | 644 | idr_destroy(&ls->ls_lkbidr); |
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index c8c298d81463..87f1a56eab32 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c | |||
@@ -325,7 +325,7 @@ int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid) | |||
325 | if (error) | 325 | if (error) |
326 | goto out; | 326 | goto out; |
327 | memcpy(rc->rc_buf, r->res_name, r->res_length); | 327 | memcpy(rc->rc_buf, r->res_name, r->res_length); |
328 | rc->rc_id = (unsigned long) r; | 328 | rc->rc_id = (unsigned long) r->res_id; |
329 | 329 | ||
330 | send_rcom(ls, mh, rc); | 330 | send_rcom(ls, mh, rc); |
331 | out: | 331 | out: |
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c index 3c025fe49ad3..ff6f27629a0c 100644 --- a/fs/dlm/recover.c +++ b/fs/dlm/recover.c | |||
@@ -277,22 +277,6 @@ static void recover_list_del(struct dlm_rsb *r) | |||
277 | dlm_put_rsb(r); | 277 | dlm_put_rsb(r); |
278 | } | 278 | } |
279 | 279 | ||
280 | static struct dlm_rsb *recover_list_find(struct dlm_ls *ls, uint64_t id) | ||
281 | { | ||
282 | struct dlm_rsb *r = NULL; | ||
283 | |||
284 | spin_lock(&ls->ls_recover_list_lock); | ||
285 | |||
286 | list_for_each_entry(r, &ls->ls_recover_list, res_recover_list) { | ||
287 | if (id == (unsigned long) r) | ||
288 | goto out; | ||
289 | } | ||
290 | r = NULL; | ||
291 | out: | ||
292 | spin_unlock(&ls->ls_recover_list_lock); | ||
293 | return r; | ||
294 | } | ||
295 | |||
296 | static void recover_list_clear(struct dlm_ls *ls) | 280 | static void recover_list_clear(struct dlm_ls *ls) |
297 | { | 281 | { |
298 | struct dlm_rsb *r, *s; | 282 | struct dlm_rsb *r, *s; |
@@ -313,6 +297,94 @@ static void recover_list_clear(struct dlm_ls *ls) | |||
313 | spin_unlock(&ls->ls_recover_list_lock); | 297 | spin_unlock(&ls->ls_recover_list_lock); |
314 | } | 298 | } |
315 | 299 | ||
300 | static int recover_idr_empty(struct dlm_ls *ls) | ||
301 | { | ||
302 | int empty = 1; | ||
303 | |||
304 | spin_lock(&ls->ls_recover_idr_lock); | ||
305 | if (ls->ls_recover_list_count) | ||
306 | empty = 0; | ||
307 | spin_unlock(&ls->ls_recover_idr_lock); | ||
308 | |||
309 | return empty; | ||
310 | } | ||
311 | |||
312 | static int recover_idr_add(struct dlm_rsb *r) | ||
313 | { | ||
314 | struct dlm_ls *ls = r->res_ls; | ||
315 | int rv, id; | ||
316 | |||
317 | rv = idr_pre_get(&ls->ls_recover_idr, GFP_NOFS); | ||
318 | if (!rv) | ||
319 | return -ENOMEM; | ||
320 | |||
321 | spin_lock(&ls->ls_recover_idr_lock); | ||
322 | if (r->res_id) { | ||
323 | spin_unlock(&ls->ls_recover_idr_lock); | ||
324 | return -1; | ||
325 | } | ||
326 | rv = idr_get_new_above(&ls->ls_recover_idr, r, 1, &id); | ||
327 | if (rv) { | ||
328 | spin_unlock(&ls->ls_recover_idr_lock); | ||
329 | return rv; | ||
330 | } | ||
331 | r->res_id = id; | ||
332 | ls->ls_recover_list_count++; | ||
333 | dlm_hold_rsb(r); | ||
334 | spin_unlock(&ls->ls_recover_idr_lock); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static void recover_idr_del(struct dlm_rsb *r) | ||
339 | { | ||
340 | struct dlm_ls *ls = r->res_ls; | ||
341 | |||
342 | spin_lock(&ls->ls_recover_idr_lock); | ||
343 | idr_remove(&ls->ls_recover_idr, r->res_id); | ||
344 | r->res_id = 0; | ||
345 | ls->ls_recover_list_count--; | ||
346 | spin_unlock(&ls->ls_recover_idr_lock); | ||
347 | |||
348 | dlm_put_rsb(r); | ||
349 | } | ||
350 | |||
351 | static struct dlm_rsb *recover_idr_find(struct dlm_ls *ls, uint64_t id) | ||
352 | { | ||
353 | struct dlm_rsb *r; | ||
354 | |||
355 | spin_lock(&ls->ls_recover_idr_lock); | ||
356 | r = idr_find(&ls->ls_recover_idr, (int)id); | ||
357 | spin_unlock(&ls->ls_recover_idr_lock); | ||
358 | return r; | ||
359 | } | ||
360 | |||
361 | static int recover_idr_clear_rsb(int id, void *p, void *data) | ||
362 | { | ||
363 | struct dlm_ls *ls = data; | ||
364 | struct dlm_rsb *r = p; | ||
365 | |||
366 | r->res_id = 0; | ||
367 | r->res_recover_locks_count = 0; | ||
368 | ls->ls_recover_list_count--; | ||
369 | |||
370 | dlm_put_rsb(r); | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static void recover_idr_clear(struct dlm_ls *ls) | ||
375 | { | ||
376 | spin_lock(&ls->ls_recover_idr_lock); | ||
377 | idr_for_each(&ls->ls_recover_idr, recover_idr_clear_rsb, ls); | ||
378 | idr_remove_all(&ls->ls_recover_idr); | ||
379 | |||
380 | if (ls->ls_recover_list_count != 0) { | ||
381 | log_error(ls, "warning: recover_list_count %d", | ||
382 | ls->ls_recover_list_count); | ||
383 | ls->ls_recover_list_count = 0; | ||
384 | } | ||
385 | spin_unlock(&ls->ls_recover_idr_lock); | ||
386 | } | ||
387 | |||
316 | 388 | ||
317 | /* Master recovery: find new master node for rsb's that were | 389 | /* Master recovery: find new master node for rsb's that were |
318 | mastered on nodes that have been removed. | 390 | mastered on nodes that have been removed. |
@@ -408,7 +480,7 @@ static int recover_master(struct dlm_rsb *r, unsigned int *count) | |||
408 | set_new_master(r); | 480 | set_new_master(r); |
409 | error = 0; | 481 | error = 0; |
410 | } else { | 482 | } else { |
411 | recover_list_add(r); | 483 | recover_idr_add(r); |
412 | error = dlm_send_rcom_lookup(r, dir_nodeid); | 484 | error = dlm_send_rcom_lookup(r, dir_nodeid); |
413 | } | 485 | } |
414 | 486 | ||
@@ -493,10 +565,10 @@ int dlm_recover_masters(struct dlm_ls *ls) | |||
493 | 565 | ||
494 | log_debug(ls, "dlm_recover_masters %u of %u", count, total); | 566 | log_debug(ls, "dlm_recover_masters %u of %u", count, total); |
495 | 567 | ||
496 | error = dlm_wait_function(ls, &recover_list_empty); | 568 | error = dlm_wait_function(ls, &recover_idr_empty); |
497 | out: | 569 | out: |
498 | if (error) | 570 | if (error) |
499 | recover_list_clear(ls); | 571 | recover_idr_clear(ls); |
500 | return error; | 572 | return error; |
501 | } | 573 | } |
502 | 574 | ||
@@ -505,7 +577,7 @@ int dlm_recover_master_reply(struct dlm_ls *ls, struct dlm_rcom *rc) | |||
505 | struct dlm_rsb *r; | 577 | struct dlm_rsb *r; |
506 | int ret_nodeid, new_master; | 578 | int ret_nodeid, new_master; |
507 | 579 | ||
508 | r = recover_list_find(ls, rc->rc_id); | 580 | r = recover_idr_find(ls, rc->rc_id); |
509 | if (!r) { | 581 | if (!r) { |
510 | log_error(ls, "dlm_recover_master_reply no id %llx", | 582 | log_error(ls, "dlm_recover_master_reply no id %llx", |
511 | (unsigned long long)rc->rc_id); | 583 | (unsigned long long)rc->rc_id); |
@@ -524,9 +596,9 @@ int dlm_recover_master_reply(struct dlm_ls *ls, struct dlm_rcom *rc) | |||
524 | r->res_nodeid = new_master; | 596 | r->res_nodeid = new_master; |
525 | set_new_master(r); | 597 | set_new_master(r); |
526 | unlock_rsb(r); | 598 | unlock_rsb(r); |
527 | recover_list_del(r); | 599 | recover_idr_del(r); |
528 | 600 | ||
529 | if (recover_list_empty(ls)) | 601 | if (recover_idr_empty(ls)) |
530 | wake_up(&ls->ls_wait_general); | 602 | wake_up(&ls->ls_wait_general); |
531 | out: | 603 | out: |
532 | return 0; | 604 | return 0; |