aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2008-02-18 22:40:12 -0500
committerMark Fasheh <mfasheh@suse.com>2008-04-18 11:56:06 -0400
commit462c7e6a257e547eebe1648396cf7c45e684091b (patch)
treed7785bd3a40d9ce5964b426cca6a1451bc5979a4 /fs/ocfs2
parent6427a727557d9c964b7b162ae11bb156e2c501d5 (diff)
ocfs2: Start the ocfs2_control handshake.
When a control daemon opens the ocfs2_control device, it must perform a handshake to tell the filesystem it is something capable of monitoring cluster status. Only after the handshake is complete will the filesystem allow mounts. This is the first part of the handshake. The daemon reads all supported ocfs2_control protocols, then writes in the protocol it will use. Signed-off-by: Joel Becker <joel.becker@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/stack_user.c144
1 files changed, 139 insertions, 5 deletions
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
index fdca5d3c7668..ff8d30757924 100644
--- a/fs/ocfs2/stack_user.c
+++ b/fs/ocfs2/stack_user.c
@@ -22,6 +22,7 @@
22#include <linux/miscdevice.h> 22#include <linux/miscdevice.h>
23#include <linux/mutex.h> 23#include <linux/mutex.h>
24#include <linux/reboot.h> 24#include <linux/reboot.h>
25#include <asm/uaccess.h>
25 26
26#include "stackglue.h" 27#include "stackglue.h"
27 28
@@ -40,6 +41,16 @@
40 */ 41 */
41 42
42/* 43/*
44 * 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/*
43 * ocfs2_live_connection is refcounted because the filesystem and 54 * ocfs2_live_connection is refcounted because the filesystem and
44 * miscdevice sides can detach in different order. Let's just be safe. 55 * miscdevice sides can detach in different order. Let's just be safe.
45 */ 56 */
@@ -48,11 +59,30 @@ struct ocfs2_live_connection {
48 struct ocfs2_cluster_connection *oc_conn; 59 struct ocfs2_cluster_connection *oc_conn;
49}; 60};
50 61
62struct ocfs2_control_private {
63 struct list_head op_list;
64 int op_state;
65};
66
51static atomic_t ocfs2_control_opened; 67static atomic_t ocfs2_control_opened;
52 68
53static LIST_HEAD(ocfs2_live_connection_list); 69static LIST_HEAD(ocfs2_live_connection_list);
70static LIST_HEAD(ocfs2_control_private_list);
54static DEFINE_MUTEX(ocfs2_control_lock); 71static DEFINE_MUTEX(ocfs2_control_lock);
55 72
73static 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
56static struct ocfs2_live_connection *ocfs2_connection_find(const char *name) 86static struct ocfs2_live_connection *ocfs2_connection_find(const char *name)
57{ 87{
58 size_t len = strlen(name); 88 size_t len = strlen(name);
@@ -119,27 +149,115 @@ static void ocfs2_live_connection_drop(struct ocfs2_live_connection *c)
119 kfree(c); 149 kfree(c);
120} 150}
121 151
152static 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
122 188
123static ssize_t ocfs2_control_write(struct file *file, 189static ssize_t ocfs2_control_write(struct file *file,
124 const char __user *buf, 190 const char __user *buf,
125 size_t count, 191 size_t count,
126 loff_t *ppos) 192 loff_t *ppos)
127{ 193{
128 return 0; 194 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;
129} 217}
130 218
219/*
220 * This is a naive version. If we ever have a new protocol, we'll expand
221 * it. Probably using seq_file.
222 */
131static ssize_t ocfs2_control_read(struct file *file, 223static ssize_t ocfs2_control_read(struct file *file,
132 char __user *buf, 224 char __user *buf,
133 size_t count, 225 size_t count,
134 loff_t *ppos) 226 loff_t *ppos)
135{ 227{
136 return 0; 228 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;
137} 248}
138 249
139static int ocfs2_control_release(struct inode *inode, struct file *file) 250static int ocfs2_control_release(struct inode *inode, struct file *file)
140{ 251{
252 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
141 if (atomic_dec_and_test(&ocfs2_control_opened)) { 260 if (atomic_dec_and_test(&ocfs2_control_opened)) {
142 mutex_lock(&ocfs2_control_lock);
143 if (!list_empty(&ocfs2_live_connection_list)) { 261 if (!list_empty(&ocfs2_live_connection_list)) {
144 /* XXX: Do bad things! */ 262 /* XXX: Do bad things! */
145 printk(KERN_ERR 263 printk(KERN_ERR
@@ -148,15 +266,31 @@ static int ocfs2_control_release(struct inode *inode, struct file *file)
148 "an emergency restart!\n"); 266 "an emergency restart!\n");
149 emergency_restart(); 267 emergency_restart();
150 } 268 }
151 mutex_unlock(&ocfs2_control_lock);
152 } 269 }
153 270
271out:
272 list_del_init(&p->op_list);
273 file->private_data = NULL;
274
275 mutex_unlock(&ocfs2_control_lock);
276
277 kfree(p);
278
154 return 0; 279 return 0;
155} 280}
156 281
157static int ocfs2_control_open(struct inode *inode, struct file *file) 282static int ocfs2_control_open(struct inode *inode, struct file *file)
158{ 283{
159 atomic_inc(&ocfs2_control_opened); 284 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);
160 294
161 return 0; 295 return 0;
162} 296}