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