aboutsummaryrefslogtreecommitdiff
path: root/fs/gfs2/lm_interface.h
blob: 378432f17f272e55a5e5cbe7c62c0a7b2043b7a2 (plain)
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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/*
 * 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 v.2.
 */

#ifndef __LM_INTERFACE_DOT_H__
#define __LM_INTERFACE_DOT_H__

/*
 * Opaque handles represent the lock module's lockspace structure, the lock
 * module's lock structures, and GFS's file system (superblock) structure.
 */

typedef void lm_lockspace_t;
typedef void lm_lock_t;
typedef void lm_fsdata_t;

typedef void (*lm_callback_t) (lm_fsdata_t *fsdata, unsigned int type,
			       void *data);

/*
 * lm_mount() flags
 *
 * LM_MFLAG_SPECTATOR
 * GFS is asking to join the filesystem's lockspace, but it doesn't want to
 * modify the filesystem.  The lock module shouldn't assign a journal to the FS
 * mount.  It shouldn't send recovery callbacks to the FS mount.  If the node
 * dies or withdraws, all locks can be wiped immediately.
 */

#define LM_MFLAG_SPECTATOR	0x00000001

/*
 * lm_lockstruct flags
 *
 * LM_LSFLAG_LOCAL
 * The lock_nolock module returns LM_LSFLAG_LOCAL to GFS, indicating that GFS
 * can make single-node optimizations.
 */

#define LM_LSFLAG_LOCAL		0x00000001

/*
 * lm_lockname types
 */

#define LM_TYPE_RESERVED	0x00
#define LM_TYPE_NONDISK		0x01
#define LM_TYPE_INODE		0x02
#define LM_TYPE_RGRP		0x03
#define LM_TYPE_META		0x04
#define LM_TYPE_IOPEN		0x05
#define LM_TYPE_FLOCK		0x06
#define LM_TYPE_PLOCK		0x07
#define LM_TYPE_QUOTA		0x08
#define LM_TYPE_JOURNAL		0x09

/*
 * lm_lock() states
 *
 * SHARED is compatible with SHARED, not with DEFERRED or EX.
 * DEFERRED is compatible with DEFERRED, not with SHARED or EX.
 */

#define LM_ST_UNLOCKED		0
#define LM_ST_EXCLUSIVE		1
#define LM_ST_DEFERRED		2
#define LM_ST_SHARED		3

/*
 * lm_lock() flags
 *
 * LM_FLAG_TRY
 * Don't wait to acquire the lock if it can't be granted immediately.
 *
 * LM_FLAG_TRY_1CB
 * Send one blocking callback if TRY is set and the lock is not granted.
 *
 * LM_FLAG_NOEXP
 * GFS sets this flag on lock requests it makes while doing journal recovery.
 * These special requests should not be blocked due to the recovery like
 * ordinary locks would be.
 *
 * LM_FLAG_ANY
 * A SHARED request may also be granted in DEFERRED, or a DEFERRED request may
 * also be granted in SHARED.  The preferred state is whichever is compatible
 * with other granted locks, or the specified state if no other locks exist.
 *
 * LM_FLAG_PRIORITY
 * Override fairness considerations.  Suppose a lock is held in a shared state
 * and there is a pending request for the deferred state.  A shared lock
 * request with the priority flag would be allowed to bypass the deferred
 * request and directly join the other shared lock.  A shared lock request
 * without the priority flag might be forced to wait until the deferred
 * requested had acquired and released the lock.
 */

#define LM_FLAG_TRY		0x00000001
#define LM_FLAG_TRY_1CB		0x00000002
#define LM_FLAG_NOEXP		0x00000004
#define LM_FLAG_ANY		0x00000008
#define LM_FLAG_PRIORITY	0x00000010

/*
 * lm_lock() and lm_async_cb return flags
 *
 * LM_OUT_ST_MASK
 * Masks the lower two bits of lock state in the returned value.
 *
 * LM_OUT_CACHEABLE
 * The lock hasn't been released so GFS can continue to cache data for it.
 *
 * LM_OUT_CANCELED
 * The lock request was canceled.
 *
 * LM_OUT_ASYNC
 * The result of the request will be returned in an LM_CB_ASYNC callback.
 */

#define LM_OUT_ST_MASK		0x00000003
#define LM_OUT_CACHEABLE	0x00000004
#define LM_OUT_CANCELED		0x00000008
#define LM_OUT_ASYNC		0x00000080
#define LM_OUT_ERROR		0x00000100

/*
 * lm_callback_t types
 *
 * LM_CB_NEED_E LM_CB_NEED_D LM_CB_NEED_S
 * Blocking callback, a remote node is requesting the given lock in
 * EXCLUSIVE, DEFERRED, or SHARED.
 *
 * LM_CB_NEED_RECOVERY
 * The given journal needs to be recovered.
 *
 * LM_CB_DROPLOCKS
 * Reduce the number of cached locks.
 *
 * LM_CB_ASYNC
 * The given lock has been granted.
 */

