aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/dlm/config.c9
-rw-r--r--fs/dlm/config.h1
-rw-r--r--fs/dlm/dlm_internal.h6
-rw-r--r--fs/dlm/lock.c119
-rw-r--r--fs/dlm/lockspace.c10
-rw-r--r--fs/dlm/memory.c22
-rw-r--r--fs/dlm/memory.h2
7 files changed, 121 insertions, 48 deletions
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 4e20f9317156..6cf72fcc0d0c 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -102,6 +102,7 @@ struct dlm_cluster {
102 unsigned int cl_protocol; 102 unsigned int cl_protocol;
103 unsigned int cl_timewarn_cs; 103 unsigned int cl_timewarn_cs;
104 unsigned int cl_waitwarn_us; 104 unsigned int cl_waitwarn_us;
105 unsigned int cl_new_rsb_count;
105}; 106};
106 107
107enum { 108enum {
@@ -116,6 +117,7 @@ enum {
116 CLUSTER_ATTR_PROTOCOL, 117 CLUSTER_ATTR_PROTOCOL,
117 CLUSTER_ATTR_TIMEWARN_CS, 118 CLUSTER_ATTR_TIMEWARN_CS,
118 CLUSTER_ATTR_WAITWARN_US, 119 CLUSTER_ATTR_WAITWARN_US,
120 CLUSTER_ATTR_NEW_RSB_COUNT,
119}; 121};
120 122
121struct cluster_attribute { 123struct cluster_attribute {
@@ -168,6 +170,7 @@ CLUSTER_ATTR(log_debug, 0);
168CLUSTER_ATTR(protocol, 0); 170CLUSTER_ATTR(protocol, 0);
169CLUSTER_ATTR(timewarn_cs, 1); 171CLUSTER_ATTR(timewarn_cs, 1);
170CLUSTER_ATTR(waitwarn_us, 0); 172CLUSTER_ATTR(waitwarn_us, 0);
173CLUSTER_ATTR(new_rsb_count, 0);
171 174
172static struct configfs_attribute *cluster_attrs[] = { 175static struct configfs_attribute *cluster_attrs[] = {
173 [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr, 176 [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
@@ -181,6 +184,7 @@ static struct configfs_attribute *cluster_attrs[] = {
181 [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr, 184 [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
182 [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr, 185 [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
183 [CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr, 186 [CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr,
187 [CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count.attr,
184 NULL, 188 NULL,
185}; 189};
186 190
@@ -450,6 +454,7 @@ static struct config_group *make_cluster(struct config_group *g,
450 cl->cl_protocol = dlm_config.ci_protocol; 454 cl->cl_protocol = dlm_config.ci_protocol;
451 cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs; 455 cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
452 cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us; 456 cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us;
457 cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count;
453 458
454 space_list = &sps->ss_group; 459 space_list = &sps->ss_group;
455 comm_list = &cms->cs_group; 460 comm_list = &cms->cs_group;
@@ -1041,6 +1046,7 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num)
1041#define DEFAULT_PROTOCOL 0 1046#define DEFAULT_PROTOCOL 0
1042#define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */ 1047#define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */
1043#define DEFAULT_WAITWARN_US 0 1048#define DEFAULT_WAITWARN_US 0
1049#define DEFAULT_NEW_RSB_COUNT 128
1044 1050
1045struct dlm_config_info dlm_config = { 1051struct dlm_config_info dlm_config = {
1046 .ci_tcp_port = DEFAULT_TCP_PORT, 1052 .ci_tcp_port = DEFAULT_TCP_PORT,
@@ -1053,6 +1059,7 @@ struct dlm_config_info dlm_config = {
1053 .ci_log_debug = DEFAULT_LOG_DEBUG, 1059 .ci_log_debug = DEFAULT_LOG_DEBUG,
1054 .ci_protocol = DEFAULT_PROTOCOL, 1060 .ci_protocol = DEFAULT_PROTOCOL,
1055 .ci_timewarn_cs = DEFAULT_TIMEWARN_CS, 1061 .ci_timewarn_cs = DEFAULT_TIMEWARN_CS,
1056 .ci_waitwarn_us = DEFAULT_WAITWARN_US 1062 .ci_waitwarn_us = DEFAULT_WAITWARN_US,
1063 .ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT
1057}; 1064};
1058 1065
diff --git a/fs/dlm/config.h b/fs/dlm/config.h
index 260574463d29..3099d0dd26c0 100644
--- a/fs/dlm/config.h
+++ b/fs/dlm/config.h
@@ -28,6 +28,7 @@ struct dlm_config_info {
28 int ci_protocol; 28 int ci_protocol;
29 int ci_timewarn_cs; 29 int ci_timewarn_cs;
30 int ci_waitwarn_us; 30 int ci_waitwarn_us;
31 int ci_new_rsb_count;
31}; 32};
32 33
33extern struct dlm_config_info dlm_config; 34extern struct dlm_config_info dlm_config;
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 23a234bddc60..6614f335e25d 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -293,7 +293,7 @@ struct dlm_rsb {
293 int res_recover_locks_count; 293 int res_recover_locks_count;
294 294
295 char *res_lvbptr; 295 char *res_lvbptr;
296 char res_name[1]; 296 char res_name[DLM_RESNAME_MAXLEN+1];
297}; 297};
298 298
299/* find_rsb() flags */ 299/* find_rsb() flags */
@@ -477,6 +477,10 @@ struct dlm_ls {
477 struct mutex ls_timeout_mutex; 477 struct mutex ls_timeout_mutex;
478 struct list_head ls_timeout; 478 struct list_head ls_timeout;
479 479
480 spinlock_t ls_new_rsb_spin;
481 int ls_new_rsb_count;
482 struct list_head ls_new_rsb; /* new rsb structs */
483
480 struct list_head ls_nodes; /* current nodes in ls */ 484 struct list_head ls_nodes; /* current nodes in ls */
481 struct list_head ls_nodes_gone; /* dead node list, recovery */ 485 struct list_head ls_nodes_gone; /* dead node list, recovery */
482 int ls_num_nodes; /* number of nodes in ls */ 486 int ls_num_nodes; /* number of nodes in ls */
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;
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 871fe6deb5fa..98a97762c893 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -493,6 +493,9 @@ static int new_lockspace(const char *name, int namelen, void **lockspace,
493 INIT_LIST_HEAD(&ls->ls_timeout); 493 INIT_LIST_HEAD(&ls->ls_timeout);
494 mutex_init(&ls->ls_timeout_mutex); 494 mutex_init(&ls->ls_timeout_mutex);
495 495
496 INIT_LIST_HEAD(&ls->ls_new_rsb);
497 spin_lock_init(&ls->ls_new_rsb_spin);
498
496 INIT_LIST_HEAD(&ls->ls_nodes); 499 INIT_LIST_HEAD(&ls->ls_nodes);
497 INIT_LIST_HEAD(&ls->ls_nodes_gone); 500 INIT_LIST_HEAD(&ls->ls_nodes_gone);
498 ls->ls_num_nodes = 0; 501 ls->ls_num_nodes = 0;
@@ -764,6 +767,13 @@ static int release_lockspace(struct dlm_ls *ls, int force)
764 767
765 vfree(ls->ls_rsbtbl); 768 vfree(ls->ls_rsbtbl);
766 769
770 while (!list_empty(&ls->ls_new_rsb)) {
771 rsb = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb,
772 res_hashchain);
773 list_del(&rsb->res_hashchain);
774 dlm_free_rsb(rsb);
775 }
776
767 /* 777 /*
768 * Free structures on any other lists 778 * Free structures on any other lists
769 */ 779 */
diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c
index 8e0d00db004f..da64df7576e1 100644
--- a/fs/dlm/memory.c
+++ b/fs/dlm/memory.c
@@ -16,6 +16,7 @@
16#include "memory.h" 16#include "memory.h"
17 17
18static struct kmem_cache *lkb_cache; 18static struct kmem_cache *lkb_cache;
19static struct kmem_cache *rsb_cache;
19 20
20 21
21int __init dlm_memory_init(void) 22int __init dlm_memory_init(void)
@@ -26,6 +27,14 @@ int __init dlm_memory_init(void)
26 __alignof__(struct dlm_lkb), 0, NULL); 27 __alignof__(struct dlm_lkb), 0, NULL);
27 if (!lkb_cache) 28 if (!lkb_cache)
28 ret = -ENOMEM; 29 ret = -ENOMEM;
30
31 rsb_cache = kmem_cache_create("dlm_rsb", sizeof(struct dlm_rsb),
32 __alignof__(struct dlm_rsb), 0, NULL);
33 if (!rsb_cache) {
34 kmem_cache_destroy(lkb_cache);
35 ret = -ENOMEM;
36 }
37
29 return ret; 38 return ret;
30} 39}
31 40
@@ -33,6 +42,8 @@ void dlm_memory_exit(void)
33{ 42{
34 if (lkb_cache) 43 if (lkb_cache)
35 kmem_cache_destroy(lkb_cache); 44 kmem_cache_destroy(lkb_cache);
45 if (rsb_cache)
46 kmem_cache_destroy(rsb_cache);
36} 47}
37 48
38char *dlm_allocate_lvb(struct dlm_ls *ls) 49char *dlm_allocate_lvb(struct dlm_ls *ls)
@@ -48,16 +59,11 @@ void dlm_free_lvb(char *p)
48 kfree(p); 59 kfree(p);
49} 60}
50 61
51/* FIXME: have some minimal space built-in to rsb for the name and 62struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls)
52 kmalloc a separate name if needed, like dentries are done */
53
54struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls, int namelen)
55{ 63{
56 struct dlm_rsb *r; 64 struct dlm_rsb *r;
57 65
58 DLM_ASSERT(namelen <= DLM_RESNAME_MAXLEN,); 66 r = kmem_cache_zalloc(rsb_cache, GFP_NOFS);
59
60 r = kzalloc(sizeof(*r) + namelen, GFP_NOFS);
61 return r; 67 return r;
62} 68}
63 69
@@ -65,7 +71,7 @@ void dlm_free_rsb(struct dlm_rsb *r)
65{ 71{
66 if (r->res_lvbptr) 72 if (r->res_lvbptr)
67 dlm_free_lvb(r->res_lvbptr); 73 dlm_free_lvb(r->res_lvbptr);
68 kfree(r); 74 kmem_cache_free(rsb_cache, r);
69} 75}
70 76
71struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls) 77struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls)
diff --git a/fs/dlm/memory.h b/fs/dlm/memory.h
index 485fb29143bd..177c11cbb0a6 100644
--- a/fs/dlm/memory.h
+++ b/fs/dlm/memory.h
@@ -16,7 +16,7 @@
16 16
17int dlm_memory_init(void); 17int dlm_memory_init(void);
18void dlm_memory_exit(void); 18void dlm_memory_exit(void);
19struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls, int namelen); 19struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls);
20void dlm_free_rsb(struct dlm_rsb *r); 20void dlm_free_rsb(struct dlm_rsb *r);
21struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls); 21struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls);
22void dlm_free_lkb(struct dlm_lkb *l); 22void dlm_free_lkb(struct dlm_lkb *l);