aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/locking/dlm/lock_dlm.h
blob: 941063498532ba9e31392ace75e361d589689e96 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
 * Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU General Public License version 2.
 */

#ifndef LOCK_DLM_DOT_H
#define LOCK_DLM_DOT_H

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/socket.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/kobject.h>
#include <linux/fcntl.h>
#include <linux/wait.h>
#include <net/sock.h>

#include <linux/dlm.h>
#include "../../lm_interface.h"

/*
 * Internally, we prefix things with gdlm_ and GDLM_ (for gfs-dlm) since a
 * prefix of lock_dlm_ gets awkward.  Externally, GFS refers to this module
 * as "lock_dlm".
 */

#define GDLM_STRNAME_BYTES	24
#define GDLM_LVB_SIZE		32
#define GDLM_DROP_COUNT		50000
#define GDLM_DROP_PERIOD	60
#define GDLM_NAME_LEN		128

/* GFS uses 12 bytes to identify a resource (32 bit type + 64 bit number).
   We sprintf these numbers into a 24 byte string of hex values to make them
   human-readable (to make debugging simpler.) */

struct gdlm_strname {
	unsigned char		name[GDLM_STRNAME_BYTES];
	unsigned short		namelen;
};

enum {
	DFL_BLOCK_LOCKS		= 0,
	DFL_SPECTATOR		= 1,
	DFL_WITHDRAW		= 2,
};

struct gdlm_ls {
	uint32_t		id;
	int			jid;
	int			first;
	int			first_done;
	unsigned long		flags;
	struct kobject		kobj;
	char			clustername[GDLM_NAME_LEN];
	char			fsname[GDLM_NAME_LEN];
	int			fsflags;
	dlm_lockspace_t		*dlm_lockspace;
	lm_callback_t		fscb;
	lm_fsdata_t		*fsdata;
	int			recover_jid;
	int			recover_jid_done;
	int			recover_jid_status;
	spinlock_t		async_lock;
	struct list_head	complete;
	struct list_head	blocking;
	struct list_head	delayed;
	struct list_head	submit;
	struct list_head	all_locks;
	uint32_t		all_locks_count;
	wait_queue_head_t	wait_control;
	struct task_struct	*thread1;
	struct task_struct	*thread2;
	wait_queue_head_t	thread_wait;
	unsigned long		drop_time;
	int			drop_locks_count;
	int			drop_locks_period;
};

enum {
	LFL_NOBLOCK		= 0,
	LFL_NOCACHE		= 1,
	LFL_DLM_UNLOCK		= 2,
	LFL_DLM_CANCEL		= 3,
	LFL_SYNC_LVB		= 4,
	LFL_FORCE_PROMOTE	= 5,
	LFL_REREQUEST		= 6,
	LFL_ACTIVE		= 7,
	LFL_INLOCK		= 8,
	LFL_CANCEL		= 9,
	LFL_NOBAST		= 10,
	LFL_HEADQUE		= 11,
	LFL_UNLOCK_DELETE	= 12,
};

struct gdlm_lock {
	struct gdlm_ls		*ls;
	struct lm_lockname	lockname;
	char			*lvb;
	struct dlm_lksb		lksb;

	int16_t			cur;
	int16_t			req;
	int16_t			prev_req;
	uint32_t		lkf;		/* dlm flags DLM_LKF_ */
	unsigned long		flags;		/* lock_dlm flags LFL_ */

	int			bast_mode;	/* protected by async_lock */
	struct completion	ast_wait;

	struct list_head	clist;		/* complete */
	struct list_head	blist;		/* blocking */
	struct list_head	delay_list;	/* delayed */
	struct list_head	all_list;	/* all locks for the fs */
	struct gdlm_lock	*hold_null;	/* NL lock for hold_lvb */
};

#define gdlm_assert(assertion, fmt, args...)                                  \
do {                                                                          \
	if (unlikely(!(assertion))) {                                         \
		printk(KERN_EMERG "lock_dlm: fatal assertion failed \"%s\"\n" \
				  "lock_dlm:  " fmt "\n",                     \
				  #assertion, ##args);                        \
		BUG();                                                        \
	}                                                                     \
} while (0)

#define log_print(lev, fmt, arg...) printk(lev "lock_dlm: " fmt "\n" , ## arg)
#define log_info(fmt, arg...)  log_print(KERN_INFO , fmt , ## arg)
#define log_error(fmt, arg...) log_print(KERN_ERR , fmt , ## arg)
#ifdef LOCK_DLM_LOG_DEBUG
#define log_debug(fmt, arg...) log_print(KERN_DEBUG , fmt , ## arg)
#else
#define log_debug(fmt, arg...)
#endif

/* sysfs.c */

int gdlm_sysfs_init(void);
void gdlm_sysfs_exit(void);
int gdlm_kobject_setup(struct gdlm_ls *, struct kobject *);
void gdlm_kobject_release(struct gdlm_ls *);

/* thread.c */

int gdlm_init_threads(struct gdlm_ls *);
void gdlm_release_threads(struct gdlm_ls *);

/* lock.c */

int16_t gdlm_make_lmstate(int16_t);
void gdlm_queue_delayed(struct gdlm_lock *);
void gdlm_submit_delayed(struct gdlm_ls *);
int gdlm_release_all_locks(struct gdlm_ls *);
void gdlm_delete_lp(struct gdlm_lock *);
unsigned int gdlm_do_lock(struct gdlm_lock *);

int gdlm_get_lock(lm_lockspace_t *, struct lm_lockname *, lm_lock_t **);
void gdlm_put_lock(lm_lock_t *);
unsigned int gdlm_lock(lm_lock_t *, unsigned int, unsigned int, unsigned int);
unsigned int gdlm_unlock(lm_lock_t *, unsigned int);
void gdlm_cancel(lm_lock_t *);
int gdlm_hold_lvb(lm_lock_t *, char **);
void gdlm_unhold_lvb(lm_lock_t *, char *);
void gdlm_sync_lvb(lm_lock_t *, char *);

/* plock.c */

int gdlm_plock_init(void);
void gdlm_plock_exit(void);
int gdlm_plock(lm_lockspace_t *, struct lm_lockname *, struct file *, int,
		struct file_lock *);
int gdlm_plock_get(lm_lockspace_t *, struct lm_lockname *, struct file *,
		struct file_lock *);
int gdlm_punlock(lm_lockspace_t *, struct lm_lockname *, struct file *,
		struct file_lock *);
#endif