Blame view

fs/ocfs2/stack_user.c 23.2 KB
8adf0536c   Joel Becker   ocfs2: Add the us...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /* -*- mode: c; c-basic-offset: 8; -*-
   * vim: noexpandtab sw=8 ts=8 sts=0:
   *
   * stack_user.c
   *
   * Code which interfaces ocfs2 with fs/dlm and a userspace stack.
   *
   * Copyright (C) 2007 Oracle.  All rights reserved.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public
   * License as published by the Free Software Foundation, version 2.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   */
  
  #include <linux/module.h>
6427a7275   Joel Becker   ocfs2: Add the oc...
21
22
23
  #include <linux/fs.h>
  #include <linux/miscdevice.h>
  #include <linux/mutex.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
24
  #include <linux/slab.h>
6427a7275   Joel Becker   ocfs2: Add the oc...
25
  #include <linux/reboot.h>
462c7e6a2   Joel Becker   ocfs2: Start the ...
26
  #include <asm/uaccess.h>
8adf0536c   Joel Becker   ocfs2: Add the us...
27
28
  
  #include "stackglue.h"
53da4939f   Mark Fasheh   ocfs2: POSIX file...
29
  #include <linux/dlm_plock.h>
8adf0536c   Joel Becker   ocfs2: Add the us...
30

6427a7275   Joel Becker   ocfs2: Add the oc...
31
32
33
34
35
36
37
38
  /*
   * The control protocol starts with a handshake.  Until the handshake
   * is complete, the control device will fail all write(2)s.
   *
   * The handshake is simple.  First, the client reads until EOF.  Each line
   * of output is a supported protocol tag.  All protocol tags are a single
   * character followed by a two hex digit version number.  Currently the
   * only things supported is T01, for "Text-base version 0x01".  Next, the
de870ef02   Joel Becker   ocfs2: Introduce ...
39
40
41
42
43
44
   * client writes the version they would like to use, including the newline.
   * Thus, the protocol tag is 'T01
  '.  If the version tag written is
   * unknown, -EINVAL is returned.  Once the negotiation is complete, the
   * client can start sending messages.
   *
d4b95eef4   Joel Becker   ocfs2: Add the 's...
45
   * The T01 protocol has three messages.  First is the "SETN" message.
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
46
47
48
49
50
51
52
53
54
   * It has the following syntax:
   *
   *  SETN<space><8-char-hex-nodenum><newline>
   *
   * This is 14 characters.
   *
   * The "SETN" message must be the first message following the protocol.
   * It tells ocfs2_control the local node number.
   *
d4b95eef4   Joel Becker   ocfs2: Add the 's...
55
56
57
58
59
60
61
62
63
64
   * Next comes the "SETV" message.  It has the following syntax:
   *
   *  SETV<space><2-char-hex-major><space><2-char-hex-minor><newline>
   *
   * This is 11 characters.
   *
   * The "SETV" message sets the filesystem locking protocol version as
   * negotiated by the client.  The client negotiates based on the maximum
   * version advertised in /sys/fs/ocfs2/max_locking_protocol.  The major
   * number from the "SETV" message must match
e603cfb07   Joel Becker   ocfs2: Remove the...
65
66
   * ocfs2_user_plugin.sp_max_proto.pv_major, and the minor number
   * must be less than or equal to ...sp_max_version.pv_minor.
d4b95eef4   Joel Becker   ocfs2: Add the 's...
67
68
69
70
   *
   * Once this information has been set, mounts will be allowed.  From this
   * point on, the "DOWN" message can be sent for node down notification.
   * It has the following syntax:
de870ef02   Joel Becker   ocfs2: Introduce ...
71
72
73
74
75
76
77
78
79
   *
   *  DOWN<space><32-char-cap-hex-uuid><space><8-char-hex-nodenum><newline>
   *
   * eg:
   *
   *  DOWN 632A924FDD844190BDA93C0DF6B94899 00000001
  
   *
   * This is 47 characters.
6427a7275   Joel Becker   ocfs2: Add the oc...
80
81
82
   */
  
  /*
462c7e6a2   Joel Becker   ocfs2: Start the ...
83
84
85
86
87
88
   * Whether or not the client has done the handshake.
   * For now, we have just one protocol version.
   */
  #define OCFS2_CONTROL_PROTO			"T01
  "
  #define OCFS2_CONTROL_PROTO_LEN			4
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
89
90
  
  /* Handshake states */
462c7e6a2   Joel Becker   ocfs2: Start the ...
91
92
  #define OCFS2_CONTROL_HANDSHAKE_INVALID		(0)
  #define OCFS2_CONTROL_HANDSHAKE_READ		(1)
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
93
94
95
96
97
98
99
  #define OCFS2_CONTROL_HANDSHAKE_PROTOCOL	(2)
  #define OCFS2_CONTROL_HANDSHAKE_VALID		(3)
  
  /* Messages */
  #define OCFS2_CONTROL_MESSAGE_OP_LEN		4
  #define OCFS2_CONTROL_MESSAGE_SETNODE_OP	"SETN"
  #define OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN	14
d4b95eef4   Joel Becker   ocfs2: Add the 's...
100
101
  #define OCFS2_CONTROL_MESSAGE_SETVERSION_OP	"SETV"
  #define OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN	11
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
102
  #define OCFS2_CONTROL_MESSAGE_DOWN_OP		"DOWN"
de870ef02   Joel Becker   ocfs2: Introduce ...
103
104
  #define OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN	47
  #define OCFS2_TEXT_UUID_LEN			32
