diff options
| author | Daniel Phillips <phillips@google.com> | 2006-03-10 21:08:16 -0500 |
|---|---|---|
| committer | Mark Fasheh <mark.fasheh@oracle.com> | 2006-06-26 17:42:42 -0400 |
| commit | 03d864c02c3ea803b1718940ac6953a257182d7a (patch) | |
| tree | 2678c34a75654693ee875d20194830429886ec58 | |
| parent | 95c4f581d6551de55cf5b8693db98b01ce07021b (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.h | 12 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmdebug.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmdomain.c | 41 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmrecovery.c | 4 |
4 files changed, 46 insertions, 13 deletions
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index 87612819c13b..0378ddbc8a8c 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 { | |||
| 88 | struct dlm_ctxt | 91 | struct 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 | ||
| 141 | static 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 c7eae5d3324e..e119e4ddf93f 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 595b1c7cbd1f..80b8cce9cf3c 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 | ||
| 52 | static void dlm_free_pagevec(void **vec, int pages) | ||
| 53 | { | ||
| 54 | while (pages--) | ||
| 55 | free_page((unsigned long)vec[pages]); | ||
| 56 | kfree(vec); | ||
| 57 | } | ||
| 58 | |||
| 59 | static 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; | ||
| 71 | out_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) | |||
| 191 | static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm) | 216 | static 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) | |||
| 301 | restart: | 326 | restart: |
| 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 4f3d482a7299..bf2a02eca62e 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 */ |
