xref: /openbmc/linux/fs/ocfs2/dlm/dlmcommon.h (revision 643d1f7f)
1 /* -*- mode: c; c-basic-offset: 8; -*-
2  * vim: noexpandtab sw=8 ts=8 sts=0:
3  *
4  * dlmcommon.h
5  *
6  * Copyright (C) 2004 Oracle.  All rights reserved.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public
19  * License along with this program; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 021110-1307, USA.
22  *
23  */
24 
25 #ifndef DLMCOMMON_H
26 #define DLMCOMMON_H
27 
28 #include <linux/kref.h>
29 
30 #define DLM_HB_NODE_DOWN_PRI     (0xf000000)
31 #define DLM_HB_NODE_UP_PRI       (0x8000000)
32 
33 #define DLM_LOCKID_NAME_MAX    32
34 
35 #define DLM_DOMAIN_NAME_MAX_LEN    255
36 #define DLM_LOCK_RES_OWNER_UNKNOWN     O2NM_MAX_NODES
37 #define DLM_THREAD_SHUFFLE_INTERVAL    5     // flush everything every 5 passes
38 #define DLM_THREAD_MS                  200   // flush at least every 200 ms
39 
40 #define DLM_HASH_SIZE_DEFAULT	(1 << 14)
41 #if DLM_HASH_SIZE_DEFAULT < PAGE_SIZE
42 # define DLM_HASH_PAGES		1
43 #else
44 # define DLM_HASH_PAGES		(DLM_HASH_SIZE_DEFAULT / PAGE_SIZE)
45 #endif
46 #define DLM_BUCKETS_PER_PAGE	(PAGE_SIZE / sizeof(struct hlist_head))
47 #define DLM_HASH_BUCKETS	(DLM_HASH_PAGES * DLM_BUCKETS_PER_PAGE)
48 
49 /* Intended to make it easier for us to switch out hash functions */
50 #define dlm_lockid_hash(_n, _l) full_name_hash(_n, _l)
51 
52 enum dlm_ast_type {
53 	DLM_AST = 0,
54 	DLM_BAST,
55 	DLM_ASTUNLOCK
56 };
57 
58 
59 #define LKM_VALID_FLAGS (LKM_VALBLK | LKM_CONVERT | LKM_UNLOCK | \
60 			 LKM_CANCEL | LKM_INVVALBLK | LKM_FORCE | \
61 			 LKM_RECOVERY | LKM_LOCAL | LKM_NOQUEUE)
62 
63 #define DLM_RECOVERY_LOCK_NAME       "$RECOVERY"
64 #define DLM_RECOVERY_LOCK_NAME_LEN   9
65 
66 static inline int dlm_is_recovery_lock(const char *lock_name, int name_len)
67 {
68 	if (name_len == DLM_RECOVERY_LOCK_NAME_LEN &&
69 	    memcmp(lock_name, DLM_RECOVERY_LOCK_NAME, name_len)==0)
70 		return 1;
71 	return 0;
72 }
73 
74 #define DLM_RECO_STATE_ACTIVE    0x0001
75 #define DLM_RECO_STATE_FINALIZE  0x0002
76 
77 struct dlm_recovery_ctxt
78 {
79 	struct list_head resources;
80 	struct list_head received;
81 	struct list_head node_data;
82 	u8  new_master;
83 	u8  dead_node;
84 	u16 state;
85 	unsigned long node_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
86 	wait_queue_head_t event;
87 };
88 
89 enum dlm_ctxt_state {
90 	DLM_CTXT_NEW = 0,
91 	DLM_CTXT_JOINED,
92 	DLM_CTXT_IN_SHUTDOWN,
93 	DLM_CTXT_LEAVING,
94 };
95 
96 struct dlm_ctxt
97 {
98 	struct list_head list;
99 	struct hlist_head **lockres_hash;
100 	struct list_head dirty_list;
101 	struct list_head purge_list;
102 	struct list_head pending_asts;
103 	struct list_head pending_basts;
104 	unsigned int purge_count;
105 	spinlock_t spinlock;
106 	spinlock_t ast_lock;
107 	char *name;
108 	u8 node_num;
109 	u32 key;
110 	u8  joining_node;
111 	wait_queue_head_t dlm_join_events;
112 	unsigned long live_nodes_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
113 	unsigned long domain_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
114 	unsigned long recovery_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
115 	struct dlm_recovery_ctxt reco;
116 	spinlock_t master_lock;
117 	struct list_head master_list;
118 	struct list_head mle_hb_events;
119 
120 	/* these give a really vague idea of the system load */
121 	atomic_t local_resources;
122 	atomic_t remote_resources;
123 	atomic_t unknown_resources;
124 
125 	/* NOTE: Next three are protected by dlm_domain_lock */
126 	struct kref dlm_refs;
127 	enum dlm_ctxt_state dlm_state;
128 	unsigned int num_joins;
129 
130 	struct o2hb_callback_func dlm_hb_up;
131 	struct o2hb_callback_func dlm_hb_down;
132 	struct task_struct *dlm_thread_task;
133 	struct task_struct *dlm_reco_thread_task;
134 	struct workqueue_struct *dlm_worker;
135 	wait_queue_head_t dlm_thread_wq;
136 	wait_queue_head_t dlm_reco_thread_wq;
137 	wait_queue_head_t ast_wq;
138 	wait_queue_head_t migration_wq;
139 
140 	struct work_struct dispatched_work;
141 	struct list_head work_list;
142 	spinlock_t work_lock;
143 	struct list_head dlm_domain_handlers;
144 	struct list_head	dlm_eviction_callbacks;
145 };
146 
147 static inline struct hlist_head *dlm_lockres_hash(struct dlm_ctxt *dlm, unsigned i)
148 {
149 	return dlm->lockres_hash[(i / DLM_BUCKETS_PER_PAGE) % DLM_HASH_PAGES] + (i % DLM_BUCKETS_PER_PAGE);
150 }
151 
152 /* these keventd work queue items are for less-frequently
153  * called functions that cannot be directly called from the
154  * net message handlers for some reason, usually because
155  * they need to send net messages of their own. */
156 void dlm_dispatch_work(struct work_struct *work);
157 
158 struct dlm_lock_resource;
159 struct dlm_work_item;
160 
161 typedef void (dlm_workfunc_t)(struct dlm_work_item *, void *);
162 
163 struct dlm_request_all_locks_priv
164 {
165 	u8 reco_master;
166 	u8 dead_node;
167 };
168 
169 struct dlm_mig_lockres_priv
170 {
171 	struct dlm_lock_resource *lockres;
172 	u8 real_master;
173 };
174 
175 struct dlm_assert_master_priv
176 {
177 	struct dlm_lock_resource *lockres;
178 	u8 request_from;
179 	u32 flags;
180 	unsigned ignore_higher:1;
181 };
182 
183 struct dlm_deref_lockres_priv
184 {
185 	struct dlm_lock_resource *deref_res;
186 	u8 deref_node;
187 };
188 
189 struct dlm_work_item
190 {
191 	struct list_head list;
192 	dlm_workfunc_t *func;
193 	struct dlm_ctxt *dlm;
194 	void *data;
195 	union {
196 		struct dlm_request_all_locks_priv ral;
197 		struct dlm_mig_lockres_priv ml;
198 		struct dlm_assert_master_priv am;
199 		struct dlm_deref_lockres_priv dl;
200 	} u;
201 };
202 
203 static inline void dlm_init_work_item(struct dlm_ctxt *dlm,
204 				      struct dlm_work_item *i,
205 				      dlm_workfunc_t *f, void *data)
206 {
207 	memset(i, 0, sizeof(*i));
208 	i->func = f;
209 	INIT_LIST_HEAD(&i->list);
210 	i->data = data;
211 	i->dlm = dlm;  /* must have already done a dlm_grab on this! */
212 }
213 
214 
215 
216 static inline void __dlm_set_joining_node(struct dlm_ctxt *dlm,
217 					  u8 node)
218 {
219 	assert_spin_locked(&dlm->spinlock);
220 
221 	dlm->joining_node = node;
222 	wake_up(&dlm->dlm_join_events);
223 }
224 
225 #define DLM_LOCK_RES_UNINITED             0x00000001
226 #define DLM_LOCK_RES_RECOVERING           0x00000002
227 #define DLM_LOCK_RES_READY                0x00000004
228 #define DLM_LOCK_RES_DIRTY                0x00000008
229 #define DLM_LOCK_RES_IN_PROGRESS          0x00000010
230 #define DLM_LOCK_RES_MIGRATING            0x00000020
231 #define DLM_LOCK_RES_DROPPING_REF         0x00000040
232 #define DLM_LOCK_RES_BLOCK_DIRTY          0x00001000
233 #define DLM_LOCK_RES_SETREF_INPROG        0x00002000
234 
235 /* max milliseconds to wait to sync up a network failure with a node death */
236 #define DLM_NODE_DEATH_WAIT_MAX (5 * 1000)
237 
238 #define DLM_PURGE_INTERVAL_MS   (8 * 1000)
239 
240 struct dlm_lock_resource
241 {
242 	/* WARNING: Please see the comment in dlm_init_lockres before
243 	 * adding fields here. */
244 	struct hlist_node hash_node;
245 	struct qstr lockname;
246 	struct kref      refs;
247 
248 	/*
249 	 * Please keep granted, converting, and blocked in this order,
250 	 * as some funcs want to iterate over all lists.
251 	 *
252 	 * All four lists are protected by the hash's reference.
253 	 */
254 	struct list_head granted;
255 	struct list_head converting;
256 	struct list_head blocked;
257 	struct list_head purge;
258 
259 	/*
260 	 * These two lists require you to hold an additional reference
261 	 * while they are on the list.
262 	 */
263 	struct list_head dirty;
264 	struct list_head recovering; // dlm_recovery_ctxt.resources list
265 
266 	/* unused lock resources have their last_used stamped and are
267 	 * put on a list for the dlm thread to run. */
268 	unsigned long    last_used;
269 
270 	unsigned migration_pending:1;
271 	atomic_t asts_reserved;
272 	spinlock_t spinlock;
273 	wait_queue_head_t wq;
274 	u8  owner;              //node which owns the lock resource, or unknown
275 	u16 state;
276 	char lvb[DLM_LVB_LEN];
277 	unsigned int inflight_locks;
278 	unsigned long refmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
279 };
280 
281 struct dlm_migratable_lock
282 {
283 	__be64 cookie;
284 
285 	/* these 3 are just padding for the in-memory structure, but
286 	 * list and flags are actually used when sent over the wire */
287 	__be16 pad1;
288 	u8 list;  // 0=granted, 1=converting, 2=blocked
289 	u8 flags;
290 
291 	s8 type;
292 	s8 convert_type;
293 	s8 highest_blocked;
294 	u8 node;
295 };  // 16 bytes
296 
297 struct dlm_lock
298 {
299 	struct dlm_migratable_lock ml;
300 
301 	struct list_head list;
302 	struct list_head ast_list;
303 	struct list_head bast_list;
304 	struct dlm_lock_resource *lockres;
305 	spinlock_t spinlock;
306 	struct kref lock_refs;
307 
308 	// ast and bast must be callable while holding a spinlock!
309 	dlm_astlockfunc_t *ast;
310 	dlm_bastlockfunc_t *bast;
311 	void *astdata;
312 	struct dlm_lockstatus *lksb;
313 	unsigned ast_pending:1,
314 		 bast_pending:1,
315 		 convert_pending:1,
316 		 lock_pending:1,
317 		 cancel_pending:1,
318 		 unlock_pending:1,
319 		 lksb_kernel_allocated:1;
320 };
321 
322 
323 #define DLM_LKSB_UNUSED1           0x01
324 #define DLM_LKSB_PUT_LVB           0x02
325 #define DLM_LKSB_GET_LVB           0x04
326 #define DLM_LKSB_UNUSED2           0x08
327 #define DLM_LKSB_UNUSED3           0x10
328 #define DLM_LKSB_UNUSED4           0x20
329 #define DLM_LKSB_UNUSED5           0x40
330 #define DLM_LKSB_UNUSED6           0x80
331 
332 
333 enum dlm_lockres_list {
334 	DLM_GRANTED_LIST = 0,
335 	DLM_CONVERTING_LIST,
336 	DLM_BLOCKED_LIST
337 };
338 
339 static inline int dlm_lvb_is_empty(char *lvb)
340 {
341 	int i;
342 	for (i=0; i<DLM_LVB_LEN; i++)
343 		if (lvb[i])
344 			return 0;
345 	return 1;
346 }
347 
348 static inline struct list_head *
349 dlm_list_idx_to_ptr(struct dlm_lock_resource *res, enum dlm_lockres_list idx)
350 {
351 	struct list_head *ret = NULL;
352 	if (idx == DLM_GRANTED_LIST)
353 		ret = &res->granted;
354 	else if (idx == DLM_CONVERTING_LIST)
355 		ret = &res->converting;
356 	else if (idx == DLM_BLOCKED_LIST)
357 		ret = &res->blocked;
358 	else
359 		BUG();
360 	return ret;
361 }
362 
363 
364 
365 
366 struct dlm_node_iter
367 {
368 	unsigned long node_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
369 	int curnode;
370 };
371 
372 
373 enum {
374 	DLM_MASTER_REQUEST_MSG    = 500,
375 	DLM_UNUSED_MSG1,         /* 501 */
376 	DLM_ASSERT_MASTER_MSG,	 /* 502 */
377 	DLM_CREATE_LOCK_MSG,	 /* 503 */
378 	DLM_CONVERT_LOCK_MSG,	 /* 504 */
379 	DLM_PROXY_AST_MSG,	 /* 505 */
380 	DLM_UNLOCK_LOCK_MSG,	 /* 506 */
381 	DLM_DEREF_LOCKRES_MSG,	 /* 507 */
382 	DLM_MIGRATE_REQUEST_MSG, /* 508 */
383 	DLM_MIG_LOCKRES_MSG, 	 /* 509 */
384 	DLM_QUERY_JOIN_MSG,	 /* 510 */
385 	DLM_ASSERT_JOINED_MSG,	 /* 511 */
386 	DLM_CANCEL_JOIN_MSG,	 /* 512 */
387 	DLM_EXIT_DOMAIN_MSG,	 /* 513 */
388 	DLM_MASTER_REQUERY_MSG,	 /* 514 */
389 	DLM_LOCK_REQUEST_MSG,	 /* 515 */
390 	DLM_RECO_DATA_DONE_MSG,	 /* 516 */
391 	DLM_BEGIN_RECO_MSG,	 /* 517 */
392 	DLM_FINALIZE_RECO_MSG	 /* 518 */
393 };
394 
395 struct dlm_reco_node_data
396 {
397 	int state;
398 	u8 node_num;
399 	struct list_head list;
400 };
401 
402 enum {
403 	DLM_RECO_NODE_DATA_DEAD = -1,
404 	DLM_RECO_NODE_DATA_INIT = 0,
405 	DLM_RECO_NODE_DATA_REQUESTING,
406 	DLM_RECO_NODE_DATA_REQUESTED,
407 	DLM_RECO_NODE_DATA_RECEIVING,
408 	DLM_RECO_NODE_DATA_DONE,
409 	DLM_RECO_NODE_DATA_FINALIZE_SENT,
410 };
411 
412 
413 enum {
414 	DLM_MASTER_RESP_NO = 0,
415 	DLM_MASTER_RESP_YES,
416 	DLM_MASTER_RESP_MAYBE,
417 	DLM_MASTER_RESP_ERROR
418 };
419 
420 
421 struct dlm_master_request
422 {
423 	u8 node_idx;
424 	u8 namelen;
425 	__be16 pad1;
426 	__be32 flags;
427 
428 	u8 name[O2NM_MAX_NAME_LEN];
429 };
430 
431 #define DLM_ASSERT_RESPONSE_REASSERT       0x00000001
432 #define DLM_ASSERT_RESPONSE_MASTERY_REF    0x00000002
433 
434 #define DLM_ASSERT_MASTER_MLE_CLEANUP      0x00000001
435 #define DLM_ASSERT_MASTER_REQUERY          0x00000002
436 #define DLM_ASSERT_MASTER_FINISH_MIGRATION 0x00000004
437 struct dlm_assert_master
438 {
439 	u8 node_idx;
440 	u8 namelen;
441 	__be16 pad1;
442 	__be32 flags;
443 
444 	u8 name[O2NM_MAX_NAME_LEN];
445 };
446 
447 #define DLM_MIGRATE_RESPONSE_MASTERY_REF   0x00000001
448 
449 struct dlm_migrate_request
450 {
451 	u8 master;
452 	u8 new_master;
453 	u8 namelen;
454 	u8 pad1;
455 	__be32 pad2;
456 	u8 name[O2NM_MAX_NAME_LEN];
457 };
458 
459 struct dlm_master_requery
460 {
461 	u8 pad1;
462 	u8 pad2;
463 	u8 node_idx;
464 	u8 namelen;
465 	__be32 pad3;
466 	u8 name[O2NM_MAX_NAME_LEN];
467 };
468 
469 #define DLM_MRES_RECOVERY   0x01
470 #define DLM_MRES_MIGRATION  0x02
471 #define DLM_MRES_ALL_DONE   0x04
472 
473 /*
474  * We would like to get one whole lockres into a single network
475  * message whenever possible.  Generally speaking, there will be
476  * at most one dlm_lock on a lockres for each node in the cluster,
477  * plus (infrequently) any additional locks coming in from userdlm.
478  *
479  * struct _dlm_lockres_page
480  * {
481  * 	dlm_migratable_lockres mres;
482  * 	dlm_migratable_lock ml[DLM_MAX_MIGRATABLE_LOCKS];
483  * 	u8 pad[DLM_MIG_LOCKRES_RESERVED];
484  * };
485  *
486  * from ../cluster/tcp.h
487  *    NET_MAX_PAYLOAD_BYTES  (4096 - sizeof(net_msg))
488  *    (roughly 4080 bytes)
489  * and sizeof(dlm_migratable_lockres) = 112 bytes
490  * and sizeof(dlm_migratable_lock) = 16 bytes
491  *
492  * Choosing DLM_MAX_MIGRATABLE_LOCKS=240 and
493  * DLM_MIG_LOCKRES_RESERVED=128 means we have this:
494  *
495  *  (DLM_MAX_MIGRATABLE_LOCKS * sizeof(dlm_migratable_lock)) +
496  *     sizeof(dlm_migratable_lockres) + DLM_MIG_LOCKRES_RESERVED =
497  *        NET_MAX_PAYLOAD_BYTES
498  *  (240 * 16) + 112 + 128 = 4080
499  *
500  * So a lockres would need more than 240 locks before it would
501  * use more than one network packet to recover.  Not too bad.
502  */
503 #define DLM_MAX_MIGRATABLE_LOCKS   240
504 
505 struct dlm_migratable_lockres
506 {
507 	u8 master;
508 	u8 lockname_len;
509 	u8 num_locks;    // locks sent in this structure
510 	u8 flags;
511 	__be32 total_locks; // locks to be sent for this migration cookie
512 	__be64 mig_cookie;  // cookie for this lockres migration
513 			 // or zero if not needed
514 	// 16 bytes
515 	u8 lockname[DLM_LOCKID_NAME_MAX];
516 	// 48 bytes
517 	u8 lvb[DLM_LVB_LEN];
518 	// 112 bytes
519 	struct dlm_migratable_lock ml[0];  // 16 bytes each, begins at byte 112
520 };
521 #define DLM_MIG_LOCKRES_MAX_LEN  \
522 	(sizeof(struct dlm_migratable_lockres) + \
523 	 (sizeof(struct dlm_migratable_lock) * \
524 	  DLM_MAX_MIGRATABLE_LOCKS) )
525 
526 /* from above, 128 bytes
527  * for some undetermined future use */
528 #define DLM_MIG_LOCKRES_RESERVED   (NET_MAX_PAYLOAD_BYTES - \
529 				    DLM_MIG_LOCKRES_MAX_LEN)
530 
531 struct dlm_create_lock
532 {
533 	__be64 cookie;
534 
535 	__be32 flags;
536 	u8 pad1;
537 	u8 node_idx;
538 	s8 requested_type;
539 	u8 namelen;
540 
541 	u8 name[O2NM_MAX_NAME_LEN];
542 };
543 
544 struct dlm_convert_lock
545 {
546 	__be64 cookie;
547 
548 	__be32 flags;
549 	u8 pad1;
550 	u8 node_idx;
551 	s8 requested_type;
552 	u8 namelen;
553 
554 	u8 name[O2NM_MAX_NAME_LEN];
555 
556 	s8 lvb[0];
557 };
558 #define DLM_CONVERT_LOCK_MAX_LEN  (sizeof(struct dlm_convert_lock)+DLM_LVB_LEN)
559 
560 struct dlm_unlock_lock
561 {
562 	__be64 cookie;
563 
564 	__be32 flags;
565 	__be16 pad1;
566 	u8 node_idx;
567 	u8 namelen;
568 
569 	u8 name[O2NM_MAX_NAME_LEN];
570 
571 	s8 lvb[0];
572 };
573 #define DLM_UNLOCK_LOCK_MAX_LEN  (sizeof(struct dlm_unlock_lock)+DLM_LVB_LEN)
574 
575 struct dlm_proxy_ast
576 {
577 	__be64 cookie;
578 
579 	__be32 flags;
580 	u8 node_idx;
581 	u8 type;
582 	u8 blocked_type;
583 	u8 namelen;
584 
585 	u8 name[O2NM_MAX_NAME_LEN];
586 
587 	s8 lvb[0];
588 };
589 #define DLM_PROXY_AST_MAX_LEN  (sizeof(struct dlm_proxy_ast)+DLM_LVB_LEN)
590 
591 #define DLM_MOD_KEY (0x666c6172)
592 enum dlm_query_join_response {
593 	JOIN_DISALLOW = 0,
594 	JOIN_OK,
595 	JOIN_OK_NO_MAP,
596 };
597 
598 struct dlm_lock_request
599 {
600 	u8 node_idx;
601 	u8 dead_node;
602 	__be16 pad1;
603 	__be32 pad2;
604 };
605 
606 struct dlm_reco_data_done
607 {
608 	u8 node_idx;
609 	u8 dead_node;
610 	__be16 pad1;
611 	__be32 pad2;
612 
613 	/* unused for now */
614 	/* eventually we can use this to attempt
615 	 * lvb recovery based on each node's info */
616 	u8 reco_lvb[DLM_LVB_LEN];
617 };
618 
619 struct dlm_begin_reco
620 {
621 	u8 node_idx;
622 	u8 dead_node;
623 	__be16 pad1;
624 	__be32 pad2;
625 };
626 
627 
628 #define BITS_PER_BYTE 8
629 #define BITS_TO_BYTES(bits) (((bits)+BITS_PER_BYTE-1)/BITS_PER_BYTE)
630 
631 struct dlm_query_join_request
632 {
633 	u8 node_idx;
634 	u8 pad1[2];
635 	u8 name_len;
636 	u8 domain[O2NM_MAX_NAME_LEN];
637 	u8 node_map[BITS_TO_BYTES(O2NM_MAX_NODES)];
638 };
639 
640 struct dlm_assert_joined
641 {
642 	u8 node_idx;
643 	u8 pad1[2];
644 	u8 name_len;
645 	u8 domain[O2NM_MAX_NAME_LEN];
646 };
647 
648 struct dlm_cancel_join
649 {
650 	u8 node_idx;
651 	u8 pad1[2];
652 	u8 name_len;
653 	u8 domain[O2NM_MAX_NAME_LEN];
654 };
655 
656 struct dlm_exit_domain
657 {
658 	u8 node_idx;
659 	u8 pad1[3];
660 };
661 
662 struct dlm_finalize_reco
663 {
664 	u8 node_idx;
665 	u8 dead_node;
666 	u8 flags;
667 	u8 pad1;
668 	__be32 pad2;
669 };
670 
671 struct dlm_deref_lockres
672 {
673 	u32 pad1;
674 	u16 pad2;
675 	u8 node_idx;
676 	u8 namelen;
677 
678 	u8 name[O2NM_MAX_NAME_LEN];
679 };
680 
681 static inline enum dlm_status
682 __dlm_lockres_state_to_status(struct dlm_lock_resource *res)
683 {
684 	enum dlm_status status = DLM_NORMAL;
685 
686 	assert_spin_locked(&res->spinlock);
687 
688 	if (res->state & DLM_LOCK_RES_RECOVERING)
689 		status = DLM_RECOVERING;
690 	else if (res->state & DLM_LOCK_RES_MIGRATING)
691 		status = DLM_MIGRATING;
692 	else if (res->state & DLM_LOCK_RES_IN_PROGRESS)
693 		status = DLM_FORWARD;
694 
695 	return status;
696 }
697 
698 static inline u8 dlm_get_lock_cookie_node(u64 cookie)
699 {
700 	u8 ret;
701 	cookie >>= 56;
702 	ret = (u8)(cookie & 0xffULL);
703 	return ret;
704 }
705 
706 static inline unsigned long long dlm_get_lock_cookie_seq(u64 cookie)
707 {
708 	unsigned long long ret;
709 	ret = ((unsigned long long)cookie) & 0x00ffffffffffffffULL;
710 	return ret;
711 }
712 
713 struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie,
714 			       struct dlm_lockstatus *lksb);
715 void dlm_lock_get(struct dlm_lock *lock);
716 void dlm_lock_put(struct dlm_lock *lock);
717 
718 void dlm_lock_attach_lockres(struct dlm_lock *lock,
719 			     struct dlm_lock_resource *res);
720 
721 int dlm_create_lock_handler(struct o2net_msg *msg, u32 len, void *data,
722 			    void **ret_data);
723 int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data,
724 			     void **ret_data);
725 int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
726 			  void **ret_data);
727 
728 void dlm_revert_pending_convert(struct dlm_lock_resource *res,
729 				struct dlm_lock *lock);
730 void dlm_revert_pending_lock(struct dlm_lock_resource *res,
731 			     struct dlm_lock *lock);
732 
733 int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data,
734 			    void **ret_data);
735 void dlm_commit_pending_cancel(struct dlm_lock_resource *res,
736 			       struct dlm_lock *lock);
737 void dlm_commit_pending_unlock(struct dlm_lock_resource *res,
738 			       struct dlm_lock *lock);
739 
740 int dlm_launch_thread(struct dlm_ctxt *dlm);
741 void dlm_complete_thread(struct dlm_ctxt *dlm);
742 int dlm_launch_recovery_thread(struct dlm_ctxt *dlm);
743 void dlm_complete_recovery_thread(struct dlm_ctxt *dlm);
744 void dlm_wait_for_recovery(struct dlm_ctxt *dlm);
745 void dlm_kick_recovery_thread(struct dlm_ctxt *dlm);
746 int dlm_is_node_dead(struct dlm_ctxt *dlm, u8 node);
747 int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout);
748 int dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout);
749 
750 void dlm_put(struct dlm_ctxt *dlm);
751 struct dlm_ctxt *dlm_grab(struct dlm_ctxt *dlm);
752 int dlm_domain_fully_joined(struct dlm_ctxt *dlm);
753 
754 void __dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
755 			      struct dlm_lock_resource *res);
756 void dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
757 			    struct dlm_lock_resource *res);
758 static inline void dlm_lockres_get(struct dlm_lock_resource *res)
759 {
760 	/* This is called on every lookup, so it might be worth
761 	 * inlining. */
762 	kref_get(&res->refs);
763 }
764 void dlm_lockres_put(struct dlm_lock_resource *res);
765 void __dlm_unhash_lockres(struct dlm_lock_resource *res);
766 void __dlm_insert_lockres(struct dlm_ctxt *dlm,
767 			  struct dlm_lock_resource *res);
768 struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm,
769 						     const char *name,
770 						     unsigned int len,
771 						     unsigned int hash);
772 struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm,
773 						const char *name,
774 						unsigned int len,
775 						unsigned int hash);
776 struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm,
777 					      const char *name,
778 					      unsigned int len);
779 
780 int dlm_is_host_down(int errno);
781 void dlm_change_lockres_owner(struct dlm_ctxt *dlm,
782 			      struct dlm_lock_resource *res,
783 			      u8 owner);
784 struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm,
785 						 const char *lockid,
786 						 int namelen,
787 						 int flags);
788 struct dlm_lock_resource *dlm_new_lockres(struct dlm_ctxt *dlm,
789 					  const char *name,
790 					  unsigned int namelen);
791 
792 #define dlm_lockres_set_refmap_bit(bit,res)  \
793 	__dlm_lockres_set_refmap_bit(bit,res,__FILE__,__LINE__)
794 #define dlm_lockres_clear_refmap_bit(bit,res)  \
795 	__dlm_lockres_clear_refmap_bit(bit,res,__FILE__,__LINE__)
796 
797 static inline void __dlm_lockres_set_refmap_bit(int bit,
798 						struct dlm_lock_resource *res,
799 						const char *file,
800 						int line)
801 {
802 	//printk("%s:%d:%.*s: setting bit %d\n", file, line,
803 	//     res->lockname.len, res->lockname.name, bit);
804 	set_bit(bit, res->refmap);
805 }
806 
807 static inline void __dlm_lockres_clear_refmap_bit(int bit,
808 						  struct dlm_lock_resource *res,
809 						  const char *file,
810 						  int line)
811 {
812 	//printk("%s:%d:%.*s: clearing bit %d\n", file, line,
813 	//     res->lockname.len, res->lockname.name, bit);
814 	clear_bit(bit, res->refmap);
815 }
816 
817 void __dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
818 				   struct dlm_lock_resource *res,
819 				   const char *file,
820 				   int line);
821 void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
822 				   struct dlm_lock_resource *res,
823 				   int new_lockres,
824 				   const char *file,
825 				   int line);
826 #define dlm_lockres_drop_inflight_ref(d,r)  \
827 	__dlm_lockres_drop_inflight_ref(d,r,__FILE__,__LINE__)
828 #define dlm_lockres_grab_inflight_ref(d,r)  \
829 	__dlm_lockres_grab_inflight_ref(d,r,0,__FILE__,__LINE__)
830 #define dlm_lockres_grab_inflight_ref_new(d,r)  \
831 	__dlm_lockres_grab_inflight_ref(d,r,1,__FILE__,__LINE__)
832 
833 void dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock);
834 void dlm_queue_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock);
835 void dlm_do_local_ast(struct dlm_ctxt *dlm,
836 		      struct dlm_lock_resource *res,
837 		      struct dlm_lock *lock);
838 int dlm_do_remote_ast(struct dlm_ctxt *dlm,
839 		      struct dlm_lock_resource *res,
840 		      struct dlm_lock *lock);
841 void dlm_do_local_bast(struct dlm_ctxt *dlm,
842 		       struct dlm_lock_resource *res,
843 		       struct dlm_lock *lock,
844 		       int blocked_type);
845 int dlm_send_proxy_ast_msg(struct dlm_ctxt *dlm,
846 			   struct dlm_lock_resource *res,
847 			   struct dlm_lock *lock,
848 			   int msg_type,
849 			   int blocked_type, int flags);
850 static inline int dlm_send_proxy_bast(struct dlm_ctxt *dlm,
851 				      struct dlm_lock_resource *res,
852 				      struct dlm_lock *lock,
853 				      int blocked_type)
854 {
855 	return dlm_send_proxy_ast_msg(dlm, res, lock, DLM_BAST,
856 				      blocked_type, 0);
857 }
858 
859 static inline int dlm_send_proxy_ast(struct dlm_ctxt *dlm,
860 				     struct dlm_lock_resource *res,
861 				     struct dlm_lock *lock,
862 				     int flags)
863 {
864 	return dlm_send_proxy_ast_msg(dlm, res, lock, DLM_AST,
865 				      0, flags);
866 }
867 
868 void dlm_print_one_lock_resource(struct dlm_lock_resource *res);
869 void __dlm_print_one_lock_resource(struct dlm_lock_resource *res);
870 
871 u8 dlm_nm_this_node(struct dlm_ctxt *dlm);
872 void dlm_kick_thread(struct dlm_ctxt *dlm, struct dlm_lock_resource *res);
873 void __dlm_dirty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res);
874 
875 
876 int dlm_nm_init(struct dlm_ctxt *dlm);
877 int dlm_heartbeat_init(struct dlm_ctxt *dlm);
878 void dlm_hb_node_down_cb(struct o2nm_node *node, int idx, void *data);
879 void dlm_hb_node_up_cb(struct o2nm_node *node, int idx, void *data);
880 
881 int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res);
882 int dlm_finish_migration(struct dlm_ctxt *dlm,
883 			 struct dlm_lock_resource *res,
884 			 u8 old_master);
885 void dlm_lockres_release_ast(struct dlm_ctxt *dlm,
886 			     struct dlm_lock_resource *res);
887 void __dlm_lockres_reserve_ast(struct dlm_lock_resource *res);
888 
889 int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data,
890 			       void **ret_data);
891 int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
892 			      void **ret_data);
893 void dlm_assert_master_post_handler(int status, void *data, void *ret_data);
894 int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
895 			      void **ret_data);
896 int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data,
897 				void **ret_data);
898 int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
899 			    void **ret_data);
900 int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
901 			       void **ret_data);
902 int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data,
903 				  void **ret_data);
904 int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data,
905 			       void **ret_data);
906 int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data,
907 			   void **ret_data);
908 int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data,
909 			      void **ret_data);
910 int dlm_do_master_requery(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
911 			  u8 nodenum, u8 *real_master);
912 
913 
914 int dlm_dispatch_assert_master(struct dlm_ctxt *dlm,
915 			       struct dlm_lock_resource *res,
916 			       int ignore_higher,
917 			       u8 request_from,
918 			       u32 flags);
919 
920 
921 int dlm_send_one_lockres(struct dlm_ctxt *dlm,
922 			 struct dlm_lock_resource *res,
923 			 struct dlm_migratable_lockres *mres,
924 			 u8 send_to,
925 			 u8 flags);
926 void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm,
927 				       struct dlm_lock_resource *res);
928 
929 /* will exit holding res->spinlock, but may drop in function */
930 void __dlm_wait_on_lockres_flags(struct dlm_lock_resource *res, int flags);
931 void __dlm_wait_on_lockres_flags_set(struct dlm_lock_resource *res, int flags);
932 
933 /* will exit holding res->spinlock, but may drop in function */
934 static inline void __dlm_wait_on_lockres(struct dlm_lock_resource *res)
935 {
936 	__dlm_wait_on_lockres_flags(res, (DLM_LOCK_RES_IN_PROGRESS|
937 				    	  DLM_LOCK_RES_RECOVERING|
938 					  DLM_LOCK_RES_MIGRATING));
939 }
940 
941 
942 int dlm_init_mle_cache(void);
943 void dlm_destroy_mle_cache(void);
944 void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up);
945 int dlm_drop_lockres_ref(struct dlm_ctxt *dlm,
946 			 struct dlm_lock_resource *res);
947 void dlm_clean_master_list(struct dlm_ctxt *dlm,
948 			   u8 dead_node);
949 int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock);
950 int __dlm_lockres_has_locks(struct dlm_lock_resource *res);
951 int __dlm_lockres_unused(struct dlm_lock_resource *res);
952 
953 static inline const char * dlm_lock_mode_name(int mode)
954 {
955 	switch (mode) {
956 		case LKM_EXMODE:
957 			return "EX";
958 		case LKM_PRMODE:
959 			return "PR";
960 		case LKM_NLMODE:
961 			return "NL";
962 	}
963 	return "UNKNOWN";
964 }
965 
966 
967 static inline int dlm_lock_compatible(int existing, int request)
968 {
969 	/* NO_LOCK compatible with all */
970 	if (request == LKM_NLMODE ||
971 	    existing == LKM_NLMODE)
972 		return 1;
973 
974 	/* EX incompatible with all non-NO_LOCK */
975 	if (request == LKM_EXMODE)
976 		return 0;
977 
978 	/* request must be PR, which is compatible with PR */
979 	if (existing == LKM_PRMODE)
980 		return 1;
981 
982 	return 0;
983 }
984 
985 static inline int dlm_lock_on_list(struct list_head *head,
986 				   struct dlm_lock *lock)
987 {
988 	struct list_head *iter;
989 	struct dlm_lock *tmplock;
990 
991 	list_for_each(iter, head) {
992 		tmplock = list_entry(iter, struct dlm_lock, list);
993 		if (tmplock == lock)
994 			return 1;
995 	}
996 	return 0;
997 }
998 
999 
1000 static inline enum dlm_status dlm_err_to_dlm_status(int err)
1001 {
1002 	enum dlm_status ret;
1003 	if (err == -ENOMEM)
1004 		ret = DLM_SYSERR;
1005 	else if (err == -ETIMEDOUT || o2net_link_down(err, NULL))
1006 		ret = DLM_NOLOCKMGR;
1007 	else if (err == -EINVAL)
1008 		ret = DLM_BADPARAM;
1009 	else if (err == -ENAMETOOLONG)
1010 		ret = DLM_IVBUFLEN;
1011 	else
1012 		ret = DLM_BADARGS;
1013 	return ret;
1014 }
1015 
1016 
1017 static inline void dlm_node_iter_init(unsigned long *map,
1018 				      struct dlm_node_iter *iter)
1019 {
1020 	memcpy(iter->node_map, map, sizeof(iter->node_map));
1021 	iter->curnode = -1;
1022 }
1023 
1024 static inline int dlm_node_iter_next(struct dlm_node_iter *iter)
1025 {
1026 	int bit;
1027 	bit = find_next_bit(iter->node_map, O2NM_MAX_NODES, iter->curnode+1);
1028 	if (bit >= O2NM_MAX_NODES) {
1029 		iter->curnode = O2NM_MAX_NODES;
1030 		return -ENOENT;
1031 	}
1032 	iter->curnode = bit;
1033 	return bit;
1034 }
1035 
1036 
1037 
1038 #endif /* DLMCOMMON_H */
1039