d4b95eef4   Joel Becker   ocfs2: Add the 's...
105
  #define OCFS2_CONTROL_MESSAGE_VERNUM_LEN	2
de870ef02   Joel Becker   ocfs2: Introduce ...
106
  #define OCFS2_CONTROL_MESSAGE_NODENUM_LEN	8
462c7e6a2   Joel Becker   ocfs2: Start the ...
107
108
  
  /*
6427a7275   Joel Becker   ocfs2: Add the oc...
109
110
111
112
113
114
115
   * ocfs2_live_connection is refcounted because the filesystem and
   * miscdevice sides can detach in different order.  Let's just be safe.
   */
  struct ocfs2_live_connection {
  	struct list_head		oc_list;
  	struct ocfs2_cluster_connection	*oc_conn;
  };
462c7e6a2   Joel Becker   ocfs2: Start the ...
116
117
118
  struct ocfs2_control_private {
  	struct list_head op_list;
  	int op_state;
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
119
  	int op_this_node;
d4b95eef4   Joel Becker   ocfs2: Add the 's...
120
  	struct ocfs2_protocol_version op_proto;
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
121
122
123
124
125
126
127
128
129
  };
  
  /* SETN<space><8-char-hex-nodenum><newline> */
  struct ocfs2_control_message_setn {
  	char	tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
  	char	space;
  	char	nodestr[OCFS2_CONTROL_MESSAGE_NODENUM_LEN];
  	char	newline;
  };
d4b95eef4   Joel Becker   ocfs2: Add the 's...
130
131
132
133
134
135
136
137
138
  /* SETV<space><2-char-hex-major><space><2-char-hex-minor><newline> */
  struct ocfs2_control_message_setv {
  	char	tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
  	char	space1;
  	char	major[OCFS2_CONTROL_MESSAGE_VERNUM_LEN];
  	char	space2;
  	char	minor[OCFS2_CONTROL_MESSAGE_VERNUM_LEN];
  	char	newline;
  };
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
139
140
141
142
143
144
145
146
147
148
149
150
151
  /* DOWN<space><32-char-cap-hex-uuid><space><8-char-hex-nodenum><newline> */
  struct ocfs2_control_message_down {
  	char	tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
  	char	space1;
  	char	uuid[OCFS2_TEXT_UUID_LEN];
  	char	space2;
  	char	nodestr[OCFS2_CONTROL_MESSAGE_NODENUM_LEN];
  	char	newline;
  };
  
  union ocfs2_control_message {
  	char					tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
  	struct ocfs2_control_message_setn	u_setn;
d4b95eef4   Joel Becker   ocfs2: Add the 's...
152
  	struct ocfs2_control_message_setv	u_setv;
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
153
  	struct ocfs2_control_message_down	u_down;
462c7e6a2   Joel Becker   ocfs2: Start the ...
154
  };
a12630b18   Joel Becker   ocfs2: Rename 'us...
155
  static struct ocfs2_stack_plugin ocfs2_user_plugin;
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
156

6427a7275   Joel Becker   ocfs2: Add the oc...
157
  static atomic_t ocfs2_control_opened;
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
158
  static int ocfs2_control_this_node = -1;
d4b95eef4   Joel Becker   ocfs2: Add the 's...
159
  static struct ocfs2_protocol_version running_proto;
6427a7275   Joel Becker   ocfs2: Add the oc...
160
161
  
  static LIST_HEAD(ocfs2_live_connection_list);
462c7e6a2   Joel Becker   ocfs2: Start the ...
162
  static LIST_HEAD(ocfs2_control_private_list);
6427a7275   Joel Becker   ocfs2: Add the oc...
163
  static DEFINE_MUTEX(ocfs2_control_lock);
462c7e6a2   Joel Becker   ocfs2: Start the ...
164
165
166
167
168
169
170
171
172
173
174
175
  static inline void ocfs2_control_set_handshake_state(struct file *file,
  						     int state)
  {
  	struct ocfs2_control_private *p = file->private_data;
  	p->op_state = state;
  }
  
  static inline int ocfs2_control_get_handshake_state(struct file *file)
  {
  	struct ocfs2_control_private *p = file->private_data;
  	return p->op_state;
  }
