blob: ff8d3075792478081f4c40bf9aa9cda6d8995064 [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
38 * client writes the version they would like to use. If the version tag
39 * written is unknown, -EINVAL is returned. Once the negotiation is
40 * complete, the client can start sending messages.
41 */
42
43/*
Joel Becker462c7e62008-02-18 19:40:12 -080044 * Whether or not the client has done the handshake.
45 * For now, we have just one protocol version.
46 */
47#define OCFS2_CONTROL_PROTO "T01\n"
48#define OCFS2_CONTROL_PROTO_LEN 4
49#define OCFS2_CONTROL_HANDSHAKE_INVALID (0)
50#define OCFS2_CONTROL_HANDSHAKE_READ (1)
51#define OCFS2_CONTROL_HANDSHAKE_VALID (2)
52
53/*
Joel Becker6427a722008-02-18 19:23:28 -080054 * ocfs2_live_connection is refcounted because the filesystem and
55 * miscdevice sides can detach in different order. Let's just be safe.
56 */
57struct ocfs2_live_connection {
58 struct list_head oc_list;
59 struct ocfs2_cluster_connection *oc_conn;
60};
61
Joel Becker462c7e62008-02-18 19:40:12 -080062struct ocfs2_control_private {
63 struct list_head op_list;
64 int op_state;
65};
66
Joel Becker6427a722008-02-18 19:23:28 -080067static atomic_t ocfs2_control_opened;
68
69static LIST_HEAD(ocfs2_live_connection_list);
Joel Becker462c7e62008-02-18 19:40:12 -080070static LIST_HEAD(ocfs2_control_private_list);
Joel Becker6427a722008-02-18 19:23:28 -080071static DEFINE_MUTEX(ocfs2_control_lock);
72
Joel Becker462c7e62008-02-18 19:40:12 -080073static inline void ocfs2_control_set_handshake_state(struct file *file,
74 int state)
75{
76 struct ocfs2_control_private *p = file->private_data;
77 p->op_state = state;
78}
79
80static inline int ocfs2_control_get_handshake_state(struct file *file)
81{
82 struct ocfs2_control_private *p = file->private_data;
83 return p->op_state;
84}
85
Joel Becker6427a722008-02-18 19:23:28 -080086static struct ocfs2_live_connection *ocfs2_connection_find(const char *name)
87{
88 size_t len = strlen(name);
89 struct ocfs2_live_connection *c;
90
91 BUG_ON(!mutex_is_locked(&ocfs2_control_lock));
92
93 list_for_each_entry(c, &ocfs2_live_connection_list, oc_list) {
94 if ((c->oc_conn->cc_namelen == len) &&
95 !strncmp(c->oc_conn->cc_name, name, len))
96 return c;
97 }
98
99 return c;
100}
101
102/*
103 * ocfs2_live_connection structures are created underneath the ocfs2
104 * mount path. Since the VFS prevents multiple calls to
105 * fill_super(), we can't get dupes here.
106 */
107static int ocfs2_live_connection_new(struct ocfs2_cluster_connection *conn,
108 struct ocfs2_live_connection **c_ret)
109{
110 int rc = 0;
111 struct ocfs2_live_connection *c;
112
113 c = kzalloc(sizeof(struct ocfs2_live_connection), GFP_KERNEL);
114 if (!c)
115 return -ENOMEM;
116
117 mutex_lock(&ocfs2_control_lock);
118 c->oc_conn = conn;
119
120 if (atomic_read(&ocfs2_control_opened))
121 list_add(&c->oc_list, &ocfs2_live_connection_list);
122 else {
123 printk(KERN_ERR
124 "ocfs2: Userspace control daemon is not present\n");
125 rc = -ESRCH;
126 }
127
128 mutex_unlock(&ocfs2_control_lock);
129
130 if (!rc)
131 *c_ret = c;
132 else
133 kfree(c);
134
135 return rc;
136}
137
138/*
139 * This function disconnects the cluster connection from ocfs2_control.
140 * Afterwards, userspace can't affect the cluster connection.
141 */
142static void ocfs2_live_connection_drop(struct ocfs2_live_connection *c)
143{
144 mutex_lock(&ocfs2_control_lock);
145 list_del_init(&c->oc_list);
146 c->oc_conn = NULL;
147 mutex_unlock(&ocfs2_control_lock);
148
149 kfree(c);
150}
151
Joel Becker462c7e62008-02-18 19:40:12 -0800152static ssize_t ocfs2_control_cfu(char *target, size_t target_len,
153 const char __user *buf, size_t count)
154{
155 /* The T01 expects write(2) calls to have exactly one command */
156 if (count != target_len)
157 return -EINVAL;
158
159 if (copy_from_user(target, buf, target_len))
160 return -EFAULT;
161
162 return count;
163}
164
165static ssize_t ocfs2_control_validate_handshake(struct file *file,
166 const char __user *buf,
167 size_t count)
168{
169 ssize_t ret;
170 char kbuf[OCFS2_CONTROL_PROTO_LEN];
171
172 ret = ocfs2_control_cfu(kbuf, OCFS2_CONTROL_PROTO_LEN,
173 buf, count);
174 if (ret != count)
175 return ret;
176
177 if (strncmp(kbuf, OCFS2_CONTROL_PROTO, OCFS2_CONTROL_PROTO_LEN))
178 return -EINVAL;
179
180 atomic_inc(&ocfs2_control_opened);
181 ocfs2_control_set_handshake_state(file,
182 OCFS2_CONTROL_HANDSHAKE_VALID);
183
184
185 return count;
186}
187
Joel Becker6427a722008-02-18 19:23:28 -0800188
189static ssize_t ocfs2_control_write(struct file *file,
190 const char __user *buf,
191 size_t count,
192 loff_t *ppos)
Joel Becker8adf0532007-11-28 14:38:40 -0800193{
Joel Becker462c7e62008-02-18 19:40:12 -0800194 ssize_t ret;
195
196 switch (ocfs2_control_get_handshake_state(file)) {
197 case OCFS2_CONTROL_HANDSHAKE_INVALID:
198 ret = -EINVAL;
199 break;
200
201 case OCFS2_CONTROL_HANDSHAKE_READ:
202 ret = ocfs2_control_validate_handshake(file, buf,
203 count);
204 break;
205
206 case OCFS2_CONTROL_HANDSHAKE_VALID:
207 ret = count; /* XXX */
208 break;
209
210 default:
211 BUG();
212 ret = -EIO;
213 break;
214 }
215
216 return ret;
Joel Becker8adf0532007-11-28 14:38:40 -0800217}
218
Joel Becker462c7e62008-02-18 19:40:12 -0800219/*
220 * This is a naive version. If we ever have a new protocol, we'll expand
221 * it. Probably using seq_file.
222 */
Joel Becker6427a722008-02-18 19:23:28 -0800223static ssize_t ocfs2_control_read(struct file *file,
224 char __user *buf,
225 size_t count,
226 loff_t *ppos)
227{
Joel Becker462c7e62008-02-18 19:40:12 -0800228 char *proto_string = OCFS2_CONTROL_PROTO;
229 size_t to_write = 0;
230
231 if (*ppos >= OCFS2_CONTROL_PROTO_LEN)
232 return 0;
233
234 to_write = OCFS2_CONTROL_PROTO_LEN - *ppos;
235 if (to_write > count)
236 to_write = count;
237 if (copy_to_user(buf, proto_string + *ppos, to_write))
238 return -EFAULT;
239
240 *ppos += to_write;
241
242 /* Have we read the whole protocol list? */
243 if (*ppos >= OCFS2_CONTROL_PROTO_LEN)
244 ocfs2_control_set_handshake_state(file,
245 OCFS2_CONTROL_HANDSHAKE_READ);
246
247 return to_write;
Joel Becker6427a722008-02-18 19:23:28 -0800248}
249
250static int ocfs2_control_release(struct inode *inode, struct file *file)
251{
Joel Becker462c7e62008-02-18 19:40:12 -0800252 struct ocfs2_control_private *p = file->private_data;
253
254 mutex_lock(&ocfs2_control_lock);
255
256 if (ocfs2_control_get_handshake_state(file) !=
257 OCFS2_CONTROL_HANDSHAKE_VALID)
258 goto out;
259
Joel Becker6427a722008-02-18 19:23:28 -0800260 if (atomic_dec_and_test(&ocfs2_control_opened)) {
Joel Becker6427a722008-02-18 19:23:28 -0800261 if (!list_empty(&ocfs2_live_connection_list)) {
262 /* XXX: Do bad things! */
263 printk(KERN_ERR
264 "ocfs2: Unexpected release of ocfs2_control!\n"
265 " Loss of cluster connection requires "
266 "an emergency restart!\n");
267 emergency_restart();
268 }
Joel Becker6427a722008-02-18 19:23:28 -0800269 }
270
Joel Becker462c7e62008-02-18 19:40:12 -0800271out:
272 list_del_init(&p->op_list);
273 file->private_data = NULL;
274
275 mutex_unlock(&ocfs2_control_lock);
276
277 kfree(p);
278
Joel Becker6427a722008-02-18 19:23:28 -0800279 return 0;
280}
281
282static int ocfs2_control_open(struct inode *inode, struct file *file)
283{
Joel Becker462c7e62008-02-18 19:40:12 -0800284 struct ocfs2_control_private *p;
285
286 p = kzalloc(sizeof(struct ocfs2_control_private), GFP_KERNEL);
287 if (!p)
288 return -ENOMEM;
289
290 mutex_lock(&ocfs2_control_lock);
291 file->private_data = p;
292 list_add(&p->op_list, &ocfs2_control_private_list);
293 mutex_unlock(&ocfs2_control_lock);
Joel Becker6427a722008-02-18 19:23:28 -0800294
295 return 0;
296}
297
298static const struct file_operations ocfs2_control_fops = {
299 .open = ocfs2_control_open,
300 .release = ocfs2_control_release,
301 .read = ocfs2_control_read,
302 .write = ocfs2_control_write,
303 .owner = THIS_MODULE,
304};
305
306struct miscdevice ocfs2_control_device = {
307 .minor = MISC_DYNAMIC_MINOR,
308 .name = "ocfs2_control",
309 .fops = &ocfs2_control_fops,
310};
311
312static int ocfs2_control_init(void)
313{
314 int rc;
315
316 atomic_set(&ocfs2_control_opened, 0);
317
318 rc = misc_register(&ocfs2_control_device);
319 if (rc)
320 printk(KERN_ERR
321 "ocfs2: Unable to register ocfs2_control device "
322 "(errno %d)\n",
323 -rc);
324
325 return rc;
326}
327
328static void ocfs2_control_exit(void)
329{
330 int rc;
331
332 rc = misc_deregister(&ocfs2_control_device);
333 if (rc)
334 printk(KERN_ERR
335 "ocfs2: Unable to deregister ocfs2_control device "
336 "(errno %d)\n",
337 -rc);
338}
339
340static int __init user_stack_init(void)
341{
342 return ocfs2_control_init();
343}
344
Joel Becker8adf0532007-11-28 14:38:40 -0800345static void __exit user_stack_exit(void)
346{
Joel Becker6427a722008-02-18 19:23:28 -0800347 ocfs2_control_exit();
Joel Becker8adf0532007-11-28 14:38:40 -0800348}
349
350MODULE_AUTHOR("Oracle");
351MODULE_DESCRIPTION("ocfs2 driver for userspace cluster stacks");
352MODULE_LICENSE("GPL");
353module_init(user_stack_init);
354module_exit(user_stack_exit);