aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Phillips <phillips@google.com>2006-03-10 21:08:16 -0500
committerMark Fasheh <mark.fasheh@oracle.com>2006-06-26 17:42:42 -0400
commit03d864c02c3ea803b1718940ac6953a257182d7a (patch)
tree2678c34a75654693ee875d20194830429886ec58
parent95c4f581d6551de55cf5b8693db98b01ce07021b (diff)
ocfs2: allocate lockres hash pages in an array
This allows us to have a hash table greater than a single page which greatly improves dlm performance on some tests. Signed-off-by: Daniel Phillips <phillips@google.com> Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
-rw-r--r--fs/ocfs2/dlm/dlmcommon.h12
-rw-r--r--fs/ocfs2/dlm/dlmdebug.c2
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c41
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c4
4 files changed, 46 insertions, 13 deletions
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
index 87612819c13..0378ddbc8a8 100644
--- a/fs/ocfs2/dlm/dlmcommon.h
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -37,7 +37,10 @@
37#define DLM_THREAD_SHUFFLE_INTERVAL 5 // flush everything every 5 passes 37#define DLM_THREAD_SHUFFLE_INTERVAL 5 // flush everything every 5 passes
38#define DLM_THREAD_MS 200 // flush at least every 200 ms 38#define DLM_THREAD_MS 200 // flush at least every 200 ms
39 39
40#define DLM_HASH_BUCKETS (PAGE_SIZE / sizeof(struct hlist_head)) 40#define DLM_HASH_SIZE (1 << 14)
41#define DLM_HASH_PAGES (DLM_HASH_SIZE / PAGE_SIZE)
42#define DLM_BUCKETS_PER_PAGE (PAGE_SIZE / sizeof(struct hlist_head))
43#define DLM_HASH_BUCKETS (DLM_HASH_PAGES * DLM_BUCKETS_PER_PAGE)
41 44
42/* Intended to make it easier for us to switch out hash functions */ 45/* Intended to make it easier for us to switch out hash functions */
43#define dlm_lockid_hash(_n, _l) full_name_hash(_n, _l) 46#define dlm_lockid_hash(_n, _l) full_name_hash(_n, _l)
@@ -88,7 +91,7 @@ enum dlm_ctxt_state {
88struct dlm_ctxt 91struct dlm_ctxt
89{ 92{
90 struct list_head list; 93 struct list_head list;
91 struct hlist_head *lockres_hash; 94 struct hlist_head **lockres_hash;
92 struct list_head dirty_list; 95 struct list_head dirty_list;
93 struct list_head purge_list; 96 struct list_head purge_list;
94 struct list_head pending_asts; 97 struct list_head pending_asts;
@@ -135,6 +138,11 @@ struct dlm_ctxt
135 struct list_head dlm_eviction_callbacks; 138 struct list_head dlm_eviction_callbacks;
136}; 139};
137 140
141static inline struct hlist_head *dlm_lockres_hash(struct dlm_ctxt *dlm, unsigned i)
142{
143 return dlm->lockres_hash[(i / DLM_BUCKETS_PER_PAGE) % DLM_HASH_PAGES] + (i % DLM_BUCKETS_PER_PAGE);
144}
145
138/* these keventd work queue items are for less-frequently 146/* these keventd work queue items are for less-frequently
139 * called functions that cannot be directly called from the 147 * called functions that cannot be directly called from the
140 * net message handlers for some reason, usually because 148 * net message handlers for some reason, usually because
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
index c7eae5d3324..e119e4ddf93 100644
--- a/fs/ocfs2/dlm/dlmdebug.c
+++ b/fs/ocfs2/dlm/dlmdebug.c
@@ -136,7 +136,7 @@ void dlm_dump_lock_resources(struct dlm_ctxt *dlm)
136 136
137 spin_lock(&dlm->spinlock); 137 spin_lock(&dlm->spinlock);
138 for (i=0; i<DLM_HASH_BUCKETS; i++) { 138 for (i=0; i<DLM_HASH_BUCKETS; i++) {
139 bucket = &(dlm->lockres_hash[i]); 139 bucket = dlm_lockres_hash(dlm, i);
140 hlist_for_each_entry(res, iter, bucket, hash_node) 140 hlist_for_each_entry(res, iter, bucket, hash_node)
141 dlm_print_one_lock_resource(res); 141 dlm_print_one_lock_resource(res);
142 } 142 }
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 595b1c7cbd1..80b8cce9cf3 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -49,6 +49,30 @@
49#define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_DOMAIN) 49#define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_DOMAIN)
50#include "cluster/masklog.h" 50#include "cluster/masklog.h"
51 51
52static void dlm_free_pagevec(void **vec, int pages)
53{
54 while (pages--)
55 free_page((unsigned long)vec[pages]);
56 kfree(vec);
57}
58
59static void **dlm_alloc_pagevec(int pages)
60{
61 void **vec = kmalloc(pages * sizeof(void *), GFP_KERNEL);
62 int i;
63
64 if (!vec)
65 return NULL;
66
67 for (i = 0; i < pages; i++)
68 if (!(vec[i] = (void *)__get_free_page(GFP_KERNEL)))
69 goto out_free;
70 return vec;
71out_free:
72 dlm_free_pagevec(vec, i);
73 return NULL;
74}
75
52/* 76/*
53 * 77 *
54 * spinlock lock ordering: if multiple locks are needed, obey this ordering: 78 * spinlock lock ordering: if multiple locks are needed, obey this ordering:
@@ -90,7 +114,7 @@ void __dlm_insert_lockres(struct dlm_ctxt *dlm,
90 assert_spin_locked(&dlm->spinlock); 114 assert_spin_locked(&dlm->spinlock);
91 115
92 q = &res->lockname; 116 q = &res->lockname;
93 bucket = &(dlm->lockres_hash[q->hash % DLM_HASH_BUCKETS]); 117 bucket = dlm_lockres_hash(dlm, q->hash);
94 118
95 /* get a reference for our hashtable */ 119 /* get a reference for our hashtable */
96 dlm_lockres_get(res); 120 dlm_lockres_get(res);
@@ -110,7 +134,8 @@ struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm,
110 134
111 assert_spin_locked(&dlm->spinlock); 135 assert_spin_locked(&dlm->spinlock);
112 136
113 bucket = dlm->lockres_hash + full_name_hash(name, len) % DLM_HASH_BUCKETS; 137 bucket = dlm_lockres_hash(dlm, hash);
138
114 hlist_for_each(list, bucket) { 139 hlist_for_each(list, bucket) {
115 struct dlm_lock_resource *res = hlist_entry(list, 140 struct dlm_lock_resource *res = hlist_entry(list,
116 struct dlm_lock_resource, hash_node); 141 struct dlm_lock_resource, hash_node);
@@ -191,7 +216,7 @@ static int dlm_wait_on_domain_helper(const char *domain)
191static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm) 216static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm)
192{ 217{
193 if (dlm->lockres_hash) 218 if (dlm->lockres_hash)
194 free_page((unsigned long) dlm->lockres_hash); 219 dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES);
195 220
196 if (dlm->name) 221 if (dlm->name)
197 kfree(dlm->name); 222 kfree(dlm->name);
@@ -301,8 +326,8 @@ static void dlm_migrate_all_locks(struct dlm_ctxt *dlm)
301restart: 326restart:
302 spin_lock(&dlm->spinlock); 327 spin_lock(&dlm->spinlock);
303 for (i = 0; i < DLM_HASH_BUCKETS; i++) { 328 for (i = 0; i < DLM_HASH_BUCKETS; i++) {
304 while (!hlist_empty(&dlm->lockres_hash[i])) { 329 while (!hlist_empty(dlm_lockres_hash(dlm, i))) {
305 res = hlist_entry(dlm->lockres_hash[i].first, 330 res = hlist_entry(dlm_lockres_hash(dlm, i)->first,
306 struct dlm_lock_resource, hash_node); 331 struct dlm_lock_resource, hash_node);
307 /* need reference when manually grabbing lockres */ 332 /* need reference when manually grabbing lockres */
308 dlm_lockres_get(res); 333 dlm_lockres_get(res);
@@ -1188,7 +1213,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
1188 goto leave; 1213 goto leave;
1189 } 1214 }
1190 1215
1191 dlm->lockres_hash = (struct hlist_head *) __get_free_page(GFP_KERNEL); 1216 dlm->lockres_hash = (struct hlist_head **)dlm_alloc_pagevec(DLM_HASH_PAGES);
1192 if (!dlm->lockres_hash) { 1217 if (!dlm->lockres_hash) {
1193 mlog_errno(-ENOMEM); 1218 mlog_errno(-ENOMEM);
1194 kfree(dlm->name); 1219 kfree(dlm->name);
@@ -1197,8 +1222,8 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
1197 goto leave; 1222 goto leave;
1198 } 1223 }
1199 1224
1200 for (i=0; i<DLM_HASH_BUCKETS; i++) 1225 for (i = 0; i < DLM_HASH_BUCKETS; i++)
1201 INIT_HLIST_HEAD(&dlm->lockres_hash[i]); 1226 INIT_HLIST_HEAD(dlm_lockres_hash(dlm, i));
1202 1227
1203 strcpy(dlm->name, domain); 1228 strcpy(dlm->name, domain);
1204 dlm->key = key; 1229 dlm->key = key;
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 4f3d482a729..bf2a02eca62 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -1719,7 +1719,7 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm,
1719 * the RECOVERING state and set the owner 1719 * the RECOVERING state and set the owner
1720 * if necessary */ 1720 * if necessary */
1721 for (i = 0; i < DLM_HASH_BUCKETS; i++) { 1721 for (i = 0; i < DLM_HASH_BUCKETS; i++) {
1722 bucket = &(dlm->lockres_hash[i]); 1722 bucket = dlm_lockres_hash(dlm, i);
1723 hlist_for_each_entry(res, hash_iter, bucket, hash_node) { 1723 hlist_for_each_entry(res, hash_iter, bucket, hash_node) {
1724 if (res->state & DLM_LOCK_RES_RECOVERING) { 1724 if (res->state & DLM_LOCK_RES_RECOVERING) {
1725 if (res->owner == dead_node) { 1725 if (res->owner == dead_node) {
@@ -1884,7 +1884,7 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node)
1884 * need to be fired as a result. 1884 * need to be fired as a result.
1885 */ 1885 */
1886 for (i = 0; i < DLM_HASH_BUCKETS; i++) { 1886 for (i = 0; i < DLM_HASH_BUCKETS; i++) {
1887 bucket = &(dlm->lockres_hash[i]); 1887 bucket = dlm_lockres_hash(dlm, i);
1888 hlist_for_each_entry(res, iter, bucket, hash_node) { 1888 hlist_for_each_entry(res, iter, bucket, hash_node) {
1889 /* always prune any $RECOVERY entries for dead nodes, 1889 /* always prune any $RECOVERY entries for dead nodes,
1890 * otherwise hangs can occur during later recovery */ 1890 * otherwise hangs can occur during later recovery */