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 uint32_t lkid;
242 int error = -ENOMEM;
243
244 ls = dlm_find_lockspace_local(proc->lockspace);
245 if (!ls)
246 return -ENOENT;
247
248 if (!params->castaddr || !params->lksb) {
249 error = -EINVAL;
250 goto out;
251 }
252
253 ua = kzalloc(sizeof(struct dlm_user_args), GFP_NOFS);
254 if (!ua)
255 goto out;
256 ua->proc = proc;
257 ua->user_lksb = params->lksb;
258 ua->castparam = params->castparam;
259 ua->castaddr = params->castaddr;
260 ua->bastparam = params->bastparam;
261 ua->bastaddr = params->bastaddr;
262 ua->xid = params->xid;
263
264 if (params->flags & DLM_LKF_CONVERT) {
265 error = dlm_user_convert(ls, ua,
266 params->mode, params->flags,
267 params->lkid, params->lvb,
268 (unsigned long) params->timeout);
269 } else if (params->flags & DLM_LKF_ORPHAN) {
270 error = dlm_user_adopt_orphan(ls, ua,
271 params->mode, params->flags,
272 params->name, params->namelen,
273 (unsigned long) params->timeout,
274 &lkid);
275 if (!error)
276 error = lkid;
277 } else {
278 error = dlm_user_request(ls, ua,
279 params->mode, params->flags,
280 params->name, params->namelen,
281 (unsigned long) params->timeout);
282 if (!error)
283 error = ua->lksb.sb_lkid;
284 }
285 out:
286 dlm_put_lockspace(ls);
287 return error;
288}
289
290static int device_user_unlock(struct dlm_user_proc *proc,
291 struct dlm_lock_params *params)
292{
293 struct dlm_ls *ls;
294 struct dlm_user_args *ua;
295 int error = -ENOMEM;
296
297 ls = dlm_find_lockspace_local(proc->lockspace);
298 if (!ls)
299 return -ENOENT;
300
301 ua = kzalloc(sizeof(struct dlm_user_args), GFP_NOFS);
302 if (!ua)
303 goto out;
304 ua->proc = proc;
305 ua->user_lksb = params->lksb;
306 ua->castparam = params->castparam;
307 ua->castaddr = params->castaddr;
308
309 if (params->flags & DLM_LKF_CANCEL)
310 error = dlm_user_cancel(ls, ua, params->flags, params->lkid);
311 else
312 error = dlm_user_unlock(ls, ua, params->flags, params->lkid,
313 params->lvb);
314 out:
315 dlm_put_lockspace(ls);
316 return error;
317}
318
319static int device_user_deadlock(struct dlm_user_proc *proc,
320 struct dlm_lock_params *params)
321{
322 struct dlm_ls *ls;
323 int error;
324
325 ls = dlm_find_lockspace_local(proc->lockspace);
326 if (!ls)
327 return -ENOENT;
328
329 error = dlm_user_deadlock(ls, params->flags, params->lkid);
330
331 dlm_put_lockspace(ls);
332 return error;
333}
334
335static int dlm_device_register(struct dlm_ls *ls, char *name)
336{
337 int error, len;
338
339
340
341 if (ls->ls_device.name)
342 return 0;
343
344 error = -ENOMEM;
345 len = strlen(name) + strlen(name_prefix) + 2;
346 ls->ls_device.name = kzalloc(len, GFP_NOFS);
347 if (!ls->ls_device.name)
348 goto fail;
349
350 snprintf((char *)ls->ls_device.name, len, "%s_%s", name_prefix,
351 name);
352 ls->ls_device.fops = &device_fops;
353 ls->ls_device.minor = MISC_DYNAMIC_MINOR;
354
355 error = misc_register(&ls->ls_device);
356 if (error) {
357 kfree(ls->ls_device.name);
358 }
359fail:
360 return error;
361}
362
363int dlm_device_deregister(struct dlm_ls *ls)
364{
365 int error;
366
367
368
369
370 if (!ls->ls_device.name)
371 return 0;
372
373 error = misc_deregister(&ls->ls_device);
374 if (!error)
375 kfree(ls->ls_device.name);
376 return error;
377}
378
379static int device_user_purge(struct dlm_user_proc *proc,
380 struct dlm_purge_params *params)
381{
382 struct dlm_ls *ls;
383 int error;
384
385 ls = dlm_find_lockspace_local(proc->lockspace);
386 if (!ls)
387 return -ENOENT;
388
389 error = dlm_user_purge(ls, proc, params->nodeid, params->pid);
390
391 dlm_put_lockspace(ls);
392 return error;
393}
394
395static int device_create_lockspace(struct dlm_lspace_params *params)
396{
397 dlm_lockspace_t *lockspace;
398 struct dlm_ls *ls;
399 int error;
400
401 if (!capable(CAP_SYS_ADMIN))
402 return -EPERM;
403
404 error = dlm_new_lockspace(params->name, NULL, params->flags,
405 DLM_USER_LVB_LEN, NULL, NULL, NULL,
406 &lockspace);
407 if (error)
408 return error;
409
410 ls = dlm_find_lockspace_local(lockspace);
411 if (!ls)
412 return -ENOENT;
413
414 error = dlm_device_register(ls, params->name);
415 dlm_put_lockspace(ls);
416
417 if (error)
418 dlm_release_lockspace(lockspace, 0);
419 else
420 error = ls->ls_device.minor;
421
422 return error;
423}
424
425static int device_remove_lockspace(struct dlm_lspace_params *params)
426{
427 dlm_lockspace_t *lockspace;
428 struct dlm_ls *ls;
429 int error, force = 0;
430
431 if (!capable(CAP_SYS_ADMIN))
432 return -EPERM;
433
434 ls = dlm_find_lockspace_device(params->minor);
435 if (!ls)
436 return -ENOENT;
437
438 if (params->flags & DLM_USER_LSFLG_FORCEFREE)
439 force = 2;
440
441 lockspace = ls->ls_local_handle;
442 dlm_put_lockspace(ls);
443
444
445
446
447
448
449
450
451 error = dlm_release_lockspace(lockspace, force);
452 if (error > 0)
453 error = 0;
454 return error;
455}
456
457
458static int check_version(struct dlm_write_request *req)
459{
460 if (req->version[0] != DLM_DEVICE_VERSION_MAJOR ||
461 (req->version[0] == DLM_DEVICE_VERSION_MAJOR &&
462 req->version[1] > DLM_DEVICE_VERSION_MINOR)) {
463
464 printk(KERN_DEBUG "dlm: process %s (%d) version mismatch "
465 "user (%d.%d.%d) kernel (%d.%d.%d)\n",
466 current->comm,
467 task_pid_nr(current),
468 req->version[0],
469 req->version[1],
470 req->version[2],
471 DLM_DEVICE_VERSION_MAJOR,
472 DLM_DEVICE_VERSION_MINOR,
473 DLM_DEVICE_VERSION_PATCH);
474 return -EINVAL;
475 }
476 return 0;
477}
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500static ssize_t device_write(struct file *file, const char __user *buf,
501 size_t count, loff_t *ppos)
502{
503 struct dlm_user_proc *proc = file->private_data;
504 struct dlm_write_request *kbuf;
505 int error;
506
507#ifdef CONFIG_COMPAT
508 if (count < sizeof(struct dlm_write_request32))
509#else
510 if (count < sizeof(struct dlm_write_request))
511#endif
512 return -EINVAL;
513
514
515
516
517
518 if (count > sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN)
519 return -EINVAL;
520
521 kbuf = kzalloc(count + 1, GFP_NOFS);
522 if (!kbuf)
523 return -ENOMEM;
524
525 if (copy_from_user(kbuf, buf, count)) {
526 error = -EFAULT;
527 goto out_free;
528 }
529
530 if (check_version(kbuf)) {
531 error = -EBADE;
532 goto out_free;
533 }
534
535#ifdef CONFIG_COMPAT
536 if (!kbuf->is64bit) {
537 struct dlm_write_request32 *k32buf;
538 int namelen = 0;
539
540 if (count > sizeof(struct dlm_write_request32))
541 namelen = count - sizeof(struct dlm_write_request32);
542
543 k32buf = (struct dlm_write_request32 *)kbuf;
544
545
546 kbuf = kzalloc(sizeof(struct dlm_write_request) + namelen + 1,
547 GFP_NOFS);
548 if (!kbuf) {
549 kfree(k32buf);
550 return -ENOMEM;
551 }
552
553 if (proc)
554 set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
555
556 compat_input(kbuf, k32buf, namelen);
557 kfree(k32buf);
558 }
559#endif
560
561
562 if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) &&
563 (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))) {
564 error = -EINVAL;
565 goto out_free;
566 }
567
568 error = -EINVAL;
569
570 switch (kbuf->cmd)
571 {
572 case DLM_USER_LOCK:
573 if (!proc) {
574 log_print("no locking on control device");
575 goto out_free;
576 }
577 error = device_user_lock(proc, &kbuf->i.lock);
578 break;
579
580 case DLM_USER_UNLOCK:
581 if (!proc) {
582 log_print("no locking on control device");
583 goto out_free;
584 }
585 error = device_user_unlock(proc, &kbuf->i.lock);
586 break;
587
588 case DLM_USER_DEADLOCK:
589 if (!proc) {
590 log_print("no locking on control device");
591 goto out_free;
592 }
593 error = device_user_deadlock(proc, &kbuf->i.lock);
594 break;
595
596 case DLM_USER_CREATE_LOCKSPACE:
597 if (proc) {
598 log_print("create/remove only on control device");
599 goto out_free;
600 }
601 error = device_create_lockspace(&kbuf->i.lspace);
602 break;
603
604 case DLM_USER_REMOVE_LOCKSPACE:
605 if (proc) {
606 log_print("create/remove only on control device");
607 goto out_free;
608 }
609 error = device_remove_lockspace(&kbuf->i.lspace);
610 break;
611
612 case DLM_USER_PURGE:
613 if (!proc) {
614 log_print("no locking on control device");
615 goto out_free;
616 }
617 error = device_user_purge(proc, &kbuf->i.purge);
618 break;
619
620 default:
621 log_print("Unknown command passed to DLM device : %d\n",
622 kbuf->cmd);
623 }
624
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_NOFS);
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
666 ls = dlm_find_lockspace_local(proc->lockspace);
667 if (!ls)
668 return -ENOENT;
669
670 set_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags);
671
672 dlm_clear_proc_locks(ls, proc);
673
674
675
676
677
678 kfree(proc);
679 file->private_data = NULL;
680
681 dlm_put_lockspace(ls);
682 dlm_put_lockspace(ls);
683
684
685
686
687 return 0;
688}
689
690static int copy_result_to_user(struct dlm_user_args *ua, int compat,
691 uint32_t flags, int mode, int copy_lvb,
692 char __user *buf, size_t count)
693{
694#ifdef CONFIG_COMPAT
695 struct dlm_lock_result32 result32;
696#endif
697 struct dlm_lock_result result;
698 void *resultptr;
699 int error=0;
700 int len;
701 int struct_len;
702
703 memset(&result, 0, sizeof(struct dlm_lock_result));
704 result.version[0] = DLM_DEVICE_VERSION_MAJOR;
705 result.version[1] = DLM_DEVICE_VERSION_MINOR;
706 result.version[2] = DLM_DEVICE_VERSION_PATCH;
707 memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
708 result.user_lksb = ua->user_lksb;
709
710
711
712
713
714
715
716 if (flags & DLM_CB_BAST) {
717 result.user_astaddr = ua->bastaddr;
718 result.user_astparam = ua->bastparam;
719 result.bast_mode = mode;
720 } else {
721 result.user_astaddr = ua->castaddr;
722 result.user_astparam = ua->castparam;
723 }
724
725#ifdef CONFIG_COMPAT
726 if (compat)
727 len = sizeof(struct dlm_lock_result32);
728 else
729#endif
730 len = sizeof(struct dlm_lock_result);
731 struct_len = len;
732
733
734
735
736 if (copy_lvb && ua->lksb.sb_lvbptr && count >= len + DLM_USER_LVB_LEN) {
737 if (copy_to_user(buf+len, ua->lksb.sb_lvbptr,
738 DLM_USER_LVB_LEN)) {
739 error = -EFAULT;
740 goto out;
741 }
742
743 result.lvb_offset = len;
744 len += DLM_USER_LVB_LEN;
745 }
746
747 result.length = len;
748 resultptr = &result;
749#ifdef CONFIG_COMPAT
750 if (compat) {
751 compat_output(&result, &result32);
752 resultptr = &result32;
753 }
754#endif
755
756 if (copy_to_user(buf, resultptr, struct_len))
757 error = -EFAULT;
758 else
759 error = len;
760 out:
761 return error;
762}
763
764static int copy_version_to_user(char __user *buf, size_t count)
765{
766 struct dlm_device_version ver;
767
768 memset(&ver, 0, sizeof(struct dlm_device_version));
769 ver.version[0] = DLM_DEVICE_VERSION_MAJOR;
770 ver.version[1] = DLM_DEVICE_VERSION_MINOR;
771 ver.version[2] = DLM_DEVICE_VERSION_PATCH;
772
773 if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version)))
774 return -EFAULT;
775 return sizeof(struct dlm_device_version);
776}
777
778
779
780static ssize_t device_read(struct file *file, char __user *buf, size_t count,
781 loff_t *ppos)
782{
783 struct dlm_user_proc *proc = file->private_data;
784 struct dlm_lkb *lkb;
785 DECLARE_WAITQUEUE(wait, current);
786 struct dlm_callback cb;
787 int rv, resid, copy_lvb = 0;
788
789 if (count == sizeof(struct dlm_device_version)) {
790 rv = copy_version_to_user(buf, count);
791 return rv;
792 }
793
794 if (!proc) {
795 log_print("non-version read from control device %zu", count);
796 return -EINVAL;
797 }
798
799#ifdef CONFIG_COMPAT
800 if (count < sizeof(struct dlm_lock_result32))
801#else
802 if (count < sizeof(struct dlm_lock_result))
803#endif
804 return -EINVAL;
805
806 try_another:
807
808
809 if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
810 return -EINVAL;
811
812 spin_lock(&proc->asts_spin);
813 if (list_empty(&proc->asts)) {
814 if (file->f_flags & O_NONBLOCK) {
815 spin_unlock(&proc->asts_spin);
816 return -EAGAIN;
817 }
818
819 add_wait_queue(&proc->wait, &wait);
820
821 repeat:
822 set_current_state(TASK_INTERRUPTIBLE);
823 if (list_empty(&proc->asts) && !signal_pending(current)) {
824 spin_unlock(&proc->asts_spin);
825 schedule();
826 spin_lock(&proc->asts_spin);
827 goto repeat;
828 }
829 set_current_state(TASK_RUNNING);
830 remove_wait_queue(&proc->wait, &wait);
831
832 if (signal_pending(current)) {
833 spin_unlock(&proc->asts_spin);
834 return -ERESTARTSYS;
835 }
836 }
837
838
839
840
841
842 lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_cb_list);
843
844 rv = dlm_rem_lkb_callback(lkb->lkb_resource->res_ls, lkb, &cb, &resid);
845 if (rv < 0) {
846
847
848 log_print("dlm_rem_lkb_callback empty %x", lkb->lkb_id);
849 list_del_init(&lkb->lkb_cb_list);
850 spin_unlock(&proc->asts_spin);
851
852 dlm_put_lkb(lkb);
853 goto try_another;
854 }
855 if (!resid)
856 list_del_init(&lkb->lkb_cb_list);
857 spin_unlock(&proc->asts_spin);
858
859 if (cb.flags & DLM_CB_SKIP) {
860
861 if (!resid)
862 dlm_put_lkb(lkb);
863 goto try_another;
864 }
865
866 if (cb.flags & DLM_CB_CAST) {
867 int old_mode, new_mode;
868
869 old_mode = lkb->lkb_last_cast.mode;
870 new_mode = cb.mode;
871
872 if (!cb.sb_status && lkb->lkb_lksb->sb_lvbptr &&
873 dlm_lvb_operations[old_mode + 1][new_mode + 1])
874 copy_lvb = 1;
875
876 lkb->lkb_lksb->sb_status = cb.sb_status;
877 lkb->lkb_lksb->sb_flags = cb.sb_flags;
878 }
879
880 rv = copy_result_to_user(lkb->lkb_ua,
881 test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
882 cb.flags, cb.mode, copy_lvb, buf, count);
883
884
885 if (!resid)
886 dlm_put_lkb(lkb);
887
888 return rv;
889}
890
891static unsigned int device_poll(struct file *file, poll_table *wait)
892{
893 struct dlm_user_proc *proc = file->private_data;
894
895 poll_wait(file, &proc->wait, wait);
896
897 spin_lock(&proc->asts_spin);
898 if (!list_empty(&proc->asts)) {
899 spin_unlock(&proc->asts_spin);
900 return POLLIN | POLLRDNORM;
901 }
902 spin_unlock(&proc->asts_spin);
903 return 0;
904}
905
906int dlm_user_daemon_available(void)
907{
908
909
910
911 if (!dlm_our_nodeid())
912 return 0;
913
914
915
916
917
918
919
920 if (dlm_monitor_unused)
921 return 1;
922
923 return atomic_read(&dlm_monitor_opened) ? 1 : 0;
924}
925
926static int ctl_device_open(struct inode *inode, struct file *file)
927{
928 file->private_data = NULL;
929 return 0;
930}
931
932static int ctl_device_close(struct inode *inode, struct file *file)
933{
934 return 0;
935}
936
937static int monitor_device_open(struct inode *inode, struct file *file)
938{
939 atomic_inc(&dlm_monitor_opened);
940 dlm_monitor_unused = 0;
941 return 0;
942}
943
944static int monitor_device_close(struct inode *inode, struct file *file)
945{
946 if (atomic_dec_and_test(&dlm_monitor_opened))
947 dlm_stop_lockspaces();
948 return 0;
949}
950
951static const struct file_operations device_fops = {
952 .open = device_open,
953 .release = device_close,
954 .read = device_read,
955 .write = device_write,
956 .poll = device_poll,
957 .owner = THIS_MODULE,
958 .llseek = noop_llseek,
959};
960
961static const struct file_operations ctl_device_fops = {
962 .open = ctl_device_open,
963 .release = ctl_device_close,
964 .read = device_read,
965 .write = device_write,
966 .owner = THIS_MODULE,
967 .llseek = noop_llseek,
968};
969
970static struct miscdevice ctl_device = {
971 .name = "dlm-control",
972 .fops = &ctl_device_fops,
973 .minor = MISC_DYNAMIC_MINOR,
974};
975
976static const struct file_operations monitor_device_fops = {
977 .open = monitor_device_open,
978 .release = monitor_device_close,
979 .owner = THIS_MODULE,
980 .llseek = noop_llseek,
981};
982
983static struct miscdevice monitor_device = {
984 .name = "dlm-monitor",
985 .fops = &monitor_device_fops,
986 .minor = MISC_DYNAMIC_MINOR,
987};
988
989int __init dlm_user_init(void)
990{
991 int error;
992
993 atomic_set(&dlm_monitor_opened, 0);
994
995 error = misc_register(&ctl_device);
996 if (error) {
997 log_print("misc_register failed for control device");
998 goto out;
999 }
1000
1001 error = misc_register(&monitor_device);
1002 if (error) {
1003 log_print("misc_register failed for monitor device");
1004 misc_deregister(&ctl_device);
1005 }
1006 out:
1007 return error;
1008}
1009
1010void dlm_user_exit(void)
1011{
1012 misc_deregister(&ctl_device);
1013 misc_deregister(&monitor_device);
1014}
1015
1016