blob: 1acb4c5813cd2be02308941598f674b696123cee [file] [log] [blame]
David Teigland597d0ca2006-07-12 16:44:04 -05001/*
David Teiglandef0c2bb2007-03-28 09:56:46 -05002 * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved.
David Teigland597d0ca2006-07-12 16:44:04 -05003 *
4 * This copyrighted material is made available to anyone wishing to use,
5 * modify, copy, or redistribute it subject to the terms and conditions
6 * of the GNU General Public License v.2.
7 */
8
9#include <linux/miscdevice.h>
10#include <linux/init.h>
11#include <linux/wait.h>
12#include <linux/module.h>
13#include <linux/file.h>
14#include <linux/fs.h>
15#include <linux/poll.h>
16#include <linux/signal.h>
17#include <linux/spinlock.h>
18#include <linux/dlm.h>
19#include <linux/dlm_device.h>
20
21#include "dlm_internal.h"
22#include "lockspace.h"
23#include "lock.h"
24#include "lvb_table.h"
Adrian Bunk84c6e8c2007-02-26 00:18:42 +010025#include "user.h"
David Teigland597d0ca2006-07-12 16:44:04 -050026
27static const char *name_prefix="dlm";
28static struct miscdevice ctl_device;
Arjan van de Ven00977a52007-02-12 00:55:34 -080029static const struct file_operations device_fops;
David Teigland597d0ca2006-07-12 16:44:04 -050030
31#ifdef CONFIG_COMPAT
32
33struct dlm_lock_params32 {
34 __u8 mode;
35 __u8 namelen;
David Teiglandd7db9232007-05-18 09:00:32 -050036 __u16 unused;
37 __u32 flags;
David Teigland597d0ca2006-07-12 16:44:04 -050038 __u32 lkid;
39 __u32 parent;
David Teiglandd7db9232007-05-18 09:00:32 -050040 __u64 xid;
41 __u64 timeout;
David Teigland597d0ca2006-07-12 16:44:04 -050042 __u32 castparam;
43 __u32 castaddr;
44 __u32 bastparam;
45 __u32 bastaddr;
46 __u32 lksb;
David Teigland597d0ca2006-07-12 16:44:04 -050047 char lvb[DLM_USER_LVB_LEN];
48 char name[0];
49};
50
51struct dlm_write_request32 {
52 __u32 version[3];
53 __u8 cmd;
54 __u8 is64bit;
55 __u8 unused[2];
56
57 union {
58 struct dlm_lock_params32 lock;
59 struct dlm_lspace_params lspace;
David Teigland72c2be72007-03-30 15:06:16 -050060 struct dlm_purge_params purge;
David Teigland597d0ca2006-07-12 16:44:04 -050061 } i;
62};
63
64struct dlm_lksb32 {
65 __u32 sb_status;
66 __u32 sb_lkid;
67 __u8 sb_flags;
68 __u32 sb_lvbptr;
69};
70
71struct dlm_lock_result32 {
David Teiglandd7db9232007-05-18 09:00:32 -050072 __u32 version[3];
David Teigland597d0ca2006-07-12 16:44:04 -050073 __u32 length;
74 __u32 user_astaddr;
75 __u32 user_astparam;
76 __u32 user_lksb;
77 struct dlm_lksb32 lksb;
78 __u8 bast_mode;
79 __u8 unused[3];
80 /* Offsets may be zero if no data is present */
81 __u32 lvb_offset;
82};
83
84static void compat_input(struct dlm_write_request *kb,
Patrick Caulfeld2a792892008-01-17 10:25:28 +000085 struct dlm_write_request32 *kb32,
86 int max_namelen)
David Teigland597d0ca2006-07-12 16:44:04 -050087{
88 kb->version[0] = kb32->version[0];
89 kb->version[1] = kb32->version[1];
90 kb->version[2] = kb32->version[2];
91
92 kb->cmd = kb32->cmd;
93 kb->is64bit = kb32->is64bit;
94 if (kb->cmd == DLM_USER_CREATE_LOCKSPACE ||
95 kb->cmd == DLM_USER_REMOVE_LOCKSPACE) {
96 kb->i.lspace.flags = kb32->i.lspace.flags;
97 kb->i.lspace.minor = kb32->i.lspace.minor;
98 strcpy(kb->i.lspace.name, kb32->i.lspace.name);
David Teigland72c2be72007-03-30 15:06:16 -050099 } else if (kb->cmd == DLM_USER_PURGE) {
100 kb->i.purge.nodeid = kb32->i.purge.nodeid;
101 kb->i.purge.pid = kb32->i.purge.pid;
David Teigland597d0ca2006-07-12 16:44:04 -0500102 } else {
103 kb->i.lock.mode = kb32->i.lock.mode;
104 kb->i.lock.namelen = kb32->i.lock.namelen;
105 kb->i.lock.flags = kb32->i.lock.flags;
106 kb->i.lock.lkid = kb32->i.lock.lkid;
107 kb->i.lock.parent = kb32->i.lock.parent;
David Teiglandd7db9232007-05-18 09:00:32 -0500108 kb->i.lock.xid = kb32->i.lock.xid;
109 kb->i.lock.timeout = kb32->i.lock.timeout;
David Teigland597d0ca2006-07-12 16:44:04 -0500110 kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
111 kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
112 kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
113 kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr;
114 kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb;
115 memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN);
Patrick Caulfeld2a792892008-01-17 10:25:28 +0000116 if (kb->i.lock.namelen <= max_namelen)
117 memcpy(kb->i.lock.name, kb32->i.lock.name,
118 kb->i.lock.namelen);
119 else
120 kb->i.lock.namelen = max_namelen;
David Teigland597d0ca2006-07-12 16:44:04 -0500121 }
122}
123
124static void compat_output(struct dlm_lock_result *res,
125 struct dlm_lock_result32 *res32)
126{
David Teiglandd7db9232007-05-18 09:00:32 -0500127 res32->version[0] = res->version[0];
128 res32->version[1] = res->version[1];
129 res32->version[2] = res->version[2];
130
David Teigland597d0ca2006-07-12 16:44:04 -0500131 res32->user_astaddr = (__u32)(long)res->user_astaddr;
132 res32->user_astparam = (__u32)(long)res->user_astparam;
133 res32->user_lksb = (__u32)(long)res->user_lksb;
134 res32->bast_mode = res->bast_mode;
135
136 res32->lvb_offset = res->lvb_offset;
137 res32->length = res->length;
138
139 res32->lksb.sb_status = res->lksb.sb_status;
140 res32->lksb.sb_flags = res->lksb.sb_flags;
141 res32->lksb.sb_lkid = res->lksb.sb_lkid;
142 res32->lksb.sb_lvbptr = (__u32)(long)res->lksb.sb_lvbptr;
143}
144#endif
145
David Teigland84d8cd62007-05-29 08:44:23 -0500146/* Figure out if this lock is at the end of its life and no longer
147 available for the application to use. The lkb still exists until
148 the final ast is read. A lock becomes EOL in three situations:
149 1. a noqueue request fails with EAGAIN
150 2. an unlock completes with EUNLOCK
151 3. a cancel of a waiting request completes with ECANCEL/EDEADLK
152 An EOL lock needs to be removed from the process's list of locks.
153 And we can't allow any new operation on an EOL lock. This is
154 not related to the lifetime of the lkb struct which is managed
155 entirely by refcount. */
156
157static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
158{
159 switch (sb_status) {
160 case -DLM_EUNLOCK:
161 return 1;
162 case -DLM_ECANCEL:
163 case -ETIMEDOUT:
David Teigland8b4021f2007-05-29 08:46:00 -0500164 case -EDEADLK:
David Teigland84d8cd62007-05-29 08:44:23 -0500165 if (lkb->lkb_grmode == DLM_LOCK_IV)
166 return 1;
167 break;
168 case -EAGAIN:
169 if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV)
170 return 1;
171 break;
172 }
173 return 0;
174}
175
David Teiglandef0c2bb2007-03-28 09:56:46 -0500176/* we could possibly check if the cancel of an orphan has resulted in the lkb
177 being removed and then remove that lkb from the orphans list and free it */
David Teigland597d0ca2006-07-12 16:44:04 -0500178
179void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
180{
181 struct dlm_ls *ls;
182 struct dlm_user_args *ua;
183 struct dlm_user_proc *proc;
David Teiglandef0c2bb2007-03-28 09:56:46 -0500184 int eol = 0, ast_type;
David Teigland597d0ca2006-07-12 16:44:04 -0500185
David Teiglandef0c2bb2007-03-28 09:56:46 -0500186 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
David Teigland597d0ca2006-07-12 16:44:04 -0500187 return;
David Teigland597d0ca2006-07-12 16:44:04 -0500188
189 ls = lkb->lkb_resource->res_ls;
190 mutex_lock(&ls->ls_clear_proc_locks);
191
192 /* If ORPHAN/DEAD flag is set, it means the process is dead so an ast
193 can't be delivered. For ORPHAN's, dlm_clear_proc_locks() freed
David Teiglandef0c2bb2007-03-28 09:56:46 -0500194 lkb->ua so we can't try to use it. This second check is necessary
195 for cases where a completion ast is received for an operation that
196 began before clear_proc_locks did its cancel/unlock. */
David Teigland597d0ca2006-07-12 16:44:04 -0500197
David Teiglandef0c2bb2007-03-28 09:56:46 -0500198 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
David Teigland597d0ca2006-07-12 16:44:04 -0500199 goto out;
David Teigland597d0ca2006-07-12 16:44:04 -0500200
201 DLM_ASSERT(lkb->lkb_astparam, dlm_print_lkb(lkb););
202 ua = (struct dlm_user_args *)lkb->lkb_astparam;
203 proc = ua->proc;
204
205 if (type == AST_BAST && ua->bastaddr == NULL)
206 goto out;
207
208 spin_lock(&proc->asts_spin);
David Teiglandef0c2bb2007-03-28 09:56:46 -0500209
210 ast_type = lkb->lkb_ast_type;
211 lkb->lkb_ast_type |= type;
212
213 if (!ast_type) {
David Teigland597d0ca2006-07-12 16:44:04 -0500214 kref_get(&lkb->lkb_ref);
215 list_add_tail(&lkb->lkb_astqueue, &proc->asts);
David Teigland597d0ca2006-07-12 16:44:04 -0500216 wake_up_interruptible(&proc->wait);
217 }
David Teiglandef0c2bb2007-03-28 09:56:46 -0500218 if (type == AST_COMP && (ast_type & AST_COMP))
219 log_debug(ls, "ast overlap %x status %x %x",
220 lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags);
David Teigland597d0ca2006-07-12 16:44:04 -0500221
David Teigland84d8cd62007-05-29 08:44:23 -0500222 eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type);
David Teiglandef0c2bb2007-03-28 09:56:46 -0500223 if (eol) {
224 lkb->lkb_ast_type &= ~AST_BAST;
225 lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
226 }
David Teiglanda1bc86e2007-01-15 10:34:52 -0600227
David Teigland597d0ca2006-07-12 16:44:04 -0500228 /* We want to copy the lvb to userspace when the completion
229 ast is read if the status is 0, the lock has an lvb and
230 lvb_ops says we should. We could probably have set_lvb_lock()
231 set update_user_lvb instead and not need old_mode */
232
233 if ((lkb->lkb_ast_type & AST_COMP) &&
234 (lkb->lkb_lksb->sb_status == 0) &&
235 lkb->lkb_lksb->sb_lvbptr &&
236 dlm_lvb_operations[ua->old_mode + 1][lkb->lkb_grmode + 1])
237 ua->update_user_lvb = 1;
238 else
239 ua->update_user_lvb = 0;
240
241 spin_unlock(&proc->asts_spin);
David Teigland34e22be2006-07-18 11:24:04 -0500242
David Teiglandef0c2bb2007-03-28 09:56:46 -0500243 if (eol) {
David Teiglandce5246b2008-01-14 15:48:58 -0600244 spin_lock(&proc->locks_spin);
David Teiglandef0c2bb2007-03-28 09:56:46 -0500245 if (!list_empty(&lkb->lkb_ownqueue)) {
246 list_del_init(&lkb->lkb_ownqueue);
247 dlm_put_lkb(lkb);
248 }
David Teiglandce5246b2008-01-14 15:48:58 -0600249 spin_unlock(&proc->locks_spin);
David Teigland34e22be2006-07-18 11:24:04 -0500250 }
David Teigland597d0ca2006-07-12 16:44:04 -0500251 out:
252 mutex_unlock(&ls->ls_clear_proc_locks);
253}
254
255static int device_user_lock(struct dlm_user_proc *proc,
256 struct dlm_lock_params *params)
257{
258 struct dlm_ls *ls;
259 struct dlm_user_args *ua;
260 int error = -ENOMEM;
261
262 ls = dlm_find_lockspace_local(proc->lockspace);
263 if (!ls)
264 return -ENOENT;
265
266 if (!params->castaddr || !params->lksb) {
267 error = -EINVAL;
268 goto out;
269 }
270
271 ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL);
272 if (!ua)
273 goto out;
274 ua->proc = proc;
275 ua->user_lksb = params->lksb;
276 ua->castparam = params->castparam;
277 ua->castaddr = params->castaddr;
278 ua->bastparam = params->bastparam;
279 ua->bastaddr = params->bastaddr;
David Teiglandd7db9232007-05-18 09:00:32 -0500280 ua->xid = params->xid;
David Teigland597d0ca2006-07-12 16:44:04 -0500281
282 if (params->flags & DLM_LKF_CONVERT)
283 error = dlm_user_convert(ls, ua,
284 params->mode, params->flags,
David Teiglandd7db9232007-05-18 09:00:32 -0500285 params->lkid, params->lvb,
286 (unsigned long) params->timeout);
David Teigland597d0ca2006-07-12 16:44:04 -0500287 else {
288 error = dlm_user_request(ls, ua,
289 params->mode, params->flags,
290 params->name, params->namelen,
David Teiglandd7db9232007-05-18 09:00:32 -0500291 (unsigned long) params->timeout);
David Teigland597d0ca2006-07-12 16:44:04 -0500292 if (!error)
293 error = ua->lksb.sb_lkid;
294 }
295 out:
296 dlm_put_lockspace(ls);
297 return error;
298}
299
300static int device_user_unlock(struct dlm_user_proc *proc,
301 struct dlm_lock_params *params)
302{
303 struct dlm_ls *ls;
304 struct dlm_user_args *ua;
305 int error = -ENOMEM;
306
307 ls = dlm_find_lockspace_local(proc->lockspace);
308 if (!ls)
309 return -ENOENT;
310
311 ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL);
312 if (!ua)
313 goto out;
314 ua->proc = proc;
315 ua->user_lksb = params->lksb;
316 ua->castparam = params->castparam;
317 ua->castaddr = params->castaddr;
318
319 if (params->flags & DLM_LKF_CANCEL)
320 error = dlm_user_cancel(ls, ua, params->flags, params->lkid);
321 else
322 error = dlm_user_unlock(ls, ua, params->flags, params->lkid,
323 params->lvb);
324 out:
325 dlm_put_lockspace(ls);
326 return error;
327}
328
David Teigland8b4021f2007-05-29 08:46:00 -0500329static int device_user_deadlock(struct dlm_user_proc *proc,
330 struct dlm_lock_params *params)
331{
332 struct dlm_ls *ls;
333 int error;
334
335 ls = dlm_find_lockspace_local(proc->lockspace);
336 if (!ls)
337 return -ENOENT;
338
339 error = dlm_user_deadlock(ls, params->flags, params->lkid);
340
341 dlm_put_lockspace(ls);
342 return error;
343}
344
Patrick Caulfield254da032007-03-21 09:23:53 +0000345static int create_misc_device(struct dlm_ls *ls, char *name)
346{
347 int error, len;
348
349 error = -ENOMEM;
350 len = strlen(name) + strlen(name_prefix) + 2;
351 ls->ls_device.name = kzalloc(len, GFP_KERNEL);
352 if (!ls->ls_device.name)
353 goto fail;
354
355 snprintf((char *)ls->ls_device.name, len, "%s_%s", name_prefix,
356 name);
357 ls->ls_device.fops = &device_fops;
358 ls->ls_device.minor = MISC_DYNAMIC_MINOR;
359
360 error = misc_register(&ls->ls_device);
361 if (error) {
362 kfree(ls->ls_device.name);
363 }
364fail:
365 return error;
366}
367
David Teigland72c2be72007-03-30 15:06:16 -0500368static int device_user_purge(struct dlm_user_proc *proc,
369 struct dlm_purge_params *params)
370{
371 struct dlm_ls *ls;
372 int error;
373
374 ls = dlm_find_lockspace_local(proc->lockspace);
375 if (!ls)
376 return -ENOENT;
377
378 error = dlm_user_purge(ls, proc, params->nodeid, params->pid);
379
380 dlm_put_lockspace(ls);
381 return error;
382}
383
David Teigland597d0ca2006-07-12 16:44:04 -0500384static int device_create_lockspace(struct dlm_lspace_params *params)
385{
386 dlm_lockspace_t *lockspace;
387 struct dlm_ls *ls;
Patrick Caulfield254da032007-03-21 09:23:53 +0000388 int error;
David Teigland597d0ca2006-07-12 16:44:04 -0500389
390 if (!capable(CAP_SYS_ADMIN))
391 return -EPERM;
392
393 error = dlm_new_lockspace(params->name, strlen(params->name),
David Teigland3ae1acf2007-05-18 08:59:31 -0500394 &lockspace, params->flags, DLM_USER_LVB_LEN);
David Teigland597d0ca2006-07-12 16:44:04 -0500395 if (error)
396 return error;
397
398 ls = dlm_find_lockspace_local(lockspace);
399 if (!ls)
400 return -ENOENT;
401
Patrick Caulfield254da032007-03-21 09:23:53 +0000402 error = create_misc_device(ls, params->name);
David Teigland597d0ca2006-07-12 16:44:04 -0500403 dlm_put_lockspace(ls);
David Teigland597d0ca2006-07-12 16:44:04 -0500404
Patrick Caulfield254da032007-03-21 09:23:53 +0000405 if (error)
406 dlm_release_lockspace(lockspace, 0);
407 else
408 error = ls->ls_device.minor;
409
David Teigland597d0ca2006-07-12 16:44:04 -0500410 return error;
411}
412
413static int device_remove_lockspace(struct dlm_lspace_params *params)
414{
415 dlm_lockspace_t *lockspace;
416 struct dlm_ls *ls;
David Teiglandc6e6f0b2006-08-30 10:50:18 -0500417 int error, force = 0;
David Teigland597d0ca2006-07-12 16:44:04 -0500418
419 if (!capable(CAP_SYS_ADMIN))
420 return -EPERM;
421
422 ls = dlm_find_lockspace_device(params->minor);
423 if (!ls)
424 return -ENOENT;
425
Patrick Caulfield254da032007-03-21 09:23:53 +0000426 /* Deregister the misc device first, so we don't have
427 * a device that's not attached to a lockspace. If
428 * dlm_release_lockspace fails then we can recreate it
429 */
David Teigland597d0ca2006-07-12 16:44:04 -0500430 error = misc_deregister(&ls->ls_device);
431 if (error) {
432 dlm_put_lockspace(ls);
433 goto out;
434 }
435 kfree(ls->ls_device.name);
436
David Teiglandc6e6f0b2006-08-30 10:50:18 -0500437 if (params->flags & DLM_USER_LSFLG_FORCEFREE)
438 force = 2;
439
David Teigland597d0ca2006-07-12 16:44:04 -0500440 lockspace = ls->ls_local_handle;
441
442 /* dlm_release_lockspace waits for references to go to zero,
443 so all processes will need to close their device for the ls
444 before the release will procede */
445
446 dlm_put_lockspace(ls);
David Teiglandc6e6f0b2006-08-30 10:50:18 -0500447 error = dlm_release_lockspace(lockspace, force);
Patrick Caulfield254da032007-03-21 09:23:53 +0000448 if (error)
449 create_misc_device(ls, ls->ls_name);
David Teiglandc6e6f0b2006-08-30 10:50:18 -0500450 out:
David Teigland597d0ca2006-07-12 16:44:04 -0500451 return error;
452}
453
454/* Check the user's version matches ours */
455static int check_version(struct dlm_write_request *req)
456{
457 if (req->version[0] != DLM_DEVICE_VERSION_MAJOR ||
458 (req->version[0] == DLM_DEVICE_VERSION_MAJOR &&
459 req->version[1] > DLM_DEVICE_VERSION_MINOR)) {
460
461 printk(KERN_DEBUG "dlm: process %s (%d) version mismatch "
462 "user (%d.%d.%d) kernel (%d.%d.%d)\n",
463 current->comm,
Pavel Emelyanovba25f9d2007-10-18 23:40:40 -0700464 task_pid_nr(current),
David Teigland597d0ca2006-07-12 16:44:04 -0500465 req->version[0],
466 req->version[1],
467 req->version[2],
468 DLM_DEVICE_VERSION_MAJOR,
469 DLM_DEVICE_VERSION_MINOR,
470 DLM_DEVICE_VERSION_PATCH);
471 return -EINVAL;
472 }
473 return 0;
474}
475
476/*
477 * device_write
478 *
479 * device_user_lock
480 * dlm_user_request -> request_lock
481 * dlm_user_convert -> convert_lock
482 *
483 * device_user_unlock
484 * dlm_user_unlock -> unlock_lock
485 * dlm_user_cancel -> cancel_lock
486 *
487 * device_create_lockspace
488 * dlm_new_lockspace
489 *
490 * device_remove_lockspace
491 * dlm_release_lockspace
492 */
493
494/* a write to a lockspace device is a lock or unlock request, a write
495 to the control device is to create/remove a lockspace */
496
497static ssize_t device_write(struct file *file, const char __user *buf,
498 size_t count, loff_t *ppos)
499{
500 struct dlm_user_proc *proc = file->private_data;
501 struct dlm_write_request *kbuf;
502 sigset_t tmpsig, allsigs;
503 int error;
504
505#ifdef CONFIG_COMPAT
506 if (count < sizeof(struct dlm_write_request32))
507#else
508 if (count < sizeof(struct dlm_write_request))
509#endif
510 return -EINVAL;
511
512 kbuf = kmalloc(count, GFP_KERNEL);
513 if (!kbuf)
514 return -ENOMEM;
515
516 if (copy_from_user(kbuf, buf, count)) {
517 error = -EFAULT;
518 goto out_free;
519 }
520
521 if (check_version(kbuf)) {
522 error = -EBADE;
523 goto out_free;
524 }
525
526#ifdef CONFIG_COMPAT
527 if (!kbuf->is64bit) {
528 struct dlm_write_request32 *k32buf;
529 k32buf = (struct dlm_write_request32 *)kbuf;
530 kbuf = kmalloc(count + (sizeof(struct dlm_write_request) -
531 sizeof(struct dlm_write_request32)), GFP_KERNEL);
532 if (!kbuf)
533 return -ENOMEM;
534
535 if (proc)
536 set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
Patrick Caulfeld2a792892008-01-17 10:25:28 +0000537 compat_input(kbuf, k32buf,
538 count - sizeof(struct dlm_write_request32));
David Teigland597d0ca2006-07-12 16:44:04 -0500539 kfree(k32buf);
540 }
541#endif
542
543 /* do we really need this? can a write happen after a close? */
544 if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) &&
545 test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
546 return -EINVAL;
547
548 sigfillset(&allsigs);
549 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
550
551 error = -EINVAL;
552
553 switch (kbuf->cmd)
554 {
555 case DLM_USER_LOCK:
556 if (!proc) {
557 log_print("no locking on control device");
558 goto out_sig;
559 }
560 error = device_user_lock(proc, &kbuf->i.lock);
561 break;
562
563 case DLM_USER_UNLOCK:
564 if (!proc) {
565 log_print("no locking on control device");
566 goto out_sig;
567 }
568 error = device_user_unlock(proc, &kbuf->i.lock);
569 break;
570
David Teigland8b4021f2007-05-29 08:46:00 -0500571 case DLM_USER_DEADLOCK:
572 if (!proc) {
573 log_print("no locking on control device");
574 goto out_sig;
575 }
576 error = device_user_deadlock(proc, &kbuf->i.lock);
577 break;
578
David Teigland597d0ca2006-07-12 16:44:04 -0500579 case DLM_USER_CREATE_LOCKSPACE:
580 if (proc) {
581 log_print("create/remove only on control device");
582 goto out_sig;
583 }
584 error = device_create_lockspace(&kbuf->i.lspace);
585 break;
586
587 case DLM_USER_REMOVE_LOCKSPACE:
588 if (proc) {
589 log_print("create/remove only on control device");
590 goto out_sig;
591 }
592 error = device_remove_lockspace(&kbuf->i.lspace);
593 break;
594
David Teigland72c2be72007-03-30 15:06:16 -0500595 case DLM_USER_PURGE:
596 if (!proc) {
597 log_print("no locking on control device");
598 goto out_sig;
599 }
600 error = device_user_purge(proc, &kbuf->i.purge);
601 break;
602
David Teigland597d0ca2006-07-12 16:44:04 -0500603 default:
604 log_print("Unknown command passed to DLM device : %d\n",
605 kbuf->cmd);
606 }
607
608 out_sig:
609 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
610 recalc_sigpending();
611 out_free:
612 kfree(kbuf);
613 return error;
614}
615
616/* Every process that opens the lockspace device has its own "proc" structure
617 hanging off the open file that's used to keep track of locks owned by the
618 process and asts that need to be delivered to the process. */
619
620static int device_open(struct inode *inode, struct file *file)
621{
622 struct dlm_user_proc *proc;
623 struct dlm_ls *ls;
624
625 ls = dlm_find_lockspace_device(iminor(inode));
626 if (!ls)
627 return -ENOENT;
628
629 proc = kzalloc(sizeof(struct dlm_user_proc), GFP_KERNEL);
630 if (!proc) {
631 dlm_put_lockspace(ls);
632 return -ENOMEM;
633 }
634
635 proc->lockspace = ls->ls_local_handle;
636 INIT_LIST_HEAD(&proc->asts);
637 INIT_LIST_HEAD(&proc->locks);
David Teiglanda1bc86e2007-01-15 10:34:52 -0600638 INIT_LIST_HEAD(&proc->unlocking);
David Teigland597d0ca2006-07-12 16:44:04 -0500639 spin_lock_init(&proc->asts_spin);
640 spin_lock_init(&proc->locks_spin);
641 init_waitqueue_head(&proc->wait);
642 file->private_data = proc;
643
644 return 0;
645}
646
647static int device_close(struct inode *inode, struct file *file)
648{
649 struct dlm_user_proc *proc = file->private_data;
650 struct dlm_ls *ls;
651 sigset_t tmpsig, allsigs;
652
653 ls = dlm_find_lockspace_local(proc->lockspace);
654 if (!ls)
655 return -ENOENT;
656
657 sigfillset(&allsigs);
658 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
659
660 set_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags);
661
662 dlm_clear_proc_locks(ls, proc);
663
664 /* at this point no more lkb's should exist for this lockspace,
665 so there's no chance of dlm_user_add_ast() being called and
666 looking for lkb->ua->proc */
667
668 kfree(proc);
669 file->private_data = NULL;
670
671 dlm_put_lockspace(ls);
672 dlm_put_lockspace(ls); /* for the find in device_open() */
673
674 /* FIXME: AUTOFREE: if this ls is no longer used do
675 device_remove_lockspace() */
676
677 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
678 recalc_sigpending();
679
680 return 0;
681}
682
683static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
684 int bmode, char __user *buf, size_t count)
685{
686#ifdef CONFIG_COMPAT
687 struct dlm_lock_result32 result32;
688#endif
689 struct dlm_lock_result result;
690 void *resultptr;
691 int error=0;
692 int len;
693 int struct_len;
694
695 memset(&result, 0, sizeof(struct dlm_lock_result));
David Teiglandd7db9232007-05-18 09:00:32 -0500696 result.version[0] = DLM_DEVICE_VERSION_MAJOR;
697 result.version[1] = DLM_DEVICE_VERSION_MINOR;
698 result.version[2] = DLM_DEVICE_VERSION_PATCH;
David Teigland597d0ca2006-07-12 16:44:04 -0500699 memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
700 result.user_lksb = ua->user_lksb;
701
702 /* FIXME: dlm1 provides for the user's bastparam/addr to not be updated
703 in a conversion unless the conversion is successful. See code
704 in dlm_user_convert() for updating ua from ua_tmp. OpenVMS, though,
705 notes that a new blocking AST address and parameter are set even if
706 the conversion fails, so maybe we should just do that. */
707
708 if (type == AST_BAST) {
709 result.user_astaddr = ua->bastaddr;
710 result.user_astparam = ua->bastparam;
711 result.bast_mode = bmode;
712 } else {
713 result.user_astaddr = ua->castaddr;
714 result.user_astparam = ua->castparam;
715 }
716
717#ifdef CONFIG_COMPAT
718 if (compat)
719 len = sizeof(struct dlm_lock_result32);
720 else
721#endif
722 len = sizeof(struct dlm_lock_result);
723 struct_len = len;
724
725 /* copy lvb to userspace if there is one, it's been updated, and
726 the user buffer has space for it */
727
728 if (ua->update_user_lvb && ua->lksb.sb_lvbptr &&
729 count >= len + DLM_USER_LVB_LEN) {
730 if (copy_to_user(buf+len, ua->lksb.sb_lvbptr,
731 DLM_USER_LVB_LEN)) {
732 error = -EFAULT;
733 goto out;
734 }
735
736 result.lvb_offset = len;
737 len += DLM_USER_LVB_LEN;
738 }
739
740 result.length = len;
741 resultptr = &result;
742#ifdef CONFIG_COMPAT
743 if (compat) {
744 compat_output(&result, &result32);
745 resultptr = &result32;
746 }
747#endif
748
749 if (copy_to_user(buf, resultptr, struct_len))
750 error = -EFAULT;
751 else
752 error = len;
753 out:
754 return error;
755}
756
David Teiglandd7db9232007-05-18 09:00:32 -0500757static int copy_version_to_user(char __user *buf, size_t count)
758{
759 struct dlm_device_version ver;
760
761 memset(&ver, 0, sizeof(struct dlm_device_version));
762 ver.version[0] = DLM_DEVICE_VERSION_MAJOR;
763 ver.version[1] = DLM_DEVICE_VERSION_MINOR;
764 ver.version[2] = DLM_DEVICE_VERSION_PATCH;
765
766 if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version)))
767 return -EFAULT;
768 return sizeof(struct dlm_device_version);
769}
770
David Teigland597d0ca2006-07-12 16:44:04 -0500771/* a read returns a single ast described in a struct dlm_lock_result */
772
773static ssize_t device_read(struct file *file, char __user *buf, size_t count,
774 loff_t *ppos)
775{
776 struct dlm_user_proc *proc = file->private_data;
777 struct dlm_lkb *lkb;
778 struct dlm_user_args *ua;
779 DECLARE_WAITQUEUE(wait, current);
780 int error, type=0, bmode=0, removed = 0;
781
David Teiglandd7db9232007-05-18 09:00:32 -0500782 if (count == sizeof(struct dlm_device_version)) {
783 error = copy_version_to_user(buf, count);
784 return error;
785 }
786
787 if (!proc) {
788 log_print("non-version read from control device %zu", count);
789 return -EINVAL;
790 }
791
David Teigland597d0ca2006-07-12 16:44:04 -0500792#ifdef CONFIG_COMPAT
793 if (count < sizeof(struct dlm_lock_result32))
794#else
795 if (count < sizeof(struct dlm_lock_result))
796#endif
797 return -EINVAL;
798
799 /* do we really need this? can a read happen after a close? */
800 if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
801 return -EINVAL;
802
803 spin_lock(&proc->asts_spin);
804 if (list_empty(&proc->asts)) {
805 if (file->f_flags & O_NONBLOCK) {
806 spin_unlock(&proc->asts_spin);
807 return -EAGAIN;
808 }
809
810 add_wait_queue(&proc->wait, &wait);
811
812 repeat:
813 set_current_state(TASK_INTERRUPTIBLE);
814 if (list_empty(&proc->asts) && !signal_pending(current)) {
815 spin_unlock(&proc->asts_spin);
816 schedule();
817 spin_lock(&proc->asts_spin);
818 goto repeat;
819 }
820 set_current_state(TASK_RUNNING);
821 remove_wait_queue(&proc->wait, &wait);
822
823 if (signal_pending(current)) {
824 spin_unlock(&proc->asts_spin);
825 return -ERESTARTSYS;
826 }
827 }
828
David Teigland597d0ca2006-07-12 16:44:04 -0500829 /* there may be both completion and blocking asts to return for
830 the lkb, don't remove lkb from asts list unless no asts remain */
831
832 lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue);
833
834 if (lkb->lkb_ast_type & AST_COMP) {
835 lkb->lkb_ast_type &= ~AST_COMP;
836 type = AST_COMP;
837 } else if (lkb->lkb_ast_type & AST_BAST) {
838 lkb->lkb_ast_type &= ~AST_BAST;
839 type = AST_BAST;
840 bmode = lkb->lkb_bastmode;
841 }
842
843 if (!lkb->lkb_ast_type) {
844 list_del(&lkb->lkb_astqueue);
845 removed = 1;
846 }
847 spin_unlock(&proc->asts_spin);
848
849 ua = (struct dlm_user_args *)lkb->lkb_astparam;
850 error = copy_result_to_user(ua,
851 test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
852 type, bmode, buf, count);
853
854 /* removes reference for the proc->asts lists added by
855 dlm_user_add_ast() and may result in the lkb being freed */
856 if (removed)
857 dlm_put_lkb(lkb);
858
859 return error;
860}
861
862static unsigned int device_poll(struct file *file, poll_table *wait)
863{
864 struct dlm_user_proc *proc = file->private_data;
865
866 poll_wait(file, &proc->wait, wait);
867
868 spin_lock(&proc->asts_spin);
869 if (!list_empty(&proc->asts)) {
870 spin_unlock(&proc->asts_spin);
871 return POLLIN | POLLRDNORM;
872 }
873 spin_unlock(&proc->asts_spin);
874 return 0;
875}
876
877static int ctl_device_open(struct inode *inode, struct file *file)
878{
879 file->private_data = NULL;
880 return 0;
881}
882
883static int ctl_device_close(struct inode *inode, struct file *file)
884{
885 return 0;
886}
887
Arjan van de Ven00977a52007-02-12 00:55:34 -0800888static const struct file_operations device_fops = {
David Teigland597d0ca2006-07-12 16:44:04 -0500889 .open = device_open,
890 .release = device_close,
891 .read = device_read,
892 .write = device_write,
893 .poll = device_poll,
894 .owner = THIS_MODULE,
895};
896
Arjan van de Ven00977a52007-02-12 00:55:34 -0800897static const struct file_operations ctl_device_fops = {
David Teigland597d0ca2006-07-12 16:44:04 -0500898 .open = ctl_device_open,
899 .release = ctl_device_close,
David Teiglandd7db9232007-05-18 09:00:32 -0500900 .read = device_read,
David Teigland597d0ca2006-07-12 16:44:04 -0500901 .write = device_write,
902 .owner = THIS_MODULE,
903};
904
905int dlm_user_init(void)
906{
907 int error;
908
909 ctl_device.name = "dlm-control";
910 ctl_device.fops = &ctl_device_fops;
911 ctl_device.minor = MISC_DYNAMIC_MINOR;
912
913 error = misc_register(&ctl_device);
914 if (error)
915 log_print("misc_register failed for control device");
916
917 return error;
918}
919
920void dlm_user_exit(void)
921{
922 misc_deregister(&ctl_device);
923}
924