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 int namelen)
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, namelen);
100 } else if (kb->cmd == DLM_USER_PURGE) {
101 kb->i.purge.nodeid = kb32->i.purge.nodeid;
102 kb->i.purge.pid = kb32->i.purge.pid;
103 } else {
104 kb->i.lock.mode = kb32->i.lock.mode;
105 kb->i.lock.namelen = kb32->i.lock.namelen;
106 kb->i.lock.flags = kb32->i.lock.flags;
107 kb->i.lock.lkid = kb32->i.lock.lkid;
108 kb->i.lock.parent = kb32->i.lock.parent;
109 kb->i.lock.xid = kb32->i.lock.xid;
110 kb->i.lock.timeout = kb32->i.lock.timeout;
111 kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
112 kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
113 kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
114 kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr;
115 kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb;
116 memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN);
117 memcpy(kb->i.lock.name, kb32->i.lock.name, namelen);
118 }
119}
120
121static void compat_output(struct dlm_lock_result *res,
122 struct dlm_lock_result32 *res32)
123{
124 res32->version[0] = res->version[0];
125 res32->version[1] = res->version[1];
126 res32->version[2] = res->version[2];
127
128 res32->user_astaddr = (__u32)(long)res->user_astaddr;
129 res32->user_astparam = (__u32)(long)res->user_astparam;
130 res32->user_lksb = (__u32)(long)res->user_lksb;
131 res32->bast_mode = res->bast_mode;
132
133 res32->lvb_offset = res->lvb_offset;
134 res32->length = res->length;
135
136 res32->lksb.sb_status = res->lksb.sb_status;
137 res32->lksb.sb_flags = res->lksb.sb_flags;
138 res32->lksb.sb_lkid = res->lksb.sb_lkid;
139 res32->lksb.sb_lvbptr = (__u32)(long)res->lksb.sb_lvbptr;
140}
141#endif
142
143
144
145
146
147
148
149
150
151
152
153
154static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
155{
156 switch (sb_status) {
157 case -DLM_EUNLOCK:
158 return 1;
159 case -DLM_ECANCEL:
160 case -ETIMEDOUT:
161 case -EDEADLK:
162 if (lkb->lkb_grmode == DLM_LOCK_IV)
163 return 1;
164 break;
165 case -EAGAIN:
166 if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV)
167 return 1;
168 break;
169 }
170 return 0;
171}
172
173
174
175
176void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
177{
178 struct dlm_ls *ls;
179 struct dlm_user_args *ua;
180 struct dlm_user_proc *proc;
181 int eol = 0, ast_type;
182
183 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
184 return;
185
186 ls = lkb->lkb_resource->res_ls;
187 mutex_lock(&ls->ls_clear_proc_locks);
188
189
190
191
192
193
194
195 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
196 goto out;
197
198 DLM_ASSERT(lkb->lkb_ua, dlm_print_lkb(lkb););
199 ua = lkb->lkb_ua;
200 proc = ua->proc;
201
202 if (type == AST_BAST && ua->bastaddr == NULL)
203 goto out;
204
205 spin_lock(&proc->asts_spin);
206
207 ast_type = lkb->lkb_ast_type;
208 lkb->lkb_ast_type |= type;
209 if (bastmode)
210 lkb->lkb_bastmode = bastmode;
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 int namelen = 0;
541
542 if (count > sizeof(struct dlm_write_request32))
543 namelen = count - sizeof(struct dlm_write_request32);
544
545 k32buf = (struct dlm_write_request32 *)kbuf;
546
547
548 kbuf = kzalloc(sizeof(struct dlm_write_request) + namelen + 1,
549 GFP_KERNEL);
550 if (!kbuf) {
551 kfree(k32buf);
552 return -ENOMEM;
553 }
554
555 if (proc)
556 set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
557
558 compat_input(kbuf, k32buf, namelen);
559 kfree(k32buf);
560 }
561#endif
562
563
564 if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) &&
565 (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))) {
566 error = -EINVAL;
567 goto out_free;
568 }
569
570 sigfillset(&allsigs);
571 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
572
573 error = -EINVAL;
574
575 switch (kbuf->cmd)
576 {
577 case DLM_USER_LOCK:
578 if (!proc) {
579 log_print("no locking on control device");
580 goto out_sig;
581 }
582 error = device_user_lock(proc, &kbuf->i.lock);
583 break;
584
585 case DLM_USER_UNLOCK:
586 if (!proc) {
587 log_print("no locking on control device");
588 goto out_sig;
589 }
590 error = device_user_unlock(proc, &kbuf->i.lock);
591 break;
592
593 case DLM_USER_DEADLOCK:
594 if (!proc) {
595 log_print("no locking on control device");
596 goto out_sig;
597 }
598 error = device_user_deadlock(proc, &kbuf->i.lock);
599 break;
600
601 case DLM_USER_CREATE_LOCKSPACE:
602 if (proc) {
603 log_print("create/remove only on control device");
604 goto out_sig;
605 }
606 error = device_create_lockspace(&kbuf->i.lspace);
607 break;
608
609 case DLM_USER_REMOVE_LOCKSPACE:
610 if (proc) {
611 log_print("create/remove only on control device");
612 goto out_sig;
613 }
614 error = device_remove_lockspace(&kbuf->i.lspace);
615 break;
616
617 case DLM_USER_PURGE:
618 if (!proc) {
619 log_print("no locking on control device");
620 goto out_sig;
621 }
622 error = device_user_purge(proc, &kbuf->i.purge);
623 break;
624
625 default:
626 log_print("Unknown command passed to DLM device : %d\n",
627 kbuf->cmd);
628 }
629
630 out_sig:
631 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
632 recalc_sigpending();
633 out_free:
634 kfree(kbuf);
635 return error;
636}
637
638
639
640
641
642static int device_open(struct inode *inode, struct file *file)
643{
644 struct dlm_user_proc *proc;
645 struct dlm_ls *ls;
646
647 ls = dlm_find_lockspace_device(iminor(inode));
648 if (!ls)
649 return -ENOENT;
650
651 proc = kzalloc(sizeof(struct dlm_user_proc), GFP_KERNEL);
652 if (!proc) {
653 dlm_put_lockspace(ls);
654 return -ENOMEM;
655 }
656
657 proc->lockspace = ls->ls_local_handle;
658 INIT_LIST_HEAD(&proc->asts);
659 INIT_LIST_HEAD(&proc->locks);
660 INIT_LIST_HEAD(&proc->unlocking);
661 spin_lock_init(&proc->asts_spin);
662 spin_lock_init(&proc->locks_spin);
663 init_waitqueue_head(&proc->wait);
664 file->private_data = proc;
665
666 return 0;
667}
668
669static int device_close(struct inode *inode, struct file *file)
670{
671 struct dlm_user_proc *proc = file->private_data;
672 struct dlm_ls *ls;
673 sigset_t tmpsig, allsigs;
674
675 ls = dlm_find_lockspace_local(proc->lockspace);
676 if (!ls)
677 return -ENOENT;
678
679 sigfillset(&allsigs);
680 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
681
682 set_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags);
683
684 dlm_clear_proc_locks(ls, proc);
685
686
687
688
689
690 kfree(proc);
691 file->private_data = NULL;
692
693 dlm_put_lockspace(ls);
694 dlm_put_lockspace(ls);
695
696
697
698
699 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
700 recalc_sigpending();
701
702 return 0;
703}
704
705static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
706 int bmode, char __user *buf, size_t count)
707{
708#ifdef CONFIG_COMPAT
709 struct dlm_lock_result32 result32;
710#endif
711 struct dlm_lock_result result;
712 void *resultptr;
713 int error=0;
714 int len;
715 int struct_len;
716
717 memset(&result, 0, sizeof(struct dlm_lock_result));
718 result.version[0] = DLM_DEVICE_VERSION_MAJOR;
719 result.version[1] = DLM_DEVICE_VERSION_MINOR;
720 result.version[2] = DLM_DEVICE_VERSION_PATCH;
721 memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
722 result.user_lksb = ua->user_lksb;
723
724
725
726
727
728
729
730 if (type == AST_BAST) {
731 result.user_astaddr = ua->bastaddr;
732 result.user_astparam = ua->bastparam;
733 result.bast_mode = bmode;
734 } else {
735 result.user_astaddr = ua->castaddr;
736 result.user_astparam = ua->castparam;
737 }
738
739#ifdef CONFIG_COMPAT
740 if (compat)
741 len = sizeof(struct dlm_lock_result32);
742 else
743#endif
744 len = sizeof(struct dlm_lock_result);
745 struct_len = len;
746
747
748
749
750 if (ua->update_user_lvb && ua->lksb.sb_lvbptr &&
751 count >= len + DLM_USER_LVB_LEN) {
752 if (copy_to_user(buf+len, ua->lksb.sb_lvbptr,
753 DLM_USER_LVB_LEN)) {
754 error = -EFAULT;
755 goto out;
756 }
757
758 result.lvb_offset = len;
759 len += DLM_USER_LVB_LEN;
760 }
761
762 result.length = len;
763 resultptr = &result;
764#ifdef CONFIG_COMPAT
765 if (compat) {
766 compat_output(&result, &result32);
767 resultptr = &result32;
768 }
769#endif
770
771 if (copy_to_user(buf, resultptr, struct_len))
772 error = -EFAULT;
773 else
774 error = len;
775 out:
776 return error;
777}
778
779static int copy_version_to_user(char __user *buf, size_t count)
780{
781 struct dlm_device_version ver;
782
783 memset(&ver, 0, sizeof(struct dlm_device_version));
784 ver.version[0] = DLM_DEVICE_VERSION_MAJOR;
785 ver.version[1] = DLM_DEVICE_VERSION_MINOR;
786 ver.version[2] = DLM_DEVICE_VERSION_PATCH;
787
788 if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version)))
789 return -EFAULT;
790 return sizeof(struct dlm_device_version);
791}
792
793
794
795static ssize_t device_read(struct file *file, char __user *buf, size_t count,
796 loff_t *ppos)
797{
798 struct dlm_user_proc *proc = file->private_data;
799 struct dlm_lkb *lkb;
800 DECLARE_WAITQUEUE(wait, current);
801 int error, type=0, bmode=0, removed = 0;
802
803 if (count == sizeof(struct dlm_device_version)) {
804 error = copy_version_to_user(buf, count);
805 return error;
806 }
807
808 if (!proc) {
809 log_print("non-version read from control device %zu", count);
810 return -EINVAL;
811 }
812
813#ifdef CONFIG_COMPAT
814 if (count < sizeof(struct dlm_lock_result32))
815#else
816 if (count < sizeof(struct dlm_lock_result))
817#endif
818 return -EINVAL;
819
820
821 if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
822 return -EINVAL;
823
824 spin_lock(&proc->asts_spin);
825 if (list_empty(&proc->asts)) {
826 if (file->f_flags & O_NONBLOCK) {
827 spin_unlock(&proc->asts_spin);
828 return -EAGAIN;
829 }
830
831 add_wait_queue(&proc->wait, &wait);
832
833 repeat:
834 set_current_state(TASK_INTERRUPTIBLE);
835 if (list_empty(&proc->asts) && !signal_pending(current)) {
836 spin_unlock(&proc->asts_spin);
837 schedule();
838 spin_lock(&proc->asts_spin);
839 goto repeat;
840 }
841 set_current_state(TASK_RUNNING);
842 remove_wait_queue(&proc->wait, &wait);
843
844 if (signal_pending(current)) {
845 spin_unlock(&proc->asts_spin);
846 return -ERESTARTSYS;
847 }
848 }
849
850
851
852
853 lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue);
854
855 if (lkb->lkb_ast_type & AST_COMP) {
856 lkb->lkb_ast_type &= ~AST_COMP;
857 type = AST_COMP;
858 } else if (lkb->lkb_ast_type & AST_BAST) {
859 lkb->lkb_ast_type &= ~AST_BAST;
860 type = AST_BAST;
861 bmode = lkb->lkb_bastmode;
862 }
863
864 if (!lkb->lkb_ast_type) {
865 list_del(&lkb->lkb_astqueue);
866 removed = 1;
867 }
868 spin_unlock(&proc->asts_spin);
869
870 error = copy_result_to_user(lkb->lkb_ua,
871 test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
872 type, bmode, buf, count);
873
874
875
876 if (removed)
877 dlm_put_lkb(lkb);
878
879 return error;
880}
881
882static unsigned int device_poll(struct file *file, poll_table *wait)
883{
884 struct dlm_user_proc *proc = file->private_data;
885
886 poll_wait(file, &proc->wait, wait);
887
888 spin_lock(&proc->asts_spin);
889 if (!list_empty(&proc->asts)) {
890 spin_unlock(&proc->asts_spin);
891 return POLLIN | POLLRDNORM;
892 }
893 spin_unlock(&proc->asts_spin);
894 return 0;
895}
896
897int dlm_user_daemon_available(void)
898{
899
900
901
902 if (!dlm_our_nodeid())
903 return 0;
904
905
906
907
908
909
910
911 if (dlm_monitor_unused)
912 return 1;
913
914 return atomic_read(&dlm_monitor_opened) ? 1 : 0;
915}
916
917static int ctl_device_open(struct inode *inode, struct file *file)
918{
919 file->private_data = NULL;
920 return 0;
921}
922
923static int ctl_device_close(struct inode *inode, struct file *file)
924{
925 return 0;
926}
927
928static int monitor_device_open(struct inode *inode, struct file *file)
929{
930 atomic_inc(&dlm_monitor_opened);
931 dlm_monitor_unused = 0;
932 return 0;
933}
934
935static int monitor_device_close(struct inode *inode, struct file *file)
936{
937 if (atomic_dec_and_test(&dlm_monitor_opened))
938 dlm_stop_lockspaces();
939 return 0;
940}
941
942static const struct file_operations device_fops = {
943 .open = device_open,
944 .release = device_close,
945 .read = device_read,
946 .write = device_write,
947 .poll = device_poll,
948 .owner = THIS_MODULE,
949};
950
951static const struct file_operations ctl_device_fops = {
952 .open = ctl_device_open,
953 .release = ctl_device_close,
954 .read = device_read,
955 .write = device_write,
956 .owner = THIS_MODULE,
957};
958
959static struct miscdevice ctl_device = {
960 .name = "dlm-control",
961 .fops = &ctl_device_fops,
962 .minor = MISC_DYNAMIC_MINOR,
963};
964
965static const struct file_operations monitor_device_fops = {
966 .open = monitor_device_open,
967 .release = monitor_device_close,
968 .owner = THIS_MODULE,
969};
970
971static struct miscdevice monitor_device = {
972 .name = "dlm-monitor",
973 .fops = &monitor_device_fops,
974 .minor = MISC_DYNAMIC_MINOR,
975};
976
977int __init dlm_user_init(void)
978{
979 int error;
980
981 atomic_set(&dlm_monitor_opened, 0);
982
983 error = misc_register(&ctl_device);
984 if (error) {
985 log_print("misc_register failed for control device");
986 goto out;
987 }
988
989 error = misc_register(&monitor_device);
990 if (error) {
991 log_print("misc_register failed for monitor device");
992 misc_deregister(&ctl_device);
993 }
994 out:
995 return error;
996}
997
998void dlm_user_exit(void)
999{
1000 misc_deregister(&ctl_device);
1001 misc_deregister(&monitor_device);
1002}
1003
1004