aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}