6427a7275   Joel Becker   ocfs2: Add the oc...
176
177
178
179
180
181
182
183
184
185
186
187
  static struct ocfs2_live_connection *ocfs2_connection_find(const char *name)
  {
  	size_t len = strlen(name);
  	struct ocfs2_live_connection *c;
  
  	BUG_ON(!mutex_is_locked(&ocfs2_control_lock));
  
  	list_for_each_entry(c, &ocfs2_live_connection_list, oc_list) {
  		if ((c->oc_conn->cc_namelen == len) &&
  		    !strncmp(c->oc_conn->cc_name, name, len))
  			return c;
  	}
226291aa4   dann frazier   ocfs2_connection_...
188
  	return NULL;
6427a7275   Joel Becker   ocfs2: Add the oc...
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
  }
  
  /*
   * ocfs2_live_connection structures are created underneath the ocfs2
   * mount path.  Since the VFS prevents multiple calls to
   * fill_super(), we can't get dupes here.
   */
  static int ocfs2_live_connection_new(struct ocfs2_cluster_connection *conn,
  				     struct ocfs2_live_connection **c_ret)
  {
  	int rc = 0;
  	struct ocfs2_live_connection *c;
  
  	c = kzalloc(sizeof(struct ocfs2_live_connection), GFP_KERNEL);
  	if (!c)
  		return -ENOMEM;
  
  	mutex_lock(&ocfs2_control_lock);
  	c->oc_conn = conn;
  
  	if (atomic_read(&ocfs2_control_opened))
  		list_add(&c->oc_list, &ocfs2_live_connection_list);
  	else {
  		printk(KERN_ERR
  		       "ocfs2: Userspace control daemon is not present
  ");
  		rc = -ESRCH;
  	}
  
  	mutex_unlock(&ocfs2_control_lock);
  
  	if (!rc)
  		*c_ret = c;
  	else
  		kfree(c);
  
  	return rc;
  }
  
  /*
   * This function disconnects the cluster connection from ocfs2_control.
   * Afterwards, userspace can't affect the cluster connection.
   */
  static void ocfs2_live_connection_drop(struct ocfs2_live_connection *c)
  {
  	mutex_lock(&ocfs2_control_lock);
  	list_del_init(&c->oc_list);
  	c->oc_conn = NULL;
  	mutex_unlock(&ocfs2_control_lock);
  
  	kfree(c);
  }
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
241
242
  static int ocfs2_control_cfu(void *target, size_t target_len,
  			     const char __user *buf, size_t count)
462c7e6a2   Joel Becker   ocfs2: Start the ...
243
244
  {
  	/* The T01 expects write(2) calls to have exactly one command */
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
245
246
  	if ((count != target_len) ||
  	    (count > sizeof(union ocfs2_control_message)))
462c7e6a2   Joel Becker   ocfs2: Start the ...
247
248
249
250
  		return -EINVAL;
  
  	if (copy_from_user(target, buf, target_len))
  		return -EFAULT;
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
251
  	return 0;
462c7e6a2   Joel Becker   ocfs2: Start the ...
252
  }
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
253
254
255
  static ssize_t ocfs2_control_validate_protocol(struct file *file,
  					       const char __user *buf,
  					       size_t count)
462c7e6a2   Joel Becker   ocfs2: Start the ...
256
257
258
259
260
261
  {
  	ssize_t ret;
  	char kbuf[OCFS2_CONTROL_PROTO_LEN];
  
  	ret = ocfs2_control_cfu(kbuf, OCFS2_CONTROL_PROTO_LEN,
  				buf, count);
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
262
  	if (ret)
462c7e6a2   Joel Becker   ocfs2: Start the ...
263
264
265
266
  		return ret;
  
  	if (strncmp(kbuf, OCFS2_CONTROL_PROTO, OCFS2_CONTROL_PROTO_LEN))
  		return -EINVAL;
462c7e6a2   Joel Becker   ocfs2: Start the ...
267
  	ocfs2_control_set_handshake_state(file,
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
268
  					  OCFS2_CONTROL_HANDSHAKE_PROTOCOL);
462c7e6a2   Joel Becker   ocfs2: Start the ...
269
270
271
  
  	return count;
  }
de870ef02   Joel Becker   ocfs2: Introduce ...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
  static void ocfs2_control_send_down(const char *uuid,
  				    int nodenum)
  {
  	struct ocfs2_live_connection *c;
  
  	mutex_lock(&ocfs2_control_lock);
  
  	c = ocfs2_connection_find(uuid);
  	if (c) {
  		BUG_ON(c->oc_conn == NULL);
  		c->oc_conn->cc_recovery_handler(nodenum,
  						c->oc_conn->cc_recovery_data);
  	}
  
  	mutex_unlock(&ocfs2_control_lock);
  }
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
288
289
290
  /*
   * Called whenever configuration elements are sent to /dev/ocfs2_control.
   * If all configuration elements are present, try to set the global
d4b95eef4   Joel Becker   ocfs2: Add the 's...
291
292
293
   * values.  If there is a problem, return an error.  Skip any missing
   * elements, and only bump ocfs2_control_opened when we have all elements
   * and are successful.
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
294
295
296
297
298
299
   */
  static int ocfs2_control_install_private(struct file *file)
  {
  	int rc = 0;
  	int set_p = 1;
  	struct ocfs2_control_private *p = file->private_data;
de870ef02   Joel Becker   ocfs2: Introduce ...
300

3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
301
  	BUG_ON(p->op_state != OCFS2_CONTROL_HANDSHAKE_PROTOCOL);
d4b95eef4   Joel Becker   ocfs2: Add the 's...
302
303
304
  	mutex_lock(&ocfs2_control_lock);
  
  	if (p->op_this_node < 0) {
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
305
  		set_p = 0;
d4b95eef4   Joel Becker   ocfs2: Add the 's...
306
307
308
309
310
  	} else if ((ocfs2_control_this_node >= 0) &&
  		   (ocfs2_control_this_node != p->op_this_node)) {
  		rc = -EINVAL;
  		goto out_unlock;
  	}
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
311

d4b95eef4   Joel Becker   ocfs2: Add the 's...
312
313
314
315
316
  	if (!p->op_proto.pv_major) {
  		set_p = 0;
  	} else if (!list_empty(&ocfs2_live_connection_list) &&
  		   ((running_proto.pv_major != p->op_proto.pv_major) ||
  		    (running_proto.pv_minor != p->op_proto.pv_minor))) {
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
317
  		rc = -EINVAL;
d4b95eef4   Joel Becker   ocfs2: Add the 's...
318
319
320
321
322
323
324
325
326
327
  		goto out_unlock;
  	}
  
  	if (set_p) {
  		ocfs2_control_this_node = p->op_this_node;
  		running_proto.pv_major = p->op_proto.pv_major;
  		running_proto.pv_minor = p->op_proto.pv_minor;
  	}
  
  out_unlock:
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
328
329
330
331
332
333
334
335
336
337
338
  	mutex_unlock(&ocfs2_control_lock);
  
  	if (!rc && set_p) {
  		/* We set the global values successfully */
  		atomic_inc(&ocfs2_control_opened);
  		ocfs2_control_set_handshake_state(file,
  					OCFS2_CONTROL_HANDSHAKE_VALID);
  	}
  
  	return rc;
  }
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
339
340
341
342
343
344
345
346
347
348
349
350
351
  static int ocfs2_control_get_this_node(void)
  {
  	int rc;
  
  	mutex_lock(&ocfs2_control_lock);
  	if (ocfs2_control_this_node < 0)
  		rc = -EINVAL;
  	else
  		rc = ocfs2_control_this_node;
  	mutex_unlock(&ocfs2_control_lock);
  
  	return rc;
  }
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
352
353
  static int ocfs2_control_do_setnode_msg(struct file *file,
  					struct ocfs2_control_message_setn *msg)
de870ef02   Joel Becker   ocfs2: Introduce ...
354
  {
de870ef02   Joel Becker   ocfs2: Introduce ...
355
  	long nodenum;
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
356
357
  	char *ptr = NULL;
  	struct ocfs2_control_private *p = file->private_data;
de870ef02   Joel Becker   ocfs2: Introduce ...
358

3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
359
360
361
  	if (ocfs2_control_get_handshake_state(file) !=
  	    OCFS2_CONTROL_HANDSHAKE_PROTOCOL)
  		return -EINVAL;
de870ef02   Joel Becker   ocfs2: Introduce ...
362

3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
  	if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_SETNODE_OP,
  		    OCFS2_CONTROL_MESSAGE_OP_LEN))
  		return -EINVAL;
  
  	if ((msg->space != ' ') || (msg->newline != '
  '))
  		return -EINVAL;
  	msg->space = msg->newline = '\0';
  
  	nodenum = simple_strtol(msg->nodestr, &ptr, 16);
  	if (!ptr || *ptr)
  		return -EINVAL;
  
  	if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||
  	    (nodenum > INT_MAX) || (nodenum < 0))
  		return -ERANGE;
  	p->op_this_node = nodenum;
  
  	return ocfs2_control_install_private(file);
  }
