blob: 40db61dc95f2550f09d592bcd2b2e751fca85291 [file] [log] [blame]
David Teigland597d0ca2006-07-12 16:44:04 -05001/*
2 * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
3 *
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"
25
26static const char *name_prefix="dlm";
27static struct miscdevice ctl_device;
Arjan van de Ven00977a52007-02-12 00:55:34 -080028static const struct file_operations device_fops;
David Teigland597d0ca2006-07-12 16:44:04 -050029
30#ifdef CONFIG_COMPAT
31
32struct dlm_lock_params32 {
33 __u8 mode;
34 __u8 namelen;
35 __u16 flags;
36 __u32 lkid;
37 __u32 parent;
38
39 __u32 castparam;
40 __u32 castaddr;
41 __u32 bastparam;
42 __u32 bastaddr;
43 __u32 lksb;
44
45 char lvb[DLM_USER_LVB_LEN];
46 char name[0];
47};
48
49struct dlm_write_request32 {
50 __u32 version[3];
51 __u8 cmd;
52 __u8 is64bit;
53 __u8 unused[2];
54
55 union {
56 struct dlm_lock_params32 lock;
57 struct dlm_lspace_params lspace;
58 } i;
59};
60
61struct dlm_lksb32 {
62 __u32 sb_status;
63 __u32 sb_lkid;
64 __u8 sb_flags;
65 __u32 sb_lvbptr;
66};
67
68struct dlm_lock_result32 {
69 __u32 length;
70 __u32 user_astaddr;
71 __u32 user_astparam;
72 __u32 user_lksb;
73 struct dlm_lksb32 lksb;
74 __u8 bast_mode;
75 __u8 unused[3];
76 /* Offsets may be zero if no data is present */
77 __u32 lvb_offset;
78};
79
80static void compat_input(struct dlm_write_request *kb,
81 struct dlm_write_request32 *kb32)
82{
83 kb->version[0] = kb32->version[0];
84 kb->version[1] = kb32->version[1];
85 kb->version[2] = kb32->version[2];
86
87 kb->cmd = kb32->cmd;
88 kb->is64bit = kb32->is64bit;
89 if (kb->cmd == DLM_USER_CREATE_LOCKSPACE ||
90 kb->cmd == DLM_USER_REMOVE_LOCKSPACE) {
91 kb->i.lspace.flags = kb32->i.lspace.flags;
92 kb->i.lspace.minor = kb32->i.lspace.minor;
93 strcpy(kb->i.lspace.name, kb32->i.lspace.name);
94 } else {
95 kb->i.lock.mode = kb32->i.lock.mode;
96 kb->i.lock.namelen = kb32->i.lock.namelen;
97 kb->i.lock.flags = kb32->i.lock.flags;
98 kb->i.lock.lkid = kb32->i.lock.lkid;
99 kb->i.lock.parent = kb32->i.lock.parent;
100 kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
101 kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
102 kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
103 kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr;
104 kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb;
105 memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN);
106 memcpy(kb->i.lock.name, kb32->i.lock.name, kb->i.lock.namelen);
107 }
108}
109
110static void compat_output(struct dlm_lock_result *res,
111 struct dlm_lock_result32 *res32)
112{
113 res32->length = res->length - (sizeof(struct dlm_lock_result) -
114 sizeof(struct dlm_lock_result32));
115 res32->user_astaddr = (__u32)(long)res->user_astaddr;
116 res32->user_astparam = (__u32)(long)res->user_astparam;
117 res32->user_lksb = (__u32)(long)res->user_lksb;
118 res32->bast_mode = res->bast_mode;
119
120 res32->lvb_offset = res->lvb_offset;
121 res32->length = res->length;
122
123 res32->lksb.sb_status = res->lksb.sb_status;
124 res32->lksb.sb_flags = res->lksb.sb_flags;
125 res32->lksb.sb_lkid = res->lksb.sb_lkid;
126 res32->lksb.sb_lvbptr = (__u32)(long)res->lksb.sb_lvbptr;
127}
128#endif
129
130
131void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
132{
133 struct dlm_ls *ls;
134 struct dlm_user_args *ua;
135 struct dlm_user_proc *proc;
David Teigland34e22be2006-07-18 11:24:04 -0500136 int remove_ownqueue = 0;
David Teigland597d0ca2006-07-12 16:44:04 -0500137
138 /* dlm_clear_proc_locks() sets ORPHAN/DEAD flag on each
139 lkb before dealing with it. We need to check this
140 flag before taking ls_clear_proc_locks mutex because if
141 it's set, dlm_clear_proc_locks() holds the mutex. */
142
143 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) {
144 /* log_print("user_add_ast skip1 %x", lkb->lkb_flags); */
145 return;
146 }
147
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
153 lkb->ua so we can't try to use it. */
154
155 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) {
156 /* log_print("user_add_ast skip2 %x", lkb->lkb_flags); */
157 goto out;
158 }
159
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);
168 if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) {
169 kref_get(&lkb->lkb_ref);
170 list_add_tail(&lkb->lkb_astqueue, &proc->asts);
171 lkb->lkb_ast_type |= type;
172 wake_up_interruptible(&proc->wait);
173 }
174
David Teigland34e22be2006-07-18 11:24:04 -0500175 /* noqueue requests that fail may need to be removed from the
176 proc's locks list, there should be a better way of detecting
177 this situation than checking all these things... */
David Teigland36098192006-07-20 08:35:39 -0500178
David Teigland34e22be2006-07-18 11:24:04 -0500179 if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV &&
180 ua->lksb.sb_status == -EAGAIN && !list_empty(&lkb->lkb_ownqueue))
181 remove_ownqueue = 1;
182
David Teiglanda1bc86e2007-01-15 10:34:52 -0600183 /* unlocks or cancels of waiting requests need to be removed from the
184 proc's unlocking list, again there must be a better way... */
185
186 if (ua->lksb.sb_status == -DLM_EUNLOCK ||
187 (ua->lksb.sb_status == -DLM_ECANCEL &&
188 lkb->lkb_grmode == DLM_LOCK_IV))
189 remove_ownqueue = 1;
190
David Teigland597d0ca2006-07-12 16:44:04 -0500191 /* We want to copy the lvb to userspace when the completion
192 ast is read if the status is 0, the lock has an lvb and
193 lvb_ops says we should. We could probably have set_lvb_lock()
194 set update_user_lvb instead and not need old_mode */
195
196 if ((lkb->lkb_ast_type & AST_COMP) &&
197 (lkb->lkb_lksb->sb_status == 0) &&
198 lkb->lkb_lksb->sb_lvbptr &&
199 dlm_lvb_operations[ua->old_mode + 1][lkb->lkb_grmode + 1])
200 ua->update_user_lvb = 1;
201 else
202 ua->update_user_lvb = 0;
203
204 spin_unlock(&proc->asts_spin);
David Teigland34e22be2006-07-18 11:24:04 -0500205
206 if (remove_ownqueue) {
207 spin_lock(&ua->proc->locks_spin);
208 list_del_init(&lkb->lkb_ownqueue);
209 spin_unlock(&ua->proc->locks_spin);
210 dlm_put_lkb(lkb);
211 }
David Teigland597d0ca2006-07-12 16:44:04 -0500212 out:
213 mutex_unlock(&ls->ls_clear_proc_locks);
214}
215
216static int device_user_lock(struct dlm_user_proc *proc,
217 struct dlm_lock_params *params)
218{
219 struct dlm_ls *ls;
220 struct dlm_user_args *ua;
221 int error = -ENOMEM;
222
223 ls = dlm_find_lockspace_local(proc->lockspace);
224 if (!ls)
225 return -ENOENT;
226
227 if (!params->castaddr || !params->lksb) {
228 error = -EINVAL;
229 goto out;
230 }
231
232 ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL);
233 if (!ua)
234 goto out;
235 ua->proc = proc;
236 ua->user_lksb = params->lksb;
237 ua->castparam = params->castparam;
238 ua->castaddr = params->castaddr;
239 ua->bastparam = params->bastparam;
240 ua->bastaddr = params->bastaddr;
241
242 if (params->flags & DLM_LKF_CONVERT)
243 error = dlm_user_convert(ls, ua,
244 params->mode, params->flags,
245 params->lkid, params->lvb);
246 else {
247 error = dlm_user_request(ls, ua,
248 params->mode, params->flags,
249 params->name, params->namelen,
250 params->parent);
251 if (!error)
252 error = ua->lksb.sb_lkid;
253 }
254 out:
255 dlm_put_lockspace(ls);
256 return error;
257}
258
259static int device_user_unlock(struct dlm_user_proc *proc,
260 struct dlm_lock_params *params)
261{
262 struct dlm_ls *ls;
263 struct dlm_user_args *ua;
264 int error = -ENOMEM;
265
266 ls = dlm_find_lockspace_local(proc->lockspace);
267 if (!ls)
268 return -ENOENT;
269
270 ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL);
271 if (!ua)
272 goto out;
273 ua->proc = proc;
274 ua->user_lksb = params->lksb;
275 ua->castparam = params->castparam;
276 ua->castaddr = params->castaddr;
277
278 if (params->flags & DLM_LKF_CANCEL)
279 error = dlm_user_cancel(ls, ua, params->flags, params->lkid);
280 else
281 error = dlm_user_unlock(ls, ua, params->flags, params->lkid,
282 params->lvb);
283 out:
284 dlm_put_lockspace(ls);
285 return error;
286}
287
288static int device_create_lockspace(struct dlm_lspace_params *params)
289{
290 dlm_lockspace_t *lockspace;
291 struct dlm_ls *ls;
292 int error, len;
293
294 if (!capable(CAP_SYS_ADMIN))
295 return -EPERM;
296
297 error = dlm_new_lockspace(params->name, strlen(params->name),
298 &lockspace, 0, DLM_USER_LVB_LEN);
299 if (error)
300 return error;
301
302 ls = dlm_find_lockspace_local(lockspace);
303 if (!ls)
304 return -ENOENT;
305
306 error = -ENOMEM;
307 len = strlen(params->name) + strlen(name_prefix) + 2;
308 ls->ls_device.name = kzalloc(len, GFP_KERNEL);
309 if (!ls->ls_device.name)
310 goto fail;
311 snprintf((char *)ls->ls_device.name, len, "%s_%s", name_prefix,
312 params->name);
313 ls->ls_device.fops = &device_fops;
314 ls->ls_device.minor = MISC_DYNAMIC_MINOR;
315
316 error = misc_register(&ls->ls_device);
317 if (error) {
318 kfree(ls->ls_device.name);
319 goto fail;
320 }
321
322 error = ls->ls_device.minor;
323 dlm_put_lockspace(ls);
324 return error;
325
326 fail:
327 dlm_put_lockspace(ls);
328 dlm_release_lockspace(lockspace, 0);
329 return error;
330}
331
332static int device_remove_lockspace(struct dlm_lspace_params *params)
333{
334 dlm_lockspace_t *lockspace;
335 struct dlm_ls *ls;
David Teiglandc6e6f0b2006-08-30 10:50:18 -0500336 int error, force = 0;
David Teigland597d0ca2006-07-12 16:44:04 -0500337
338 if (!capable(CAP_SYS_ADMIN))
339 return -EPERM;
340
341 ls = dlm_find_lockspace_device(params->minor);
342 if (!ls)
343 return -ENOENT;
344
345 error = misc_deregister(&ls->ls_device);
346 if (error) {
347 dlm_put_lockspace(ls);
348 goto out;
349 }
350 kfree(ls->ls_device.name);
351
David Teiglandc6e6f0b2006-08-30 10:50:18 -0500352 if (params->flags & DLM_USER_LSFLG_FORCEFREE)
353 force = 2;
354
David Teigland597d0ca2006-07-12 16:44:04 -0500355 lockspace = ls->ls_local_handle;
356
357 /* dlm_release_lockspace waits for references to go to zero,
358 so all processes will need to close their device for the ls
359 before the release will procede */
360
361 dlm_put_lockspace(ls);
David Teiglandc6e6f0b2006-08-30 10:50:18 -0500362 error = dlm_release_lockspace(lockspace, force);
363 out:
David Teigland597d0ca2006-07-12 16:44:04 -0500364 return error;
365}
366
367/* Check the user's version matches ours */
368static int check_version(struct dlm_write_request *req)
369{
370 if (req->version[0] != DLM_DEVICE_VERSION_MAJOR ||
371 (req->version[0] == DLM_DEVICE_VERSION_MAJOR &&
372 req->version[1] > DLM_DEVICE_VERSION_MINOR)) {
373
374 printk(KERN_DEBUG "dlm: process %s (%d) version mismatch "
375 "user (%d.%d.%d) kernel (%d.%d.%d)\n",
376 current->comm,
377 current->pid,
378 req->version[0],
379 req->version[1],
380 req->version[2],
381 DLM_DEVICE_VERSION_MAJOR,
382 DLM_DEVICE_VERSION_MINOR,
383 DLM_DEVICE_VERSION_PATCH);
384 return -EINVAL;
385 }
386 return 0;
387}
388
389/*
390 * device_write
391 *
392 * device_user_lock
393 * dlm_user_request -> request_lock
394 * dlm_user_convert -> convert_lock
395 *
396 * device_user_unlock
397 * dlm_user_unlock -> unlock_lock
398 * dlm_user_cancel -> cancel_lock
399 *
400 * device_create_lockspace
401 * dlm_new_lockspace
402 *
403 * device_remove_lockspace
404 * dlm_release_lockspace
405 */
406
407/* a write to a lockspace device is a lock or unlock request, a write
408 to the control device is to create/remove a lockspace */
409
410static ssize_t device_write(struct file *file, const char __user *buf,
411 size_t count, loff_t *ppos)
412{
413 struct dlm_user_proc *proc = file->private_data;
414 struct dlm_write_request *kbuf;
415 sigset_t tmpsig, allsigs;
416 int error;
417
418#ifdef CONFIG_COMPAT
419 if (count < sizeof(struct dlm_write_request32))
420#else
421 if (count < sizeof(struct dlm_write_request))
422#endif
423 return -EINVAL;
424
425 kbuf = kmalloc(count, GFP_KERNEL);
426 if (!kbuf)
427 return -ENOMEM;
428
429 if (copy_from_user(kbuf, buf, count)) {
430 error = -EFAULT;
431 goto out_free;
432 }
433
434 if (check_version(kbuf)) {
435 error = -EBADE;
436 goto out_free;
437 }
438
439#ifdef CONFIG_COMPAT
440 if (!kbuf->is64bit) {
441 struct dlm_write_request32 *k32buf;
442 k32buf = (struct dlm_write_request32 *)kbuf;
443 kbuf = kmalloc(count + (sizeof(struct dlm_write_request) -
444 sizeof(struct dlm_write_request32)), GFP_KERNEL);
445 if (!kbuf)
446 return -ENOMEM;
447
448 if (proc)
449 set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
450 compat_input(kbuf, k32buf);
451 kfree(k32buf);
452 }
453#endif
454
455 /* do we really need this? can a write happen after a close? */
456 if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) &&
457 test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
458 return -EINVAL;
459
460 sigfillset(&allsigs);
461 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
462
463 error = -EINVAL;
464
465 switch (kbuf->cmd)
466 {
467 case DLM_USER_LOCK:
468 if (!proc) {
469 log_print("no locking on control device");
470 goto out_sig;
471 }
472 error = device_user_lock(proc, &kbuf->i.lock);
473 break;
474
475 case DLM_USER_UNLOCK:
476 if (!proc) {
477 log_print("no locking on control device");
478 goto out_sig;
479 }
480 error = device_user_unlock(proc, &kbuf->i.lock);
481 break;
482
483 case DLM_USER_CREATE_LOCKSPACE:
484 if (proc) {
485 log_print("create/remove only on control device");
486 goto out_sig;
487 }
488 error = device_create_lockspace(&kbuf->i.lspace);
489 break;
490
491 case DLM_USER_REMOVE_LOCKSPACE:
492 if (proc) {
493 log_print("create/remove only on control device");
494 goto out_sig;
495 }
496 error = device_remove_lockspace(&kbuf->i.lspace);
497 break;
498
499 default:
500 log_print("Unknown command passed to DLM device : %d\n",
501 kbuf->cmd);
502 }
503
504 out_sig:
505 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
506 recalc_sigpending();
507 out_free:
508 kfree(kbuf);
509 return error;
510}
511
512/* Every process that opens the lockspace device has its own "proc" structure
513 hanging off the open file that's used to keep track of locks owned by the
514 process and asts that need to be delivered to the process. */
515
516static int device_open(struct inode *inode, struct file *file)
517{
518 struct dlm_user_proc *proc;
519 struct dlm_ls *ls;
520
521 ls = dlm_find_lockspace_device(iminor(inode));
522 if (!ls)
523 return -ENOENT;
524
525 proc = kzalloc(sizeof(struct dlm_user_proc), GFP_KERNEL);
526 if (!proc) {
527 dlm_put_lockspace(ls);
528 return -ENOMEM;
529 }
530
531 proc->lockspace = ls->ls_local_handle;
532 INIT_LIST_HEAD(&proc->asts);
533 INIT_LIST_HEAD(&proc->locks);
David Teiglanda1bc86e2007-01-15 10:34:52 -0600534 INIT_LIST_HEAD(&proc->unlocking);
David Teigland597d0ca2006-07-12 16:44:04 -0500535 spin_lock_init(&proc->asts_spin);
536 spin_lock_init(&proc->locks_spin);
537 init_waitqueue_head(&proc->wait);
538 file->private_data = proc;
539
540 return 0;
541}
542
543static int device_close(struct inode *inode, struct file *file)
544{
545 struct dlm_user_proc *proc = file->private_data;
546 struct dlm_ls *ls;
547 sigset_t tmpsig, allsigs;
548
549 ls = dlm_find_lockspace_local(proc->lockspace);
550 if (!ls)
551 return -ENOENT;
552
553 sigfillset(&allsigs);
554 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
555
556 set_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags);
557
558 dlm_clear_proc_locks(ls, proc);
559
560 /* at this point no more lkb's should exist for this lockspace,
561 so there's no chance of dlm_user_add_ast() being called and
562 looking for lkb->ua->proc */
563
564 kfree(proc);
565 file->private_data = NULL;
566
567 dlm_put_lockspace(ls);
568 dlm_put_lockspace(ls); /* for the find in device_open() */
569
570 /* FIXME: AUTOFREE: if this ls is no longer used do
571 device_remove_lockspace() */
572
573 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
574 recalc_sigpending();
575
576 return 0;
577}
578
579static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
580 int bmode, char __user *buf, size_t count)
581{
582#ifdef CONFIG_COMPAT
583 struct dlm_lock_result32 result32;
584#endif
585 struct dlm_lock_result result;
586 void *resultptr;
587 int error=0;
588 int len;
589 int struct_len;
590
591 memset(&result, 0, sizeof(struct dlm_lock_result));
592 memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
593 result.user_lksb = ua->user_lksb;
594
595 /* FIXME: dlm1 provides for the user's bastparam/addr to not be updated
596 in a conversion unless the conversion is successful. See code
597 in dlm_user_convert() for updating ua from ua_tmp. OpenVMS, though,
598 notes that a new blocking AST address and parameter are set even if
599 the conversion fails, so maybe we should just do that. */
600
601 if (type == AST_BAST) {
602 result.user_astaddr = ua->bastaddr;
603 result.user_astparam = ua->bastparam;
604 result.bast_mode = bmode;
605 } else {
606 result.user_astaddr = ua->castaddr;
607 result.user_astparam = ua->castparam;
608 }
609
610#ifdef CONFIG_COMPAT
611 if (compat)
612 len = sizeof(struct dlm_lock_result32);
613 else
614#endif
615 len = sizeof(struct dlm_lock_result);
616 struct_len = len;
617
618 /* copy lvb to userspace if there is one, it's been updated, and
619 the user buffer has space for it */
620
621 if (ua->update_user_lvb && ua->lksb.sb_lvbptr &&
622 count >= len + DLM_USER_LVB_LEN) {
623 if (copy_to_user(buf+len, ua->lksb.sb_lvbptr,
624 DLM_USER_LVB_LEN)) {
625 error = -EFAULT;
626 goto out;
627 }
628
629 result.lvb_offset = len;
630 len += DLM_USER_LVB_LEN;
631 }
632
633 result.length = len;
634 resultptr = &result;
635#ifdef CONFIG_COMPAT
636 if (compat) {
637 compat_output(&result, &result32);
638 resultptr = &result32;
639 }
640#endif
641
642 if (copy_to_user(buf, resultptr, struct_len))
643 error = -EFAULT;
644 else
645 error = len;
646 out:
647 return error;
648}
649
650/* a read returns a single ast described in a struct dlm_lock_result */
651
652static ssize_t device_read(struct file *file, char __user *buf, size_t count,
653 loff_t *ppos)
654{
655 struct dlm_user_proc *proc = file->private_data;
656 struct dlm_lkb *lkb;
657 struct dlm_user_args *ua;
658 DECLARE_WAITQUEUE(wait, current);
659 int error, type=0, bmode=0, removed = 0;
660
661#ifdef CONFIG_COMPAT
662 if (count < sizeof(struct dlm_lock_result32))
663#else
664 if (count < sizeof(struct dlm_lock_result))
665#endif
666 return -EINVAL;
667
668 /* do we really need this? can a read happen after a close? */
669 if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
670 return -EINVAL;
671
672 spin_lock(&proc->asts_spin);
673 if (list_empty(&proc->asts)) {
674 if (file->f_flags & O_NONBLOCK) {
675 spin_unlock(&proc->asts_spin);
676 return -EAGAIN;
677 }
678
679 add_wait_queue(&proc->wait, &wait);
680
681 repeat:
682 set_current_state(TASK_INTERRUPTIBLE);
683 if (list_empty(&proc->asts) && !signal_pending(current)) {
684 spin_unlock(&proc->asts_spin);
685 schedule();
686 spin_lock(&proc->asts_spin);
687 goto repeat;
688 }
689 set_current_state(TASK_RUNNING);
690 remove_wait_queue(&proc->wait, &wait);
691
692 if (signal_pending(current)) {
693 spin_unlock(&proc->asts_spin);
694 return -ERESTARTSYS;
695 }
696 }
697
698 if (list_empty(&proc->asts)) {
699 spin_unlock(&proc->asts_spin);
700 return -EAGAIN;
701 }
702
703 /* there may be both completion and blocking asts to return for
704 the lkb, don't remove lkb from asts list unless no asts remain */
705
706 lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue);
707
708 if (lkb->lkb_ast_type & AST_COMP) {
709 lkb->lkb_ast_type &= ~AST_COMP;
710 type = AST_COMP;
711 } else if (lkb->lkb_ast_type & AST_BAST) {
712 lkb->lkb_ast_type &= ~AST_BAST;
713 type = AST_BAST;
714 bmode = lkb->lkb_bastmode;
715 }
716
717 if (!lkb->lkb_ast_type) {
718 list_del(&lkb->lkb_astqueue);
719 removed = 1;
720 }
721 spin_unlock(&proc->asts_spin);
722
723 ua = (struct dlm_user_args *)lkb->lkb_astparam;
724 error = copy_result_to_user(ua,
725 test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
726 type, bmode, buf, count);
727
728 /* removes reference for the proc->asts lists added by
729 dlm_user_add_ast() and may result in the lkb being freed */
730 if (removed)
731 dlm_put_lkb(lkb);
732
733 return error;
734}
735
736static unsigned int device_poll(struct file *file, poll_table *wait)
737{
738 struct dlm_user_proc *proc = file->private_data;
739
740 poll_wait(file, &proc->wait, wait);
741
742 spin_lock(&proc->asts_spin);
743 if (!list_empty(&proc->asts)) {
744 spin_unlock(&proc->asts_spin);
745 return POLLIN | POLLRDNORM;
746 }
747 spin_unlock(&proc->asts_spin);
748 return 0;
749}
750
751static int ctl_device_open(struct inode *inode, struct file *file)
752{
753 file->private_data = NULL;
754 return 0;
755}
756
757static int ctl_device_close(struct inode *inode, struct file *file)
758{
759 return 0;
760}
761
Arjan van de Ven00977a52007-02-12 00:55:34 -0800762static const struct file_operations device_fops = {
David Teigland597d0ca2006-07-12 16:44:04 -0500763 .open = device_open,
764 .release = device_close,
765 .read = device_read,
766 .write = device_write,
767 .poll = device_poll,
768 .owner = THIS_MODULE,
769};
770
Arjan van de Ven00977a52007-02-12 00:55:34 -0800771static const struct file_operations ctl_device_fops = {
David Teigland597d0ca2006-07-12 16:44:04 -0500772 .open = ctl_device_open,
773 .release = ctl_device_close,
774 .write = device_write,
775 .owner = THIS_MODULE,
776};
777
778int dlm_user_init(void)
779{
780 int error;
781
782 ctl_device.name = "dlm-control";
783 ctl_device.fops = &ctl_device_fops;
784 ctl_device.minor = MISC_DYNAMIC_MINOR;
785
786 error = misc_register(&ctl_device);
787 if (error)
788 log_print("misc_register failed for control device");
789
790 return error;
791}
792
793void dlm_user_exit(void)
794{
795 misc_deregister(&ctl_device);
796}
797