1
2
3
4
5
6
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#include "user.h"
26
27static const char name_prefix[] = "dlm";
28static const struct file_operations device_fops;
29static atomic_t dlm_monitor_opened;
30static int dlm_monitor_unused = 1;
31
32#ifdef CONFIG_COMPAT
33
34struct dlm_lock_params32 {
35 __u8 mode;
36 __u8 namelen;
37 __u16 unused;
38 __u32 flags;
39 __u32 lkid;
40 __u32 parent;
41 __u64 xid;
42 __u64 timeout;
43 __u32 castparam;
44 __u32 castaddr;
45 __u32 bastparam;
46 __u32 bastaddr;
47 __u32 lksb;
48 char lvb[DLM_USER_LVB_LEN];
49 char name[0];
50};
51
52struct dlm_write_request32 {
53 __u32 version[3];
54 __u8 cmd;
55 __u8 is64bit;
56 __u8 unused[2];
57
58 union {
59 struct dlm_lock_params32 lock;
60 struct dlm_lspace_params lspace;
61 struct dlm_purge_params purge;
62 } i;
63};
64
65struct dlm_lksb32 {
66 __u32 sb_status;
67 __u32 sb_lkid;
68 __u8 sb_flags;
69 __u32 sb_lvbptr;
70};
71
72struct dlm_lock_result32 {
73 __u32 version[3];
74 __u32 length;
75 __u32 user_astaddr;
76 __u32 user_astparam;
77 __u32 user_lksb;
78 struct dlm_lksb32 lksb;
79 __u8 bast_mode;
80 __u8 unused[3];
81
82 __u32 lvb_offset;
83};
84
85static void compat_input(struct dlm_write_request *kb,
86 struct dlm_write_request32 *kb32,
87 size_t count)
88{
89 kb->version[0] = kb32->version[0];
90 kb->version[1] = kb32->version[1];
91 kb->version[2] = kb32->version[2];
92
93 kb->cmd = kb32->cmd;
94 kb->is64bit = kb32->is64bit;
95 if (kb->cmd == DLM_USER_CREATE_LOCKSPACE ||
96 kb->cmd == DLM_USER_REMOVE_LOCKSPACE) {
97 kb->i.lspace.flags = kb32->i.lspace.flags;
98 kb->i.lspace.minor = kb32->i.lspace.minor;
99 memcpy(kb->i.lspace.name, kb32->i.lspace.name, count -
100 offsetof(struct dlm_write_request32, i.lspace.name));
101 } else if (kb->cmd == DLM_USER_PURGE) {
102 kb->i.purge.nodeid = kb32->i.purge.nodeid;
103 kb->i.purge.pid = kb32->i.purge.pid;
104 } else {
105 kb->i.lock.mode = kb32->i.lock.mode;
106 kb->i.lock.namelen = kb32->i.lock.namelen;
107 kb->i.lock.flags = kb32->i.lock.flags;
108 kb->i.lock.lkid = kb32->i.lock.lkid;
109 kb->i.lock.parent = kb32->i.lock.parent;
110 kb->i.lock.xid = kb32->i.lock.xid;
111 kb->i.lock.timeout = kb32->i.lock.timeout;
112 kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
113 kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
114 kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
115 kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr;
116 kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb;
117 memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN);
118 memcpy(kb->i.lock.name, kb32->i.lock.name, count -
119 offsetof(struct dlm_write_request32, i.lock.name));
120 }
121}
122
123static void compat_output(struct dlm_lock_result *res,
124 struct dlm_lock_result32 *res32)
125{
126 res32->version[0] = res->version[0];
127 res32->version[1] = res->version[1];
128 res32->version[2] = res->version[2];
129
130 res32->user_astaddr = (__u32)(long)res->user_astaddr;
131 res32->user_astparam = (__u32)(long)res->user_astparam;
132 res32->user_lksb = (__u32)(long)res->user_lksb;
133 res32->bast_mode = res->bast_mode;
134
135 res32->lvb_offset = res->lvb_offset;
136 res32->length = res->length;
137
138 res32->lksb.sb_status = res->lksb.sb_status;
139 res32->lksb.sb_flags = res->lksb.sb_flags;
140 res32->lksb.sb_lkid = res->lksb.sb_lkid;
141 res32->lksb.sb_lvbptr = (__u32)(long)res->lksb.sb_lvbptr;
142}
143#endif
144
145
146
147
148
149
150
151
152
153
154
155
156static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
157{
158 switch (sb_status) {
159 case -DLM_EUNLOCK:
160 return 1;
161 case -DLM_ECANCEL:
162 case -ETIMEDOUT:
163 case -EDEADLK:
164 if (lkb->lkb_grmode == DLM_LOCK_IV)
165 return 1;
166 break;
167 case -EAGAIN:
168 if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV)
169 return 1;
170 break;
171 }
172 return 0;
173}
174
175
176
177
178void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
179{
180 struct dlm_ls *ls;
181 struct dlm_user_args *ua;
182 struct dlm_user_proc *proc;
183 int eol = 0, ast_type;
184
185 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
186 return;
187
188 ls = lkb->lkb_resource->res_ls;
189 mutex_lock(&ls->ls_clear_proc_locks);
190
191
192
193
194
195
196
197 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
198 goto out;
199
200 DLM_ASSERT(lkb->lkb_ua, dlm_print_lkb(lkb););
201 ua = lkb->lkb_ua;
202 proc = ua->proc;
203
204 if (type == AST_BAST && ua->bastaddr == NULL)
205 goto out;
206
207 spin_lock(&proc->asts_spin);
208
209 ast_type = lkb->lkb_ast_type;
210 lkb->lkb_ast_type |= type;
211
212 if (!ast_type) {
213 kref_get(&lkb->lkb_ref);
214 list_add_tail(&lkb->lkb_astqueue, &proc->asts);
215 wake_up_interruptible(&proc->wait);
216 }
217 if (type == AST_COMP && (ast_type & AST_COMP))
218 log_debug(ls, "ast overlap %x status %x %x",
219 lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags);
220
221 eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type);
222 if (eol) {
223 lkb->lkb_ast_type &= ~AST_BAST;
224 lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
225 }
226
227
228
229
230
231
232 if ((lkb->lkb_ast_type & AST_COMP) &&
233 (lkb->lkb_lksb->sb_status == 0) &&
234 lkb->lkb_lksb->sb_lvbptr &&
235 dlm_lvb_operations[ua->old_mode + 1][lkb->lkb_grmode + 1])
236 ua->update_user_lvb = 1;
237 else
238 ua->update_user_lvb = 0;
239
240 spin_unlock(&proc->asts_spin);
241
242 if (eol) {
243 spin_lock(&proc->locks_spin);
244 if (!list_empty(&lkb->lkb_ownqueue)) {
245 list_del_init(&lkb->lkb_ownqueue);
246 dlm_put_lkb(lkb);
247 }
248 spin_unlock(&proc->locks_spin);
249 }
250 out:
251 mutex_unlock(&ls->ls_clear_proc_locks);
252}
253
254static int device_user_lock(struct dlm_user_proc *proc,
255 struct dlm_lock_params *params)
256{
257 struct dlm_ls *ls;
258 struct dlm_user_args *ua;
259 int error = -ENOMEM;
260
261 ls = dlm_find_lockspace_local(proc->lockspace);
262 if (!ls)
263 return -ENOENT;
264
265 if (!params->castaddr || !params->lksb) {
266 error = -EINVAL;
267 goto out;
268 }
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 ua->bastparam = params->bastparam;
278 ua->bastaddr = params->bastaddr;
279 ua->xid = params->xid;
280
281 if (params->flags & DLM_LKF_CONVERT)
282 error = dlm_user_convert(ls, ua,
283 params->mode, params->flags,
284 params->lkid, params->lvb,
285 (unsigned long) params->timeout);
286 else {
287 error = dlm_user_request(ls, ua,
288 params->mode, params->flags,
289 params->name, params->namelen,
290 (unsigned long) params->timeout);
291 if (!error)
292 error = ua->lksb.sb_lkid;
293 }
294 out:
295 dlm_put_lockspace(ls);
296 return error;
297}
298
299static int device_user_unlock(struct dlm_user_proc *proc,
300 struct dlm_lock_params *params)
301{
302 struct dlm_ls *ls;
303 struct dlm_user_args *ua;
304 int error = -ENOMEM;
305
306 ls = dlm_find_lockspace_local(proc->lockspace);
307 if (!ls)
308 return -ENOENT;
309
310 ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL);
311 if (!ua)
312 goto out;
313 ua->proc = proc;
314 ua->user_lksb = params->lksb;
315 ua->castparam = params->castparam;
316 ua->castaddr = params->castaddr;
317
318 if (params->flags & DLM_LKF_CANCEL)
319 error = dlm_user_cancel(ls, ua, params->flags, params->lkid);
320 else
321 error = dlm_user_unlock(ls, ua, params->flags, params->lkid,
322 params->lvb);
323 out:
324 dlm_put_lockspace(ls);
325 return error;
326}
327
328static int device_user_deadlock(struct dlm_user_proc *proc,
329 struct dlm_lock_params *params)
330{
331 struct dlm_ls *ls;
332 int error;
333
334 ls = dlm_find_lockspace_local(proc->lockspace);
335 if (!ls)
336 return -ENOENT;
337
338 error = dlm_user_deadlock(ls, params->flags, params->lkid);
339
340 dlm_put_lockspace(ls);
341 return error;
342}
343
344static int dlm_device_register(struct dlm_ls *ls, char *name)
345{
346 int error, len;
347
348
349
350 if (ls->ls_device.name)
351 return 0;
352
353 error = -ENOMEM;
354 len = strlen(name) + strlen(name_prefix) + 2;
355 ls->ls_device.name = kzalloc(len, GFP_KERNEL);
356 if (!ls->ls_device.name)
357 goto fail;
358
359 snprintf((char *)ls->ls_device.name, len, "%s_%s", name_prefix,
360 name);
361 ls->ls_device.fops = &device_fops;
362 ls->ls_device.minor = MISC_DYNAMIC_MINOR;
363
364 error = misc_register(&ls->ls_device);
365 if (error) {
366 kfree(ls->ls_device.name);
367 }
368fail:
369 return error;
370}
371
372int dlm_device_deregister(struct dlm_ls *ls)
373{
374 int error;
375
376
377
378
379 if (!ls->ls_device.name)
380 return 0;
381
382 error = misc_deregister(&ls->ls_device);
383 if (!error)
384 kfree(ls->ls_device.name);
385 return error;
386}
387
388static int device_user_purge(struct dlm_user_proc *proc,
389 struct dlm_purge_params *params)
390{
391 struct dlm_ls *ls;
392 int error;
393
394 ls = dlm_find_lockspace_local(proc->lockspace);
395 if (!ls)
396 return -ENOENT;
397
398 error = dlm_user_purge(ls, proc, params->nodeid, params->pid);
399
400 dlm_put_lockspace(ls);
401 return error;
402}
403
404static int device_create_lockspace(struct dlm_lspace_params *params)
405{
406 dlm_lockspace_t *lockspace;
407 struct dlm_ls *ls;
408 int error;
409
410 if (!capable(CAP_SYS_ADMIN))
411 return -EPERM;
412
413 error = dlm_new_lockspace(params->name, strlen(params->name),
414 &lockspace, params->flags, DLM_USER_LVB_LEN);
415 if (error)
416 return error;
417
418 ls = dlm_find_lockspace_local(lockspace);
419 if (!ls)
420 return -ENOENT;
421
422 error = dlm_device_register(ls, params->name);
423 dlm_put_lockspace(ls);
424
425 if (error)
426 dlm_release_lockspace(lockspace, 0);
427 else
428 error = ls->ls_device.minor;
429
430 return error;
431}
432
433static int device_remove_lockspace(struct dlm_lspace_params *params)
434{
435 dlm_lockspace_t *lockspace;
436 struct dlm_ls *ls;
437 int error, force = 0;
438
439 if (!capable(CAP_SYS_ADMIN))
440 return -EPERM;
441
442 ls = dlm_find_lockspace_device(params->minor);
443 if (!ls)
444 return -ENOENT;
445
446 if (params->flags & DLM_USER_LSFLG_FORCEFREE)
447 force = 2;
448
449 lockspace = ls->ls_local_handle;
450 dlm_put_lockspace(ls);
451
452
453
454
455
456
457
458
459 error = dlm_release_lockspace(lockspace, force);
460 if (error > 0)
461 error = 0;
462 return error;
463}
464
465
466static int check_version(struct dlm_write_request *req)
467{
468 if (req->version[0] != DLM_DEVICE_VERSION_MAJOR ||
469 (req->version[0] == DLM_DEVICE_VERSION_MAJOR &&
470 req->version[1] > DLM_DEVICE_VERSION_MINOR)) {
471
472 printk(KERN_DEBUG "dlm: process %s (%d) version mismatch "
473 "user (%d.%d.%d) kernel (%d.%d.%d)\n",
474 current->comm,
475 task_pid_nr(current),
476 req->version[0],
477 req->version[1],
478 req->version[2],
479 DLM_DEVICE_VERSION_MAJOR,
480 DLM_DEVICE_VERSION_MINOR,
481 DLM_DEVICE_VERSION_PATCH);
482 return -EINVAL;
483 }
484 return 0;
485}
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508static ssize_t device_write(struct file *file, const char __user *buf,
509 size_t count, loff_t *ppos)
510{
511 struct dlm_user_proc *proc = file->private_data;
512 struct dlm_write_request *kbuf;
513 sigset_t tmpsig, allsigs;
514 int error;
515
516#ifdef CONFIG_COMPAT
517 if (count < sizeof(struct dlm_write_request32))
518#else
519 if (count < sizeof(struct dlm_write_request))
520#endif
521 return -EINVAL;
522
523 kbuf = kzalloc(count + 1, GFP_KERNEL);
524 if (!kbuf)
525 return -ENOMEM;
526
527 if (copy_from_user(kbuf, buf, count)) {
528 error = -EFAULT;
529 goto out_free;
530 }
531
532 if (check_version(kbuf)) {
533 error = -EBADE;
534 goto out_free;
535 }
536
537#ifdef CONFIG_COMPAT
538 if (!kbuf->is64bit) {
539 struct dlm_write_request32 *k32buf;
540 k32buf = (struct dlm_write_request32 *)kbuf;
541 kbuf = kmalloc(count + 1 + (sizeof(struct dlm_write_request) -
542 sizeof(struct dlm_write_request32)), GFP_KERNEL);
543 if (!kbuf) {
544 kfree(k32buf);
545 return -ENOMEM;
546 }
547
548 if (proc)
549 set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
550 compat_input(kbuf, k32buf, count + 1);
551 kfree(k32buf);
552 }
553#endif
554
555
556 if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) &&
557 (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))) {
558 error = -EINVAL;
559 goto out_free;
560 }
561
562 sigfillset(&allsigs);
563 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
564
565 error = -EINVAL;
566
567 switch (kbuf->cmd)
568 {
569 case DLM_USER_LOCK:
570 if (!proc) {
571 log_print("no locking on control device");
572 goto out_sig;
573 }
574 error = device_user_lock(proc, &kbuf->i.lock);
575 break;
576
577 case DLM_USER_UNLOCK:
578 if (!proc) {
579 log_print("no locking on control device");
580 goto out_sig;
581 }
582 error = device_user_unlock(proc, &kbuf->i.lock);
583 break;
584
585 case DLM_USER_DEADLOCK:
586 if (!proc) {
587 log_print("no locking on control device");
588 goto out_sig;
589 }
590 error = device_user_deadlock(proc, &kbuf->i.lock);
591 break;
592
593 case DLM_USER_CREATE_LOCKSPACE:
594 if (proc) {
595 log_print("create/remove only on control device");
596 goto out_sig;
597 }
598 error = device_create_lockspace(&kbuf->i.lspace);
599 break;
600
601 case DLM_USER_REMOVE_LOCKSPACE:
602 if (proc) {
603 log_print("create/remove only on control device");
604 goto out_sig;
605 }
606 error = device_remove_lockspace(&kbuf->i.lspace);
607 break;
608
609 case DLM_USER_PURGE:
610 if (!proc) {
611 log_print("no locking on control device");
612 goto out_sig;
613 }
614 error = device_user_purge(proc, &kbuf->i.purge);
615 break;
616
617 default:
618 log_print("Unknown command passed to DLM device : %d\n",
619 kbuf->cmd);
620 }
621
622 out_sig:
623 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
624 recalc_sigpending();
625 out_free:
626 kfree(kbuf);
627 return error;
628}
629
630
631
632
633
634static int device_open(struct inode *inode, struct file *file)
635{
636 struct dlm_user_proc *proc;
637 struct dlm_ls *ls;
638
639 ls = dlm_find_lockspace_device(iminor(inode));
640 if (!ls)
641 return -ENOENT;
642
643 proc = kzalloc(sizeof(struct dlm_user_proc), GFP_KERNEL);
644 if (!proc) {
645 dlm_put_lockspace(ls);
646 return -ENOMEM;
647 }
648
649 proc->lockspace = ls->ls_local_handle;
650 INIT_LIST_HEAD(&proc->asts);
651 INIT_LIST_HEAD(&proc->locks);
652 INIT_LIST_HEAD(&proc->unlocking);
653 spin_lock_init(&proc->asts_spin);
654 spin_lock_init(&proc->locks_spin);
655 init_waitqueue_head(&proc->wait);
656 file->private_data = proc;
657
658 return 0;
659}
660
661static int device_close(struct inode *inode, struct file *file)
662{
663 struct dlm_user_proc *proc = file->private_data;
664 struct dlm_ls *ls;
665 sigset_t tmpsig, allsigs;
666
667 ls = dlm_find_lockspace_local(proc->lockspace);
668 if (!ls)
669 return -ENOENT;
670
671 sigfillset(&allsigs);
672 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
673
674 set_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags);
675
676 dlm_clear_proc_locks(ls, proc);
677
678
679
680
681
682 kfree(proc);
683 file->private_data = NULL;
684
685 dlm_put_lockspace(ls);
686 dlm_put_lockspace(ls);
687
688
689
690
691 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
692 recalc_sigpending();
693
694 return 0;
695}
696
697static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
698 int bmode, char __user *buf, size_t count)
699{
700#ifdef CONFIG_COMPAT
701 struct dlm_lock_result32 result32;
702#endif
703 struct dlm_lock_result result;
704 void *resultptr;
705 int error=0;
706 int len;
707 int struct_len;
708
709 memset(&result, 0, sizeof(struct dlm_lock_result));
710 result.version[0] = DLM_DEVICE_VERSION_MAJOR;
711 result.version[1] = DLM_DEVICE_VERSION_MINOR;
712 result.version[2] = DLM_DEVICE_VERSION_PATCH;
713 memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
714 result.user_lksb = ua->user_lksb;
715
716
717
718
719
720
721
722 if (type == AST_BAST) {
723 result.user_astaddr = ua->bastaddr;
724 result.user_astparam = ua->bastparam;
725 result.bast_mode = bmode;
726 } else {
727 result.user_astaddr = ua->castaddr;
728 result.user_astparam = ua->castparam;
729 }
730
731#ifdef CONFIG_COMPAT
732 if (compat)
733 len = sizeof(struct dlm_lock_result32);
734 else
735#endif
736 len = sizeof(struct dlm_lock_result);
737 struct_len = len;
738
739
740
741
742 if (ua->update_user_lvb && ua->lksb.sb_lvbptr &&
743 count >= len + DLM_USER_LVB_LEN) {
744 if (copy_to_user(buf+len, ua->lksb.sb_lvbptr,
745 DLM_USER_LVB_LEN)) {
746 error = -EFAULT;
747 goto out;
748 }
749
750 result.lvb_offset = len;
751 len += DLM_USER_LVB_LEN;
752 }
753
754 result.length = len;
755 resultptr = &result;
756#ifdef CONFIG_COMPAT
757 if (compat) {
758 compat_output(&result, &result32);
759 resultptr = &result32;
760 }
761#endif
762
763 if (copy_to_user(buf, resultptr, struct_len))
764 error = -EFAULT;
765 else
766 error = len;
767 out:
768 return error;
769}
770
771static int copy_version_to_user(char __user *buf, size_t count)
772{
773 struct dlm_device_version ver;
774
775 memset(&ver, 0, sizeof(struct dlm_device_version));
776 ver.version[0] = DLM_DEVICE_VERSION_MAJOR;
777 ver.version[1] = DLM_DEVICE_VERSION_MINOR;
778 ver.version[2] = DLM_DEVICE_VERSION_PATCH;
779
780 if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version)))
781 return -EFAULT;
782 return sizeof(struct dlm_device_version);
783}
784
785
786
787static ssize_t device_read(struct file *file, char __user *buf, size_t count,
788 loff_t *ppos)
789{
790 struct dlm_user_proc *proc = file->private_data;
791 struct dlm_lkb *lkb;
792 DECLARE_WAITQUEUE(wait, current);
793 int error, type=0, bmode=0, removed = 0;
794
795 if (count == sizeof(struct dlm_device_version)) {
796 error = copy_version_to_user(buf, count);
797 return error;
798 }
799
800 if (!proc) {
801 log_print("non-version read from control device %zu", count);
802 return -EINVAL;
803 }
804
805#ifdef CONFIG_COMPAT
806 if (count < sizeof(struct dlm_lock_result32))
807#else
808 if (count < sizeof(struct dlm_lock_result))
809#endif
810 return -EINVAL;
811
812
813 if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
814 return -EINVAL;
815
816 spin_lock(&proc->asts_spin);
817 if (list_empty(&proc->asts)) {
818 if (file->f_flags & O_NONBLOCK) {
819 spin_unlock(&proc->asts_spin);
820 return -EAGAIN;
821 }
822
823 add_wait_queue(&proc->wait, &wait);
824
825 repeat:
826 set_current_state(TASK_INTERRUPTIBLE);
827 if (list_empty(&proc->asts) && !signal_pending(current)) {
828 spin_unlock(&proc->asts_spin);
829 schedule();
830 spin_lock(&proc->asts_spin);
831 goto repeat;
832 }
833 set_current_state(TASK_RUNNING);
834 remove_wait_queue(&proc->wait, &wait);
835
836 if (signal_pending(current)) {
837 spin_unlock(&proc->asts_spin);
838 return -ERESTARTSYS;
839 }
840 }
841
842
843
844
845 lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue);
846
847 if (lkb->lkb_ast_type & AST_COMP) {
848 lkb->lkb_ast_type &= ~AST_COMP;
849 type = AST_COMP;
850 } else if (lkb->lkb_ast_type & AST_BAST) {
851 lkb->lkb_ast_type &= ~AST_BAST;
852 type = AST_BAST;
853 bmode = lkb->lkb_bastmode;
854 }
855
856 if (!lkb->lkb_ast_type) {
857 list_del(&lkb->lkb_astqueue);
858 removed = 1;
859 }
860 spin_unlock(&proc->asts_spin);
861
862 error = copy_result_to_user(lkb->lkb_ua,
863 test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
864 type, bmode, buf, count);
865
866
867
868 if (removed)
869 dlm_put_lkb(lkb);
870
871 return error;
872}
873
874static unsigned int device_poll(struct file *file, poll_table *wait)
875{
876 struct dlm_user_proc *proc = file->private_data;
877
878 poll_wait(file, &proc->wait, wait);
879
880 spin_lock(&proc->asts_spin);
881 if (!list_empty(&proc->asts)) {
882 spin_unlock(&proc->asts_spin);
883 return POLLIN | POLLRDNORM;
884 }
885 spin_unlock(&proc->asts_spin);
886 return 0;
887}
888
889int dlm_user_daemon_available(void)
890{
891
892
893
894 if (!dlm_our_nodeid())
895 return 0;
896
897
898
899
900
901
902
903 if (dlm_monitor_unused)
904 return 1;
905
906 return atomic_read(&dlm_monitor_opened) ? 1 : 0;
907}
908
909static int ctl_device_open(struct inode *inode, struct file *file)
910{
911 file->private_data = NULL;
912 return 0;
913}
914
915static int ctl_device_close(struct inode *inode, struct file *file)
916{
917 return 0;
918}
919
920static int monitor_device_open(struct inode *inode, struct file *file)
921{
922 atomic_inc(&dlm_monitor_opened);
923 dlm_monitor_unused = 0;
924 return 0;
925}
926
927static int monitor_device_close(struct inode *inode, struct file *file)
928{
929 if (atomic_dec_and_test(&dlm_monitor_opened))
930 dlm_stop_lockspaces();
931 return 0;
932}
933
934static const struct file_operations device_fops = {
935 .open = device_open,
936 .release = device_close,
937 .read = device_read,
938 .write = device_write,
939 .poll = device_poll,
940 .owner = THIS_MODULE,
941};
942
943static const struct file_operations ctl_device_fops = {
944 .open = ctl_device_open,
945 .release = ctl_device_close,
946 .read = device_read,
947 .write = device_write,
948 .owner = THIS_MODULE,
949};
950
951static struct miscdevice ctl_device = {
952 .name = "dlm-control",
953 .fops = &ctl_device_fops,
954 .minor = MISC_DYNAMIC_MINOR,
955};
956
957static const struct file_operations monitor_device_fops = {
958 .open = monitor_device_open,
959 .release = monitor_device_close,
960 .owner = THIS_MODULE,
961};
962
963static struct miscdevice monitor_device = {
964 .name = "dlm-monitor",
965 .fops = &monitor_device_fops,
966 .minor = MISC_DYNAMIC_MINOR,
967};
968
969int __init dlm_user_init(void)
970{
971 int error;
972
973 atomic_set(&dlm_monitor_opened, 0);
974
975 error = misc_register(&ctl_device);
976 if (error) {
977 log_print("misc_register failed for control device");
978 goto out;
979 }
980
981 error = misc_register(&monitor_device);
982 if (error) {
983 log_print("misc_register failed for monitor device");
984 misc_deregister(&ctl_device);
985 }
986 out:
987 return error;
988}
989
990void dlm_user_exit(void)
991{
992 misc_deregister(&ctl_device);
993 misc_deregister(&monitor_device);
994}
995
996