blob: de982c11e69bd3f0f833b474bb0a7f2ac2ac98f7 [file] [log] [blame]
Joel Becker8adf0532007-11-28 14:38:40 -08001/* -*- mode: c; c-basic-offset: 8; -*-
2 * vim: noexpandtab sw=8 ts=8 sts=0:
3 *
4 * stack_user.c
5 *
6 * Code which interfaces ocfs2 with fs/dlm and a userspace stack.
7 *
8 * Copyright (C) 2007 Oracle. All rights reserved.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public
12 * License as published by the Free Software Foundation, version 2.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 */
19
20#include <linux/module.h>
Joel Becker6427a722008-02-18 19:23:28 -080021#include <linux/fs.h>
22#include <linux/miscdevice.h>
23#include <linux/mutex.h>
24#include <linux/reboot.h>
Joel Becker462c7e62008-02-18 19:40:12 -080025#include <asm/uaccess.h>
Joel Becker8adf0532007-11-28 14:38:40 -080026
27#include "stackglue.h"
28
29
Joel Becker6427a722008-02-18 19:23:28 -080030/*
31 * The control protocol starts with a handshake. Until the handshake
32 * is complete, the control device will fail all write(2)s.
33 *
34 * The handshake is simple. First, the client reads until EOF. Each line
35 * of output is a supported protocol tag. All protocol tags are a single
36 * character followed by a two hex digit version number. Currently the
37 * only things supported is T01, for "Text-base version 0x01". Next, the
Joel Beckerde870ef2008-02-18 17:07:09 -080038 * client writes the version they would like to use, including the newline.
39 * Thus, the protocol tag is 'T01\n'. If the version tag written is
40 * unknown, -EINVAL is returned. Once the negotiation is complete, the
41 * client can start sending messages.
42 *
Joel Beckerd4b95ee2008-02-20 15:39:44 -080043 * The T01 protocol has three messages. First is the "SETN" message.
Joel Becker3cfd4ab2008-02-20 14:44:34 -080044 * It has the following syntax:
45 *
46 * SETN<space><8-char-hex-nodenum><newline>
47 *
48 * This is 14 characters.
49 *
50 * The "SETN" message must be the first message following the protocol.
51 * It tells ocfs2_control the local node number.
52 *
Joel Beckerd4b95ee2008-02-20 15:39:44 -080053 * Next comes the "SETV" message. It has the following syntax:
54 *
55 * SETV<space><2-char-hex-major><space><2-char-hex-minor><newline>
56 *
57 * This is 11 characters.
58 *
59 * The "SETV" message sets the filesystem locking protocol version as
60 * negotiated by the client. The client negotiates based on the maximum
61 * version advertised in /sys/fs/ocfs2/max_locking_protocol. The major
62 * number from the "SETV" message must match
63 * user_stack.sp_proto->lp_max_version.pv_major, and the minor number
64 * must be less than or equal to ...->lp_max_version.pv_minor.
65 *
66 * Once this information has been set, mounts will be allowed. From this
67 * point on, the "DOWN" message can be sent for node down notification.
68 * It has the following syntax:
Joel Beckerde870ef2008-02-18 17:07:09 -080069 *
70 * DOWN<space><32-char-cap-hex-uuid><space><8-char-hex-nodenum><newline>
71 *
72 * eg:
73 *
74 * DOWN 632A924FDD844190BDA93C0DF6B94899 00000001\n
75 *
76 * This is 47 characters.
Joel Becker6427a722008-02-18 19:23:28 -080077 */
78
79/*
Joel Becker462c7e62008-02-18 19:40:12 -080080 * Whether or not the client has done the handshake.
81 * For now, we have just one protocol version.
82 */
83#define OCFS2_CONTROL_PROTO "T01\n"
84#define OCFS2_CONTROL_PROTO_LEN 4
Joel Becker3cfd4ab2008-02-20 14:44:34 -080085
86/* Handshake states */
Joel Becker462c7e62008-02-18 19:40:12 -080087#define OCFS2_CONTROL_HANDSHAKE_INVALID (0)
88#define OCFS2_CONTROL_HANDSHAKE_READ (1)
Joel Becker3cfd4ab2008-02-20 14:44:34 -080089#define OCFS2_CONTROL_HANDSHAKE_PROTOCOL (2)
90#define OCFS2_CONTROL_HANDSHAKE_VALID (3)
91
92/* Messages */
93#define OCFS2_CONTROL_MESSAGE_OP_LEN 4
94#define OCFS2_CONTROL_MESSAGE_SETNODE_OP "SETN"
95#define OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN 14
Joel Beckerd4b95ee2008-02-20 15:39:44 -080096#define OCFS2_CONTROL_MESSAGE_SETVERSION_OP "SETV"
97#define OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN 11
Joel Becker3cfd4ab2008-02-20 14:44:34 -080098#define OCFS2_CONTROL_MESSAGE_DOWN_OP "DOWN"
Joel Beckerde870ef2008-02-18 17:07:09 -080099#define OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN 47
100#define OCFS2_TEXT_UUID_LEN 32
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800101#define OCFS2_CONTROL_MESSAGE_VERNUM_LEN 2
Joel Beckerde870ef2008-02-18 17:07:09 -0800102#define OCFS2_CONTROL_MESSAGE_NODENUM_LEN 8
Joel Becker462c7e62008-02-18 19:40:12 -0800103
104/*
Joel Becker6427a722008-02-18 19:23:28 -0800105 * ocfs2_live_connection is refcounted because the filesystem and
106 * miscdevice sides can detach in different order. Let's just be safe.
107 */
108struct ocfs2_live_connection {
109 struct list_head oc_list;
110 struct ocfs2_cluster_connection *oc_conn;
111};
112
Joel Becker462c7e62008-02-18 19:40:12 -0800113struct ocfs2_control_private {
114 struct list_head op_list;
115 int op_state;
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800116 int op_this_node;
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800117 struct ocfs2_protocol_version op_proto;
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800118};
119
120/* SETN<space><8-char-hex-nodenum><newline> */
121struct ocfs2_control_message_setn {
122 char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
123 char space;
124 char nodestr[OCFS2_CONTROL_MESSAGE_NODENUM_LEN];
125 char newline;
126};
127
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800128/* SETV<space><2-char-hex-major><space><2-char-hex-minor><newline> */
129struct ocfs2_control_message_setv {
130 char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
131 char space1;
132 char major[OCFS2_CONTROL_MESSAGE_VERNUM_LEN];
133 char space2;
134 char minor[OCFS2_CONTROL_MESSAGE_VERNUM_LEN];
135 char newline;
136};
137
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800138/* DOWN<space><32-char-cap-hex-uuid><space><8-char-hex-nodenum><newline> */
139struct ocfs2_control_message_down {
140 char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
141 char space1;
142 char uuid[OCFS2_TEXT_UUID_LEN];
143 char space2;
144 char nodestr[OCFS2_CONTROL_MESSAGE_NODENUM_LEN];
145 char newline;
146};
147
148union ocfs2_control_message {
149 char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
150 struct ocfs2_control_message_setn u_setn;
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800151 struct ocfs2_control_message_setv u_setv;
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800152 struct ocfs2_control_message_down u_down;
Joel Becker462c7e62008-02-18 19:40:12 -0800153};
154
Joel Becker6427a722008-02-18 19:23:28 -0800155static atomic_t ocfs2_control_opened;
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800156static int ocfs2_control_this_node = -1;
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800157static struct ocfs2_protocol_version running_proto;
Joel Becker6427a722008-02-18 19:23:28 -0800158
159static LIST_HEAD(ocfs2_live_connection_list);
Joel Becker462c7e62008-02-18 19:40:12 -0800160static LIST_HEAD(ocfs2_control_private_list);
Joel Becker6427a722008-02-18 19:23:28 -0800161static DEFINE_MUTEX(ocfs2_control_lock);
162
Joel Becker462c7e62008-02-18 19:40:12 -0800163static inline void ocfs2_control_set_handshake_state(struct file *file,
164 int state)
165{
166 struct ocfs2_control_private *p = file->private_data;
167 p->op_state = state;
168}
169
170static inline int ocfs2_control_get_handshake_state(struct file *file)
171{
172 struct ocfs2_control_private *p = file->private_data;
173 return p->op_state;
174}
175
Joel Becker6427a722008-02-18 19:23:28 -0800176static struct ocfs2_live_connection *ocfs2_connection_find(const char *name)
177{
178 size_t len = strlen(name);
179 struct ocfs2_live_connection *c;
180
181 BUG_ON(!mutex_is_locked(&ocfs2_control_lock));
182
183 list_for_each_entry(c, &ocfs2_live_connection_list, oc_list) {
184 if ((c->oc_conn->cc_namelen == len) &&
185 !strncmp(c->oc_conn->cc_name, name, len))
186 return c;
187 }
188
189 return c;
190}
191
192/*
193 * ocfs2_live_connection structures are created underneath the ocfs2
194 * mount path. Since the VFS prevents multiple calls to
195 * fill_super(), we can't get dupes here.
196 */
197static int ocfs2_live_connection_new(struct ocfs2_cluster_connection *conn,
198 struct ocfs2_live_connection **c_ret)
199{
200 int rc = 0;
201 struct ocfs2_live_connection *c;
202
203 c = kzalloc(sizeof(struct ocfs2_live_connection), GFP_KERNEL);
204 if (!c)
205 return -ENOMEM;
206
207 mutex_lock(&ocfs2_control_lock);
208 c->oc_conn = conn;
209
210 if (atomic_read(&ocfs2_control_opened))
211 list_add(&c->oc_list, &ocfs2_live_connection_list);
212 else {
213 printk(KERN_ERR
214 "ocfs2: Userspace control daemon is not present\n");
215 rc = -ESRCH;
216 }
217
218 mutex_unlock(&ocfs2_control_lock);
219
220 if (!rc)
221 *c_ret = c;
222 else
223 kfree(c);
224
225 return rc;
226}
227
228/*
229 * This function disconnects the cluster connection from ocfs2_control.
230 * Afterwards, userspace can't affect the cluster connection.
231 */
232static void ocfs2_live_connection_drop(struct ocfs2_live_connection *c)
233{
234 mutex_lock(&ocfs2_control_lock);
235 list_del_init(&c->oc_list);
236 c->oc_conn = NULL;
237 mutex_unlock(&ocfs2_control_lock);
238
239 kfree(c);
240}
241
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800242static int ocfs2_control_cfu(void *target, size_t target_len,
243 const char __user *buf, size_t count)
Joel Becker462c7e62008-02-18 19:40:12 -0800244{
245 /* The T01 expects write(2) calls to have exactly one command */
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800246 if ((count != target_len) ||
247 (count > sizeof(union ocfs2_control_message)))
Joel Becker462c7e62008-02-18 19:40:12 -0800248 return -EINVAL;
249
250 if (copy_from_user(target, buf, target_len))
251 return -EFAULT;
252
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800253 return 0;
Joel Becker462c7e62008-02-18 19:40:12 -0800254}
255
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800256static ssize_t ocfs2_control_validate_protocol(struct file *file,
257 const char __user *buf,
258 size_t count)
Joel Becker462c7e62008-02-18 19:40:12 -0800259{
260 ssize_t ret;
261 char kbuf[OCFS2_CONTROL_PROTO_LEN];
262
263 ret = ocfs2_control_cfu(kbuf, OCFS2_CONTROL_PROTO_LEN,
264 buf, count);
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800265 if (ret)
Joel Becker462c7e62008-02-18 19:40:12 -0800266 return ret;
267
268 if (strncmp(kbuf, OCFS2_CONTROL_PROTO, OCFS2_CONTROL_PROTO_LEN))
269 return -EINVAL;
270
Joel Becker462c7e62008-02-18 19:40:12 -0800271 ocfs2_control_set_handshake_state(file,
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800272 OCFS2_CONTROL_HANDSHAKE_PROTOCOL);
Joel Becker462c7e62008-02-18 19:40:12 -0800273
274 return count;
275}
276
Joel Beckerde870ef2008-02-18 17:07:09 -0800277static void ocfs2_control_send_down(const char *uuid,
278 int nodenum)
279{
280 struct ocfs2_live_connection *c;
281
282 mutex_lock(&ocfs2_control_lock);
283
284 c = ocfs2_connection_find(uuid);
285 if (c) {
286 BUG_ON(c->oc_conn == NULL);
287 c->oc_conn->cc_recovery_handler(nodenum,
288 c->oc_conn->cc_recovery_data);
289 }
290
291 mutex_unlock(&ocfs2_control_lock);
292}
293
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800294/*
295 * Called whenever configuration elements are sent to /dev/ocfs2_control.
296 * If all configuration elements are present, try to set the global
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800297 * values. If there is a problem, return an error. Skip any missing
298 * elements, and only bump ocfs2_control_opened when we have all elements
299 * and are successful.
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800300 */
301static int ocfs2_control_install_private(struct file *file)
Joel Beckerde870ef2008-02-18 17:07:09 -0800302{
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800303 int rc = 0;
304 int set_p = 1;
305 struct ocfs2_control_private *p = file->private_data;
306
307 BUG_ON(p->op_state != OCFS2_CONTROL_HANDSHAKE_PROTOCOL);
308
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800309 mutex_lock(&ocfs2_control_lock);
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800310
311 if (p->op_this_node < 0) {
312 set_p = 0;
313 } else if ((ocfs2_control_this_node >= 0) &&
314 (ocfs2_control_this_node != p->op_this_node)) {
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800315 rc = -EINVAL;
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800316 goto out_unlock;
317 }
318
319 if (!p->op_proto.pv_major) {
320 set_p = 0;
321 } else if (!list_empty(&ocfs2_live_connection_list) &&
322 ((running_proto.pv_major != p->op_proto.pv_major) ||
323 (running_proto.pv_minor != p->op_proto.pv_minor))) {
324 rc = -EINVAL;
325 goto out_unlock;
326 }
327
328 if (set_p) {
329 ocfs2_control_this_node = p->op_this_node;
330 running_proto.pv_major = p->op_proto.pv_major;
331 running_proto.pv_minor = p->op_proto.pv_minor;
332 }
333
334out_unlock:
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800335 mutex_unlock(&ocfs2_control_lock);
336
337 if (!rc && set_p) {
338 /* We set the global values successfully */
339 atomic_inc(&ocfs2_control_opened);
340 ocfs2_control_set_handshake_state(file,
341 OCFS2_CONTROL_HANDSHAKE_VALID);
342 }
343
344 return rc;
345}
346
347static int ocfs2_control_do_setnode_msg(struct file *file,
348 struct ocfs2_control_message_setn *msg)
349{
Joel Beckerde870ef2008-02-18 17:07:09 -0800350 long nodenum;
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800351 char *ptr = NULL;
352 struct ocfs2_control_private *p = file->private_data;
Joel Beckerde870ef2008-02-18 17:07:09 -0800353
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800354 if (ocfs2_control_get_handshake_state(file) !=
355 OCFS2_CONTROL_HANDSHAKE_PROTOCOL)
Joel Beckerde870ef2008-02-18 17:07:09 -0800356 return -EINVAL;
357
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800358 if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_SETNODE_OP,
359 OCFS2_CONTROL_MESSAGE_OP_LEN))
Joel Beckerde870ef2008-02-18 17:07:09 -0800360 return -EINVAL;
Joel Beckerde870ef2008-02-18 17:07:09 -0800361
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800362 if ((msg->space != ' ') || (msg->newline != '\n'))
363 return -EINVAL;
364 msg->space = msg->newline = '\0';
365
366 nodenum = simple_strtol(msg->nodestr, &ptr, 16);
367 if (!ptr || *ptr)
368 return -EINVAL;
369
370 if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||
371 (nodenum > INT_MAX) || (nodenum < 0))
372 return -ERANGE;
373 p->op_this_node = nodenum;
374
375 return ocfs2_control_install_private(file);
376}
377
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800378static int ocfs2_control_do_setversion_msg(struct file *file,
379 struct ocfs2_control_message_setv *msg)
380 {
381 long major, minor;
382 char *ptr = NULL;
383 struct ocfs2_control_private *p = file->private_data;
384 struct ocfs2_protocol_version *max =
385 &user_stack.sp_proto->lp_max_version;
386
387 if (ocfs2_control_get_handshake_state(file) !=
388 OCFS2_CONTROL_HANDSHAKE_PROTOCOL)
389 return -EINVAL;
390
391 if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_SETVERSION_OP,
392 OCFS2_CONTROL_MESSAGE_OP_LEN))
393 return -EINVAL;
394
395 if ((msg->space1 != ' ') || (msg->space2 != ' ') ||
396 (msg->newline != '\n'))
397 return -EINVAL;
398 msg->space1 = msg->space2 = msg->newline = '\0';
399
400 major = simple_strtol(msg->major, &ptr, 16);
401 if (!ptr || *ptr)
402 return -EINVAL;
403 minor = simple_strtol(msg->minor, &ptr, 16);
404 if (!ptr || *ptr)
405 return -EINVAL;
406
407 /*
408 * The major must be between 1 and 255, inclusive. The minor
409 * must be between 0 and 255, inclusive. The version passed in
410 * must be within the maximum version supported by the filesystem.
411 */
412 if ((major == LONG_MIN) || (major == LONG_MAX) ||
413 (major > (u8)-1) || (major < 1))
414 return -ERANGE;
415 if ((minor == LONG_MIN) || (minor == LONG_MAX) ||
416 (minor > (u8)-1) || (minor < 0))
417 return -ERANGE;
418 if ((major != max->pv_major) ||
419 (minor > max->pv_minor))
420 return -EINVAL;
421
422 p->op_proto.pv_major = major;
423 p->op_proto.pv_minor = minor;
424
425 return ocfs2_control_install_private(file);
426}
427
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800428static int ocfs2_control_do_down_msg(struct file *file,
429 struct ocfs2_control_message_down *msg)
430{
431 long nodenum;
432 char *p = NULL;
433
434 if (ocfs2_control_get_handshake_state(file) !=
435 OCFS2_CONTROL_HANDSHAKE_VALID)
436 return -EINVAL;
437
438 if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_DOWN_OP,
439 OCFS2_CONTROL_MESSAGE_OP_LEN))
440 return -EINVAL;
441
442 if ((msg->space1 != ' ') || (msg->space2 != ' ') ||
443 (msg->newline != '\n'))
444 return -EINVAL;
445 msg->space1 = msg->space2 = msg->newline = '\0';
446
447 nodenum = simple_strtol(msg->nodestr, &p, 16);
Joel Beckerde870ef2008-02-18 17:07:09 -0800448 if (!p || *p)
449 return -EINVAL;
450
451 if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||
452 (nodenum > INT_MAX) || (nodenum < 0))
453 return -ERANGE;
454
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800455 ocfs2_control_send_down(msg->uuid, nodenum);
Joel Beckerde870ef2008-02-18 17:07:09 -0800456
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800457 return 0;
458}
459
460static ssize_t ocfs2_control_message(struct file *file,
461 const char __user *buf,
462 size_t count)
463{
464 ssize_t ret;
465 union ocfs2_control_message msg;
466
467 /* Try to catch padding issues */
468 WARN_ON(offsetof(struct ocfs2_control_message_down, uuid) !=
469 (sizeof(msg.u_down.tag) + sizeof(msg.u_down.space1)));
470
471 memset(&msg, 0, sizeof(union ocfs2_control_message));
472 ret = ocfs2_control_cfu(&msg, count, buf, count);
473 if (ret)
474 goto out;
475
476 if ((count == OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN) &&
477 !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_SETNODE_OP,
478 OCFS2_CONTROL_MESSAGE_OP_LEN))
479 ret = ocfs2_control_do_setnode_msg(file, &msg.u_setn);
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800480 else if ((count == OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN) &&
481 !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_SETVERSION_OP,
482 OCFS2_CONTROL_MESSAGE_OP_LEN))
483 ret = ocfs2_control_do_setversion_msg(file, &msg.u_setv);
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800484 else if ((count == OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN) &&
485 !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_DOWN_OP,
486 OCFS2_CONTROL_MESSAGE_OP_LEN))
487 ret = ocfs2_control_do_down_msg(file, &msg.u_down);
488 else
489 ret = -EINVAL;
490
491out:
492 return ret ? ret : count;
Joel Beckerde870ef2008-02-18 17:07:09 -0800493}
Joel Becker6427a722008-02-18 19:23:28 -0800494
495static ssize_t ocfs2_control_write(struct file *file,
496 const char __user *buf,
497 size_t count,
498 loff_t *ppos)
Joel Becker8adf0532007-11-28 14:38:40 -0800499{
Joel Becker462c7e62008-02-18 19:40:12 -0800500 ssize_t ret;
501
502 switch (ocfs2_control_get_handshake_state(file)) {
503 case OCFS2_CONTROL_HANDSHAKE_INVALID:
504 ret = -EINVAL;
505 break;
506
507 case OCFS2_CONTROL_HANDSHAKE_READ:
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800508 ret = ocfs2_control_validate_protocol(file, buf,
509 count);
Joel Becker462c7e62008-02-18 19:40:12 -0800510 break;
511
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800512 case OCFS2_CONTROL_HANDSHAKE_PROTOCOL:
Joel Becker462c7e62008-02-18 19:40:12 -0800513 case OCFS2_CONTROL_HANDSHAKE_VALID:
Joel Beckerde870ef2008-02-18 17:07:09 -0800514 ret = ocfs2_control_message(file, buf, count);
Joel Becker462c7e62008-02-18 19:40:12 -0800515 break;
516
517 default:
518 BUG();
519 ret = -EIO;
520 break;
521 }
522
523 return ret;
Joel Becker8adf0532007-11-28 14:38:40 -0800524}
525
Joel Becker462c7e62008-02-18 19:40:12 -0800526/*
527 * This is a naive version. If we ever have a new protocol, we'll expand
528 * it. Probably using seq_file.
529 */
Joel Becker6427a722008-02-18 19:23:28 -0800530static ssize_t ocfs2_control_read(struct file *file,
531 char __user *buf,
532 size_t count,
533 loff_t *ppos)
534{
Joel Becker462c7e62008-02-18 19:40:12 -0800535 char *proto_string = OCFS2_CONTROL_PROTO;
536 size_t to_write = 0;
537
538 if (*ppos >= OCFS2_CONTROL_PROTO_LEN)
539 return 0;
540
541 to_write = OCFS2_CONTROL_PROTO_LEN - *ppos;
542 if (to_write > count)
543 to_write = count;
544 if (copy_to_user(buf, proto_string + *ppos, to_write))
545 return -EFAULT;
546
547 *ppos += to_write;
548
549 /* Have we read the whole protocol list? */
550 if (*ppos >= OCFS2_CONTROL_PROTO_LEN)
551 ocfs2_control_set_handshake_state(file,
552 OCFS2_CONTROL_HANDSHAKE_READ);
553
554 return to_write;
Joel Becker6427a722008-02-18 19:23:28 -0800555}
556
557static int ocfs2_control_release(struct inode *inode, struct file *file)
558{
Joel Becker462c7e62008-02-18 19:40:12 -0800559 struct ocfs2_control_private *p = file->private_data;
560
561 mutex_lock(&ocfs2_control_lock);
562
563 if (ocfs2_control_get_handshake_state(file) !=
564 OCFS2_CONTROL_HANDSHAKE_VALID)
565 goto out;
566
Joel Becker6427a722008-02-18 19:23:28 -0800567 if (atomic_dec_and_test(&ocfs2_control_opened)) {
Joel Becker6427a722008-02-18 19:23:28 -0800568 if (!list_empty(&ocfs2_live_connection_list)) {
569 /* XXX: Do bad things! */
570 printk(KERN_ERR
571 "ocfs2: Unexpected release of ocfs2_control!\n"
572 " Loss of cluster connection requires "
573 "an emergency restart!\n");
574 emergency_restart();
575 }
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800576 /*
577 * Last valid close clears the node number and resets
578 * the locking protocol version
579 */
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800580 ocfs2_control_this_node = -1;
Joel Beckerd4b95ee2008-02-20 15:39:44 -0800581 running_proto.pv_major = 0;
582 running_proto.pv_major = 0;
Joel Becker6427a722008-02-18 19:23:28 -0800583 }
584
Joel Becker462c7e62008-02-18 19:40:12 -0800585out:
586 list_del_init(&p->op_list);
587 file->private_data = NULL;
588
589 mutex_unlock(&ocfs2_control_lock);
590
591 kfree(p);
592
Joel Becker6427a722008-02-18 19:23:28 -0800593 return 0;
594}
595
596static int ocfs2_control_open(struct inode *inode, struct file *file)
597{
Joel Becker462c7e62008-02-18 19:40:12 -0800598 struct ocfs2_control_private *p;
599
600 p = kzalloc(sizeof(struct ocfs2_control_private), GFP_KERNEL);
601 if (!p)
602 return -ENOMEM;
Joel Becker3cfd4ab2008-02-20 14:44:34 -0800603 p->op_this_node = -1;
Joel Becker462c7e62008-02-18 19:40:12 -0800604
605 mutex_lock(&ocfs2_control_lock);
606 file->private_data = p;
607 list_add(&p->op_list, &ocfs2_control_private_list);
608 mutex_unlock(&ocfs2_control_lock);
Joel Becker6427a722008-02-18 19:23:28 -0800609
610 return 0;
611}
612
613static const struct file_operations ocfs2_control_fops = {
614 .open = ocfs2_control_open,
615 .release = ocfs2_control_release,
616 .read = ocfs2_control_read,
617 .write = ocfs2_control_write,
618 .owner = THIS_MODULE,
619};
620
621struct miscdevice ocfs2_control_device = {
622 .minor = MISC_DYNAMIC_MINOR,
623 .name = "ocfs2_control",
624 .fops = &ocfs2_control_fops,
625};
626
627static int ocfs2_control_init(void)
628{
629 int rc;
630
631 atomic_set(&ocfs2_control_opened, 0);
632
633 rc = misc_register(&ocfs2_control_device);
634 if (rc)
635 printk(KERN_ERR
636 "ocfs2: Unable to register ocfs2_control device "
637 "(errno %d)\n",
638 -rc);
639
640 return rc;
641}
642
643static void ocfs2_control_exit(void)
644{
645 int rc;
646
647 rc = misc_deregister(&ocfs2_control_device);
648 if (rc)
649 printk(KERN_ERR
650 "ocfs2: Unable to deregister ocfs2_control device "
651 "(errno %d)\n",
652 -rc);
653}
654
655static int __init user_stack_init(void)
656{
657 return ocfs2_control_init();
658}
659
Joel Becker8adf0532007-11-28 14:38:40 -0800660static void __exit user_stack_exit(void)
661{
Joel Becker6427a722008-02-18 19:23:28 -0800662 ocfs2_control_exit();
Joel Becker8adf0532007-11-28 14:38:40 -0800663}
664
665MODULE_AUTHOR("Oracle");
666MODULE_DESCRIPTION("ocfs2 driver for userspace cluster stacks");
667MODULE_LICENSE("GPL");
668module_init(user_stack_init);
669module_exit(user_stack_exit);