d4b95eef4   Joel Becker   ocfs2: Add the 's...
383
384
385
386
387
388
389
  static int ocfs2_control_do_setversion_msg(struct file *file,
  					   struct ocfs2_control_message_setv *msg)
   {
  	long major, minor;
  	char *ptr = NULL;
  	struct ocfs2_control_private *p = file->private_data;
  	struct ocfs2_protocol_version *max =
e603cfb07   Joel Becker   ocfs2: Remove the...
390
  		&ocfs2_user_plugin.sp_max_proto;
d4b95eef4   Joel Becker   ocfs2: Add the 's...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
  
  	if (ocfs2_control_get_handshake_state(file) !=
  	    OCFS2_CONTROL_HANDSHAKE_PROTOCOL)
  		return -EINVAL;
  
  	if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_SETVERSION_OP,
  		    OCFS2_CONTROL_MESSAGE_OP_LEN))
  		return -EINVAL;
  
  	if ((msg->space1 != ' ') || (msg->space2 != ' ') ||
  	    (msg->newline != '
  '))
  		return -EINVAL;
  	msg->space1 = msg->space2 = msg->newline = '\0';
  
  	major = simple_strtol(msg->major, &ptr, 16);
  	if (!ptr || *ptr)
  		return -EINVAL;
  	minor = simple_strtol(msg->minor, &ptr, 16);
  	if (!ptr || *ptr)
  		return -EINVAL;
  
  	/*
  	 * The major must be between 1 and 255, inclusive.  The minor
  	 * must be between 0 and 255, inclusive.  The version passed in
  	 * must be within the maximum version supported by the filesystem.
  	 */
  	if ((major == LONG_MIN) || (major == LONG_MAX) ||
  	    (major > (u8)-1) || (major < 1))
  		return -ERANGE;
  	if ((minor == LONG_MIN) || (minor == LONG_MAX) ||
  	    (minor > (u8)-1) || (minor < 0))
  		return -ERANGE;
  	if ((major != max->pv_major) ||
  	    (minor > max->pv_minor))
  		return -EINVAL;
  
  	p->op_proto.pv_major = major;
  	p->op_proto.pv_minor = minor;
  
  	return ocfs2_control_install_private(file);
  }
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
433
434
435
436
437
438
439
440
441
  static int ocfs2_control_do_down_msg(struct file *file,
  				     struct ocfs2_control_message_down *msg)
  {
  	long nodenum;
  	char *p = NULL;
  
  	if (ocfs2_control_get_handshake_state(file) !=
  	    OCFS2_CONTROL_HANDSHAKE_VALID)
  		return -EINVAL;
de870ef02   Joel Becker   ocfs2: Introduce ...
442

3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
443
444
  	if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_DOWN_OP,
  		    OCFS2_CONTROL_MESSAGE_OP_LEN))
