1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /****************************************************************************** |
3 | ******************************************************************************* |
4 | ** |
5 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
6 | ** Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. |
7 | ** |
8 | ** |
9 | ******************************************************************************* |
10 | ******************************************************************************/ |
11 | |
12 | #ifndef __DLM_INTERNAL_DOT_H__ |
13 | #define __DLM_INTERNAL_DOT_H__ |
14 | |
15 | /* |
16 | * This is the main header file to be included in each DLM source file. |
17 | */ |
18 | |
19 | #include <linux/slab.h> |
20 | #include <linux/sched.h> |
21 | #include <linux/types.h> |
22 | #include <linux/ctype.h> |
23 | #include <linux/spinlock.h> |
24 | #include <linux/vmalloc.h> |
25 | #include <linux/list.h> |
26 | #include <linux/errno.h> |
27 | #include <linux/random.h> |
28 | #include <linux/delay.h> |
29 | #include <linux/socket.h> |
30 | #include <linux/kthread.h> |
31 | #include <linux/kobject.h> |
32 | #include <linux/kref.h> |
33 | #include <linux/kernel.h> |
34 | #include <linux/jhash.h> |
35 | #include <linux/miscdevice.h> |
36 | #include <linux/mutex.h> |
37 | #include <linux/idr.h> |
38 | #include <linux/ratelimit.h> |
39 | #include <linux/uaccess.h> |
40 | |
41 | #include <linux/dlm.h> |
42 | #include "config.h" |
43 | |
44 | struct dlm_ls; |
45 | struct dlm_lkb; |
46 | struct dlm_rsb; |
47 | struct dlm_member; |
48 | struct dlm_rsbtable; |
49 | struct dlm_recover; |
50 | struct dlm_header; |
51 | struct dlm_message; |
52 | struct dlm_rcom; |
53 | struct dlm_mhandle; |
54 | struct dlm_msg; |
55 | |
56 | #define log_print(fmt, args...) \ |
57 | printk(KERN_ERR "dlm: "fmt"\n" , ##args) |
58 | #define log_print_ratelimited(fmt, args...) \ |
59 | printk_ratelimited(KERN_ERR "dlm: "fmt"\n", ##args) |
60 | #define log_error(ls, fmt, args...) \ |
61 | printk(KERN_ERR "dlm: %s: " fmt "\n", (ls)->ls_name , ##args) |
62 | |
63 | #define log_rinfo(ls, fmt, args...) \ |
64 | do { \ |
65 | if (dlm_config.ci_log_info) \ |
66 | printk(KERN_INFO "dlm: %s: " fmt "\n", \ |
67 | (ls)->ls_name, ##args); \ |
68 | else if (dlm_config.ci_log_debug) \ |
69 | printk(KERN_DEBUG "dlm: %s: " fmt "\n", \ |
70 | (ls)->ls_name , ##args); \ |
71 | } while (0) |
72 | |
73 | #define log_debug(ls, fmt, args...) \ |
74 | do { \ |
75 | if (dlm_config.ci_log_debug) \ |
76 | printk(KERN_DEBUG "dlm: %s: " fmt "\n", \ |
77 | (ls)->ls_name , ##args); \ |
78 | } while (0) |
79 | |
80 | #define log_limit(ls, fmt, args...) \ |
81 | do { \ |
82 | if (dlm_config.ci_log_debug) \ |
83 | printk_ratelimited(KERN_DEBUG "dlm: %s: " fmt "\n", \ |
84 | (ls)->ls_name , ##args); \ |
85 | } while (0) |
86 | |
87 | #define DLM_ASSERT(x, do) \ |
88 | { \ |
89 | if (!(x)) \ |
90 | { \ |
91 | printk(KERN_ERR "\nDLM: Assertion failed on line %d of file %s\n" \ |
92 | "DLM: assertion: \"%s\"\n" \ |
93 | "DLM: time = %lu\n", \ |
94 | __LINE__, __FILE__, #x, jiffies); \ |
95 | {do} \ |
96 | printk("\n"); \ |
97 | panic("DLM: Record message above and reboot.\n"); \ |
98 | } \ |
99 | } |
100 | |
101 | |
102 | #define DLM_RTF_SHRINK_BIT 0 |
103 | |
104 | struct dlm_rsbtable { |
105 | struct rb_root keep; |
106 | struct rb_root toss; |
107 | spinlock_t lock; |
108 | unsigned long flags; |
109 | }; |
110 | |
111 | |
112 | /* |
113 | * Lockspace member (per node in a ls) |
114 | */ |
115 | |
116 | struct dlm_member { |
117 | struct list_head list; |
118 | int nodeid; |
119 | int weight; |
120 | int slot; |
121 | int slot_prev; |
122 | int comm_seq; |
123 | uint32_t generation; |
124 | }; |
125 | |
126 | /* |
127 | * Save and manage recovery state for a lockspace. |
128 | */ |
129 | |
130 | struct dlm_recover { |
131 | struct list_head list; |
132 | struct dlm_config_node *nodes; |
133 | int nodes_count; |
134 | uint64_t seq; |
135 | }; |
136 | |
137 | /* |
138 | * Pass input args to second stage locking function. |
139 | */ |
140 | |
141 | struct dlm_args { |
142 | uint32_t flags; |
143 | void (*astfn) (void *astparam); |
144 | void *astparam; |
145 | void (*bastfn) (void *astparam, int mode); |
146 | int mode; |
147 | struct dlm_lksb *lksb; |
148 | }; |
149 | |
150 | |
151 | /* |
152 | * Lock block |
153 | * |
154 | * A lock can be one of three types: |
155 | * |
156 | * local copy lock is mastered locally |
157 | * (lkb_nodeid is zero and DLM_LKF_MSTCPY is not set) |
158 | * process copy lock is mastered on a remote node |
159 | * (lkb_nodeid is non-zero and DLM_LKF_MSTCPY is not set) |
160 | * master copy master node's copy of a lock owned by remote node |
161 | * (lkb_nodeid is non-zero and DLM_LKF_MSTCPY is set) |
162 | * |
163 | * lkb_exflags: a copy of the most recent flags arg provided to dlm_lock or |
164 | * dlm_unlock. The dlm does not modify these or use any private flags in |
165 | * this field; it only contains DLM_LKF_ flags from dlm.h. These flags |
166 | * are sent as-is to the remote master when the lock is remote. |
167 | * |
168 | * lkb_flags: internal dlm flags (DLM_IFL_ prefix) from dlm_internal.h. |
169 | * Some internal flags are shared between the master and process nodes; |
170 | * these shared flags are kept in the lower two bytes. One of these |
171 | * flags set on the master copy will be propagated to the process copy |
172 | * and v.v. Other internal flags are private to the master or process |
173 | * node (e.g. DLM_IFL_MSTCPY). These are kept in the high two bytes. |
174 | * |
175 | * lkb_sbflags: status block flags. These flags are copied directly into |
176 | * the caller's lksb.sb_flags prior to the dlm_lock/dlm_unlock completion |
177 | * ast. All defined in dlm.h with DLM_SBF_ prefix. |
178 | * |
179 | * lkb_status: the lock status indicates which rsb queue the lock is |
180 | * on, grant, convert, or wait. DLM_LKSTS_ WAITING/GRANTED/CONVERT |
181 | * |
182 | * lkb_wait_type: the dlm message type (DLM_MSG_ prefix) for which a |
183 | * reply is needed. Only set when the lkb is on the lockspace waiters |
184 | * list awaiting a reply from a remote node. |
185 | * |
186 | * lkb_nodeid: when the lkb is a local copy, nodeid is 0; when the lkb |
187 | * is a master copy, nodeid specifies the remote lock holder, when the |
188 | * lkb is a process copy, the nodeid specifies the lock master. |
189 | */ |
190 | |
191 | /* lkb_status */ |
192 | |
193 | #define DLM_LKSTS_WAITING 1 |
194 | #define DLM_LKSTS_GRANTED 2 |
195 | #define DLM_LKSTS_CONVERT 3 |
196 | |
197 | /* lkb_iflags */ |
198 | |
199 | #define DLM_IFL_MSTCPY_BIT 16 |
200 | #define __DLM_IFL_MIN_BIT DLM_IFL_MSTCPY_BIT |
201 | #define DLM_IFL_RESEND_BIT 17 |
202 | #define DLM_IFL_DEAD_BIT 18 |
203 | #define DLM_IFL_OVERLAP_UNLOCK_BIT 19 |
204 | #define DLM_IFL_OVERLAP_CANCEL_BIT 20 |
205 | #define DLM_IFL_ENDOFLIFE_BIT 21 |
206 | #define DLM_IFL_DEADLOCK_CANCEL_BIT 24 |
207 | #define DLM_IFL_CB_PENDING_BIT 25 |
208 | #define __DLM_IFL_MAX_BIT DLM_IFL_CB_PENDING_BIT |
209 | |
210 | /* lkb_dflags */ |
211 | |
212 | #define DLM_DFL_USER_BIT 0 |
213 | #define __DLM_DFL_MIN_BIT DLM_DFL_USER_BIT |
214 | #define DLM_DFL_ORPHAN_BIT 1 |
215 | #define __DLM_DFL_MAX_BIT DLM_DFL_ORPHAN_BIT |
216 | |
217 | #define DLM_CB_CAST 0x00000001 |
218 | #define DLM_CB_BAST 0x00000002 |
219 | |
220 | struct dlm_callback { |
221 | uint32_t flags; /* DLM_CBF_ */ |
222 | int sb_status; /* copy to lksb status */ |
223 | uint8_t sb_flags; /* copy to lksb flags */ |
224 | int8_t mode; /* rq mode of bast, gr mode of cast */ |
225 | |
226 | struct list_head list; |
227 | struct kref ref; |
228 | }; |
229 | |
230 | struct dlm_lkb { |
231 | struct dlm_rsb *lkb_resource; /* the rsb */ |
232 | struct kref lkb_ref; |
233 | int lkb_nodeid; /* copied from rsb */ |
234 | int lkb_ownpid; /* pid of lock owner */ |
235 | uint32_t lkb_id; /* our lock ID */ |
236 | uint32_t lkb_remid; /* lock ID on remote partner */ |
237 | uint32_t lkb_exflags; /* external flags from caller */ |
238 | unsigned long lkb_sbflags; /* lksb flags */ |
239 | unsigned long lkb_dflags; /* distributed flags */ |
240 | unsigned long lkb_iflags; /* internal flags */ |
241 | uint32_t lkb_lvbseq; /* lvb sequence number */ |
242 | |
243 | int8_t lkb_status; /* granted, waiting, convert */ |
244 | int8_t lkb_rqmode; /* requested lock mode */ |
245 | int8_t lkb_grmode; /* granted lock mode */ |
246 | int8_t lkb_highbast; /* highest mode bast sent for */ |
247 | |
248 | int8_t lkb_wait_type; /* type of reply waiting for */ |
249 | atomic_t lkb_wait_count; |
250 | int lkb_wait_nodeid; /* for debugging */ |
251 | |
252 | struct list_head lkb_statequeue; /* rsb g/c/w list */ |
253 | struct list_head lkb_rsb_lookup; /* waiting for rsb lookup */ |
254 | struct list_head lkb_wait_reply; /* waiting for remote reply */ |
255 | struct list_head lkb_ownqueue; /* list of locks for a process */ |
256 | ktime_t lkb_timestamp; |
257 | |
258 | spinlock_t lkb_cb_lock; |
259 | struct work_struct lkb_cb_work; |
260 | struct list_head lkb_cb_list; /* for ls_cb_delay or proc->asts */ |
261 | struct list_head lkb_callbacks; |
262 | struct dlm_callback *lkb_last_cast; |
263 | struct dlm_callback *lkb_last_cb; |
264 | int lkb_last_bast_mode; |
265 | ktime_t lkb_last_cast_time; /* for debugging */ |
266 | ktime_t lkb_last_bast_time; /* for debugging */ |
267 | |
268 | uint64_t lkb_recover_seq; /* from ls_recover_seq */ |
269 | |
270 | char *lkb_lvbptr; |
271 | struct dlm_lksb *lkb_lksb; /* caller's status block */ |
272 | void (*lkb_astfn) (void *astparam); |
273 | void (*lkb_bastfn) (void *astparam, int mode); |
274 | union { |
275 | void *lkb_astparam; /* caller's ast arg */ |
276 | struct dlm_user_args *lkb_ua; |
277 | }; |
278 | }; |
279 | |
280 | /* |
281 | * res_master_nodeid is "normal": 0 is unset/invalid, non-zero is the real |
282 | * nodeid, even when nodeid is our_nodeid. |
283 | * |
284 | * res_nodeid is "odd": -1 is unset/invalid, zero means our_nodeid, |
285 | * greater than zero when another nodeid. |
286 | * |
287 | * (TODO: remove res_nodeid and only use res_master_nodeid) |
288 | */ |
289 | |
290 | struct dlm_rsb { |
291 | struct dlm_ls *res_ls; /* the lockspace */ |
292 | struct kref res_ref; |
293 | struct mutex res_mutex; |
294 | unsigned long res_flags; |
295 | int res_length; /* length of rsb name */ |
296 | int res_nodeid; |
297 | int res_master_nodeid; |
298 | int res_dir_nodeid; |
299 | int res_id; /* for ls_recover_idr */ |
300 | uint32_t res_lvbseq; |
301 | uint32_t res_hash; |
302 | uint32_t res_bucket; /* rsbtbl */ |
303 | unsigned long res_toss_time; |
304 | uint32_t res_first_lkid; |
305 | struct list_head res_lookup; /* lkbs waiting on first */ |
306 | union { |
307 | struct list_head res_hashchain; |
308 | struct rb_node res_hashnode; /* rsbtbl */ |
309 | }; |
310 | struct list_head res_grantqueue; |
311 | struct list_head res_convertqueue; |
312 | struct list_head res_waitqueue; |
313 | |
314 | struct list_head res_root_list; /* used for recovery */ |
315 | struct list_head res_recover_list; /* used for recovery */ |
316 | int res_recover_locks_count; |
317 | |
318 | char *res_lvbptr; |
319 | char res_name[DLM_RESNAME_MAXLEN+1]; |
320 | }; |
321 | |
322 | /* dlm_master_lookup() flags */ |
323 | |
324 | #define DLM_LU_RECOVER_DIR 1 |
325 | #define DLM_LU_RECOVER_MASTER 2 |
326 | |
327 | /* dlm_master_lookup() results */ |
328 | |
329 | #define DLM_LU_MATCH 1 |
330 | #define DLM_LU_ADD 2 |
331 | |
332 | /* find_rsb() flags */ |
333 | |
334 | #define R_REQUEST 0x00000001 |
335 | #define R_RECEIVE_REQUEST 0x00000002 |
336 | #define R_RECEIVE_RECOVER 0x00000004 |
337 | |
338 | /* rsb_flags */ |
339 | |
340 | enum rsb_flags { |
341 | RSB_MASTER_UNCERTAIN, |
342 | RSB_VALNOTVALID, |
343 | RSB_VALNOTVALID_PREV, |
344 | RSB_NEW_MASTER, |
345 | RSB_NEW_MASTER2, |
346 | RSB_RECOVER_CONVERT, |
347 | RSB_RECOVER_GRANT, |
348 | RSB_RECOVER_LVB_INVAL, |
349 | }; |
350 | |
351 | static inline void rsb_set_flag(struct dlm_rsb *r, enum rsb_flags flag) |
352 | { |
353 | __set_bit(flag, &r->res_flags); |
354 | } |
355 | |
356 | static inline void rsb_clear_flag(struct dlm_rsb *r, enum rsb_flags flag) |
357 | { |
358 | __clear_bit(flag, &r->res_flags); |
359 | } |
360 | |
361 | static inline int rsb_flag(struct dlm_rsb *r, enum rsb_flags flag) |
362 | { |
363 | return test_bit(flag, &r->res_flags); |
364 | } |
365 | |
366 | |
367 | /* dlm_header is first element of all structs sent between nodes */ |
368 | |
369 | #define 0x00030000 |
370 | #define 0x00000002 |
371 | |
372 | #define DLM_VERSION_3_1 0x00030001 |
373 | #define DLM_VERSION_3_2 0x00030002 |
374 | |
375 | #define 0x00000001 |
376 | |
377 | #define DLM_MSG 1 |
378 | #define DLM_RCOM 2 |
379 | #define DLM_OPTS 3 |
380 | #define DLM_ACK 4 |
381 | #define DLM_FIN 5 |
382 | |
383 | struct { |
384 | __le32 ; |
385 | union { |
386 | /* for DLM_MSG and DLM_RCOM */ |
387 | __le32 ; |
388 | /* for DLM_ACK and DLM_OPTS */ |
389 | __le32 ; |
390 | } ; |
391 | __le32 ; /* nodeid of sender */ |
392 | __le16 ; |
393 | uint8_t ; /* DLM_MSG, DLM_RCOM */ |
394 | uint8_t ; |
395 | }; |
396 | |
397 | #define DLM_MSG_REQUEST 1 |
398 | #define DLM_MSG_CONVERT 2 |
399 | #define DLM_MSG_UNLOCK 3 |
400 | #define DLM_MSG_CANCEL 4 |
401 | #define DLM_MSG_REQUEST_REPLY 5 |
402 | #define DLM_MSG_CONVERT_REPLY 6 |
403 | #define DLM_MSG_UNLOCK_REPLY 7 |
404 | #define DLM_MSG_CANCEL_REPLY 8 |
405 | #define DLM_MSG_GRANT 9 |
406 | #define DLM_MSG_BAST 10 |
407 | #define DLM_MSG_LOOKUP 11 |
408 | #define DLM_MSG_REMOVE 12 |
409 | #define DLM_MSG_LOOKUP_REPLY 13 |
410 | #define DLM_MSG_PURGE 14 |
411 | |
412 | struct dlm_message { |
413 | struct dlm_header ; |
414 | __le32 m_type; /* DLM_MSG_ */ |
415 | __le32 m_nodeid; |
416 | __le32 m_pid; |
417 | __le32 m_lkid; /* lkid on sender */ |
418 | __le32 m_remid; /* lkid on receiver */ |
419 | __le32 m_parent_lkid; |
420 | __le32 m_parent_remid; |
421 | __le32 m_exflags; |
422 | __le32 m_sbflags; |
423 | __le32 m_flags; |
424 | __le32 m_lvbseq; |
425 | __le32 m_hash; |
426 | __le32 m_status; |
427 | __le32 m_grmode; |
428 | __le32 m_rqmode; |
429 | __le32 m_bastmode; |
430 | __le32 m_asts; |
431 | __le32 m_result; /* 0 or -EXXX */ |
432 | char []; /* name or lvb */ |
433 | }; |
434 | |
435 | |
436 | #define DLM_RS_NODES 0x00000001 |
437 | #define DLM_RS_NODES_ALL 0x00000002 |
438 | #define DLM_RS_DIR 0x00000004 |
439 | #define DLM_RS_DIR_ALL 0x00000008 |
440 | #define DLM_RS_LOCKS 0x00000010 |
441 | #define DLM_RS_LOCKS_ALL 0x00000020 |
442 | #define DLM_RS_DONE 0x00000040 |
443 | #define DLM_RS_DONE_ALL 0x00000080 |
444 | |
445 | #define DLM_RCOM_STATUS 1 |
446 | #define DLM_RCOM_NAMES 2 |
447 | #define DLM_RCOM_LOOKUP 3 |
448 | #define DLM_RCOM_LOCK 4 |
449 | #define DLM_RCOM_STATUS_REPLY 5 |
450 | #define DLM_RCOM_NAMES_REPLY 6 |
451 | #define DLM_RCOM_LOOKUP_REPLY 7 |
452 | #define DLM_RCOM_LOCK_REPLY 8 |
453 | |
454 | struct dlm_rcom { |
455 | struct dlm_header ; |
456 | __le32 rc_type; /* DLM_RCOM_ */ |
457 | __le32 rc_result; /* multi-purpose */ |
458 | __le64 rc_id; /* match reply with request */ |
459 | __le64 rc_seq; /* sender's ls_recover_seq */ |
460 | __le64 rc_seq_reply; /* remote ls_recover_seq */ |
461 | char rc_buf[]; |
462 | }; |
463 | |
464 | struct { |
465 | __le16 ; |
466 | __le16 ; |
467 | __le32 ; |
468 | /* need to be 8 byte aligned */ |
469 | char []; |
470 | }; |
471 | |
472 | /* encapsulation header */ |
473 | struct dlm_opts { |
474 | struct dlm_header ; |
475 | uint8_t o_nextcmd; |
476 | uint8_t o_pad; |
477 | __le16 o_optlen; |
478 | __le32 o_pad2; |
479 | char o_opts[]; |
480 | }; |
481 | |
482 | union dlm_packet { |
483 | struct dlm_header ; /* common to other two */ |
484 | struct dlm_message message; |
485 | struct dlm_rcom rcom; |
486 | struct dlm_opts opts; |
487 | }; |
488 | |
489 | #define DLM_RSF_NEED_SLOTS 0x00000001 |
490 | |
491 | /* RCOM_STATUS data */ |
492 | struct rcom_status { |
493 | __le32 rs_flags; |
494 | __le32 rs_unused1; |
495 | __le64 rs_unused2; |
496 | }; |
497 | |
498 | /* RCOM_STATUS_REPLY data */ |
499 | struct rcom_config { |
500 | __le32 rf_lvblen; |
501 | __le32 rf_lsflags; |
502 | |
503 | /* DLM_HEADER_SLOTS adds: */ |
504 | __le32 rf_flags; |
505 | __le16 rf_our_slot; |
506 | __le16 rf_num_slots; |
507 | __le32 rf_generation; |
508 | __le32 rf_unused1; |
509 | __le64 rf_unused2; |
510 | }; |
511 | |
512 | struct rcom_slot { |
513 | __le32 ro_nodeid; |
514 | __le16 ro_slot; |
515 | __le16 ro_unused1; |
516 | __le64 ro_unused2; |
517 | }; |
518 | |
519 | struct rcom_lock { |
520 | __le32 rl_ownpid; |
521 | __le32 rl_lkid; |
522 | __le32 rl_remid; |
523 | __le32 rl_parent_lkid; |
524 | __le32 rl_parent_remid; |
525 | __le32 rl_exflags; |
526 | __le32 rl_flags; |
527 | __le32 rl_lvbseq; |
528 | __le32 rl_result; |
529 | int8_t rl_rqmode; |
530 | int8_t rl_grmode; |
531 | int8_t rl_status; |
532 | int8_t rl_asts; |
533 | __le16 rl_wait_type; |
534 | __le16 rl_namelen; |
535 | char rl_name[DLM_RESNAME_MAXLEN]; |
536 | char rl_lvb[]; |
537 | }; |
538 | |
539 | /* |
540 | * The max number of resources per rsbtbl bucket that shrink will attempt |
541 | * to remove in each iteration. |
542 | */ |
543 | |
544 | #define DLM_REMOVE_NAMES_MAX 8 |
545 | |
546 | struct dlm_ls { |
547 | struct list_head ls_list; /* list of lockspaces */ |
548 | dlm_lockspace_t *ls_local_handle; |
549 | uint32_t ls_global_id; /* global unique lockspace ID */ |
550 | uint32_t ls_generation; |
551 | uint32_t ls_exflags; |
552 | int ls_lvblen; |
553 | atomic_t ls_count; /* refcount of processes in |
554 | the dlm using this ls */ |
555 | wait_queue_head_t ls_count_wait; |
556 | int ls_create_count; /* create/release refcount */ |
557 | unsigned long ls_flags; /* LSFL_ */ |
558 | unsigned long ls_scan_time; |
559 | struct kobject ls_kobj; |
560 | |
561 | struct idr ls_lkbidr; |
562 | spinlock_t ls_lkbidr_spin; |
563 | |
564 | struct dlm_rsbtable *ls_rsbtbl; |
565 | uint32_t ls_rsbtbl_size; |
566 | |
567 | struct mutex ls_waiters_mutex; |
568 | struct list_head ls_waiters; /* lkbs needing a reply */ |
569 | |
570 | struct mutex ls_orphans_mutex; |
571 | struct list_head ls_orphans; |
572 | |
573 | spinlock_t ls_new_rsb_spin; |
574 | int ls_new_rsb_count; |
575 | struct list_head ls_new_rsb; /* new rsb structs */ |
576 | |
577 | char *ls_remove_names[DLM_REMOVE_NAMES_MAX]; |
578 | int ls_remove_lens[DLM_REMOVE_NAMES_MAX]; |
579 | |
580 | struct list_head ls_nodes; /* current nodes in ls */ |
581 | struct list_head ls_nodes_gone; /* dead node list, recovery */ |
582 | int ls_num_nodes; /* number of nodes in ls */ |
583 | int ls_low_nodeid; |
584 | int ls_total_weight; |
585 | int *ls_node_array; |
586 | |
587 | int ls_slot; |
588 | int ls_num_slots; |
589 | int ls_slots_size; |
590 | struct dlm_slot *ls_slots; |
591 | |
592 | struct dlm_rsb ls_local_rsb; /* for returning errors */ |
593 | struct dlm_lkb ls_local_lkb; /* for returning errors */ |
594 | struct dlm_message ls_local_ms; /* for faking a reply */ |
595 | |
596 | struct dentry *ls_debug_rsb_dentry; /* debugfs */ |
597 | struct dentry *ls_debug_waiters_dentry; /* debugfs */ |
598 | struct dentry *ls_debug_locks_dentry; /* debugfs */ |
599 | struct dentry *ls_debug_all_dentry; /* debugfs */ |
600 | struct dentry *ls_debug_toss_dentry; /* debugfs */ |
601 | struct dentry *ls_debug_queued_asts_dentry; /* debugfs */ |
602 | |
603 | wait_queue_head_t ls_uevent_wait; /* user part of join/leave */ |
604 | int ls_uevent_result; |
605 | struct completion ls_recovery_done; |
606 | int ls_recovery_result; |
607 | |
608 | struct miscdevice ls_device; |
609 | |
610 | struct workqueue_struct *ls_callback_wq; |
611 | |
612 | /* recovery related */ |
613 | |
614 | spinlock_t ls_cb_lock; |
615 | struct list_head ls_cb_delay; /* save for queue_work later */ |
616 | struct timer_list ls_timer; |
617 | struct task_struct *ls_recoverd_task; |
618 | struct mutex ls_recoverd_active; |
619 | spinlock_t ls_recover_lock; |
620 | unsigned long ls_recover_begin; /* jiffies timestamp */ |
621 | uint32_t ls_recover_status; /* DLM_RS_ */ |
622 | uint64_t ls_recover_seq; |
623 | struct dlm_recover *ls_recover_args; |
624 | struct rw_semaphore ls_in_recovery; /* block local requests */ |
625 | struct rw_semaphore ls_recv_active; /* block dlm_recv */ |
626 | struct list_head ls_requestqueue;/* queue remote requests */ |
627 | atomic_t ls_requestqueue_cnt; |
628 | wait_queue_head_t ls_requestqueue_wait; |
629 | struct mutex ls_requestqueue_mutex; |
630 | struct dlm_rcom *ls_recover_buf; |
631 | int ls_recover_nodeid; /* for debugging */ |
632 | unsigned int ls_recover_dir_sent_res; /* for log info */ |
633 | unsigned int ls_recover_dir_sent_msg; /* for log info */ |
634 | unsigned int ls_recover_locks_in; /* for log info */ |
635 | uint64_t ls_rcom_seq; |
636 | spinlock_t ls_rcom_spin; |
637 | struct list_head ls_recover_list; |
638 | spinlock_t ls_recover_list_lock; |
639 | int ls_recover_list_count; |
640 | struct idr ls_recover_idr; |
641 | spinlock_t ls_recover_idr_lock; |
642 | wait_queue_head_t ls_wait_general; |
643 | wait_queue_head_t ls_recover_lock_wait; |
644 | spinlock_t ls_clear_proc_locks; |
645 | |
646 | struct list_head ls_root_list; /* root resources */ |
647 | struct rw_semaphore ls_root_sem; /* protect root_list */ |
648 | |
649 | const struct dlm_lockspace_ops *ls_ops; |
650 | void *ls_ops_arg; |
651 | |
652 | int ls_namelen; |
653 | char ls_name[DLM_LOCKSPACE_LEN + 1]; |
654 | }; |
655 | |
656 | /* |
657 | * LSFL_RECOVER_STOP - dlm_ls_stop() sets this to tell dlm recovery routines |
658 | * that they should abort what they're doing so new recovery can be started. |
659 | * |
660 | * LSFL_RECOVER_DOWN - dlm_ls_stop() sets this to tell dlm_recoverd that it |
661 | * should do down_write() on the in_recovery rw_semaphore. (doing down_write |
662 | * within dlm_ls_stop causes complaints about the lock acquired/released |
663 | * in different contexts.) |
664 | * |
665 | * LSFL_RECOVER_LOCK - dlm_recoverd holds the in_recovery rw_semaphore. |
666 | * It sets this after it is done with down_write() on the in_recovery |
667 | * rw_semaphore and clears it after it has released the rw_semaphore. |
668 | * |
669 | * LSFL_RECOVER_WORK - dlm_ls_start() sets this to tell dlm_recoverd that it |
670 | * should begin recovery of the lockspace. |
671 | * |
672 | * LSFL_RUNNING - set when normal locking activity is enabled. |
673 | * dlm_ls_stop() clears this to tell dlm locking routines that they should |
674 | * quit what they are doing so recovery can run. dlm_recoverd sets |
675 | * this after recovery is finished. |
676 | */ |
677 | |
678 | #define LSFL_RECOVER_STOP 0 |
679 | #define LSFL_RECOVER_DOWN 1 |
680 | #define LSFL_RECOVER_LOCK 2 |
681 | #define LSFL_RECOVER_WORK 3 |
682 | #define LSFL_RUNNING 4 |
683 | |
684 | #define LSFL_RCOM_READY 5 |
685 | #define LSFL_RCOM_WAIT 6 |
686 | #define LSFL_UEVENT_WAIT 7 |
687 | #define LSFL_CB_DELAY 9 |
688 | #define LSFL_NODIR 10 |
689 | |
690 | /* much of this is just saving user space pointers associated with the |
691 | lock that we pass back to the user lib with an ast */ |
692 | |
693 | struct dlm_user_args { |
694 | struct dlm_user_proc *proc; /* each process that opens the lockspace |
695 | device has private data |
696 | (dlm_user_proc) on the struct file, |
697 | the process's locks point back to it*/ |
698 | struct dlm_lksb lksb; |
699 | struct dlm_lksb __user *user_lksb; |
700 | void __user *castparam; |
701 | void __user *castaddr; |
702 | void __user *bastparam; |
703 | void __user *bastaddr; |
704 | uint64_t xid; |
705 | }; |
706 | |
707 | #define DLM_PROC_FLAGS_CLOSING 1 |
708 | #define DLM_PROC_FLAGS_COMPAT 2 |
709 | |
710 | /* locks list is kept so we can remove all a process's locks when it |
711 | exits (or orphan those that are persistent) */ |
712 | |
713 | struct dlm_user_proc { |
714 | dlm_lockspace_t *lockspace; |
715 | unsigned long flags; /* DLM_PROC_FLAGS */ |
716 | struct list_head asts; |
717 | spinlock_t asts_spin; |
718 | struct list_head locks; |
719 | spinlock_t locks_spin; |
720 | struct list_head unlocking; |
721 | wait_queue_head_t wait; |
722 | }; |
723 | |
724 | static inline int dlm_locking_stopped(struct dlm_ls *ls) |
725 | { |
726 | return !test_bit(LSFL_RUNNING, &ls->ls_flags); |
727 | } |
728 | |
729 | static inline int dlm_recovery_stopped(struct dlm_ls *ls) |
730 | { |
731 | return test_bit(LSFL_RECOVER_STOP, &ls->ls_flags); |
732 | } |
733 | |
734 | static inline int dlm_no_directory(struct dlm_ls *ls) |
735 | { |
736 | return test_bit(LSFL_NODIR, &ls->ls_flags); |
737 | } |
738 | |
739 | /* takes a snapshot from dlm atomic flags */ |
740 | static inline uint32_t dlm_flags_val(const unsigned long *addr, |
741 | uint32_t min, uint32_t max) |
742 | { |
743 | uint32_t bit = min, val = 0; |
744 | |
745 | for_each_set_bit_from(bit, addr, max + 1) { |
746 | val |= BIT(bit); |
747 | } |
748 | |
749 | return val; |
750 | } |
751 | |
752 | static inline uint32_t dlm_iflags_val(const struct dlm_lkb *lkb) |
753 | { |
754 | return dlm_flags_val(addr: &lkb->lkb_iflags, __DLM_IFL_MIN_BIT, |
755 | __DLM_IFL_MAX_BIT); |
756 | } |
757 | |
758 | static inline uint32_t dlm_dflags_val(const struct dlm_lkb *lkb) |
759 | { |
760 | return dlm_flags_val(addr: &lkb->lkb_dflags, __DLM_DFL_MIN_BIT, |
761 | __DLM_DFL_MAX_BIT); |
762 | } |
763 | |
764 | /* coming from UAPI header |
765 | * |
766 | * TODO: |
767 | * Move this to UAPI header and let other values point to them and use BIT() |
768 | */ |
769 | #define DLM_SBF_DEMOTED_BIT 0 |
770 | #define __DLM_SBF_MIN_BIT DLM_SBF_DEMOTED_BIT |
771 | #define DLM_SBF_VALNOTVALID_BIT 1 |
772 | #define DLM_SBF_ALTMODE_BIT 2 |
773 | #define __DLM_SBF_MAX_BIT DLM_SBF_ALTMODE_BIT |
774 | |
775 | static inline uint32_t dlm_sbflags_val(const struct dlm_lkb *lkb) |
776 | { |
777 | /* be sure the next person updates this */ |
778 | BUILD_BUG_ON(BIT(__DLM_SBF_MAX_BIT) != DLM_SBF_ALTMODE); |
779 | |
780 | return dlm_flags_val(addr: &lkb->lkb_sbflags, __DLM_SBF_MIN_BIT, |
781 | __DLM_SBF_MAX_BIT); |
782 | } |
783 | |
784 | static inline void dlm_set_flags_val(unsigned long *addr, uint32_t val, |
785 | uint32_t min, uint32_t max) |
786 | { |
787 | uint32_t bit; |
788 | |
789 | for (bit = min; bit < (max + 1); bit++) { |
790 | if (val & BIT(bit)) |
791 | set_bit(nr: bit, addr); |
792 | else |
793 | clear_bit(nr: bit, addr); |
794 | } |
795 | } |
796 | |
797 | static inline void dlm_set_dflags_val(struct dlm_lkb *lkb, uint32_t val) |
798 | { |
799 | dlm_set_flags_val(addr: &lkb->lkb_dflags, val, __DLM_DFL_MIN_BIT, |
800 | __DLM_DFL_MAX_BIT); |
801 | } |
802 | |
803 | static inline void dlm_set_sbflags_val(struct dlm_lkb *lkb, uint32_t val) |
804 | { |
805 | dlm_set_flags_val(addr: &lkb->lkb_sbflags, val, __DLM_SBF_MIN_BIT, |
806 | __DLM_SBF_MAX_BIT); |
807 | } |
808 | |
809 | int dlm_plock_init(void); |
810 | void dlm_plock_exit(void); |
811 | |
812 | #ifdef CONFIG_DLM_DEBUG |
813 | void dlm_register_debugfs(void); |
814 | void dlm_unregister_debugfs(void); |
815 | void dlm_create_debug_file(struct dlm_ls *ls); |
816 | void dlm_delete_debug_file(struct dlm_ls *ls); |
817 | void *dlm_create_debug_comms_file(int nodeid, void *data); |
818 | void dlm_delete_debug_comms_file(void *ctx); |
819 | #else |
820 | static inline void dlm_register_debugfs(void) { } |
821 | static inline void dlm_unregister_debugfs(void) { } |
822 | static inline void dlm_create_debug_file(struct dlm_ls *ls) { } |
823 | static inline void dlm_delete_debug_file(struct dlm_ls *ls) { } |
824 | static inline void *dlm_create_debug_comms_file(int nodeid, void *data) { return NULL; } |
825 | static inline void dlm_delete_debug_comms_file(void *ctx) { } |
826 | #endif |
827 | |
828 | #endif /* __DLM_INTERNAL_DOT_H__ */ |
829 | |
830 | |