#define LM_CB_NEED_E		257
#define LM_CB_NEED_D		258
#define LM_CB_NEED_S		259
#define LM_CB_NEED_RECOVERY	260
#define LM_CB_DROPLOCKS		261
#define LM_CB_ASYNC		262

/*
 * lm_recovery_done() messages
 */

#define LM_RD_GAVEUP		308
#define LM_RD_SUCCESS		309


struct lm_lockname {
	uint64_t ln_number;
	unsigned int ln_type;
};

#define lm_name_equal(name1, name2) \
	(((name1)->ln_number == (name2)->ln_number) && \
	 ((name1)->ln_type == (name2)->ln_type)) \

struct lm_async_cb {
	struct lm_lockname lc_name;
	int lc_ret;
};

struct lm_lockstruct;

struct lm_lockops {
	char lm_proto_name[256];

	/*
	 * Mount/Unmount
	 */

	int (*lm_mount) (char *table_name, char *host_data,
			 lm_callback_t cb, lm_fsdata_t *fsdata,
			 unsigned int min_lvb_size, int flags,
			 struct lm_lockstruct *lockstruct,
			 struct kobject *fskobj);

	void (*lm_others_may_mount) (lm_lockspace_t *lockspace);

	void (*lm_unmount) (lm_lockspace_t *lockspace);

	void (*lm_withdraw) (lm_lockspace_t *lockspace);

	/*
	 * Lock oriented operations
	 */

	int (*lm_get_lock) (lm_lockspace_t *lockspace,
			    struct lm_lockname *name, lm_lock_t **lockp);

	void (*lm_put_lock) (lm_lock_t *lock);

	unsigned int (*lm_lock) (lm_lock_t *lock, unsigned int cur_state,
				 unsigned int req_state, unsigned int flags);

	unsigned int (*lm_unlock) (lm_lock_t *lock, unsigned int cur_state);

	void (*lm_cancel) (lm_lock_t *lock);

	int (*lm_hold_lvb) (lm_lock_t *lock, char **lvbp);
	void (*lm_unhold_lvb) (lm_lock_t *lock, char *lvb);
	void (*lm_sync_lvb) (lm_lock_t *lock, char *lvb);

	/*
	 * Posix Lock oriented operations
	 */

	int (*lm_plock_get) (lm_lockspace_t *lockspace,
			     struct lm_lockname *name,
			     struct file *file, struct file_lock *fl);

	int (*lm_plock) (lm_lockspace_t *lockspace,
			 struct lm_lockname *name,
			 struct file *file, int cmd, struct file_lock *fl);

	int (*lm_punlock) (lm_lockspace_t *lockspace,
			   struct lm_lockname *name,
			   struct file *file, struct file_lock *fl);

	/*
	 * Client oriented operations
	 */

	void (*lm_recovery_done) (lm_lockspace_t *lockspace, unsigned int jid,
				  unsigned int message);

	struct module *lm_owner;
};

/*
 * lm_mount() return values
 *
 * ls_jid - the journal ID this node should use
 * ls_first - this node is the first to mount the file system
 * ls_lvb_size - size in bytes of lock value blocks
 * ls_lockspace - lock module's context for this file system
 * ls_ops - lock module's functions
 * ls_flags - lock module features
 */

struct lm_lockstruct {
	unsigned int ls_jid;
	unsigned int ls_first;
	unsigned int ls_lvb_size;
	lm_lockspace_t *ls_lockspace;
	struct lm_lockops *ls_ops;
	int ls_flags;
};

void __init gfs2_init_lmh(void);

/*
 * Lock module bottom interface.  A lock module makes itself available to GFS
 * with these functions.
 *
 * For the time being, we copy the gfs1 lock module bottom interface so the
 * same lock modules can be used with both gfs1 and gfs2 (it won't be possible
 * to load both gfs1 and gfs2 at once.)  Eventually the lock modules will fork
 * for gfs1/gfs2 and this API can change to the gfs2_ prefix.
 */

int gfs_register_lockproto(struct lm_lockops *proto);

void gfs_unregister_lockproto(struct lm_lockops *proto);

/*
 * Lock module top interface.  GFS calls these functions when mounting or
 * unmounting a file system.
 */

int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data,
			 lm_callback_t cb, lm_fsdata_t *fsdata,
			 unsigned int min_lvb_size, int flags,
			 struct lm_lockstruct *lockstruct,
			 struct kobject *fskobj);

void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct);

void gfs2_withdraw_lockproto(struct lm_lockstruct *lockstruct);

#endif /* __LM_INTERFACE_DOT_H__ */