aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorSunil Mushran <sunil.mushran@oracle.com>2009-02-26 18:00:41 -0500
committerMark Fasheh <mfasheh@suse.com>2009-04-03 14:39:19 -0400
commit2ed6c750d645d09b5948e46fada3ca1fda3157b5 (patch)
tree47d2a6b7d3f6407312f9857abdaf114f14223286 /fs/ocfs2
parente2b66ddcce922529e058cf74d839c4c49c8379a1 (diff)
ocfs2/dlm: Activate dlm->master_hash for master list entries
With this patch, the mles are stored in a hash and not a simple list. This should improve the mle lookup time when the number of outstanding masteries is large. Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/dlm/dlmcommon.h4
-rw-r--r--fs/ocfs2/dlm/dlmdebug.c24
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c1
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c61
4 files changed, 60 insertions, 30 deletions
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
index 425653f88e9..aa55271a7ac 100644
--- a/fs/ocfs2/dlm/dlmcommon.h
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -56,12 +56,13 @@ enum dlm_mle_type {
56}; 56};
57 57
58struct dlm_lock_name { 58struct dlm_lock_name {
59 unsigned int hash;
59 unsigned int len; 60 unsigned int len;
60 unsigned char name[DLM_LOCKID_NAME_MAX]; 61 unsigned char name[DLM_LOCKID_NAME_MAX];
61}; 62};
62 63
63struct dlm_master_list_entry { 64struct dlm_master_list_entry {
64 struct list_head list; 65 struct hlist_node master_hash_node;
65 struct list_head hb_events; 66 struct list_head hb_events;
66 struct dlm_ctxt *dlm; 67 struct dlm_ctxt *dlm;
67 spinlock_t spinlock; 68 spinlock_t spinlock;
@@ -152,7 +153,6 @@ struct dlm_ctxt
152 struct dlm_recovery_ctxt reco; 153 struct dlm_recovery_ctxt reco;
153 spinlock_t master_lock; 154 spinlock_t master_lock;
154 struct hlist_head **master_hash; 155 struct hlist_head **master_hash;
155 struct list_head master_list;
156 struct list_head mle_hb_events; 156 struct list_head mle_hb_events;
157 157
158 /* these give a really vague idea of the system load */ 158 /* these give a really vague idea of the system load */
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
index c82feb7b00b..336a98e82eb 100644
--- a/fs/ocfs2/dlm/dlmdebug.c
+++ b/fs/ocfs2/dlm/dlmdebug.c
@@ -501,18 +501,25 @@ static struct file_operations debug_purgelist_fops = {
501static int debug_mle_print(struct dlm_ctxt *dlm, struct debug_buffer *db) 501static int debug_mle_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
502{ 502{
503 struct dlm_master_list_entry *mle; 503 struct dlm_master_list_entry *mle;
504 int out = 0; 504 struct hlist_head *bucket;
505 struct hlist_node *list;
506 int i, out = 0;
505 unsigned long total = 0; 507 unsigned long total = 0;
506 508
507 out += snprintf(db->buf + out, db->len - out, 509 out += snprintf(db->buf + out, db->len - out,
508 "Dumping MLEs for Domain: %s\n", dlm->name); 510 "Dumping MLEs for Domain: %s\n", dlm->name);
509 511
510 spin_lock(&dlm->master_lock); 512 spin_lock(&dlm->master_lock);
511 list_for_each_entry(mle, &dlm->master_list, list) { 513 for (i = 0; i < DLM_HASH_BUCKETS; i++) {
512 ++total; 514 bucket = dlm_master_hash(dlm, i);
513 if (db->len - out < 200) 515 hlist_for_each(list, bucket) {
514 continue; 516 mle = hlist_entry(list, struct dlm_master_list_entry,
515 out += dump_mle(mle, db->buf + out, db->len - out); 517 master_hash_node);
518 ++total;
519 if (db->len - out < 200)
520 continue;
521 out += dump_mle(mle, db->buf + out, db->len - out);
522 }
516 } 523 }
517 spin_unlock(&dlm->master_lock); 524 spin_unlock(&dlm->master_lock);
518 525
@@ -813,12 +820,11 @@ static int debug_state_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
813 /* Lists: Dirty=Empty Purge=InUse PendingASTs=Empty ... */ 820 /* Lists: Dirty=Empty Purge=InUse PendingASTs=Empty ... */
814 out += snprintf(db->buf + out, db->len - out, 821 out += snprintf(db->buf + out, db->len - out,
815 "Lists: Dirty=%s Purge=%s PendingASTs=%s " 822 "Lists: Dirty=%s Purge=%s PendingASTs=%s "
816 "PendingBASTs=%s Master=%s\n", 823 "PendingBASTs=%s\n",
817 (list_empty(&dlm->dirty_list) ? "Empty" : "InUse"), 824 (list_empty(&dlm->dirty_list) ? "Empty" : "InUse"),
818 (list_empty(&dlm->purge_list) ? "Empty" : "InUse"), 825 (list_empty(&dlm->purge_list) ? "Empty" : "InUse"),
819 (list_empty(&dlm->pending_asts) ? "Empty" : "InUse"), 826 (list_empty(&dlm->pending_asts) ? "Empty" : "InUse"),
820 (list_empty(&dlm->pending_basts) ? "Empty" : "InUse"), 827 (list_empty(&dlm->pending_basts) ? "Empty" : "InUse"));
821 (list_empty(&dlm->master_list) ? "Empty" : "InUse"));
822 828
823 /* Purge Count: xxx Refs: xxx */ 829 /* Purge Count: xxx Refs: xxx */
824 out += snprintf(db->buf + out, db->len - out, 830 out += snprintf(db->buf + out, db->len - out,
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 45315046daf..869648c6104 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -1597,7 +1597,6 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
1597 init_waitqueue_head(&dlm->reco.event); 1597 init_waitqueue_head(&dlm->reco.event);
1598 init_waitqueue_head(&dlm->ast_wq); 1598 init_waitqueue_head(&dlm->ast_wq);
1599 init_waitqueue_head(&dlm->migration_wq); 1599 init_waitqueue_head(&dlm->migration_wq);
1600 INIT_LIST_HEAD(&dlm->master_list);
1601 INIT_LIST_HEAD(&dlm->mle_hb_events); 1600 INIT_LIST_HEAD(&dlm->mle_hb_events);
1602 1601
1603 dlm->joining_node = DLM_LOCK_RES_OWNER_UNKNOWN; 1602 dlm->joining_node = DLM_LOCK_RES_OWNER_UNKNOWN;
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index ec6da3c37dc..804558174a7 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -69,7 +69,8 @@ static int dlm_do_assert_master(struct dlm_ctxt *dlm,
69static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data); 69static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data);
70 70
71static inline void __dlm_mle_name(struct dlm_master_list_entry *mle, 71static inline void __dlm_mle_name(struct dlm_master_list_entry *mle,
72 unsigned char **name, unsigned int *namelen) 72 unsigned char **name, unsigned int *namelen,
73 unsigned int *namehash)
73{ 74{
74 BUG_ON(mle->type != DLM_MLE_BLOCK && 75 BUG_ON(mle->type != DLM_MLE_BLOCK &&
75 mle->type != DLM_MLE_MASTER && 76 mle->type != DLM_MLE_MASTER &&
@@ -78,9 +79,13 @@ static inline void __dlm_mle_name(struct dlm_master_list_entry *mle,
78 if (mle->type != DLM_MLE_MASTER) { 79 if (mle->type != DLM_MLE_MASTER) {
79 *name = mle->u.mlename.name; 80 *name = mle->u.mlename.name;
80 *namelen = mle->u.mlename.len; 81 *namelen = mle->u.mlename.len;
82 if (namehash)
83 *namehash = mle->u.mlename.hash;
81 } else { 84 } else {
82 *name = (unsigned char *)mle->u.mleres->lockname.name; 85 *name = (unsigned char *)mle->u.mleres->lockname.name;
83 *namelen = mle->u.mleres->lockname.len; 86 *namelen = mle->u.mleres->lockname.len;
87 if (namehash)
88 *namehash = mle->u.mleres->lockname.hash;
84 } 89 }
85} 90}
86 91
@@ -95,7 +100,7 @@ static inline int dlm_mle_equal(struct dlm_ctxt *dlm,
95 if (dlm != mle->dlm) 100 if (dlm != mle->dlm)
96 return 0; 101 return 0;
97 102
98 __dlm_mle_name(mle, &mlename, &mlelen); 103 __dlm_mle_name(mle, &mlename, &mlelen, NULL);
99 104
100 if (namelen != mlelen || memcmp(name, mlename, namelen) != 0) 105 if (namelen != mlelen || memcmp(name, mlename, namelen) != 0)
101 return 0; 106 return 0;
@@ -294,7 +299,7 @@ static void dlm_init_mle(struct dlm_master_list_entry *mle,
294 299
295 mle->dlm = dlm; 300 mle->dlm = dlm;
296 mle->type = type; 301 mle->type = type;
297 INIT_LIST_HEAD(&mle->list); 302 INIT_HLIST_NODE(&mle->master_hash_node);
298 INIT_LIST_HEAD(&mle->hb_events); 303 INIT_LIST_HEAD(&mle->hb_events);
299 memset(mle->maybe_map, 0, sizeof(mle->maybe_map)); 304 memset(mle->maybe_map, 0, sizeof(mle->maybe_map));
300 spin_lock_init(&mle->spinlock); 305 spin_lock_init(&mle->spinlock);
@@ -317,6 +322,7 @@ static void dlm_init_mle(struct dlm_master_list_entry *mle,
317 BUG_ON(!name); 322 BUG_ON(!name);
318 memcpy(mle->u.mlename.name, name, namelen); 323 memcpy(mle->u.mlename.name, name, namelen);
319 mle->u.mlename.len = namelen; 324 mle->u.mlename.len = namelen;
325 mle->u.mlename.hash = dlm_lockid_hash(name, namelen);
320 } 326 }
321 327
322 /* copy off the node_map and register hb callbacks on our copy */ 328 /* copy off the node_map and register hb callbacks on our copy */
@@ -334,15 +340,21 @@ void __dlm_unlink_mle(struct dlm_ctxt *dlm, struct dlm_master_list_entry *mle)
334 assert_spin_locked(&dlm->spinlock); 340 assert_spin_locked(&dlm->spinlock);
335 assert_spin_locked(&dlm->master_lock); 341 assert_spin_locked(&dlm->master_lock);
336 342
337 if (!list_empty(&mle->list)) 343 if (!hlist_unhashed(&mle->master_hash_node))
338 list_del_init(&mle->list); 344 hlist_del_init(&mle->master_hash_node);
339} 345}
340 346
341void __dlm_insert_mle(struct dlm_ctxt *dlm, struct dlm_master_list_entry *mle) 347void __dlm_insert_mle(struct dlm_ctxt *dlm, struct dlm_master_list_entry *mle)
342{ 348{
349 struct hlist_head *bucket;
350 unsigned char *mname;
351 unsigned int mlen, hash;
352
343 assert_spin_locked(&dlm->master_lock); 353 assert_spin_locked(&dlm->master_lock);
344 354
345 list_add(&mle->list, &dlm->master_list); 355 __dlm_mle_name(mle, &mname, &mlen, &hash);
356 bucket = dlm_master_hash(dlm, hash);
357 hlist_add_head(&mle->master_hash_node, bucket);
346} 358}
347 359
348/* returns 1 if found, 0 if not */ 360/* returns 1 if found, 0 if not */
@@ -351,10 +363,17 @@ static int dlm_find_mle(struct dlm_ctxt *dlm,
351 char *name, unsigned int namelen) 363 char *name, unsigned int namelen)
352{ 364{
353 struct dlm_master_list_entry *tmpmle; 365 struct dlm_master_list_entry *tmpmle;
366 struct hlist_head *bucket;
367 struct hlist_node *list;
368 unsigned int hash;
354 369
355 assert_spin_locked(&dlm->master_lock); 370 assert_spin_locked(&dlm->master_lock);
356 371
357 list_for_each_entry(tmpmle, &dlm->master_list, list) { 372 hash = dlm_lockid_hash(name, namelen);
373 bucket = dlm_master_hash(dlm, hash);
374 hlist_for_each(list, bucket) {
375 tmpmle = hlist_entry(list, struct dlm_master_list_entry,
376 master_hash_node);
358 if (!dlm_mle_equal(dlm, tmpmle, name, namelen)) 377 if (!dlm_mle_equal(dlm, tmpmle, name, namelen))
359 continue; 378 continue;
360 dlm_get_mle(tmpmle); 379 dlm_get_mle(tmpmle);
@@ -428,23 +447,20 @@ static void dlm_mle_release(struct kref *kref)
428{ 447{
429 struct dlm_master_list_entry *mle; 448 struct dlm_master_list_entry *mle;
430 struct dlm_ctxt *dlm; 449 struct dlm_ctxt *dlm;
450 unsigned char *mname;
451 unsigned int mlen;
431 452
432 mlog_entry_void(); 453 mlog_entry_void();
433 454
434 mle = container_of(kref, struct dlm_master_list_entry, mle_refs); 455 mle = container_of(kref, struct dlm_master_list_entry, mle_refs);
435 dlm = mle->dlm; 456 dlm = mle->dlm;
436 457
437 if (mle->type != DLM_MLE_MASTER) {
438 mlog(0, "calling mle_release for %.*s, type %d\n",
439 mle->u.mlename.len, mle->u.mlename.name, mle->type);
440 } else {
441 mlog(0, "calling mle_release for %.*s, type %d\n",
442 mle->u.mleres->lockname.len,
443 mle->u.mleres->lockname.name, mle->type);
444 }
445 assert_spin_locked(&dlm->spinlock); 458 assert_spin_locked(&dlm->spinlock);
446 assert_spin_locked(&dlm->master_lock); 459 assert_spin_locked(&dlm->master_lock);
447 460
461 __dlm_mle_name(mle, &mname, &mlen, NULL);
462 mlog(0, "Releasing mle for %.*s, type %d\n", mlen, mname, mle->type);
463
448 /* remove from list if not already */ 464 /* remove from list if not already */
449 __dlm_unlink_mle(dlm, mle); 465 __dlm_unlink_mle(dlm, mle);
450 466
@@ -1342,7 +1358,7 @@ static int dlm_do_master_request(struct dlm_lock_resource *res,
1342 1358
1343 BUG_ON(mle->type == DLM_MLE_MIGRATION); 1359 BUG_ON(mle->type == DLM_MLE_MIGRATION);
1344 1360
1345 __dlm_mle_name(mle, &mlename, &mlenamelen); 1361 __dlm_mle_name(mle, &mlename, &mlenamelen, NULL);
1346 1362
1347 request.namelen = (u8)mlenamelen; 1363 request.namelen = (u8)mlenamelen;
1348 memcpy(request.name, mlename, request.namelen); 1364 memcpy(request.name, mlename, request.namelen);
@@ -3286,8 +3302,11 @@ static void dlm_clean_block_mle(struct dlm_ctxt *dlm,
3286 3302
3287void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node) 3303void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node)
3288{ 3304{
3289 struct dlm_master_list_entry *mle, *next; 3305 struct dlm_master_list_entry *mle;
3290 struct dlm_lock_resource *res; 3306 struct dlm_lock_resource *res;
3307 struct hlist_head *bucket;
3308 struct hlist_node *list;
3309 unsigned int i;
3291 3310
3292 mlog_entry("dlm=%s, dead node=%u\n", dlm->name, dead_node); 3311 mlog_entry("dlm=%s, dead node=%u\n", dlm->name, dead_node);
3293top: 3312top:
@@ -3295,7 +3314,12 @@ top:
3295 3314
3296 /* clean the master list */ 3315 /* clean the master list */
3297 spin_lock(&dlm->master_lock); 3316 spin_lock(&dlm->master_lock);
3298 list_for_each_entry_safe(mle, next, &dlm->master_list, list) { 3317 for (i = 0; i < DLM_HASH_BUCKETS; i++) {
3318 bucket = dlm_master_hash(dlm, i);
3319 hlist_for_each(list, bucket) {
3320 mle = hlist_entry(list, struct dlm_master_list_entry,
3321 master_hash_node);
3322
3299 BUG_ON(mle->type != DLM_MLE_BLOCK && 3323 BUG_ON(mle->type != DLM_MLE_BLOCK &&
3300 mle->type != DLM_MLE_MASTER && 3324 mle->type != DLM_MLE_MASTER &&
3301 mle->type != DLM_MLE_MIGRATION); 3325 mle->type != DLM_MLE_MIGRATION);
@@ -3351,6 +3375,7 @@ top:
3351 /* this may be the last reference */ 3375 /* this may be the last reference */
3352 __dlm_put_mle(mle); 3376 __dlm_put_mle(mle);
3353 } 3377 }
3378 }
3354 spin_unlock(&dlm->master_lock); 3379 spin_unlock(&dlm->master_lock);
3355} 3380}
3356 3381