blob: 3e746a6ebac36b8a18a4ffccd6e6a30cc961a1e8 [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;
36 __u16 flags;
37 __u32 lkid;
38 __u32 parent;
39
40 __u32 castparam;
41 __u32 castaddr;
42 __u32 bastparam;
43 __u32 bastaddr;
44 __u32 lksb;
45
46 char lvb[DLM_USER_LVB_LEN];
47 char name[0];
48};
49
50struct dlm_write_request32 {
51 __u32 version[3];
52 __u8 cmd;
53 __u8 is64bit;
54 __u8 unused[2];
55
56 union {
57 struct dlm_lock_params32 lock;
58 struct dlm_lspace_params lspace;
David Teigland72c2be72007-03-30 15:06:16 -050059 struct dlm_purge_params purge;
David Teigland597d0ca2006-07-12 16:44:04 -050060 } i;
61};
62
63struct dlm_lksb32 {
64 __u32 sb_status;
65 __u32 sb_lkid;
66 __u8 sb_flags;
67 __u32 sb_lvbptr;
68};
69
70struct dlm_lock_result32 {
71 __u32 length;
72 __u32 user_astaddr;
73 __u32 user_astparam;
74 __u32 user_lksb;
75 struct dlm_lksb32 lksb;
76 __u8 bast_mode;
77 __u8 unused[3];
78 /* Offsets may be zero if no data is present */
79 __u32 lvb_offset;
80};
81
82static void compat_input(struct dlm_write_request *kb,
83 struct dlm_write_request32 *kb32)
84{
85 kb->version[0] = kb32->version[0];
86 kb->version[1] = kb32->version[1];
87 kb->version[2] = kb32->version[2];
88
89 kb->cmd = kb32->cmd;
90 kb->is64bit = kb32->is64bit;
91 if (kb->cmd == DLM_USER_CREATE_LOCKSPACE ||
92 kb->cmd == DLM_USER_REMOVE_LOCKSPACE) {
93 kb->i.lspace.flags = kb32->i.lspace.flags;
94 kb->i.lspace.minor = kb32->i.lspace.minor;
95 strcpy(kb->i.lspace.name, kb32->i.lspace.name);
David Teigland72c2be72007-03-30 15:06:16 -050096 } else if (kb->cmd == DLM_USER_PURGE) {
97 kb->i.purge.nodeid = kb32->i.purge.nodeid;
98 kb->i.purge.pid = kb32->i.purge.pid;
David Teigland597d0ca2006-07-12 16:44:04 -050099 } else {
100 kb->i.lock.mode = kb32->i.lock.mode;
101 kb->i.lock.namelen = kb32->i.lock.namelen;
102 kb->i.lock.flags = kb32->i.lock.flags;
103 kb->i.lock.lkid = kb32->i.lock.lkid;
104 kb->i.lock.parent = kb32->i.lock.parent;
105 kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
106 kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
107 kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
108 kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr;
109 kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb;
110 memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN);
111 memcpy(kb->i.lock.name, kb32->i.lock.name, kb->i.lock.namelen);
112 }
113}
114
115static void compat_output(struct dlm_lock_result *res,
116 struct dlm_lock_result32 *res32)
117{
118 res32->length = res->length - (sizeof(struct dlm_lock_result) -
119 sizeof(struct dlm_lock_result32));
120 res32->user_astaddr = (__u32)(long)res->user_astaddr;
121 res32->user_astparam = (__u32)(long)res->user_astparam;
122 res32->user_lksb = (__u32)(long)res->user_lksb;
123 res32->bast_mode = res->bast_mode;
124
125 res32->lvb_offset = res->lvb_offset;
126 res32->length = res->length;
127
128 res32->lksb.sb_status = res->lksb.sb_status;
129 res32->lksb.sb_flags = res->lksb.sb_flags;
130 res32->lksb.sb_lkid = res->lksb.sb_lkid;
131 res32->lksb.sb_lvbptr = (__u32)(long)res->lksb.sb_lvbptr;
132}
133#endif
134
David Teiglandef0c2bb2007-03-28 09:56:46 -0500135/* we could possibly check if the cancel of an orphan has resulted in the lkb
136 being removed and then remove that lkb from the orphans list and free it */
David Teigland597d0ca2006-07-12 16:44:04 -0500137
138void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
139{
140 struct dlm_ls *ls;
141 struct dlm_user_args *ua;
142 struct dlm_user_proc *proc;
David Teiglandef0c2bb2007-03-28 09:56:46 -0500143 int eol = 0, ast_type;
David Teigland597d0ca2006-07-12 16:44:04 -0500144
David Teiglandef0c2bb2007-03-28 09:56:46 -0500145 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
David Teigland597d0ca2006-07-12 16:44:04 -0500146 return;
David Teigland597d0ca2006-07-12 16:44:04 -0500147
148 ls = lkb->lkb_resource->res_ls;
149 mutex_lock(&ls->ls_clear_proc_locks);
150
151 /* If ORPHAN/DEAD flag is set, it means the process is dead so an ast
152 can't be delivered. For ORPHAN's, dlm_clear_proc_locks() freed
David Teiglandef0c2bb2007-03-28 09:56:46 -0500153 lkb->ua so we can't try to use it. This second check is necessary
154 for cases where a completion ast is received for an operation that
155 began before clear_proc_locks did its cancel/unlock. */
David Teigland597d0ca2006-07-12 16:44:04 -0500156
David Teiglandef0c2bb2007-03-28 09:56:46 -0500157 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
David Teigland597d0ca2006-07-12 16:44:04 -0500158 goto out;
David Teigland597d0ca2006-07-12 16:44:04 -0500159
160 DLM_ASSERT(lkb->lkb_astparam, dlm_print_lkb(lkb););
161 ua = (struct dlm_user_args *)lkb->lkb_astparam;
162 proc = ua->proc;
163
164 if (type == AST_BAST && ua->bastaddr == NULL)
165 goto out;
166
167 spin_lock(&proc->asts_spin);
David Teiglandef0c2bb2007-03-28 09:56:46 -0500168
169 ast_type = lkb->lkb_ast_type;
170 lkb->lkb_ast_type |= type;
171
172 if (!ast_type) {
David Teigland597d0ca2006-07-12 16:44:04 -0500173 kref_get(&lkb->lkb_ref);
174 list_add_tail(&lkb->lkb_astqueue, &proc->asts);
David Teigland597d0ca2006-07-12 16:44:04 -0500175 wake_up_interruptible(&proc->wait);
176 }
David Teiglandef0c2bb2007-03-28 09:56:46 -0500177 if (type == AST_COMP && (ast_type & AST_COMP))
178 log_debug(ls, "ast overlap %x status %x %x",
179 lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags);
David Teigland597d0ca2006-07-12 16:44:04 -0500180
David Teiglandef0c2bb2007-03-28 09:56:46 -0500181 /* Figure out if this lock is at the end of its life and no longer
182 available for the application to use. The lkb still exists until
183 the final ast is read. A lock becomes EOL in three situations:
184 1. a noqueue request fails with EAGAIN
185 2. an unlock completes with EUNLOCK
186 3. a cancel of a waiting request completes with ECANCEL
187 An EOL lock needs to be removed from the process's list of locks.
188 And we can't allow any new operation on an EOL lock. This is
189 not related to the lifetime of the lkb struct which is managed
190 entirely by refcount. */
David Teigland36098192006-07-20 08:35:39 -0500191
David Teiglandef0c2bb2007-03-28 09:56:46 -0500192 if (type == AST_COMP &&
193 lkb->lkb_grmode == DLM_LOCK_IV &&
194 ua->lksb.sb_status == -EAGAIN)
195 eol = 1;
196 else if (ua->lksb.sb_status == -DLM_EUNLOCK ||
David Teiglanda1bc86e2007-01-15 10:34:52 -0600197 (ua->lksb.sb_status == -DLM_ECANCEL &&
198 lkb->lkb_grmode == DLM_LOCK_IV))
David Teiglandef0c2bb2007-03-28 09:56:46 -0500199 eol = 1;
200 if (eol) {
201 lkb->lkb_ast_type &= ~AST_BAST;
202 lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
203 }
David Teiglanda1bc86e2007-01-15 10:34:52 -0600204
David Teigland597d0ca2006-07-12 16:44:04 -0500205 /* We want to copy the lvb to userspace when the completion
206 ast is read if the status is 0, the lock has an lvb and
207 lvb_ops says we should. We could probably have set_lvb_lock()
208 set update_user_lvb instead and not need old_mode */
209
210 if ((lkb->lkb_ast_type & AST_COMP) &&
211 (lkb->lkb_lksb->sb_status == 0) &&
212 lkb->lkb_lksb->sb_lvbptr &&
213 dlm_lvb_operations[ua->old_mode + 1][lkb->lkb_grmode + 1])
214 ua->update_user_lvb = 1;
215 else
216 ua->update_user_lvb = 0;
217
218 spin_unlock(&proc->asts_spin);
David Teigland34e22be2006-07-18 11:24:04 -0500219
David Teiglandef0c2bb2007-03-28 09:56:46 -0500220 if (eol) {
David Teigland34e22be2006-07-18 11:24:04 -0500221 spin_lock(&ua->proc->locks_spin);
David Teiglandef0c2bb2007-03-28 09:56:46 -0500222 if (!list_empty(&lkb->lkb_ownqueue)) {
223 list_del_init(&lkb->lkb_ownqueue);
224 dlm_put_lkb(lkb);
225 }
David Teigland34e22be2006-07-18 11:24:04 -0500226 spin_unlock(&ua->proc->locks_spin);
David Teigland34e22be2006-07-18 11:24:04 -0500227 }
David Teigland597d0ca2006-07-12 16:44:04 -0500228 out:
229 mutex_unlock(&ls->ls_clear_proc_locks);
230}
231
232static int device_user_lock(struct dlm_user_proc *proc,
233 struct dlm_lock_params *params)
234{
235 struct dlm_ls *ls;
236 struct dlm_user_args *ua;
237 int error = -ENOMEM;
238
239 ls = dlm_find_lockspace_local(proc->lockspace);
240 if (!ls)
241 return -ENOENT;
242
243 if (!params->castaddr || !params->lksb) {
244 error = -EINVAL;
245 goto out;
246 }
247
248 ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL);
249 if (!ua)
250 goto out;
251 ua->proc = proc;
252 ua->user_lksb = params->lksb;
253 ua->castparam = params->castparam;
254 ua->castaddr = params->castaddr;
255 ua->bastparam = params->bastparam;
256 ua->bastaddr = params->bastaddr;
257
258 if (params->flags & DLM_LKF_CONVERT)
259 error = dlm_user_convert(ls, ua,
260 params->mode, params->flags,
261 params->lkid, params->lvb);
262 else {
263 error = dlm_user_request(ls, ua,
264 params->mode, params->flags,
265 params->name, params->namelen,
266 params->parent);
267 if (!error)
268 error = ua->lksb.sb_lkid;
269 }
270 out:
271 dlm_put_lockspace(ls);
272 return error;
273}
274
275static int device_user_unlock(struct dlm_user_proc *proc,
276 struct dlm_lock_params *params)
277{
278 struct dlm_ls *ls;
279 struct dlm_user_args *ua;
280 int error = -ENOMEM;
281
282 ls = dlm_find_lockspace_local(proc->lockspace);
283 if (!ls)
284 return -ENOENT;
285
286 ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL);
287 if (!ua)
288 goto out;
289 ua->proc = proc;
290 ua->user_lksb = params->lksb;
291 ua->castparam = params->castparam;
292 ua->castaddr = params->castaddr;
293
294 if (params->flags & DLM_LKF_CANCEL)
295 error = dlm_user_cancel(ls, ua, params->flags, params->lkid);
296 else
297 error = dlm_user_unlock(ls, ua, params->flags, params->lkid,
298 params->lvb);
299 out:
300 dlm_put_lockspace(ls);
301 return error;
302}
303
Patrick Caulfield254da032007-03-21 09:23:53 +0000304static int create_misc_device(struct dlm_ls *ls, char *name)
305{
306 int error, len;
307
308 error = -ENOMEM;
309 len = strlen(name) + strlen(name_prefix) + 2;
310 ls->ls_device.name = kzalloc(len, GFP_KERNEL);
311 if (!ls->ls_device.name)
312 goto fail;
313
314 snprintf((char *)ls->ls_device.name, len, "%s_%s", name_prefix,
315 name);
316 ls->ls_device.fops = &device_fops;
317 ls->ls_device.minor = MISC_DYNAMIC_MINOR;
318
319 error = misc_register(&ls->ls_device);
320 if (error) {
321 kfree(ls->ls_device.name);
322 }
323fail:
324 return error;
325}
326
David Teigland72c2be72007-03-30 15:06:16 -0500327static int device_user_purge(struct dlm_user_proc *proc,
328 struct dlm_purge_params *params)
329{
330 struct dlm_ls *ls;
331 int error;
332
333 ls = dlm_find_lockspace_local(proc->lockspace);
334 if (!ls)
335 return -ENOENT;
336
337 error = dlm_user_purge(ls, proc, params->nodeid, params->pid);
338
339 dlm_put_lockspace(ls);
340 return error;
341}
342
David Teigland597d0ca2006-07-12 16:44:04 -0500343static int device_create_lockspace(struct dlm_lspace_params *params)
344{
345 dlm_lockspace_t *lockspace;
346 struct dlm_ls *ls;
Patrick Caulfield254da032007-03-21 09:23:53 +0000347 int error;
David Teigland597d0ca2006-07-12 16:44:04 -0500348
349 if (!capable(CAP_SYS_ADMIN))
350 return -EPERM;
351
352 error = dlm_new_lockspace(params->name, strlen(params->name),
353 &lockspace, 0, DLM_USER_LVB_LEN);
354 if (error)
355 return error;
356
357 ls = dlm_find_lockspace_local(lockspace);
358 if (!ls)
359 return -ENOENT;
360
Patrick Caulfield254da032007-03-21 09:23:53 +0000361 error = create_misc_device(ls, params->name);
David Teigland597d0ca2006-07-12 16:44:04 -0500362 dlm_put_lockspace(ls);
David Teigland597d0ca2006-07-12 16:44:04 -0500363
Patrick Caulfield254da032007-03-21 09:23:53 +0000364 if (error)
365 dlm_release_lockspace(lockspace, 0);
366 else
367 error = ls->ls_device.minor;
368
David Teigland597d0ca2006-07-12 16:44:04 -0500369 return error;
370}
371
372static int device_remove_lockspace(struct dlm_lspace_params *params)
373{
374 dlm_lockspace_t *lockspace;
375 struct dlm_ls *ls;
David Teiglandc6e6f0b2006-08-30 10:50:18 -0500376 int error, force = 0;
David Teigland597d0ca2006-07-12 16:44:04 -0500377
378 if (!capable(CAP_SYS_ADMIN))
379 return -EPERM;
380
381 ls = dlm_find_lockspace_device(params->minor);
382 if (!ls)
383 return -ENOENT;
384
Patrick Caulfield254da032007-03-21 09:23:53 +0000385 /* Deregister the misc device first, so we don't have
386 * a device that's not attached to a lockspace. If
387 * dlm_release_lockspace fails then we can recreate it
388 */
David Teigland597d0ca2006-07-12 16:44:04 -0500389 error = misc_deregister(&ls->ls_device);
390 if (error) {
391 dlm_put_lockspace(ls);
392 goto out;
393 }
394 kfree(ls->ls_device.name);
395
David Teiglandc6e6f0b2006-08-30 10:50:18 -0500396 if (params->flags & DLM_USER_LSFLG_FORCEFREE)
397 force = 2;
398
David Teigland597d0ca2006-07-12 16:44:04 -0500399 lockspace = ls->ls_local_handle;
400
401 /* dlm_release_lockspace waits for references to go to zero,
402 so all processes will need to close their device for the ls
403 before the release will procede */
404
405 dlm_put_lockspace(ls);
David Teiglandc6e6f0b2006-08-30 10:50:18 -0500406 error = dlm_release_lockspace(lockspace, force);
Patrick Caulfield254da032007-03-21 09:23:53 +0000407 if (error)
408 create_misc_device(ls, ls->ls_name);
David Teiglandc6e6f0b2006-08-30 10:50:18 -0500409 out:
David Teigland597d0ca2006-07-12 16:44:04 -0500410 return error;
411}
412
413/* Check the user's version matches ours */
414static int check_version(struct dlm_write_request *req)
415{
416 if (req->version[0] != DLM_DEVICE_VERSION_MAJOR ||
417 (req->version[0] == DLM_DEVICE_VERSION_MAJOR &&
418 req->version[1] > DLM_DEVICE_VERSION_MINOR)) {
419
420 printk(KERN_DEBUG "dlm: process %s (%d) version mismatch "
421 "user (%d.%d.%d) kernel (%d.%d.%d)\n",
422 current->comm,
423 current->pid,
424 req->version[0],
425 req->version[1],
426 req->version[2],
427 DLM_DEVICE_VERSION_MAJOR,
428 DLM_DEVICE_VERSION_MINOR,
429 DLM_DEVICE_VERSION_PATCH);
430 return -EINVAL;
431 }
432 return 0;
433}
434
435/*
436 * device_write
437 *
438 * device_user_lock
439 * dlm_user_request -> request_lock
440 * dlm_user_convert -> convert_lock
441 *
442 * device_user_unlock
443 * dlm_user_unlock -> unlock_lock
444 * dlm_user_cancel -> cancel_lock
445 *
446 * device_create_lockspace
447 * dlm_new_lockspace
448 *
449 * device_remove_lockspace
450 * dlm_release_lockspace
451 */
452
453/* a write to a lockspace device is a lock or unlock request, a write
454 to the control device is to create/remove a lockspace */
455
456static ssize_t device_write(struct file *file, const char __user *buf,
457 size_t count, loff_t *ppos)
458{
459 struct dlm_user_proc *proc = file->private_data;
460 struct dlm_write_request *kbuf;
461 sigset_t tmpsig, allsigs;
462 int error;
463
464#ifdef CONFIG_COMPAT
465 if (count < sizeof(struct dlm_write_request32))
466#else
467 if (count < sizeof(struct dlm_write_request))
468#endif
469 return -EINVAL;
470
471 kbuf = kmalloc(count, GFP_KERNEL);
472 if (!kbuf)
473 return -ENOMEM;
474
475 if (copy_from_user(kbuf, buf, count)) {
476 error = -EFAULT;
477 goto out_free;
478 }
479
480 if (check_version(kbuf)) {
481 error = -EBADE;
482 goto out_free;
483 }
484
485#ifdef CONFIG_COMPAT
486 if (!kbuf->is64bit) {
487 struct dlm_write_request32 *k32buf;
488 k32buf = (struct dlm_write_request32 *)kbuf;
489 kbuf = kmalloc(count + (sizeof(struct dlm_write_request) -
490 sizeof(struct dlm_write_request32)), GFP_KERNEL);
491 if (!kbuf)
492 return -ENOMEM;
493
494 if (proc)
495 set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
496 compat_input(kbuf, k32buf);
497 kfree(k32buf);
498 }
499#endif
500
501 /* do we really need this? can a write happen after a close? */
502 if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) &&
503 test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
504 return -EINVAL;
505
506 sigfillset(&allsigs);
507 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
508
509 error = -EINVAL;
510
511 switch (kbuf->cmd)
512 {
513 case DLM_USER_LOCK:
514 if (!proc) {
515 log_print("no locking on control device");
516 goto out_sig;
517 }
518 error = device_user_lock(proc, &kbuf->i.lock);
519 break;
520
521 case DLM_USER_UNLOCK:
522 if (!proc) {
523 log_print("no locking on control device");
524 goto out_sig;
525 }
526 error = device_user_unlock(proc, &kbuf->i.lock);
527 break;
528
529 case DLM_USER_CREATE_LOCKSPACE:
530 if (proc) {
531 log_print("create/remove only on control device");
532 goto out_sig;
533 }
534 error = device_create_lockspace(&kbuf->i.lspace);
535 break;
536
537 case DLM_USER_REMOVE_LOCKSPACE:
538 if (proc) {
539 log_print("create/remove only on control device");
540 goto out_sig;
541 }
542 error = device_remove_lockspace(&kbuf->i.lspace);
543 break;
544
David Teigland72c2be72007-03-30 15:06:16 -0500545 case DLM_USER_PURGE:
546 if (!proc) {
547 log_print("no locking on control device");
548 goto out_sig;
549 }
550 error = device_user_purge(proc, &kbuf->i.purge);
551 break;
552
David Teigland597d0ca2006-07-12 16:44:04 -0500553 default:
554 log_print("Unknown command passed to DLM device : %d\n",
555 kbuf->cmd);
556 }
557
558 out_sig:
559 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
560 recalc_sigpending();
561 out_free:
562 kfree(kbuf);
563 return error;
564}
565
566/* Every process that opens the lockspace device has its own "proc" structure
567 hanging off the open file that's used to keep track of locks owned by the
568 process and asts that need to be delivered to the process. */
569
570static int device_open(struct inode *inode, struct file *file)
571{
572 struct dlm_user_proc *proc;
573 struct dlm_ls *ls;
574
575 ls = dlm_find_lockspace_device(iminor(inode));
576 if (!ls)
577 return -ENOENT;
578
579 proc = kzalloc(sizeof(struct dlm_user_proc), GFP_KERNEL);
580 if (!proc) {
581 dlm_put_lockspace(ls);
582 return -ENOMEM;
583 }
584
585 proc->lockspace = ls->ls_local_handle;
586 INIT_LIST_HEAD(&proc->asts);
587 INIT_LIST_HEAD(&proc->locks);
David Teiglanda1bc86e2007-01-15 10:34:52 -0600588 INIT_LIST_HEAD(&proc->unlocking);
David Teigland597d0ca2006-07-12 16:44:04 -0500589 spin_lock_init(&proc->asts_spin);
590 spin_lock_init(&proc->locks_spin);
591 init_waitqueue_head(&proc->wait);
592 file->private_data = proc;
593
594 return 0;
595}
596
597static int device_close(struct inode *inode, struct file *file)
598{
599 struct dlm_user_proc *proc = file->private_data;
600 struct dlm_ls *ls;
601 sigset_t tmpsig, allsigs;
602
603 ls = dlm_find_lockspace_local(proc->lockspace);
604 if (!ls)
605 return -ENOENT;
606
607 sigfillset(&allsigs);
608 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
609
610 set_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags);
611
612 dlm_clear_proc_locks(ls, proc);
613
614 /* at this point no more lkb's should exist for this lockspace,
615 so there's no chance of dlm_user_add_ast() being called and
616 looking for lkb->ua->proc */
617
618 kfree(proc);
619 file->private_data = NULL;
620
621 dlm_put_lockspace(ls);
622 dlm_put_lockspace(ls); /* for the find in device_open() */
623
624 /* FIXME: AUTOFREE: if this ls is no longer used do
625 device_remove_lockspace() */
626
627 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
628 recalc_sigpending();
629
630 return 0;
631}
632
633static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
634 int bmode, char __user *buf, size_t count)
635{
636#ifdef CONFIG_COMPAT
637 struct dlm_lock_result32 result32;
638#endif
639 struct dlm_lock_result result;
640 void *resultptr;
641 int error=0;
642 int len;
643 int struct_len;
644
645 memset(&result, 0, sizeof(struct dlm_lock_result));
646 memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
647 result.user_lksb = ua->user_lksb;
648
649 /* FIXME: dlm1 provides for the user's bastparam/addr to not be updated
650 in a conversion unless the conversion is successful. See code
651 in dlm_user_convert() for updating ua from ua_tmp. OpenVMS, though,
652 notes that a new blocking AST address and parameter are set even if
653 the conversion fails, so maybe we should just do that. */
654
655 if (type == AST_BAST) {
656 result.user_astaddr = ua->bastaddr;
657 result.user_astparam = ua->bastparam;
658 result.bast_mode = bmode;
659 } else {
660 result.user_astaddr = ua->castaddr;
661 result.user_astparam = ua->castparam;
662 }
663
664#ifdef CONFIG_COMPAT
665 if (compat)
666 len = sizeof(struct dlm_lock_result32);
667 else
668#endif
669 len = sizeof(struct dlm_lock_result);
670 struct_len = len;
671
672 /* copy lvb to userspace if there is one, it's been updated, and
673 the user buffer has space for it */
674
675 if (ua->update_user_lvb && ua->lksb.sb_lvbptr &&
676 count >= len + DLM_USER_LVB_LEN) {
677 if (copy_to_user(buf+len, ua->lksb.sb_lvbptr,
678 DLM_USER_LVB_LEN)) {
679 error = -EFAULT;
680 goto out;
681 }
682
683 result.lvb_offset = len;
684 len += DLM_USER_LVB_LEN;
685 }
686
687 result.length = len;
688 resultptr = &result;
689#ifdef CONFIG_COMPAT
690 if (compat) {
691 compat_output(&result, &result32);
692 resultptr = &result32;
693 }
694#endif
695
696 if (copy_to_user(buf, resultptr, struct_len))
697 error = -EFAULT;
698 else
699 error = len;
700 out:
701 return error;
702}
703
704/* a read returns a single ast described in a struct dlm_lock_result */
705
706static ssize_t device_read(struct file *file, char __user *buf, size_t count,
707 loff_t *ppos)
708{
709 struct dlm_user_proc *proc = file->private_data;
710 struct dlm_lkb *lkb;
711 struct dlm_user_args *ua;
712 DECLARE_WAITQUEUE(wait, current);
713 int error, type=0, bmode=0, removed = 0;
714
715#ifdef CONFIG_COMPAT
716 if (count < sizeof(struct dlm_lock_result32))
717#else
718 if (count < sizeof(struct dlm_lock_result))
719#endif
720 return -EINVAL;
721
722 /* do we really need this? can a read happen after a close? */
723 if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
724 return -EINVAL;
725
726 spin_lock(&proc->asts_spin);
727 if (list_empty(&proc->asts)) {
728 if (file->f_flags & O_NONBLOCK) {
729 spin_unlock(&proc->asts_spin);
730 return -EAGAIN;
731 }
732
733 add_wait_queue(&proc->wait, &wait);
734
735 repeat:
736 set_current_state(TASK_INTERRUPTIBLE);
737 if (list_empty(&proc->asts) && !signal_pending(current)) {
738 spin_unlock(&proc->asts_spin);
739 schedule();
740 spin_lock(&proc->asts_spin);
741 goto repeat;
742 }
743 set_current_state(TASK_RUNNING);
744 remove_wait_queue(&proc->wait, &wait);
745
746 if (signal_pending(current)) {
747 spin_unlock(&proc->asts_spin);
748 return -ERESTARTSYS;
749 }
750 }
751
752 if (list_empty(&proc->asts)) {
753 spin_unlock(&proc->asts_spin);
754 return -EAGAIN;
755 }
756
757 /* there may be both completion and blocking asts to return for
758 the lkb, don't remove lkb from asts list unless no asts remain */
759
760 lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue);
761
762 if (lkb->lkb_ast_type & AST_COMP) {
763 lkb->lkb_ast_type &= ~AST_COMP;
764 type = AST_COMP;
765 } else if (lkb->lkb_ast_type & AST_BAST) {
766 lkb->lkb_ast_type &= ~AST_BAST;
767 type = AST_BAST;
768 bmode = lkb->lkb_bastmode;
769 }
770
771 if (!lkb->lkb_ast_type) {
772 list_del(&lkb->lkb_astqueue);
773 removed = 1;
774 }
775 spin_unlock(&proc->asts_spin);
776
777 ua = (struct dlm_user_args *)lkb->lkb_astparam;
778 error = copy_result_to_user(ua,
779 test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
780 type, bmode, buf, count);
781
782 /* removes reference for the proc->asts lists added by
783 dlm_user_add_ast() and may result in the lkb being freed */
784 if (removed)
785 dlm_put_lkb(lkb);
786
787 return error;
788}
789
790static unsigned int device_poll(struct file *file, poll_table *wait)
791{
792 struct dlm_user_proc *proc = file->private_data;
793
794 poll_wait(file, &proc->wait, wait);
795
796 spin_lock(&proc->asts_spin);
797 if (!list_empty(&proc->asts)) {
798 spin_unlock(&proc->asts_spin);
799 return POLLIN | POLLRDNORM;
800 }
801 spin_unlock(&proc->asts_spin);
802 return 0;
803}
804
805static int ctl_device_open(struct inode *inode, struct file *file)
806{
807 file->private_data = NULL;
808 return 0;
809}
810
811static int ctl_device_close(struct inode *inode, struct file *file)
812{
813 return 0;
814}
815
Arjan van de Ven00977a52007-02-12 00:55:34 -0800816static const struct file_operations device_fops = {
David Teigland597d0ca2006-07-12 16:44:04 -0500817 .open = device_open,
818 .release = device_close,
819 .read = device_read,
820 .write = device_write,
821 .poll = device_poll,
822 .owner = THIS_MODULE,
823};
824
Arjan van de Ven00977a52007-02-12 00:55:34 -0800825static const struct file_operations ctl_device_fops = {
David Teigland597d0ca2006-07-12 16:44:04 -0500826 .open = ctl_device_open,
827 .release = ctl_device_close,
828 .write = device_write,
829 .owner = THIS_MODULE,
830};
831
832int dlm_user_init(void)
833{
834 int error;
835
836 ctl_device.name = "dlm-control";
837 ctl_device.fops = &ctl_device_fops;
838 ctl_device.minor = MISC_DYNAMIC_MINOR;
839
840 error = misc_register(&ctl_device);
841 if (error)
842 log_print("misc_register failed for control device");
843
844 return error;
845}
846
847void dlm_user_exit(void)
848{
849 misc_deregister(&ctl_device);
850}
851