diff options
Diffstat (limited to 'fs/ocfs2/dlm/dlmdomain.c')
-rw-r--r-- | fs/ocfs2/dlm/dlmdomain.c | 101 |
1 files changed, 72 insertions, 29 deletions
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 8f3a9e3106fd..ba27c5c5e959 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include "dlmapi.h" | 41 | #include "dlmapi.h" |
42 | #include "dlmcommon.h" | 42 | #include "dlmcommon.h" |
43 | 43 | ||
44 | #include "dlmdebug.h" | ||
45 | #include "dlmdomain.h" | 44 | #include "dlmdomain.h" |
46 | 45 | ||
47 | #include "dlmver.h" | 46 | #include "dlmver.h" |
@@ -49,6 +48,33 @@ | |||
49 | #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_DOMAIN) | 48 | #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_DOMAIN) |
50 | #include "cluster/masklog.h" | 49 | #include "cluster/masklog.h" |
51 | 50 | ||
51 | static void dlm_free_pagevec(void **vec, int pages) | ||
52 | { | ||
53 | while (pages--) | ||
54 | free_page((unsigned long)vec[pages]); | ||
55 | kfree(vec); | ||
56 | } | ||
57 | |||
58 | static void **dlm_alloc_pagevec(int pages) | ||
59 | { | ||
60 | void **vec = kmalloc(pages * sizeof(void *), GFP_KERNEL); | ||
61 | int i; | ||
62 | |||
63 | if (!vec) | ||
64 | return NULL; | ||
65 | |||
66 | for (i = 0; i < pages; i++) | ||
67 | if (!(vec[i] = (void *)__get_free_page(GFP_KERNEL))) | ||
68 | goto out_free; | ||
69 | |||
70 | mlog(0, "Allocated DLM hash pagevec; %d pages (%lu expected), %lu buckets per page\n", | ||
71 | pages, DLM_HASH_PAGES, (unsigned long)DLM_BUCKETS_PER_PAGE); | ||
72 | return vec; | ||
73 | out_free: | ||
74 | dlm_free_pagevec(vec, i); | ||
75 | return NULL; | ||
76 | } | ||
77 | |||
52 | /* | 78 | /* |
53 | * | 79 | * |
54 | * spinlock lock ordering: if multiple locks are needed, obey this ordering: | 80 | * spinlock lock ordering: if multiple locks are needed, obey this ordering: |
@@ -90,8 +116,7 @@ void __dlm_insert_lockres(struct dlm_ctxt *dlm, | |||
90 | assert_spin_locked(&dlm->spinlock); | 116 | assert_spin_locked(&dlm->spinlock); |
91 | 117 | ||
92 | q = &res->lockname; | 118 | q = &res->lockname; |
93 | q->hash = full_name_hash(q->name, q->len); | 119 | bucket = dlm_lockres_hash(dlm, q->hash); |
94 | bucket = &(dlm->lockres_hash[q->hash % DLM_HASH_BUCKETS]); | ||
95 | 120 | ||
96 | /* get a reference for our hashtable */ | 121 | /* get a reference for our hashtable */ |
97 | dlm_lockres_get(res); | 122 | dlm_lockres_get(res); |
@@ -100,34 +125,32 @@ void __dlm_insert_lockres(struct dlm_ctxt *dlm, | |||
100 | } | 125 | } |
101 | 126 | ||
102 | struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm, | 127 | struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm, |
103 | const char *name, | 128 | const char *name, |
104 | unsigned int len) | 129 | unsigned int len, |
130 | unsigned int hash) | ||
105 | { | 131 | { |
106 | unsigned int hash; | ||
107 | struct hlist_node *iter; | ||
108 | struct dlm_lock_resource *tmpres=NULL; | ||
109 | struct hlist_head *bucket; | 132 | struct hlist_head *bucket; |
133 | struct hlist_node *list; | ||
110 | 134 | ||
111 | mlog_entry("%.*s\n", len, name); | 135 | mlog_entry("%.*s\n", len, name); |
112 | 136 | ||
113 | assert_spin_locked(&dlm->spinlock); | 137 | assert_spin_locked(&dlm->spinlock); |
114 | 138 | ||
115 | hash = full_name_hash(name, len); | 139 | bucket = dlm_lockres_hash(dlm, hash); |
116 | |||
117 | bucket = &(dlm->lockres_hash[hash % DLM_HASH_BUCKETS]); | ||
118 | |||
119 | /* check for pre-existing lock */ | ||
120 | hlist_for_each(iter, bucket) { | ||
121 | tmpres = hlist_entry(iter, struct dlm_lock_resource, hash_node); | ||
122 | if (tmpres->lockname.len == len && | ||
123 | memcmp(tmpres->lockname.name, name, len) == 0) { | ||
124 | dlm_lockres_get(tmpres); | ||
125 | break; | ||
126 | } | ||
127 | 140 | ||
128 | tmpres = NULL; | 141 | hlist_for_each(list, bucket) { |
142 | struct dlm_lock_resource *res = hlist_entry(list, | ||
143 | struct dlm_lock_resource, hash_node); | ||
144 | if (res->lockname.name[0] != name[0]) | ||
145 | continue; | ||
146 | if (unlikely(res->lockname.len != len)) | ||
147 | continue; | ||
148 | if (memcmp(res->lockname.name + 1, name + 1, len - 1)) | ||
149 | continue; | ||
150 | dlm_lockres_get(res); | ||
151 | return res; | ||
129 | } | 152 | } |
130 | return tmpres; | 153 | return NULL; |
131 | } | 154 | } |
132 | 155 | ||
133 | struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm, | 156 | struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm, |
@@ -135,9 +158,10 @@ struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm, | |||
135 | unsigned int len) | 158 | unsigned int len) |
136 | { | 159 | { |
137 | struct dlm_lock_resource *res; | 160 | struct dlm_lock_resource *res; |
161 | unsigned int hash = dlm_lockid_hash(name, len); | ||
138 | 162 | ||
139 | spin_lock(&dlm->spinlock); | 163 | spin_lock(&dlm->spinlock); |
140 | res = __dlm_lookup_lockres(dlm, name, len); | 164 | res = __dlm_lookup_lockres(dlm, name, len, hash); |
141 | spin_unlock(&dlm->spinlock); | 165 | spin_unlock(&dlm->spinlock); |
142 | return res; | 166 | return res; |
143 | } | 167 | } |
@@ -194,7 +218,7 @@ static int dlm_wait_on_domain_helper(const char *domain) | |||
194 | static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm) | 218 | static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm) |
195 | { | 219 | { |
196 | if (dlm->lockres_hash) | 220 | if (dlm->lockres_hash) |
197 | free_page((unsigned long) dlm->lockres_hash); | 221 | dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES); |
198 | 222 | ||
199 | if (dlm->name) | 223 | if (dlm->name) |
200 | kfree(dlm->name); | 224 | kfree(dlm->name); |
@@ -278,11 +302,21 @@ int dlm_domain_fully_joined(struct dlm_ctxt *dlm) | |||
278 | return ret; | 302 | return ret; |
279 | } | 303 | } |
280 | 304 | ||
305 | static void dlm_destroy_dlm_worker(struct dlm_ctxt *dlm) | ||
306 | { | ||
307 | if (dlm->dlm_worker) { | ||
308 | flush_workqueue(dlm->dlm_worker); | ||
309 | destroy_workqueue(dlm->dlm_worker); | ||
310 | dlm->dlm_worker = NULL; | ||
311 | } | ||
312 | } | ||
313 | |||
281 | static void dlm_complete_dlm_shutdown(struct dlm_ctxt *dlm) | 314 | static void dlm_complete_dlm_shutdown(struct dlm_ctxt *dlm) |
282 | { | 315 | { |
283 | dlm_unregister_domain_handlers(dlm); | 316 | dlm_unregister_domain_handlers(dlm); |
284 | dlm_complete_thread(dlm); | 317 | dlm_complete_thread(dlm); |
285 | dlm_complete_recovery_thread(dlm); | 318 | dlm_complete_recovery_thread(dlm); |
319 | dlm_destroy_dlm_worker(dlm); | ||
286 | 320 | ||
287 | /* We've left the domain. Now we can take ourselves out of the | 321 | /* We've left the domain. Now we can take ourselves out of the |
288 | * list and allow the kref stuff to help us free the | 322 | * list and allow the kref stuff to help us free the |
@@ -304,8 +338,8 @@ static void dlm_migrate_all_locks(struct dlm_ctxt *dlm) | |||
304 | restart: | 338 | restart: |
305 | spin_lock(&dlm->spinlock); | 339 | spin_lock(&dlm->spinlock); |
306 | for (i = 0; i < DLM_HASH_BUCKETS; i++) { | 340 | for (i = 0; i < DLM_HASH_BUCKETS; i++) { |
307 | while (!hlist_empty(&dlm->lockres_hash[i])) { | 341 | while (!hlist_empty(dlm_lockres_hash(dlm, i))) { |
308 | res = hlist_entry(dlm->lockres_hash[i].first, | 342 | res = hlist_entry(dlm_lockres_hash(dlm, i)->first, |
309 | struct dlm_lock_resource, hash_node); | 343 | struct dlm_lock_resource, hash_node); |
310 | /* need reference when manually grabbing lockres */ | 344 | /* need reference when manually grabbing lockres */ |
311 | dlm_lockres_get(res); | 345 | dlm_lockres_get(res); |
@@ -1126,6 +1160,13 @@ static int dlm_join_domain(struct dlm_ctxt *dlm) | |||
1126 | goto bail; | 1160 | goto bail; |
1127 | } | 1161 | } |
1128 | 1162 | ||
1163 | dlm->dlm_worker = create_singlethread_workqueue("dlm_wq"); | ||
1164 | if (!dlm->dlm_worker) { | ||
1165 | status = -ENOMEM; | ||
1166 | mlog_errno(status); | ||
1167 | goto bail; | ||
1168 | } | ||
1169 | |||
1129 | do { | 1170 | do { |
1130 | unsigned int backoff; | 1171 | unsigned int backoff; |
1131 | status = dlm_try_to_join_domain(dlm); | 1172 | status = dlm_try_to_join_domain(dlm); |
@@ -1166,6 +1207,7 @@ bail: | |||
1166 | dlm_unregister_domain_handlers(dlm); | 1207 | dlm_unregister_domain_handlers(dlm); |
1167 | dlm_complete_thread(dlm); | 1208 | dlm_complete_thread(dlm); |
1168 | dlm_complete_recovery_thread(dlm); | 1209 | dlm_complete_recovery_thread(dlm); |
1210 | dlm_destroy_dlm_worker(dlm); | ||
1169 | } | 1211 | } |
1170 | 1212 | ||
1171 | return status; | 1213 | return status; |
@@ -1191,7 +1233,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, | |||
1191 | goto leave; | 1233 | goto leave; |
1192 | } | 1234 | } |
1193 | 1235 | ||
1194 | dlm->lockres_hash = (struct hlist_head *) __get_free_page(GFP_KERNEL); | 1236 | dlm->lockres_hash = (struct hlist_head **)dlm_alloc_pagevec(DLM_HASH_PAGES); |
1195 | if (!dlm->lockres_hash) { | 1237 | if (!dlm->lockres_hash) { |
1196 | mlog_errno(-ENOMEM); | 1238 | mlog_errno(-ENOMEM); |
1197 | kfree(dlm->name); | 1239 | kfree(dlm->name); |
@@ -1200,8 +1242,8 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, | |||
1200 | goto leave; | 1242 | goto leave; |
1201 | } | 1243 | } |
1202 | 1244 | ||
1203 | for (i=0; i<DLM_HASH_BUCKETS; i++) | 1245 | for (i = 0; i < DLM_HASH_BUCKETS; i++) |
1204 | INIT_HLIST_HEAD(&dlm->lockres_hash[i]); | 1246 | INIT_HLIST_HEAD(dlm_lockres_hash(dlm, i)); |
1205 | 1247 | ||
1206 | strcpy(dlm->name, domain); | 1248 | strcpy(dlm->name, domain); |
1207 | dlm->key = key; | 1249 | dlm->key = key; |
@@ -1231,6 +1273,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, | |||
1231 | 1273 | ||
1232 | dlm->dlm_thread_task = NULL; | 1274 | dlm->dlm_thread_task = NULL; |
1233 | dlm->dlm_reco_thread_task = NULL; | 1275 | dlm->dlm_reco_thread_task = NULL; |
1276 | dlm->dlm_worker = NULL; | ||
1234 | init_waitqueue_head(&dlm->dlm_thread_wq); | 1277 | init_waitqueue_head(&dlm->dlm_thread_wq); |
1235 | init_waitqueue_head(&dlm->dlm_reco_thread_wq); | 1278 | init_waitqueue_head(&dlm->dlm_reco_thread_wq); |
1236 | init_waitqueue_head(&dlm->reco.event); | 1279 | init_waitqueue_head(&dlm->reco.event); |