ocfs2_dlm: disallow a domain join if node maps mismatch
[linux-2.6-block.git] / fs / ocfs2 / dlm / dlmdomain.c
1 /* -*- mode: c; c-basic-offset: 8; -*-
2  * vim: noexpandtab sw=8 ts=8 sts=0:
3  *
4  * dlmdomain.c
5  *
6  * defines domain join / leave apis
7  *
8  * Copyright (C) 2004 Oracle.  All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public
21  * License along with this program; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 021110-1307, USA.
24  *
25  */
26
27 #include <linux/module.h>
28 #include <linux/types.h>
29 #include <linux/slab.h>
30 #include <linux/highmem.h>
31 #include <linux/utsname.h>
32 #include <linux/init.h>
33 #include <linux/spinlock.h>
34 #include <linux/delay.h>
35 #include <linux/err.h>
36
37 #include "cluster/heartbeat.h"
38 #include "cluster/nodemanager.h"
39 #include "cluster/tcp.h"
40
41 #include "dlmapi.h"
42 #include "dlmcommon.h"
43
44 #include "dlmdomain.h"
45
46 #include "dlmver.h"
47
48 #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_DOMAIN)
49 #include "cluster/masklog.h"
50
51 /*
52  * ocfs2 node maps are array of long int, which limits to send them freely
53  * across the wire due to endianness issues. To workaround this, we convert
54  * long ints to byte arrays. Following 3 routines are helper functions to
55  * set/test/copy bits within those array of bytes
56  */
57 static inline void byte_set_bit(u8 nr, u8 map[])
58 {
59         map[nr >> 3] |= (1UL << (nr & 7));
60 }
61
62 static inline int byte_test_bit(u8 nr, u8 map[])
63 {
64         return ((1UL << (nr & 7)) & (map[nr >> 3])) != 0;
65 }
66
67 static inline void byte_copymap(u8 dmap[], unsigned long smap[],
68                         unsigned int sz)
69 {
70         unsigned int nn;
71
72         if (!sz)
73                 return;
74
75         memset(dmap, 0, ((sz + 7) >> 3));
76         for (nn = 0 ; nn < sz; nn++)
77                 if (test_bit(nn, smap))
78                         byte_set_bit(nn, dmap);
79 }
80
81 static void dlm_free_pagevec(void **vec, int pages)
82 {
83         while (pages--)
84                 free_page((unsigned long)vec[pages]);
85         kfree(vec);
86 }
87
88 static void **dlm_alloc_pagevec(int pages)
89 {
90         void **vec = kmalloc(pages * sizeof(void *), GFP_KERNEL);
91         int i;
92
93         if (!vec)
94                 return NULL;
95
96         for (i = 0; i < pages; i++)
97                 if (!(vec[i] = (void *)__get_free_page(GFP_KERNEL)))
98                         goto out_free;
99
100         mlog(0, "Allocated DLM hash pagevec; %d pages (%lu expected), %lu buckets per page\n",
101              pages, (unsigned long)DLM_HASH_PAGES,
102              (unsigned long)DLM_BUCKETS_PER_PAGE);
103         return vec;
104 out_free:
105         dlm_free_pagevec(vec, i);
106         return NULL;
107 }
108
109 /*
110  *
111  * spinlock lock ordering: if multiple locks are needed, obey this ordering:
112  *    dlm_domain_lock
113  *    struct dlm_ctxt->spinlock
114  *    struct dlm_lock_resource->spinlock
115  *    struct dlm_ctxt->master_lock
116  *    struct dlm_ctxt->ast_lock
117  *    dlm_master_list_entry->spinlock
118  *    dlm_lock->spinlock
119  *
120  */
121
122 DEFINE_SPINLOCK(dlm_domain_lock);
123 LIST_HEAD(dlm_domains);
124 static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events);
125
126 #define DLM_DOMAIN_BACKOFF_MS 200
127
128 static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
129                                   void **ret_data);
130 static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
131                                      void **ret_data);
132 static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data,
133                                    void **ret_data);
134 static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,
135                                    void **ret_data);
136
137 static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm);
138
139 void __dlm_unhash_lockres(struct dlm_lock_resource *lockres)
140 {
141         hlist_del_init(&lockres->hash_node);
142         dlm_lockres_put(lockres);
143 }
144
145 void __dlm_insert_lockres(struct dlm_ctxt *dlm,
146                        struct dlm_lock_resource *res)
147 {
148         struct hlist_head *bucket;
149         struct qstr *q;
150
151         assert_spin_locked(&dlm->spinlock);
152
153         q = &res->lockname;
154         bucket = dlm_lockres_hash(dlm, q->hash);
155
156         /* get a reference for our hashtable */
157         dlm_lockres_get(res);
158
159         hlist_add_head(&res->hash_node, bucket);
160 }
161
162 struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm,
163                                                      const char *name,
164                                                      unsigned int len,
165                                                      unsigned int hash)
166 {
167         struct hlist_head *bucket;
168         struct hlist_node *list;
169
170         mlog_entry("%.*s\n", len, name);
171
172         assert_spin_locked(&dlm->spinlock);
173
174         bucket = dlm_lockres_hash(dlm, hash);
175
176         hlist_for_each(list, bucket) {
177                 struct dlm_lock_resource *res = hlist_entry(list,
178                         struct dlm_lock_resource, hash_node);
179                 if (res->lockname.name[0] != name[0])
180                         continue;
181                 if (unlikely(res->lockname.len != len))
182                         continue;
183                 if (memcmp(res->lockname.name + 1, name + 1, len - 1))
184                         continue;
185                 dlm_lockres_get(res);
186                 return res;
187         }
188         return NULL;
189 }
190
191 /* intended to be called by functions which do not care about lock
192  * resources which are being purged (most net _handler functions).
193  * this will return NULL for any lock resource which is found but
194  * currently in the process of dropping its mastery reference.
195  * use __dlm_lookup_lockres_full when you need the lock resource
196  * regardless (e.g. dlm_get_lock_resource) */
197 struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm,
198                                                 const char *name,
199                                                 unsigned int len,
200                                                 unsigned int hash)
201 {
202         struct dlm_lock_resource *res = NULL;
203
204         mlog_entry("%.*s\n", len, name);
205
206         assert_spin_locked(&dlm->spinlock);
207
208         res = __dlm_lookup_lockres_full(dlm, name, len, hash);
209         if (res) {
210                 spin_lock(&res->spinlock);
211                 if (res->state & DLM_LOCK_RES_DROPPING_REF) {
212                         spin_unlock(&res->spinlock);
213                         dlm_lockres_put(res);
214                         return NULL;
215                 }
216                 spin_unlock(&res->spinlock);
217         }
218
219         return res;
220 }
221
222 struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm,
223                                     const char *name,
224                                     unsigned int len)
225 {
226         struct dlm_lock_resource *res;
227         unsigned int hash = dlm_lockid_hash(name, len);
228
229         spin_lock(&dlm->spinlock);
230         res = __dlm_lookup_lockres(dlm, name, len, hash);
231         spin_unlock(&dlm->spinlock);
232         return res;
233 }
234
235 static struct dlm_ctxt * __dlm_lookup_domain_full(const char *domain, int len)
236 {
237         struct dlm_ctxt *tmp = NULL;
238         struct list_head *iter;
239
240         assert_spin_locked(&dlm_domain_lock);
241
242         /* tmp->name here is always NULL terminated,
243          * but domain may not be! */
244         list_for_each(iter, &dlm_domains) {
245                 tmp = list_entry (iter, struct dlm_ctxt, list);
246                 if (strlen(tmp->name) == len &&
247                     memcmp(tmp->name, domain, len)==0)
248                         break;
249                 tmp = NULL;
250         }
251
252         return tmp;
253 }
254
255 /* For null terminated domain strings ONLY */
256 static struct dlm_ctxt * __dlm_lookup_domain(const char *domain)
257 {
258         assert_spin_locked(&dlm_domain_lock);
259
260         return __dlm_lookup_domain_full(domain, strlen(domain));
261 }
262
263
264 /* returns true on one of two conditions:
265  * 1) the domain does not exist
266  * 2) the domain exists and it's state is "joined" */
267 static int dlm_wait_on_domain_helper(const char *domain)
268 {
269         int ret = 0;
270         struct dlm_ctxt *tmp = NULL;
271
272         spin_lock(&dlm_domain_lock);
273
274         tmp = __dlm_lookup_domain(domain);
275         if (!tmp)
276                 ret = 1;
277         else if (tmp->dlm_state == DLM_CTXT_JOINED)
278                 ret = 1;
279
280         spin_unlock(&dlm_domain_lock);
281         return ret;
282 }
283
284 static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm)
285 {
286         if (dlm->lockres_hash)
287                 dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES);
288
289         if (dlm->name)
290                 kfree(dlm->name);
291
292         kfree(dlm);
293 }
294
295 /* A little strange - this function will be called while holding
296  * dlm_domain_lock and is expected to be holding it on the way out. We
297  * will however drop and reacquire it multiple times */
298 static void dlm_ctxt_release(struct kref *kref)
299 {
300         struct dlm_ctxt *dlm;
301
302         dlm = container_of(kref, struct dlm_ctxt, dlm_refs);
303
304         BUG_ON(dlm->num_joins);
305         BUG_ON(dlm->dlm_state == DLM_CTXT_JOINED);
306
307         /* we may still be in the list if we hit an error during join. */
308         list_del_init(&dlm->list);
309
310         spin_unlock(&dlm_domain_lock);
311
312         mlog(0, "freeing memory from domain %s\n", dlm->name);
313
314         wake_up(&dlm_domain_events);
315
316         dlm_free_ctxt_mem(dlm);
317
318         spin_lock(&dlm_domain_lock);
319 }
320
321 void dlm_put(struct dlm_ctxt *dlm)
322 {
323         spin_lock(&dlm_domain_lock);
324         kref_put(&dlm->dlm_refs, dlm_ctxt_release);
325         spin_unlock(&dlm_domain_lock);
326 }
327
328 static void __dlm_get(struct dlm_ctxt *dlm)
329 {
330         kref_get(&dlm->dlm_refs);
331 }
332
333 /* given a questionable reference to a dlm object, gets a reference if
334  * it can find it in the list, otherwise returns NULL in which case
335  * you shouldn't trust your pointer. */
336 struct dlm_ctxt *dlm_grab(struct dlm_ctxt *dlm)
337 {
338         struct list_head *iter;
339         struct dlm_ctxt *target = NULL;
340
341         spin_lock(&dlm_domain_lock);
342
343         list_for_each(iter, &dlm_domains) {
344                 target = list_entry (iter, struct dlm_ctxt, list);
345
346                 if (target == dlm) {
347                         __dlm_get(target);
348                         break;
349                 }
350
351                 target = NULL;
352         }
353
354         spin_unlock(&dlm_domain_lock);
355
356         return target;
357 }
358
359 int dlm_domain_fully_joined(struct dlm_ctxt *dlm)
360 {
361         int ret;
362
363         spin_lock(&dlm_domain_lock);
364         ret = (dlm->dlm_state == DLM_CTXT_JOINED) ||
365                 (dlm->dlm_state == DLM_CTXT_IN_SHUTDOWN);
366         spin_unlock(&dlm_domain_lock);
367
368         return ret;
369 }
370
371 static void dlm_destroy_dlm_worker(struct dlm_ctxt *dlm)
372 {
373         if (dlm->dlm_worker) {
374                 flush_workqueue(dlm->dlm_worker);
375                 destroy_workqueue(dlm->dlm_worker);
376                 dlm->dlm_worker = NULL;
377         }
378 }
379
380 static void dlm_complete_dlm_shutdown(struct dlm_ctxt *dlm)
381 {
382         dlm_unregister_domain_handlers(dlm);
383         dlm_complete_thread(dlm);
384         dlm_complete_recovery_thread(dlm);
385         dlm_destroy_dlm_worker(dlm);
386
387         /* We've left the domain. Now we can take ourselves out of the
388          * list and allow the kref stuff to help us free the
389          * memory. */
390         spin_lock(&dlm_domain_lock);
391         list_del_init(&dlm->list);
392         spin_unlock(&dlm_domain_lock);
393
394         /* Wake up anyone waiting for us to remove this domain */
395         wake_up(&dlm_domain_events);
396 }
397
398 static int dlm_migrate_all_locks(struct dlm_ctxt *dlm)
399 {
400         int i, num, n, ret = 0;
401         struct dlm_lock_resource *res;
402         struct hlist_node *iter;
403         struct hlist_head *bucket;
404         int dropped;
405
406         mlog(0, "Migrating locks from domain %s\n", dlm->name);
407
408         num = 0;
409         spin_lock(&dlm->spinlock);
410         for (i = 0; i < DLM_HASH_BUCKETS; i++) {
411 redo_bucket:
412                 n = 0;
413                 bucket = dlm_lockres_hash(dlm, i);
414                 iter = bucket->first;
415                 while (iter) {
416                         n++;
417                         res = hlist_entry(iter, struct dlm_lock_resource,
418                                           hash_node);
419                         dlm_lockres_get(res);
420                         /* migrate, if necessary.  this will drop the dlm
421                          * spinlock and retake it if it does migration. */
422                         dropped = dlm_empty_lockres(dlm, res);
423
424                         spin_lock(&res->spinlock);
425                         __dlm_lockres_calc_usage(dlm, res);
426                         iter = res->hash_node.next;
427                         spin_unlock(&res->spinlock);
428
429                         dlm_lockres_put(res);
430
431                         cond_resched_lock(&dlm->spinlock);
432
433                         if (dropped)
434                                 goto redo_bucket;
435                 }
436                 num += n;
437                 mlog(0, "%s: touched %d lockreses in bucket %d "
438                      "(tot=%d)\n", dlm->name, n, i, num);
439         }
440         spin_unlock(&dlm->spinlock);
441         wake_up(&dlm->dlm_thread_wq);
442
443         /* let the dlm thread take care of purging, keep scanning until
444          * nothing remains in the hash */
445         if (num) {
446                 mlog(0, "%s: %d lock resources in hash last pass\n",
447                      dlm->name, num);
448                 ret = -EAGAIN;
449         }
450         mlog(0, "DONE Migrating locks from domain %s\n", dlm->name);
451         return ret;
452 }
453
454 static int dlm_no_joining_node(struct dlm_ctxt *dlm)
455 {
456         int ret;
457
458         spin_lock(&dlm->spinlock);
459         ret = dlm->joining_node == DLM_LOCK_RES_OWNER_UNKNOWN;
460         spin_unlock(&dlm->spinlock);
461
462         return ret;
463 }
464
465 static void dlm_mark_domain_leaving(struct dlm_ctxt *dlm)
466 {
467         /* Yikes, a double spinlock! I need domain_lock for the dlm
468          * state and the dlm spinlock for join state... Sorry! */
469 again:
470         spin_lock(&dlm_domain_lock);
471         spin_lock(&dlm->spinlock);
472
473         if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) {
474                 mlog(0, "Node %d is joining, we wait on it.\n",
475                           dlm->joining_node);
476                 spin_unlock(&dlm->spinlock);
477                 spin_unlock(&dlm_domain_lock);
478
479                 wait_event(dlm->dlm_join_events, dlm_no_joining_node(dlm));
480                 goto again;
481         }
482
483         dlm->dlm_state = DLM_CTXT_LEAVING;
484         spin_unlock(&dlm->spinlock);
485         spin_unlock(&dlm_domain_lock);
486 }
487
488 static void __dlm_print_nodes(struct dlm_ctxt *dlm)
489 {
490         int node = -1;
491
492         assert_spin_locked(&dlm->spinlock);
493
494         printk(KERN_INFO "ocfs2_dlm: Nodes in domain (\"%s\"): ", dlm->name);
495
496         while ((node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES,
497                                      node + 1)) < O2NM_MAX_NODES) {
498                 printk("%d ", node);
499         }
500         printk("\n");
501 }
502
503 static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,
504                                    void **ret_data)
505 {
506         struct dlm_ctxt *dlm = data;
507         unsigned int node;
508         struct dlm_exit_domain *exit_msg = (struct dlm_exit_domain *) msg->buf;
509
510         mlog_entry("%p %u %p", msg, len, data);
511
512         if (!dlm_grab(dlm))
513                 return 0;
514
515         node = exit_msg->node_idx;
516
517         printk(KERN_INFO "ocfs2_dlm: Node %u leaves domain %s\n", node, dlm->name);
518
519         spin_lock(&dlm->spinlock);
520         clear_bit(node, dlm->domain_map);
521         __dlm_print_nodes(dlm);
522
523         /* notify anything attached to the heartbeat events */
524         dlm_hb_event_notify_attached(dlm, node, 0);
525
526         spin_unlock(&dlm->spinlock);
527
528         dlm_put(dlm);
529
530         return 0;
531 }
532
533 static int dlm_send_one_domain_exit(struct dlm_ctxt *dlm,
534                                     unsigned int node)
535 {
536         int status;
537         struct dlm_exit_domain leave_msg;
538
539         mlog(0, "Asking node %u if we can leave the domain %s me = %u\n",
540                   node, dlm->name, dlm->node_num);
541
542         memset(&leave_msg, 0, sizeof(leave_msg));
543         leave_msg.node_idx = dlm->node_num;
544
545         status = o2net_send_message(DLM_EXIT_DOMAIN_MSG, dlm->key,
546                                     &leave_msg, sizeof(leave_msg), node,
547                                     NULL);
548
549         mlog(0, "status return %d from o2net_send_message\n", status);
550
551         return status;
552 }
553
554
555 static void dlm_leave_domain(struct dlm_ctxt *dlm)
556 {
557         int node, clear_node, status;
558
559         /* At this point we've migrated away all our locks and won't
560          * accept mastership of new ones. The dlm is responsible for
561          * almost nothing now. We make sure not to confuse any joining
562          * nodes and then commence shutdown procedure. */
563
564         spin_lock(&dlm->spinlock);
565         /* Clear ourselves from the domain map */
566         clear_bit(dlm->node_num, dlm->domain_map);
567         while ((node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES,
568                                      0)) < O2NM_MAX_NODES) {
569                 /* Drop the dlm spinlock. This is safe wrt the domain_map.
570                  * -nodes cannot be added now as the
571                  *   query_join_handlers knows to respond with OK_NO_MAP
572                  * -we catch the right network errors if a node is
573                  *   removed from the map while we're sending him the
574                  *   exit message. */
575                 spin_unlock(&dlm->spinlock);
576
577                 clear_node = 1;
578
579                 status = dlm_send_one_domain_exit(dlm, node);
580                 if (status < 0 &&
581                     status != -ENOPROTOOPT &&
582                     status != -ENOTCONN) {
583                         mlog(ML_NOTICE, "Error %d sending domain exit message "
584                              "to node %d\n", status, node);
585
586                         /* Not sure what to do here but lets sleep for
587                          * a bit in case this was a transient
588                          * error... */
589                         msleep(DLM_DOMAIN_BACKOFF_MS);
590                         clear_node = 0;
591                 }
592
593                 spin_lock(&dlm->spinlock);
594                 /* If we're not clearing the node bit then we intend
595                  * to loop back around to try again. */
596                 if (clear_node)
597                         clear_bit(node, dlm->domain_map);
598         }
599         spin_unlock(&dlm->spinlock);
600 }
601
602 int dlm_joined(struct dlm_ctxt *dlm)
603 {
604         int ret = 0;
605
606         spin_lock(&dlm_domain_lock);
607
608         if (dlm->dlm_state == DLM_CTXT_JOINED)
609                 ret = 1;
610
611         spin_unlock(&dlm_domain_lock);
612
613         return ret;
614 }
615
616 int dlm_shutting_down(struct dlm_ctxt *dlm)
617 {
618         int ret = 0;
619
620         spin_lock(&dlm_domain_lock);
621
622         if (dlm->dlm_state == DLM_CTXT_IN_SHUTDOWN)
623                 ret = 1;
624
625         spin_unlock(&dlm_domain_lock);
626
627         return ret;
628 }
629
630 void dlm_unregister_domain(struct dlm_ctxt *dlm)
631 {
632         int leave = 0;
633
634         spin_lock(&dlm_domain_lock);
635         BUG_ON(dlm->dlm_state != DLM_CTXT_JOINED);
636         BUG_ON(!dlm->num_joins);
637
638         dlm->num_joins--;
639         if (!dlm->num_joins) {
640                 /* We mark it "in shutdown" now so new register
641                  * requests wait until we've completely left the
642                  * domain. Don't use DLM_CTXT_LEAVING yet as we still
643                  * want new domain joins to communicate with us at
644                  * least until we've completed migration of our
645                  * resources. */
646                 dlm->dlm_state = DLM_CTXT_IN_SHUTDOWN;
647                 leave = 1;
648         }
649         spin_unlock(&dlm_domain_lock);
650
651         if (leave) {
652                 mlog(0, "shutting down domain %s\n", dlm->name);
653
654                 /* We changed dlm state, notify the thread */
655                 dlm_kick_thread(dlm, NULL);
656
657                 while (dlm_migrate_all_locks(dlm)) {
658                         mlog(0, "%s: more migration to do\n", dlm->name);
659                 }
660                 dlm_mark_domain_leaving(dlm);
661                 dlm_leave_domain(dlm);
662                 dlm_complete_dlm_shutdown(dlm);
663         }
664         dlm_put(dlm);
665 }
666 EXPORT_SYMBOL_GPL(dlm_unregister_domain);
667
668 static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
669                                   void **ret_data)
670 {
671         struct dlm_query_join_request *query;
672         enum dlm_query_join_response response;
673         struct dlm_ctxt *dlm = NULL;
674         u8 nodenum;
675
676         query = (struct dlm_query_join_request *) msg->buf;
677
678         mlog(0, "node %u wants to join domain %s\n", query->node_idx,
679                   query->domain);
680
681         /*
682          * If heartbeat doesn't consider the node live, tell it
683          * to back off and try again.  This gives heartbeat a chance
684          * to catch up.
685          */
686         if (!o2hb_check_node_heartbeating(query->node_idx)) {
687                 mlog(0, "node %u is not in our live map yet\n",
688                      query->node_idx);
689
690                 response = JOIN_DISALLOW;
691                 goto respond;
692         }
693
694         response = JOIN_OK_NO_MAP;
695
696         spin_lock(&dlm_domain_lock);
697         dlm = __dlm_lookup_domain_full(query->domain, query->name_len);
698         if (!dlm)
699                 goto unlock_respond;
700
701         /*
702          * There is a small window where the joining node may not see the
703          * node(s) that just left but still part of the cluster. DISALLOW
704          * join request if joining node has different node map.
705          */
706         nodenum=0;
707         while (nodenum < O2NM_MAX_NODES) {
708                 if (test_bit(nodenum, dlm->domain_map)) {
709                         if (!byte_test_bit(nodenum, query->node_map)) {
710                                 response = JOIN_DISALLOW;
711                                 goto unlock_respond;
712                         }
713                 }
714                 nodenum++;
715         }
716
717         /* Once the dlm ctxt is marked as leaving then we don't want
718          * to be put in someone's domain map. 
719          * Also, explicitly disallow joining at certain troublesome
720          * times (ie. during recovery). */
721         if (dlm && dlm->dlm_state != DLM_CTXT_LEAVING) {
722                 int bit = query->node_idx;
723                 spin_lock(&dlm->spinlock);
724
725                 if (dlm->dlm_state == DLM_CTXT_NEW &&
726                     dlm->joining_node == DLM_LOCK_RES_OWNER_UNKNOWN) {
727                         /*If this is a brand new context and we
728                          * haven't started our join process yet, then
729                          * the other node won the race. */
730                         response = JOIN_OK_NO_MAP;
731                 } else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) {
732                         /* Disallow parallel joins. */
733                         response = JOIN_DISALLOW;
734                 } else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) {
735                         mlog(ML_NOTICE, "node %u trying to join, but recovery "
736                              "is ongoing.\n", bit);
737                         response = JOIN_DISALLOW;
738                 } else if (test_bit(bit, dlm->recovery_map)) {
739                         mlog(ML_NOTICE, "node %u trying to join, but it "
740                              "still needs recovery.\n", bit);
741                         response = JOIN_DISALLOW;
742                 } else if (test_bit(bit, dlm->domain_map)) {
743                         mlog(ML_NOTICE, "node %u trying to join, but it "
744                              "is still in the domain! needs recovery?\n",
745                              bit);
746                         response = JOIN_DISALLOW;
747                 } else {
748                         /* Alright we're fully a part of this domain
749                          * so we keep some state as to who's joining
750                          * and indicate to him that needs to be fixed
751                          * up. */
752                         response = JOIN_OK;
753                         __dlm_set_joining_node(dlm, query->node_idx);
754                 }
755
756                 spin_unlock(&dlm->spinlock);
757         }
758 unlock_respond:
759         spin_unlock(&dlm_domain_lock);
760
761 respond:
762         mlog(0, "We respond with %u\n", response);
763
764         return response;
765 }
766
767 static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
768                                      void **ret_data)
769 {
770         struct dlm_assert_joined *assert;
771         struct dlm_ctxt *dlm = NULL;
772
773         assert = (struct dlm_assert_joined *) msg->buf;
774
775         mlog(0, "node %u asserts join on domain %s\n", assert->node_idx,
776                   assert->domain);
777
778         spin_lock(&dlm_domain_lock);
779         dlm = __dlm_lookup_domain_full(assert->domain, assert->name_len);
780         /* XXX should we consider no dlm ctxt an error? */
781         if (dlm) {
782                 spin_lock(&dlm->spinlock);
783
784                 /* Alright, this node has officially joined our
785                  * domain. Set him in the map and clean up our
786                  * leftover join state. */
787                 BUG_ON(dlm->joining_node != assert->node_idx);
788                 set_bit(assert->node_idx, dlm->domain_map);
789                 __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);
790
791                 printk(KERN_INFO "ocfs2_dlm: Node %u joins domain %s\n",
792                        assert->node_idx, dlm->name);
793                 __dlm_print_nodes(dlm);
794
795                 /* notify anything attached to the heartbeat events */
796                 dlm_hb_event_notify_attached(dlm, assert->node_idx, 1);
797
798                 spin_unlock(&dlm->spinlock);
799         }
800         spin_unlock(&dlm_domain_lock);
801
802         return 0;
803 }
804
805 static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data,
806                                    void **ret_data)
807 {
808         struct dlm_cancel_join *cancel;
809         struct dlm_ctxt *dlm = NULL;
810
811         cancel = (struct dlm_cancel_join *) msg->buf;
812
813         mlog(0, "node %u cancels join on domain %s\n", cancel->node_idx,
814                   cancel->domain);
815
816         spin_lock(&dlm_domain_lock);
817         dlm = __dlm_lookup_domain_full(cancel->domain, cancel->name_len);
818
819         if (dlm) {
820                 spin_lock(&dlm->spinlock);
821
822                 /* Yikes, this guy wants to cancel his join. No
823                  * problem, we simply cleanup our join state. */
824                 BUG_ON(dlm->joining_node != cancel->node_idx);
825                 __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);
826
827                 spin_unlock(&dlm->spinlock);
828         }
829         spin_unlock(&dlm_domain_lock);
830
831         return 0;
832 }
833
834 static int dlm_send_one_join_cancel(struct dlm_ctxt *dlm,
835                                     unsigned int node)
836 {
837         int status;
838         struct dlm_cancel_join cancel_msg;
839
840         memset(&cancel_msg, 0, sizeof(cancel_msg));
841         cancel_msg.node_idx = dlm->node_num;
842         cancel_msg.name_len = strlen(dlm->name);
843         memcpy(cancel_msg.domain, dlm->name, cancel_msg.name_len);
844
845         status = o2net_send_message(DLM_CANCEL_JOIN_MSG, DLM_MOD_KEY,
846                                     &cancel_msg, sizeof(cancel_msg), node,
847                                     NULL);
848         if (status < 0) {
849                 mlog_errno(status);
850                 goto bail;
851         }
852
853 bail:
854         return status;
855 }
856
857 /* map_size should be in bytes. */
858 static int dlm_send_join_cancels(struct dlm_ctxt *dlm,
859                                  unsigned long *node_map,
860                                  unsigned int map_size)
861 {
862         int status, tmpstat;
863         unsigned int node;
864
865         if (map_size != (BITS_TO_LONGS(O2NM_MAX_NODES) *
866                          sizeof(unsigned long))) {
867                 mlog(ML_ERROR,
868                      "map_size %u != BITS_TO_LONGS(O2NM_MAX_NODES) %u\n",
869                      map_size, BITS_TO_LONGS(O2NM_MAX_NODES));
870                 return -EINVAL;
871         }
872
873         status = 0;
874         node = -1;
875         while ((node = find_next_bit(node_map, O2NM_MAX_NODES,
876                                      node + 1)) < O2NM_MAX_NODES) {
877                 if (node == dlm->node_num)
878                         continue;
879
880                 tmpstat = dlm_send_one_join_cancel(dlm, node);
881                 if (tmpstat) {
882                         mlog(ML_ERROR, "Error return %d cancelling join on "
883                              "node %d\n", tmpstat, node);
884                         if (!status)
885                                 status = tmpstat;
886                 }
887         }
888
889         if (status)
890                 mlog_errno(status);
891         return status;
892 }
893
894 static int dlm_request_join(struct dlm_ctxt *dlm,
895                             int node,
896                             enum dlm_query_join_response *response)
897 {
898         int status, retval;
899         struct dlm_query_join_request join_msg;
900
901         mlog(0, "querying node %d\n", node);
902
903         memset(&join_msg, 0, sizeof(join_msg));
904         join_msg.node_idx = dlm->node_num;
905         join_msg.name_len = strlen(dlm->name);
906         memcpy(join_msg.domain, dlm->name, join_msg.name_len);
907
908         /* copy live node map to join message */
909         byte_copymap(join_msg.node_map, dlm->live_nodes_map, O2NM_MAX_NODES);
910
911         status = o2net_send_message(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY, &join_msg,
912                                     sizeof(join_msg), node, &retval);
913         if (status < 0 && status != -ENOPROTOOPT) {
914                 mlog_errno(status);
915                 goto bail;
916         }
917
918         /* -ENOPROTOOPT from the net code means the other side isn't
919             listening for our message type -- that's fine, it means
920             his dlm isn't up, so we can consider him a 'yes' but not
921             joined into the domain.  */
922         if (status == -ENOPROTOOPT) {
923                 status = 0;
924                 *response = JOIN_OK_NO_MAP;
925         } else if (retval == JOIN_DISALLOW ||
926                    retval == JOIN_OK ||
927                    retval == JOIN_OK_NO_MAP) {
928                 *response = retval;
929         } else {
930                 status = -EINVAL;
931                 mlog(ML_ERROR, "invalid response %d from node %u\n", retval,
932                      node);
933         }
934
935         mlog(0, "status %d, node %d response is %d\n", status, node,
936                   *response);
937
938 bail:
939         return status;
940 }
941
942 static int dlm_send_one_join_assert(struct dlm_ctxt *dlm,
943                                     unsigned int node)
944 {
945         int status;
946         struct dlm_assert_joined assert_msg;
947
948         mlog(0, "Sending join assert to node %u\n", node);
949
950         memset(&assert_msg, 0, sizeof(assert_msg));
951         assert_msg.node_idx = dlm->node_num;
952         assert_msg.name_len = strlen(dlm->name);
953         memcpy(assert_msg.domain, dlm->name, assert_msg.name_len);
954
955         status = o2net_send_message(DLM_ASSERT_JOINED_MSG, DLM_MOD_KEY,
956                                     &assert_msg, sizeof(assert_msg), node,
957                                     NULL);
958         if (status < 0)
959                 mlog_errno(status);
960
961         return status;
962 }
963
964 static void dlm_send_join_asserts(struct dlm_ctxt *dlm,
965                                   unsigned long *node_map)
966 {
967         int status, node, live;
968
969         status = 0;
970         node = -1;
971         while ((node = find_next_bit(node_map, O2NM_MAX_NODES,
972                                      node + 1)) < O2NM_MAX_NODES) {
973                 if (node == dlm->node_num)
974                         continue;
975
976                 do {
977                         /* It is very important that this message be
978                          * received so we spin until either the node
979                          * has died or it gets the message. */
980                         status = dlm_send_one_join_assert(dlm, node);
981
982                         spin_lock(&dlm->spinlock);
983                         live = test_bit(node, dlm->live_nodes_map);
984                         spin_unlock(&dlm->spinlock);
985
986                         if (status) {
987                                 mlog(ML_ERROR, "Error return %d asserting "
988                                      "join on node %d\n", status, node);
989
990                                 /* give us some time between errors... */
991                                 if (live)
992                                         msleep(DLM_DOMAIN_BACKOFF_MS);
993                         }
994                 } while (status && live);
995         }
996 }
997
998 struct domain_join_ctxt {
999         unsigned long live_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
1000         unsigned long yes_resp_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
1001 };
1002
1003 static int dlm_should_restart_join(struct dlm_ctxt *dlm,
1004                                    struct domain_join_ctxt *ctxt,
1005                                    enum dlm_query_join_response response)
1006 {
1007         int ret;
1008
1009         if (response == JOIN_DISALLOW) {
1010                 mlog(0, "Latest response of disallow -- should restart\n");
1011                 return 1;
1012         }
1013
1014         spin_lock(&dlm->spinlock);
1015         /* For now, we restart the process if the node maps have
1016          * changed at all */
1017         ret = memcmp(ctxt->live_map, dlm->live_nodes_map,
1018                      sizeof(dlm->live_nodes_map));
1019         spin_unlock(&dlm->spinlock);
1020
1021         if (ret)
1022                 mlog(0, "Node maps changed -- should restart\n");
1023
1024         return ret;
1025 }
1026
1027 static int dlm_try_to_join_domain(struct dlm_ctxt *dlm)
1028 {
1029         int status = 0, tmpstat, node;
1030         struct domain_join_ctxt *ctxt;
1031         enum dlm_query_join_response response;
1032
1033         mlog_entry("%p", dlm);
1034
1035         ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
1036         if (!ctxt) {
1037                 status = -ENOMEM;
1038                 mlog_errno(status);
1039                 goto bail;
1040         }
1041
1042         /* group sem locking should work for us here -- we're already
1043          * registered for heartbeat events so filling this should be
1044          * atomic wrt getting those handlers called. */
1045         o2hb_fill_node_map(dlm->live_nodes_map, sizeof(dlm->live_nodes_map));
1046
1047         spin_lock(&dlm->spinlock);
1048         memcpy(ctxt->live_map, dlm->live_nodes_map, sizeof(ctxt->live_map));
1049
1050         __dlm_set_joining_node(dlm, dlm->node_num);
1051
1052         spin_unlock(&dlm->spinlock);
1053
1054         node = -1;
1055         while ((node = find_next_bit(ctxt->live_map, O2NM_MAX_NODES,
1056                                      node + 1)) < O2NM_MAX_NODES) {
1057                 if (node == dlm->node_num)
1058                         continue;
1059
1060                 status = dlm_request_join(dlm, node, &response);
1061                 if (status < 0) {
1062                         mlog_errno(status);
1063                         goto bail;
1064                 }
1065
1066                 /* Ok, either we got a response or the node doesn't have a
1067                  * dlm up. */
1068                 if (response == JOIN_OK)
1069                         set_bit(node, ctxt->yes_resp_map);
1070
1071                 if (dlm_should_restart_join(dlm, ctxt, response)) {
1072                         status = -EAGAIN;
1073                         goto bail;
1074                 }
1075         }
1076
1077         mlog(0, "Yay, done querying nodes!\n");
1078
1079         /* Yay, everyone agree's we can join the domain. My domain is
1080          * comprised of all nodes who were put in the
1081          * yes_resp_map. Copy that into our domain map and send a join
1082          * assert message to clean up everyone elses state. */
1083         spin_lock(&dlm->spinlock);
1084         memcpy(dlm->domain_map, ctxt->yes_resp_map,
1085                sizeof(ctxt->yes_resp_map));
1086         set_bit(dlm->node_num, dlm->domain_map);
1087         spin_unlock(&dlm->spinlock);
1088
1089         dlm_send_join_asserts(dlm, ctxt->yes_resp_map);
1090
1091         /* Joined state *must* be set before the joining node
1092          * information, otherwise the query_join handler may read no
1093          * current joiner but a state of NEW and tell joining nodes
1094          * we're not in the domain. */
1095         spin_lock(&dlm_domain_lock);
1096         dlm->dlm_state = DLM_CTXT_JOINED;
1097         dlm->num_joins++;
1098         spin_unlock(&dlm_domain_lock);
1099
1100 bail:
1101         spin_lock(&dlm->spinlock);
1102         __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);
1103         if (!status)
1104                 __dlm_print_nodes(dlm);
1105         spin_unlock(&dlm->spinlock);
1106
1107         if (ctxt) {
1108                 /* Do we need to send a cancel message to any nodes? */
1109                 if (status < 0) {
1110                         tmpstat = dlm_send_join_cancels(dlm,
1111                                                         ctxt->yes_resp_map,
1112                                                         sizeof(ctxt->yes_resp_map));
1113                         if (tmpstat < 0)
1114                                 mlog_errno(tmpstat);
1115                 }
1116                 kfree(ctxt);
1117         }
1118
1119         mlog(0, "returning %d\n", status);
1120         return status;
1121 }
1122
1123 static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm)
1124 {
1125         o2hb_unregister_callback(&dlm->dlm_hb_up);
1126         o2hb_unregister_callback(&dlm->dlm_hb_down);
1127         o2net_unregister_handler_list(&dlm->dlm_domain_handlers);
1128 }
1129
1130 static int dlm_register_domain_handlers(struct dlm_ctxt *dlm)
1131 {
1132         int status;
1133
1134         mlog(0, "registering handlers.\n");
1135
1136         o2hb_setup_callback(&dlm->dlm_hb_down, O2HB_NODE_DOWN_CB,
1137                             dlm_hb_node_down_cb, dlm, DLM_HB_NODE_DOWN_PRI);
1138         status = o2hb_register_callback(&dlm->dlm_hb_down);
1139         if (status)
1140                 goto bail;
1141
1142         o2hb_setup_callback(&dlm->dlm_hb_up, O2HB_NODE_UP_CB,
1143                             dlm_hb_node_up_cb, dlm, DLM_HB_NODE_UP_PRI);
1144         status = o2hb_register_callback(&dlm->dlm_hb_up);
1145         if (status)
1146                 goto bail;
1147
1148         status = o2net_register_handler(DLM_MASTER_REQUEST_MSG, dlm->key,
1149                                         sizeof(struct dlm_master_request),
1150                                         dlm_master_request_handler,
1151                                         dlm, NULL, &dlm->dlm_domain_handlers);
1152         if (status)
1153                 goto bail;
1154
1155         status = o2net_register_handler(DLM_ASSERT_MASTER_MSG, dlm->key,
1156                                         sizeof(struct dlm_assert_master),
1157                                         dlm_assert_master_handler,
1158                                         dlm, dlm_assert_master_post_handler,
1159                                         &dlm->dlm_domain_handlers);
1160         if (status)
1161                 goto bail;
1162
1163         status = o2net_register_handler(DLM_CREATE_LOCK_MSG, dlm->key,
1164                                         sizeof(struct dlm_create_lock),
1165                                         dlm_create_lock_handler,
1166                                         dlm, NULL, &dlm->dlm_domain_handlers);
1167         if (status)
1168                 goto bail;
1169
1170         status = o2net_register_handler(DLM_CONVERT_LOCK_MSG, dlm->key,
1171                                         DLM_CONVERT_LOCK_MAX_LEN,
1172                                         dlm_convert_lock_handler,
1173                                         dlm, NULL, &dlm->dlm_domain_handlers);
1174         if (status)
1175                 goto bail;
1176
1177         status = o2net_register_handler(DLM_UNLOCK_LOCK_MSG, dlm->key,
1178                                         DLM_UNLOCK_LOCK_MAX_LEN,
1179                                         dlm_unlock_lock_handler,
1180                                         dlm, NULL, &dlm->dlm_domain_handlers);
1181         if (status)
1182                 goto bail;
1183
1184         status = o2net_register_handler(DLM_PROXY_AST_MSG, dlm->key,
1185                                         DLM_PROXY_AST_MAX_LEN,
1186                                         dlm_proxy_ast_handler,
1187                                         dlm, NULL, &dlm->dlm_domain_handlers);
1188         if (status)
1189                 goto bail;
1190
1191         status = o2net_register_handler(DLM_EXIT_DOMAIN_MSG, dlm->key,
1192                                         sizeof(struct dlm_exit_domain),
1193                                         dlm_exit_domain_handler,
1194                                         dlm, NULL, &dlm->dlm_domain_handlers);
1195         if (status)
1196                 goto bail;
1197
1198         status = o2net_register_handler(DLM_DEREF_LOCKRES_MSG, dlm->key,
1199                                         sizeof(struct dlm_deref_lockres),
1200                                         dlm_deref_lockres_handler,
1201                                         dlm, NULL, &dlm->dlm_domain_handlers);
1202         if (status)
1203                 goto bail;
1204
1205         status = o2net_register_handler(DLM_MIGRATE_REQUEST_MSG, dlm->key,
1206                                         sizeof(struct dlm_migrate_request),
1207                                         dlm_migrate_request_handler,
1208                                         dlm, NULL, &dlm->dlm_domain_handlers);
1209         if (status)
1210                 goto bail;
1211
1212         status = o2net_register_handler(DLM_MIG_LOCKRES_MSG, dlm->key,
1213                                         DLM_MIG_LOCKRES_MAX_LEN,
1214                                         dlm_mig_lockres_handler,
1215                                         dlm, NULL, &dlm->dlm_domain_handlers);
1216         if (status)
1217                 goto bail;
1218
1219         status = o2net_register_handler(DLM_MASTER_REQUERY_MSG, dlm->key,
1220                                         sizeof(struct dlm_master_requery),
1221                                         dlm_master_requery_handler,
1222                                         dlm, NULL, &dlm->dlm_domain_handlers);
1223         if (status)
1224                 goto bail;
1225
1226         status = o2net_register_handler(DLM_LOCK_REQUEST_MSG, dlm->key,
1227                                         sizeof(struct dlm_lock_request),
1228                                         dlm_request_all_locks_handler,
1229                                         dlm, NULL, &dlm->dlm_domain_handlers);
1230         if (status)
1231                 goto bail;
1232
1233         status = o2net_register_handler(DLM_RECO_DATA_DONE_MSG, dlm->key,
1234                                         sizeof(struct dlm_reco_data_done),
1235                                         dlm_reco_data_done_handler,
1236                                         dlm, NULL, &dlm->dlm_domain_handlers);
1237         if (status)
1238                 goto bail;
1239
1240         status = o2net_register_handler(DLM_BEGIN_RECO_MSG, dlm->key,
1241                                         sizeof(struct dlm_begin_reco),
1242                                         dlm_begin_reco_handler,
1243                                         dlm, NULL, &dlm->dlm_domain_handlers);
1244         if (status)
1245                 goto bail;
1246
1247         status = o2net_register_handler(DLM_FINALIZE_RECO_MSG, dlm->key,
1248                                         sizeof(struct dlm_finalize_reco),
1249                                         dlm_finalize_reco_handler,
1250                                         dlm, NULL, &dlm->dlm_domain_handlers);
1251         if (status)
1252                 goto bail;
1253
1254 bail:
1255         if (status)
1256                 dlm_unregister_domain_handlers(dlm);
1257
1258         return status;
1259 }
1260
1261 static int dlm_join_domain(struct dlm_ctxt *dlm)
1262 {
1263         int status;
1264
1265         BUG_ON(!dlm);
1266
1267         mlog(0, "Join domain %s\n", dlm->name);
1268
1269         status = dlm_register_domain_handlers(dlm);
1270         if (status) {
1271                 mlog_errno(status);
1272                 goto bail;
1273         }
1274
1275         status = dlm_launch_thread(dlm);
1276         if (status < 0) {
1277                 mlog_errno(status);
1278                 goto bail;
1279         }
1280
1281         status = dlm_launch_recovery_thread(dlm);
1282         if (status < 0) {
1283                 mlog_errno(status);
1284                 goto bail;
1285         }
1286
1287         dlm->dlm_worker = create_singlethread_workqueue("dlm_wq");
1288         if (!dlm->dlm_worker) {
1289                 status = -ENOMEM;
1290                 mlog_errno(status);
1291                 goto bail;
1292         }
1293
1294         do {
1295                 unsigned int backoff;
1296                 status = dlm_try_to_join_domain(dlm);
1297
1298                 /* If we're racing another node to the join, then we
1299                  * need to back off temporarily and let them
1300                  * complete. */
1301                 if (status == -EAGAIN) {
1302                         if (signal_pending(current)) {
1303                                 status = -ERESTARTSYS;
1304                                 goto bail;
1305                         }
1306
1307                         /*
1308                          * <chip> After you!
1309                          * <dale> No, after you!
1310                          * <chip> I insist!
1311                          * <dale> But you first!
1312                          * ...
1313                          */
1314                         backoff = (unsigned int)(jiffies & 0x3);
1315                         backoff *= DLM_DOMAIN_BACKOFF_MS;
1316                         mlog(0, "backoff %d\n", backoff);
1317                         msleep(backoff);
1318                 }
1319         } while (status == -EAGAIN);
1320
1321         if (status < 0) {
1322                 mlog_errno(status);
1323                 goto bail;
1324         }
1325
1326         status = 0;
1327 bail:
1328         wake_up(&dlm_domain_events);
1329
1330         if (status) {
1331                 dlm_unregister_domain_handlers(dlm);
1332                 dlm_complete_thread(dlm);
1333                 dlm_complete_recovery_thread(dlm);
1334                 dlm_destroy_dlm_worker(dlm);
1335         }
1336
1337         return status;
1338 }
1339
1340 static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
1341                                 u32 key)
1342 {
1343         int i;
1344         struct dlm_ctxt *dlm = NULL;
1345
1346         dlm = kzalloc(sizeof(*dlm), GFP_KERNEL);
1347         if (!dlm) {
1348                 mlog_errno(-ENOMEM);
1349                 goto leave;
1350         }
1351
1352         dlm->name = kmalloc(strlen(domain) + 1, GFP_KERNEL);
1353         if (dlm->name == NULL) {
1354                 mlog_errno(-ENOMEM);
1355                 kfree(dlm);
1356                 dlm = NULL;
1357                 goto leave;
1358         }
1359
1360         dlm->lockres_hash = (struct hlist_head **)dlm_alloc_pagevec(DLM_HASH_PAGES);
1361         if (!dlm->lockres_hash) {
1362                 mlog_errno(-ENOMEM);
1363                 kfree(dlm->name);
1364                 kfree(dlm);
1365                 dlm = NULL;
1366                 goto leave;
1367         }
1368
1369         for (i = 0; i < DLM_HASH_BUCKETS; i++)
1370                 INIT_HLIST_HEAD(dlm_lockres_hash(dlm, i));
1371
1372         strcpy(dlm->name, domain);
1373         dlm->key = key;
1374         dlm->node_num = o2nm_this_node();
1375
1376         spin_lock_init(&dlm->spinlock);
1377         spin_lock_init(&dlm->master_lock);
1378         spin_lock_init(&dlm->ast_lock);
1379         INIT_LIST_HEAD(&dlm->list);
1380         INIT_LIST_HEAD(&dlm->dirty_list);
1381         INIT_LIST_HEAD(&dlm->reco.resources);
1382         INIT_LIST_HEAD(&dlm->reco.received);
1383         INIT_LIST_HEAD(&dlm->reco.node_data);
1384         INIT_LIST_HEAD(&dlm->purge_list);
1385         INIT_LIST_HEAD(&dlm->dlm_domain_handlers);
1386         dlm->reco.state = 0;
1387
1388         INIT_LIST_HEAD(&dlm->pending_asts);
1389         INIT_LIST_HEAD(&dlm->pending_basts);
1390
1391         mlog(0, "dlm->recovery_map=%p, &(dlm->recovery_map[0])=%p\n",
1392                   dlm->recovery_map, &(dlm->recovery_map[0]));
1393
1394         memset(dlm->recovery_map, 0, sizeof(dlm->recovery_map));
1395         memset(dlm->live_nodes_map, 0, sizeof(dlm->live_nodes_map));
1396         memset(dlm->domain_map, 0, sizeof(dlm->domain_map));
1397
1398         dlm->dlm_thread_task = NULL;
1399         dlm->dlm_reco_thread_task = NULL;
1400         dlm->dlm_worker = NULL;
1401         init_waitqueue_head(&dlm->dlm_thread_wq);
1402         init_waitqueue_head(&dlm->dlm_reco_thread_wq);
1403         init_waitqueue_head(&dlm->reco.event);
1404         init_waitqueue_head(&dlm->ast_wq);
1405         init_waitqueue_head(&dlm->migration_wq);
1406         INIT_LIST_HEAD(&dlm->master_list);
1407         INIT_LIST_HEAD(&dlm->mle_hb_events);
1408
1409         dlm->joining_node = DLM_LOCK_RES_OWNER_UNKNOWN;
1410         init_waitqueue_head(&dlm->dlm_join_events);
1411
1412         dlm->reco.new_master = O2NM_INVALID_NODE_NUM;
1413         dlm->reco.dead_node = O2NM_INVALID_NODE_NUM;
1414         atomic_set(&dlm->local_resources, 0);
1415         atomic_set(&dlm->remote_resources, 0);
1416         atomic_set(&dlm->unknown_resources, 0);
1417
1418         spin_lock_init(&dlm->work_lock);
1419         INIT_LIST_HEAD(&dlm->work_list);
1420         INIT_WORK(&dlm->dispatched_work, dlm_dispatch_work);
1421
1422         kref_init(&dlm->dlm_refs);
1423         dlm->dlm_state = DLM_CTXT_NEW;
1424
1425         INIT_LIST_HEAD(&dlm->dlm_eviction_callbacks);
1426
1427         mlog(0, "context init: refcount %u\n",
1428                   atomic_read(&dlm->dlm_refs.refcount));
1429
1430 leave:
1431         return dlm;
1432 }
1433
1434 /*
1435  * dlm_register_domain: one-time setup per "domain"
1436  */
1437 struct dlm_ctxt * dlm_register_domain(const char *domain,
1438                                u32 key)
1439 {
1440         int ret;
1441         struct dlm_ctxt *dlm = NULL;
1442         struct dlm_ctxt *new_ctxt = NULL;
1443
1444         if (strlen(domain) > O2NM_MAX_NAME_LEN) {
1445                 ret = -ENAMETOOLONG;
1446                 mlog(ML_ERROR, "domain name length too long\n");
1447                 goto leave;
1448         }
1449
1450         if (!o2hb_check_local_node_heartbeating()) {
1451                 mlog(ML_ERROR, "the local node has not been configured, or is "
1452                      "not heartbeating\n");
1453                 ret = -EPROTO;
1454                 goto leave;
1455         }
1456
1457         mlog(0, "register called for domain \"%s\"\n", domain);
1458
1459 retry:
1460         dlm = NULL;
1461         if (signal_pending(current)) {
1462                 ret = -ERESTARTSYS;
1463                 mlog_errno(ret);
1464                 goto leave;
1465         }
1466
1467         spin_lock(&dlm_domain_lock);
1468
1469         dlm = __dlm_lookup_domain(domain);
1470         if (dlm) {
1471                 if (dlm->dlm_state != DLM_CTXT_JOINED) {
1472                         spin_unlock(&dlm_domain_lock);
1473
1474                         mlog(0, "This ctxt is not joined yet!\n");
1475                         wait_event_interruptible(dlm_domain_events,
1476                                                  dlm_wait_on_domain_helper(
1477                                                          domain));
1478                         goto retry;
1479                 }
1480
1481                 __dlm_get(dlm);
1482                 dlm->num_joins++;
1483
1484                 spin_unlock(&dlm_domain_lock);
1485
1486                 ret = 0;
1487                 goto leave;
1488         }
1489
1490         /* doesn't exist */
1491         if (!new_ctxt) {
1492                 spin_unlock(&dlm_domain_lock);
1493
1494                 new_ctxt = dlm_alloc_ctxt(domain, key);
1495                 if (new_ctxt)
1496                         goto retry;
1497
1498                 ret = -ENOMEM;
1499                 mlog_errno(ret);
1500                 goto leave;
1501         }
1502
1503         /* a little variable switch-a-roo here... */
1504         dlm = new_ctxt;
1505         new_ctxt = NULL;
1506
1507         /* add the new domain */
1508         list_add_tail(&dlm->list, &dlm_domains);
1509         spin_unlock(&dlm_domain_lock);
1510
1511         ret = dlm_join_domain(dlm);
1512         if (ret) {
1513                 mlog_errno(ret);
1514                 dlm_put(dlm);
1515                 goto leave;
1516         }
1517
1518         ret = 0;
1519 leave:
1520         if (new_ctxt)
1521                 dlm_free_ctxt_mem(new_ctxt);
1522
1523         if (ret < 0)
1524                 dlm = ERR_PTR(ret);
1525
1526         return dlm;
1527 }
1528 EXPORT_SYMBOL_GPL(dlm_register_domain);
1529
1530 static LIST_HEAD(dlm_join_handlers);
1531
1532 static void dlm_unregister_net_handlers(void)
1533 {
1534         o2net_unregister_handler_list(&dlm_join_handlers);
1535 }
1536
1537 static int dlm_register_net_handlers(void)
1538 {
1539         int status = 0;
1540
1541         status = o2net_register_handler(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY,
1542                                         sizeof(struct dlm_query_join_request),
1543                                         dlm_query_join_handler,
1544                                         NULL, NULL, &dlm_join_handlers);
1545         if (status)
1546                 goto bail;
1547
1548         status = o2net_register_handler(DLM_ASSERT_JOINED_MSG, DLM_MOD_KEY,
1549                                         sizeof(struct dlm_assert_joined),
1550                                         dlm_assert_joined_handler,
1551                                         NULL, NULL, &dlm_join_handlers);
1552         if (status)
1553                 goto bail;
1554
1555         status = o2net_register_handler(DLM_CANCEL_JOIN_MSG, DLM_MOD_KEY,
1556                                         sizeof(struct dlm_cancel_join),
1557                                         dlm_cancel_join_handler,
1558                                         NULL, NULL, &dlm_join_handlers);
1559
1560 bail:
1561         if (status < 0)
1562                 dlm_unregister_net_handlers();
1563
1564         return status;
1565 }
1566
1567 /* Domain eviction callback handling.
1568  *
1569  * The file system requires notification of node death *before* the
1570  * dlm completes it's recovery work, otherwise it may be able to
1571  * acquire locks on resources requiring recovery. Since the dlm can
1572  * evict a node from it's domain *before* heartbeat fires, a similar
1573  * mechanism is required. */
1574
1575 /* Eviction is not expected to happen often, so a per-domain lock is
1576  * not necessary. Eviction callbacks are allowed to sleep for short
1577  * periods of time. */
1578 static DECLARE_RWSEM(dlm_callback_sem);
1579
1580 void dlm_fire_domain_eviction_callbacks(struct dlm_ctxt *dlm,
1581                                         int node_num)
1582 {
1583         struct list_head *iter;
1584         struct dlm_eviction_cb *cb;
1585
1586         down_read(&dlm_callback_sem);
1587         list_for_each(iter, &dlm->dlm_eviction_callbacks) {
1588                 cb = list_entry(iter, struct dlm_eviction_cb, ec_item);
1589
1590                 cb->ec_func(node_num, cb->ec_data);
1591         }
1592         up_read(&dlm_callback_sem);
1593 }
1594
1595 void dlm_setup_eviction_cb(struct dlm_eviction_cb *cb,
1596                            dlm_eviction_func *f,
1597                            void *data)
1598 {
1599         INIT_LIST_HEAD(&cb->ec_item);
1600         cb->ec_func = f;
1601         cb->ec_data = data;
1602 }
1603 EXPORT_SYMBOL_GPL(dlm_setup_eviction_cb);
1604
1605 void dlm_register_eviction_cb(struct dlm_ctxt *dlm,
1606                               struct dlm_eviction_cb *cb)
1607 {
1608         down_write(&dlm_callback_sem);
1609         list_add_tail(&cb->ec_item, &dlm->dlm_eviction_callbacks);
1610         up_write(&dlm_callback_sem);
1611 }
1612 EXPORT_SYMBOL_GPL(dlm_register_eviction_cb);
1613
1614 void dlm_unregister_eviction_cb(struct dlm_eviction_cb *cb)
1615 {
1616         down_write(&dlm_callback_sem);
1617         list_del_init(&cb->ec_item);
1618         up_write(&dlm_callback_sem);
1619 }
1620 EXPORT_SYMBOL_GPL(dlm_unregister_eviction_cb);
1621
1622 static int __init dlm_init(void)
1623 {
1624         int status;
1625
1626         dlm_print_version();
1627
1628         status = dlm_init_mle_cache();
1629         if (status)
1630                 return -1;
1631
1632         status = dlm_register_net_handlers();
1633         if (status) {
1634                 dlm_destroy_mle_cache();
1635                 return -1;
1636         }
1637
1638         return 0;
1639 }
1640
1641 static void __exit dlm_exit (void)
1642 {
1643         dlm_unregister_net_handlers();
1644         dlm_destroy_mle_cache();
1645 }
1646
1647 MODULE_AUTHOR("Oracle");
1648 MODULE_LICENSE("GPL");
1649
1650 module_init(dlm_init);
1651 module_exit(dlm_exit);