de870ef02   Joel Becker   ocfs2: Introduce ...
445
  		return -EINVAL;
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
446
447
448
  	if ((msg->space1 != ' ') || (msg->space2 != ' ') ||
  	    (msg->newline != '
  '))
de870ef02   Joel Becker   ocfs2: Introduce ...
449
  		return -EINVAL;
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
450
  	msg->space1 = msg->space2 = msg->newline = '\0';
de870ef02   Joel Becker   ocfs2: Introduce ...
451

3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
452
  	nodenum = simple_strtol(msg->nodestr, &p, 16);
de870ef02   Joel Becker   ocfs2: Introduce ...
453
454
455
456
457
458
  	if (!p || *p)
  		return -EINVAL;
  
  	if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||
  	    (nodenum > INT_MAX) || (nodenum < 0))
  		return -ERANGE;
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
459
  	ocfs2_control_send_down(msg->uuid, nodenum);
de870ef02   Joel Becker   ocfs2: Introduce ...
460

3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
  	return 0;
  }
  
  static ssize_t ocfs2_control_message(struct file *file,
  				     const char __user *buf,
  				     size_t count)
  {
  	ssize_t ret;
  	union ocfs2_control_message msg;
  
  	/* Try to catch padding issues */
  	WARN_ON(offsetof(struct ocfs2_control_message_down, uuid) !=
  		(sizeof(msg.u_down.tag) + sizeof(msg.u_down.space1)));
  
  	memset(&msg, 0, sizeof(union ocfs2_control_message));
  	ret = ocfs2_control_cfu(&msg, count, buf, count);
  	if (ret)
  		goto out;
  
  	if ((count == OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN) &&
  	    !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_SETNODE_OP,
  		     OCFS2_CONTROL_MESSAGE_OP_LEN))
  		ret = ocfs2_control_do_setnode_msg(file, &msg.u_setn);
d4b95eef4   Joel Becker   ocfs2: Add the 's...
484
485
486
487
  	else if ((count == OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN) &&
  		 !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_SETVERSION_OP,
  			  OCFS2_CONTROL_MESSAGE_OP_LEN))
  		ret = ocfs2_control_do_setversion_msg(file, &msg.u_setv);
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
488
489
490
491
492
493
494
495
496
  	else if ((count == OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN) &&
  		 !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_DOWN_OP,
  			  OCFS2_CONTROL_MESSAGE_OP_LEN))
  		ret = ocfs2_control_do_down_msg(file, &msg.u_down);
  	else
  		ret = -EINVAL;
  
  out:
  	return ret ? ret : count;
de870ef02   Joel Becker   ocfs2: Introduce ...
497
  }
6427a7275   Joel Becker   ocfs2: Add the oc...
498
499
500
501
502
  
  static ssize_t ocfs2_control_write(struct file *file,
  				   const char __user *buf,
  				   size_t count,
  				   loff_t *ppos)
8adf0536c   Joel Becker   ocfs2: Add the us...
503
  {
462c7e6a2   Joel Becker   ocfs2: Start the ...
504
505
506
507
508
509
510
511
  	ssize_t ret;
  
  	switch (ocfs2_control_get_handshake_state(file)) {
  		case OCFS2_CONTROL_HANDSHAKE_INVALID:
  			ret = -EINVAL;
  			break;
  
  		case OCFS2_CONTROL_HANDSHAKE_READ:
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
512
513
  			ret = ocfs2_control_validate_protocol(file, buf,
  							      count);
462c7e6a2   Joel Becker   ocfs2: Start the ...
514
  			break;
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
515
  		case OCFS2_CONTROL_HANDSHAKE_PROTOCOL:
462c7e6a2   Joel Becker   ocfs2: Start the ...
516
  		case OCFS2_CONTROL_HANDSHAKE_VALID:
de870ef02   Joel Becker   ocfs2: Introduce ...
517
  			ret = ocfs2_control_message(file, buf, count);
462c7e6a2   Joel Becker   ocfs2: Start the ...
518
519
520
521
522
523
524
525
526
  			break;
  
  		default:
  			BUG();
  			ret = -EIO;
  			break;
  	}
  
  	return ret;
8adf0536c   Joel Becker   ocfs2: Add the us...
527
  }
462c7e6a2   Joel Becker   ocfs2: Start the ...
528
529
530
531
  /*
   * This is a naive version.  If we ever have a new protocol, we'll expand
   * it.  Probably using seq_file.
   */
