aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm/lock.c
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2011-07-07 15:05:03 -0400
committerDavid Teigland <teigland@redhat.com>2011-07-12 17:02:09 -0400
commit3881ac04ebf94268ba3d6e486aa524fd41f893a9 (patch)
tree2ddb5c099f60f541d7e50f669f84fd58c3920bec /fs/dlm/lock.c
parent3d6aa675fff9eee5a6339d67b355b63a6d69565f (diff)
dlm: improve rsb searches
By pre-allocating rsb structs before searching the hash table, they can be inserted immediately. This avoids always having to repeat the search when adding the struct to hash list. This also adds space to the rsb struct for a max resource name, so an rsb allocation can be used by any request. The constant size also allows us to finally use a slab for the rsb structs. Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm/lock.c')
-rw-r--r--fs/dlm/lock.c119
1 files changed, 82 insertions, 37 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 784cde417ced..9ebeaa6e6903 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -327,19 +327,68 @@ static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode)
327 * Basic operations on rsb's and lkb's 327 * Basic operations on rsb's and lkb's
328 */ 328 */
329 329
330static struct dlm_rsb *create_rsb(struct dlm_ls *ls, char *name, int len) 330static int pre_rsb_struct(struct dlm_ls *ls)
331{
332 struct dlm_rsb *r1, *r2;
333 int count = 0;
334
335 spin_lock(&ls->ls_new_rsb_spin);
336 if (ls->ls_new_rsb_count > dlm_config.ci_new_rsb_count / 2) {
337 spin_unlock(&ls->ls_new_rsb_spin);
338 return 0;
339 }
340 spin_unlock(&ls->ls_new_rsb_spin);
341
342 r1 = dlm_allocate_rsb(ls);
343 r2 = dlm_allocate_rsb(ls);
344
345 spin_lock(&ls->ls_new_rsb_spin);
346 if (r1) {
347 list_add(&r1->res_hashchain, &ls->ls_new_rsb);
348 ls->ls_new_rsb_count++;
349 }
350 if (r2) {
351 list_add(&r2->res_hashchain, &ls->ls_new_rsb);
352 ls->ls_new_rsb_count++;
353 }
354 count = ls->ls_new_rsb_count;
355 spin_unlock(&ls->ls_new_rsb_spin);
356
357 if (!count)
358 return -ENOMEM;
359 return 0;
360}
361
362/* If ls->ls_new_rsb is empty, return -EAGAIN, so the caller can
363 unlock any spinlocks, go back and call pre_rsb_struct again.
364 Otherwise, take an rsb off the list and return it. */
365
366static int get_rsb_struct(struct dlm_ls *ls, char *name, int len,
367 struct dlm_rsb **r_ret)
331{ 368{
332 struct dlm_rsb *r; 369 struct dlm_rsb *r;
370 int count;
333 371
334 r = dlm_allocate_rsb(ls, len); 372 spin_lock(&ls->ls_new_rsb_spin);
335 if (!r) 373 if (list_empty(&ls->ls_new_rsb)) {
336 return NULL; 374 count = ls->ls_new_rsb_count;
375 spin_unlock(&ls->ls_new_rsb_spin);
376 log_debug(ls, "find_rsb retry %d %d %s",
377 count, dlm_config.ci_new_rsb_count, name);
378 return -EAGAIN;
379 }
380
381 r = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb, res_hashchain);
382 list_del(&r->res_hashchain);
383 ls->ls_new_rsb_count--;
384 spin_unlock(&ls->ls_new_rsb_spin);
337 385
338 r->res_ls = ls; 386 r->res_ls = ls;
339 r->res_length = len; 387 r->res_length = len;
340 memcpy(r->res_name, name, len); 388 memcpy(r->res_name, name, len);
341 mutex_init(&r->res_mutex); 389 mutex_init(&r->res_mutex);
342 390
391 INIT_LIST_HEAD(&r->res_hashchain);
343 INIT_LIST_HEAD(&r->res_lookup); 392 INIT_LIST_HEAD(&r->res_lookup);
344 INIT_LIST_HEAD(&r->res_grantqueue); 393 INIT_LIST_HEAD(&r->res_grantqueue);
345 INIT_LIST_HEAD(&r->res_convertqueue); 394 INIT_LIST_HEAD(&r->res_convertqueue);
@@ -347,7 +396,8 @@ static struct dlm_rsb *create_rsb(struct dlm_ls *ls, char *name, int len)
347 INIT_LIST_HEAD(&r->res_root_list); 396 INIT_LIST_HEAD(&r->res_root_list);
348 INIT_LIST_HEAD(&r->res_recover_list); 397 INIT_LIST_HEAD(&r->res_recover_list);
349 398
350 return r; 399 *r_ret = r;
400 return 0;
351} 401}
352 402
353static int search_rsb_list(struct list_head *head, char *name, int len, 403static int search_rsb_list(struct list_head *head, char *name, int len,
@@ -405,16 +455,6 @@ static int _search_rsb(struct dlm_ls *ls, char *name, int len, int b,
405 return error; 455 return error;
406} 456}
407 457
408static int search_rsb(struct dlm_ls *ls, char *name, int len, int b,
409 unsigned int flags, struct dlm_rsb **r_ret)
410{
411 int error;
412 spin_lock(&ls->ls_rsbtbl[b].lock);
413 error = _search_rsb(ls, name, len, b, flags, r_ret);
414 spin_unlock(&ls->ls_rsbtbl[b].lock);
415 return error;
416}
417
418/* 458/*
419 * Find rsb in rsbtbl and potentially create/add one 459 * Find rsb in rsbtbl and potentially create/add one
420 * 460 *
@@ -432,35 +472,48 @@ static int search_rsb(struct dlm_ls *ls, char *name, int len, int b,
432static int find_rsb(struct dlm_ls *ls, char *name, int namelen, 472static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
433 unsigned int flags, struct dlm_rsb **r_ret) 473 unsigned int flags, struct dlm_rsb **r_ret)
434{ 474{
435 struct dlm_rsb *r = NULL, *tmp; 475 struct dlm_rsb *r = NULL;
436 uint32_t hash, bucket; 476 uint32_t hash, bucket;
437 int error = -EINVAL; 477 int error;
438 478
439 if (namelen > DLM_RESNAME_MAXLEN) 479 if (namelen > DLM_RESNAME_MAXLEN) {
480 error = -EINVAL;
440 goto out; 481 goto out;
482 }
441 483
442 if (dlm_no_directory(ls)) 484 if (dlm_no_directory(ls))
443 flags |= R_CREATE; 485 flags |= R_CREATE;
444 486
445 error = 0;
446 hash = jhash(name, namelen, 0); 487 hash = jhash(name, namelen, 0);
447 bucket = hash & (ls->ls_rsbtbl_size - 1); 488 bucket = hash & (ls->ls_rsbtbl_size - 1);
448 489
449 error = search_rsb(ls, name, namelen, bucket, flags, &r); 490 retry:
491 if (flags & R_CREATE) {
492 error = pre_rsb_struct(ls);
493 if (error < 0)
494 goto out;
495 }
496
497 spin_lock(&ls->ls_rsbtbl[bucket].lock);
498
499 error = _search_rsb(ls, name, namelen, bucket, flags, &r);
450 if (!error) 500 if (!error)
451 goto out; 501 goto out_unlock;
452 502
453 if (error == -EBADR && !(flags & R_CREATE)) 503 if (error == -EBADR && !(flags & R_CREATE))
454 goto out; 504 goto out_unlock;
455 505
456 /* the rsb was found but wasn't a master copy */ 506 /* the rsb was found but wasn't a master copy */
457 if (error == -ENOTBLK) 507 if (error == -ENOTBLK)
458 goto out; 508 goto out_unlock;
459 509
460 error = -ENOMEM; 510 error = get_rsb_struct(ls, name, namelen, &r);
461 r = create_rsb(ls, name, namelen); 511 if (error == -EAGAIN) {
462 if (!r) 512 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
463 goto out; 513 goto retry;
514 }
515 if (error)
516 goto out_unlock;
464 517
465 r->res_hash = hash; 518 r->res_hash = hash;
466 r->res_bucket = bucket; 519 r->res_bucket = bucket;
@@ -474,18 +527,10 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
474 nodeid = 0; 527 nodeid = 0;
475 r->res_nodeid = nodeid; 528 r->res_nodeid = nodeid;
476 } 529 }
477
478 spin_lock(&ls->ls_rsbtbl[bucket].lock);
479 error = _search_rsb(ls, name, namelen, bucket, 0, &tmp);
480 if (!error) {
481 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
482 dlm_free_rsb(r);
483 r = tmp;
484 goto out;
485 }
486 list_add(&r->res_hashchain, &ls->ls_rsbtbl[bucket].list); 530 list_add(&r->res_hashchain, &ls->ls_rsbtbl[bucket].list);
487 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
488 error = 0; 531 error = 0;
532 out_unlock:
533 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
489 out: 534 out:
490 *r_ret = r; 535 *r_ret = r;
491 return error; 536 return error;