6427a7275   Joel Becker   ocfs2: Add the oc...
532
533
534
535
536
  static ssize_t ocfs2_control_read(struct file *file,
  				  char __user *buf,
  				  size_t count,
  				  loff_t *ppos)
  {
7600c72b7   Akinobu Mita   ocfs2: use simple...
537
  	ssize_t ret;
462c7e6a2   Joel Becker   ocfs2: Start the ...
538

7600c72b7   Akinobu Mita   ocfs2: use simple...
539
540
  	ret = simple_read_from_buffer(buf, count, ppos,
  			OCFS2_CONTROL_PROTO, OCFS2_CONTROL_PROTO_LEN);
462c7e6a2   Joel Becker   ocfs2: Start the ...
541
542
  
  	/* Have we read the whole protocol list? */
7600c72b7   Akinobu Mita   ocfs2: use simple...
543
  	if (ret > 0 && *ppos >= OCFS2_CONTROL_PROTO_LEN)
462c7e6a2   Joel Becker   ocfs2: Start the ...
544
545
  		ocfs2_control_set_handshake_state(file,
  						  OCFS2_CONTROL_HANDSHAKE_READ);
7600c72b7   Akinobu Mita   ocfs2: use simple...
546
  	return ret;
6427a7275   Joel Becker   ocfs2: Add the oc...
547
548
549
550
  }
  
  static int ocfs2_control_release(struct inode *inode, struct file *file)
  {
462c7e6a2   Joel Becker   ocfs2: Start the ...
551
552
553
554
555
556
557
  	struct ocfs2_control_private *p = file->private_data;
  
  	mutex_lock(&ocfs2_control_lock);
  
  	if (ocfs2_control_get_handshake_state(file) !=
  	    OCFS2_CONTROL_HANDSHAKE_VALID)
  		goto out;
6427a7275   Joel Becker   ocfs2: Add the oc...
558
  	if (atomic_dec_and_test(&ocfs2_control_opened)) {
6427a7275   Joel Becker   ocfs2: Add the oc...
559
560
561
562
563
564
565
566
567
568
  		if (!list_empty(&ocfs2_live_connection_list)) {
  			/* XXX: Do bad things! */
  			printk(KERN_ERR
  			       "ocfs2: Unexpected release of ocfs2_control!
  "
  			       "       Loss of cluster connection requires "
  			       "an emergency restart!
  ");
  			emergency_restart();
  		}
d4b95eef4   Joel Becker   ocfs2: Add the 's...
569
570
571
572
  		/*
  		 * Last valid close clears the node number and resets
  		 * the locking protocol version
  		 */
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
573
  		ocfs2_control_this_node = -1;
d4b95eef4   Joel Becker   ocfs2: Add the 's...
574
575
  		running_proto.pv_major = 0;
  		running_proto.pv_major = 0;
6427a7275   Joel Becker   ocfs2: Add the oc...
576
  	}
462c7e6a2   Joel Becker   ocfs2: Start the ...
577
578
579
580
581
582
583
  out:
  	list_del_init(&p->op_list);
  	file->private_data = NULL;
  
  	mutex_unlock(&ocfs2_control_lock);
  
  	kfree(p);
6427a7275   Joel Becker   ocfs2: Add the oc...
584
585
586
587
588
  	return 0;
  }
  
  static int ocfs2_control_open(struct inode *inode, struct file *file)
  {
462c7e6a2   Joel Becker   ocfs2: Start the ...
589
590
591
592
593
  	struct ocfs2_control_private *p;
  
  	p = kzalloc(sizeof(struct ocfs2_control_private), GFP_KERNEL);
  	if (!p)
  		return -ENOMEM;
3cfd4ab6b   Joel Becker   ocfs2: Add the lo...
594
  	p->op_this_node = -1;
462c7e6a2   Joel Becker   ocfs2: Start the ...
595
596
597
598
599
  
  	mutex_lock(&ocfs2_control_lock);
  	file->private_data = p;
  	list_add(&p->op_list, &ocfs2_control_private_list);
  	mutex_unlock(&ocfs2_control_lock);
6427a7275   Joel Becker   ocfs2: Add the oc...
600
601
602
603
604
605
606
607
608
609
  
  	return 0;
  }
  
  static const struct file_operations ocfs2_control_fops = {
  	.open    = ocfs2_control_open,
  	.release = ocfs2_control_release,
  	.read    = ocfs2_control_read,
  	.write   = ocfs2_control_write,
  	.owner   = THIS_MODULE,
6038f373a   Arnd Bergmann   llseek: automatic...
610
  	.llseek  = default_llseek,
6427a7275   Joel Becker   ocfs2: Add the oc...
611
  };
4d8755b5e   Adrian Bunk   ocfs2: make struc...
612
  static struct miscdevice ocfs2_control_device = {
6427a7275   Joel Becker   ocfs2: Add the oc...
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
  	.minor		= MISC_DYNAMIC_MINOR,
  	.name		= "ocfs2_control",
  	.fops		= &ocfs2_control_fops,
  };
  
  static int ocfs2_control_init(void)
  {
  	int rc;
  
  	atomic_set(&ocfs2_control_opened, 0);
  
  	rc = misc_register(&ocfs2_control_device);
  	if (rc)
  		printk(KERN_ERR
  		       "ocfs2: Unable to register ocfs2_control device "
  		       "(errno %d)
  ",
  		       -rc);
  
  	return rc;
  }
  
  static void ocfs2_control_exit(void)
  {
  	int rc;
  
  	rc = misc_deregister(&ocfs2_control_device);
  	if (rc)
  		printk(KERN_ERR
  		       "ocfs2: Unable to deregister ocfs2_control device "
  		       "(errno %d)
  ",
  		       -rc);
  }
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
647
648
  static void fsdlm_lock_ast_wrapper(void *astarg)
  {
c0e413385   Joel Becker   ocfs2: Attach the...
649
  	struct ocfs2_dlm_lksb *lksb = astarg;
a796d2862   Joel Becker   ocfs2: Pass lksbs...
650
  	int status = lksb->lksb_fsdlm.sb_status;
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
651

cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
652
653
654
655
656
657
658
659
660
661
662
  	/*
  	 * For now we're punting on the issue of other non-standard errors
  	 * where we can't tell if the unlock_ast or lock_ast should be called.
  	 * The main "other error" that's possible is EINVAL which means the
  	 * function was called with invalid args, which shouldn't be possible
  	 * since the caller here is under our control.  Other non-standard
  	 * errors probably fall into the same category, or otherwise are fatal
  	 * which means we can't carry on anyway.
  	 */
  
  	if (status == -DLM_EUNLOCK || status == -DLM_ECANCEL)
110946c8f   Joel Becker   ocfs2: Hang the l...
663
  		lksb->lksb_conn->cc_proto->lp_unlock_ast(lksb, 0);
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
664
  	else
110946c8f   Joel Becker   ocfs2: Hang the l...
665
  		lksb->lksb_conn->cc_proto->lp_lock_ast(lksb);
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
666
667
668
669
  }
  
  static void fsdlm_blocking_ast_wrapper(void *astarg, int level)
  {
c0e413385   Joel Becker   ocfs2: Attach the...
670
  	struct ocfs2_dlm_lksb *lksb = astarg;
a796d2862   Joel Becker   ocfs2: Pass lksbs...
671

110946c8f   Joel Becker   ocfs2: Hang the l...
672
  	lksb->lksb_conn->cc_proto->lp_blocking_ast(lksb, level);
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
673
674
675
676
  }
  
  static int user_dlm_lock(struct ocfs2_cluster_connection *conn,
  			 int mode,
c0e413385   Joel Becker   ocfs2: Attach the...
677
  			 struct ocfs2_dlm_lksb *lksb,
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
678
679
  			 u32 flags,
  			 void *name,
a796d2862   Joel Becker   ocfs2: Pass lksbs...
680
  			 unsigned int namelen)
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
681
682
683
684
685
686
687
688
689
  {
  	int ret;
  
  	if (!lksb->lksb_fsdlm.sb_lvbptr)
  		lksb->lksb_fsdlm.sb_lvbptr = (char *)lksb +
  					     sizeof(struct dlm_lksb);
  
  	ret = dlm_lock(conn->cc_lockspace, mode, &lksb->lksb_fsdlm,
  		       flags|DLM_LKF_NODLCKWT, name, namelen, 0,
a796d2862   Joel Becker   ocfs2: Pass lksbs...
690
  		       fsdlm_lock_ast_wrapper, lksb,
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
691
692
693
694
695
  		       fsdlm_blocking_ast_wrapper);
  	return ret;
  }
  
  static int user_dlm_unlock(struct ocfs2_cluster_connection *conn,
c0e413385   Joel Becker   ocfs2: Attach the...
696
  			   struct ocfs2_dlm_lksb *lksb,
a796d2862   Joel Becker   ocfs2: Pass lksbs...
697
  			   u32 flags)
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
698
699
700
701
  {
  	int ret;
  
  	ret = dlm_unlock(conn->cc_lockspace, lksb->lksb_fsdlm.sb_lkid,
a796d2862   Joel Becker   ocfs2: Pass lksbs...
702
  			 flags, &lksb->lksb_fsdlm, lksb);
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
703
704
  	return ret;
  }
c0e413385   Joel Becker   ocfs2: Attach the...
705
  static int user_dlm_lock_status(struct ocfs2_dlm_lksb *lksb)
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
706
707
708
  {
  	return lksb->lksb_fsdlm.sb_status;
  }
c0e413385   Joel Becker   ocfs2: Attach the...
709
  static int user_dlm_lvb_valid(struct ocfs2_dlm_lksb *lksb)
1c520dfbf   Joel Becker   ocfs2: Provide th...
710
711
712
713
714
  {
  	int invalid = lksb->lksb_fsdlm.sb_flags & DLM_SBF_VALNOTVALID;
  
  	return !invalid;
  }
c0e413385   Joel Becker   ocfs2: Attach the...
715
  static void *user_dlm_lvb(struct ocfs2_dlm_lksb *lksb)
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
716
  {
66f502a41   David Teigland   ocfs2: initialize...
717
718
719
  	if (!lksb->lksb_fsdlm.sb_lvbptr)
  		lksb->lksb_fsdlm.sb_lvbptr = (char *)lksb +
  					     sizeof(struct dlm_lksb);
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
720
721
  	return (void *)(lksb->lksb_fsdlm.sb_lvbptr);
  }
c0e413385   Joel Becker   ocfs2: Attach the...
722
  static void user_dlm_dump_lksb(struct ocfs2_dlm_lksb *lksb)
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
723
724
  {
  }
53da4939f   Mark Fasheh   ocfs2: POSIX file...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
  static int user_plock(struct ocfs2_cluster_connection *conn,
  		      u64 ino,
  		      struct file *file,
  		      int cmd,
  		      struct file_lock *fl)
  {
  	/*
  	 * This more or less just demuxes the plock request into any
  	 * one of three dlm calls.
  	 *
  	 * Internally, fs/dlm will pass these to a misc device, which
  	 * a userspace daemon will read and write to.
  	 *
  	 * For now, cancel requests (which happen internally only),
  	 * are turned into unlocks. Most of this function taken from
  	 * gfs2_lock.
  	 */
  
  	if (cmd == F_CANCELLK) {
  		cmd = F_SETLK;
  		fl->fl_type = F_UNLCK;
  	}
  
  	if (IS_GETLK(cmd))
  		return dlm_posix_get(conn->cc_lockspace, ino, file, fl);
  	else if (fl->fl_type == F_UNLCK)
  		return dlm_posix_unlock(conn->cc_lockspace, ino, file, fl);
  	else
  		return dlm_posix_lock(conn->cc_lockspace, ino, file, cmd, fl);
  }
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
  /*
   * Compare a requested locking protocol version against the current one.
   *
   * If the major numbers are different, they are incompatible.
   * If the current minor is greater than the request, they are incompatible.
   * If the current minor is less than or equal to the request, they are
   * compatible, and the requester should run at the current minor version.
   */
  static int fs_protocol_compare(struct ocfs2_protocol_version *existing,
  			       struct ocfs2_protocol_version *request)
  {
  	if (existing->pv_major != request->pv_major)
  		return 1;
  
  	if (existing->pv_minor > request->pv_minor)
  		return 1;
  
  	if (existing->pv_minor < request->pv_minor)
  		request->pv_minor = existing->pv_minor;
  
  	return 0;
  }
  
  static int user_cluster_connect(struct ocfs2_cluster_connection *conn)
  {
  	dlm_lockspace_t *fsdlm;
3a05d7961   Coly Li   ocfs2: explicit d...
781
  	struct ocfs2_live_connection *uninitialized_var(control);
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
  	int rc = 0;
  
  	BUG_ON(conn == NULL);
  
  	rc = ocfs2_live_connection_new(conn, &control);
  	if (rc)
  		goto out;
  
  	/*
  	 * running_proto must have been set before we allowed any mounts
  	 * to proceed.
  	 */
  	if (fs_protocol_compare(&running_proto, &conn->cc_version)) {
  		printk(KERN_ERR
  		       "Unable to mount with fs locking protocol version "
  		       "%u.%u because the userspace control daemon has "
  		       "negotiated %u.%u
  ",
  		       conn->cc_version.pv_major, conn->cc_version.pv_minor,
  		       running_proto.pv_major, running_proto.pv_minor);
  		rc = -EPROTO;
  		ocfs2_live_connection_drop(control);
  		goto out;
  	}
60f98d183   David Teigland   dlm: add recovery...
806
807
  	rc = dlm_new_lockspace(conn->cc_name, NULL, DLM_LSFL_FS, DLM_LVB_LEN,
  			       NULL, NULL, NULL, &fsdlm);
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
808
809
810
811
812
813
814
815
816
817
  	if (rc) {
  		ocfs2_live_connection_drop(control);
  		goto out;
  	}
  
  	conn->cc_private = control;
  	conn->cc_lockspace = fsdlm;
  out:
  	return rc;
  }
2c39450b3   Joel Becker   ocfs2: Remove ->h...
818
  static int user_cluster_disconnect(struct ocfs2_cluster_connection *conn)
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
  {
  	dlm_release_lockspace(conn->cc_lockspace, 2);
  	conn->cc_lockspace = NULL;
  	ocfs2_live_connection_drop(conn->cc_private);
  	conn->cc_private = NULL;
  	return 0;
  }
  
  static int user_cluster_this_node(unsigned int *this_node)
  {
  	int rc;
  
  	rc = ocfs2_control_get_this_node();
  	if (rc < 0)
  		return rc;
  
  	*this_node = rc;
  	return 0;
  }
a12630b18   Joel Becker   ocfs2: Rename 'us...
838
  static struct ocfs2_stack_operations ocfs2_user_plugin_ops = {
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
839
840
841
842
843
844
  	.connect	= user_cluster_connect,
  	.disconnect	= user_cluster_disconnect,
  	.this_node	= user_cluster_this_node,
  	.dlm_lock	= user_dlm_lock,
  	.dlm_unlock	= user_dlm_unlock,
  	.lock_status	= user_dlm_lock_status,
1c520dfbf   Joel Becker   ocfs2: Provide th...
845
  	.lvb_valid	= user_dlm_lvb_valid,
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
846
  	.lock_lvb	= user_dlm_lvb,
53da4939f   Mark Fasheh   ocfs2: POSIX file...
847
  	.plock		= user_plock,
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
848
849
  	.dump_lksb	= user_dlm_dump_lksb,
  };
a12630b18   Joel Becker   ocfs2: Rename 'us...
850
  static struct ocfs2_stack_plugin ocfs2_user_plugin = {
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
851
  	.sp_name	= "user",
a12630b18   Joel Becker   ocfs2: Rename 'us...
852
  	.sp_ops		= &ocfs2_user_plugin_ops,
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
853
854
  	.sp_owner	= THIS_MODULE,
  };
a12630b18   Joel Becker   ocfs2: Rename 'us...
855
  static int __init ocfs2_user_plugin_init(void)
6427a7275   Joel Becker   ocfs2: Add the oc...
856
  {
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
857
858
859
860
  	int rc;
  
  	rc = ocfs2_control_init();
  	if (!rc) {
a12630b18   Joel Becker   ocfs2: Rename 'us...
861
  		rc = ocfs2_stack_glue_register(&ocfs2_user_plugin);
cf4d8d75d   David Teigland   ocfs2: add fsdlm ...
862
863
864
865
866
  		if (rc)
  			ocfs2_control_exit();
  	}
  
  	return rc;
6427a7275   Joel Becker   ocfs2: Add the oc...
867
  }
a12630b18   Joel Becker   ocfs2: Rename 'us...
868
  static void __exit ocfs2_user_plugin_exit(void)
8adf0536c   Joel Becker   ocfs2: Add the us...
869
  {
a12630b18   Joel Becker   ocfs2: Rename 'us...
870
  	ocfs2_stack_glue_unregister(&ocfs2_user_plugin);
6427a7275   Joel Becker   ocfs2: Add the oc...
871
  	ocfs2_control_exit();
8adf0536c   Joel Becker   ocfs2: Add the us...
872
873
874
875
876
  }
  
  MODULE_AUTHOR("Oracle");
  MODULE_DESCRIPTION("ocfs2 driver for userspace cluster stacks");
  MODULE_LICENSE("GPL");
a12630b18   Joel Becker   ocfs2: Rename 'us...
877
878
  module_init(ocfs2_user_plugin_init);
  module_exit(ocfs2_user_plugin_exit);