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, NULL, params->flags,
396 DLM_USER_LVB_LEN, NULL, NULL, NULL,
397 &lockspace);
398 if (error)
399 return error;
400
401 ls = dlm_find_lockspace_local(lockspace);
402 if (!ls)
403 return -ENOENT;
404
405 error = dlm_device_register(ls, params->name);
406 dlm_put_lockspace(ls);
407
408 if (error)
409 dlm_release_lockspace(lockspace, 0);
410 else
411 error = ls->ls_device.minor;
412
413 return error;
414}
415
416static int device_remove_lockspace(struct dlm_lspace_params *params)
417{
418 dlm_lockspace_t *lockspace;
419 struct dlm_ls *ls;
420 int error, force = 0;
421
422 if (!capable(CAP_SYS_ADMIN))
423 return -EPERM;
424
425 ls = dlm_find_lockspace_device(params->minor);
426 if (!ls)
427 return -ENOENT;
428
429 if (params->flags & DLM_USER_LSFLG_FORCEFREE)
430 force = 2;
431
432 lockspace = ls->ls_local_handle;
433 dlm_put_lockspace(ls);
434
435
436
437
438
439
440
441
442 error = dlm_release_lockspace(lockspace, force);
443 if (error > 0)
444 error = 0;
445 return error;
446}
447
448
449static int check_version(struct dlm_write_request *req)
450{
451 if (req->version[0] != DLM_DEVICE_VERSION_MAJOR ||
452 (req->version[0] == DLM_DEVICE_VERSION_MAJOR &&
453 req->version[1] > DLM_DEVICE_VERSION_MINOR)) {
454
455 printk(KERN_DEBUG "dlm: process %s (%d) version mismatch "
456 "user (%d.%d.%d) kernel (%d.%d.%d)\n",
457 current->comm,
458 task_pid_nr(current),
459 req->version[0],
460 req->version[1],
461 req->version[2],
462 DLM_DEVICE_VERSION_MAJOR,
463 DLM_DEVICE_VERSION_MINOR,
464 DLM_DEVICE_VERSION_PATCH);
465 return -EINVAL;
466 }
467 return 0;
468}
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491static ssize_t device_write(struct file *file, const char __user *buf,
492 size_t count, loff_t *ppos)
493{
494 struct dlm_user_proc *proc = file->private_data;
495 struct dlm_write_request *kbuf;
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
506
507
508
509 if (count > sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN)
510 return -EINVAL;
511
512 kbuf = kzalloc(count + 1, GFP_NOFS);
513 if (!kbuf)
514 return -ENOMEM;
515
516 if (copy_from_user(kbuf, buf, count)) {
517 error = -EFAULT;
518 goto out_free;
519 }
520
521 if (check_version(kbuf)) {
522 error = -EBADE;
523 goto out_free;
524 }
525
526#ifdef CONFIG_COMPAT
527 if (!kbuf->is64bit) {
528 struct dlm_write_request32 *k32buf;
529 int namelen = 0;
530
531 if (count > sizeof(struct dlm_write_request32))
532 namelen = count - sizeof(struct dlm_write_request32);
533
534 k32buf = (struct dlm_write_request32 *)kbuf;
535
536
537 kbuf = kzalloc(sizeof(struct dlm_write_request) + namelen + 1,
538 GFP_NOFS);
539 if (!kbuf) {
540 kfree(k32buf);
541 return -ENOMEM;
542 }
543
544 if (proc)
545 set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
546
547 compat_input(kbuf, k32buf, namelen);
548 kfree(k32buf);
549 }
550#endif
551
552
553 if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) &&
554 (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))) {
555 error = -EINVAL;
556 goto out_free;
557 }
558
559 error = -EINVAL;
560
561 switch (kbuf->cmd)
562 {
563 case DLM_USER_LOCK:
564 if (!proc) {
565 log_print("no locking on control device");
566 goto out_free;
567 }
568 error = device_user_lock(proc, &kbuf->i.lock);
569 break;
570
571 case DLM_USER_UNLOCK:
572 if (!proc) {
573 log_print("no locking on control device");
574 goto out_free;
575 }
576 error = device_user_unlock(proc, &kbuf->i.lock);
577 break;
578
579 case DLM_USER_DEADLOCK:
580 if (!proc) {
581 log_print("no locking on control device");
582 goto out_free;
583 }
584 error = device_user_deadlock(proc, &kbuf->i.lock);
585 break;
586
587 case DLM_USER_CREATE_LOCKSPACE:
588 if (proc) {
589 log_print("create/remove only on control device");
590 goto out_free;
591 }
592 error = device_create_lockspace(&kbuf->i.lspace);
593 break;
594
595 case DLM_USER_REMOVE_LOCKSPACE:
596 if (proc) {
597 log_print("create/remove only on control device");
598 goto out_free;
599 }
600 error = device_remove_lockspace(&kbuf->i.lspace);
601 break;
602
603 case DLM_USER_PURGE:
604 if (!proc) {
605 log_print("no locking on control device");
606 goto out_free;
607 }
608 error = device_user_purge(proc, &kbuf->i.purge);
609 break;
610
611 default:
612 log_print("Unknown command passed to DLM device : %d\n",
613 kbuf->cmd);
614 }
615
616 out_free:
617 kfree(kbuf);
618 return error;
619}
620
621
622
623
624
625static int device_open(struct inode *inode, struct file *file)
626{
627 struct dlm_user_proc *proc;
628 struct dlm_ls *ls;
629
630 ls = dlm_find_lockspace_device(iminor(inode));
631 if (!ls)
632 return -ENOENT;
633
634 proc = kzalloc(sizeof(struct dlm_user_proc), GFP_NOFS);
635 if (!proc) {
636 dlm_put_lockspace(ls);
637 return -ENOMEM;
638 }
639
640 proc->lockspace = ls->ls_local_handle;
641 INIT_LIST_HEAD(&proc->asts);
642 INIT_LIST_HEAD(&proc->locks);
643 INIT_LIST_HEAD(&proc->unlocking);
644 spin_lock_init(&proc->asts_spin);
645 spin_lock_init(&proc->locks_spin);
646 init_waitqueue_head(&proc->wait);
647 file->private_data = proc;
648
649 return 0;
650}
651
652static int device_close(struct inode *inode, struct file *file)
653{
654 struct dlm_user_proc *proc = file->private_data;
655 struct dlm_ls *ls;
656
657 ls = dlm_find_lockspace_local(proc->lockspace);
658 if (!ls)
659 return -ENOENT;
660
661 set_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags);
662
663 dlm_clear_proc_locks(ls, proc);
664
665
666
667
668
669 kfree(proc);
670 file->private_data = NULL;
671
672 dlm_put_lockspace(ls);
673 dlm_put_lockspace(ls);
674
675
676
677
678 return 0;
679}
680
681static int copy_result_to_user(struct dlm_user_args *ua, int compat,
682 uint32_t flags, int mode, int copy_lvb,
683 char __user *buf, size_t count)
684{
685#ifdef CONFIG_COMPAT
686 struct dlm_lock_result32 result32;
687#endif
688 struct dlm_lock_result result;
689 void *resultptr;
690 int error=0;
691 int len;
692 int struct_len;
693
694 memset(&result, 0, sizeof(struct dlm_lock_result));
695 result.version[0] = DLM_DEVICE_VERSION_MAJOR;
696 result.version[1] = DLM_DEVICE_VERSION_MINOR;
697 result.version[2] = DLM_DEVICE_VERSION_PATCH;
698 memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
699 result.user_lksb = ua->user_lksb;
700
701
702
703
704
705
706
707 if (flags & DLM_CB_BAST) {
708 result.user_astaddr = ua->bastaddr;
709 result.user_astparam = ua->bastparam;
710 result.bast_mode = mode;
711 } else {
712 result.user_astaddr = ua->castaddr;
713 result.user_astparam = ua->castparam;
714 }
715
716#ifdef CONFIG_COMPAT
717 if (compat)
718 len = sizeof(struct dlm_lock_result32);
719 else
720#endif
721 len = sizeof(struct dlm_lock_result);
722 struct_len = len;
723
724
725
726
727 if (copy_lvb && ua->lksb.sb_lvbptr && count >= len + DLM_USER_LVB_LEN) {
728 if (copy_to_user(buf+len, ua->lksb.sb_lvbptr,
729 DLM_USER_LVB_LEN)) {
730 error = -EFAULT;
731 goto out;
732 }
733
734 result.lvb_offset = len;
735 len += DLM_USER_LVB_LEN;
736 }
737
738 result.length = len;
739 resultptr = &result;
740#ifdef CONFIG_COMPAT
741 if (compat) {
742 compat_output(&result, &result32);
743 resultptr = &result32;
744 }
745#endif
746
747 if (copy_to_user(buf, resultptr, struct_len))
748 error = -EFAULT;
749 else
750 error = len;
751 out:
752 return error;
753}
754
755static int copy_version_to_user(char __user *buf, size_t count)
756{
757 struct dlm_device_version ver;
758
759 memset(&ver, 0, sizeof(struct dlm_device_version));
760 ver.version[0] = DLM_DEVICE_VERSION_MAJOR;
761 ver.version[1] = DLM_DEVICE_VERSION_MINOR;
762 ver.version[2] = DLM_DEVICE_VERSION_PATCH;
763
764 if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version)))
765 return -EFAULT;
766 return sizeof(struct dlm_device_version);
767}
768
769
770
771static ssize_t device_read(struct file *file, char __user *buf, size_t count,
772 loff_t *ppos)
773{
774 struct dlm_user_proc *proc = file->private_data;
775 struct dlm_lkb *lkb;
776 DECLARE_WAITQUEUE(wait, current);
777 struct dlm_callback cb;
778 int rv, resid, copy_lvb = 0;
779
780 if (count == sizeof(struct dlm_device_version)) {
781 rv = copy_version_to_user(buf, count);
782 return rv;
783 }
784
785 if (!proc) {
786 log_print("non-version read from control device %zu", count);
787 return -EINVAL;
788 }
789
790#ifdef CONFIG_COMPAT
791 if (count < sizeof(struct dlm_lock_result32))
792#else
793 if (count < sizeof(struct dlm_lock_result))
794#endif
795 return -EINVAL;
796
797 try_another:
798
799
800 if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
801 return -EINVAL;
802
803 spin_lock(&proc->asts_spin);
804 if (list_empty(&proc->asts)) {
805 if (file->f_flags & O_NONBLOCK) {
806 spin_unlock(&proc->asts_spin);
807 return -EAGAIN;
808 }
809
810 add_wait_queue(&proc->wait, &wait);
811
812 repeat:
813 set_current_state(TASK_INTERRUPTIBLE);
814 if (list_empty(&proc->asts) && !signal_pending(current)) {
815 spin_unlock(&proc->asts_spin);
816 schedule();
817 spin_lock(&proc->asts_spin);
818 goto repeat;
819 }
820 set_current_state(TASK_RUNNING);
821 remove_wait_queue(&proc->wait, &wait);
822
823 if (signal_pending(current)) {
824 spin_unlock(&proc->asts_spin);
825 return -ERESTARTSYS;
826 }
827 }
828
829
830
831
832
833 lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_cb_list);
834
835 rv = dlm_rem_lkb_callback(lkb->lkb_resource->res_ls, lkb, &cb, &resid);
836 if (rv < 0) {
837
838
839 log_print("dlm_rem_lkb_callback empty %x", lkb->lkb_id);
840 list_del_init(&lkb->lkb_cb_list);
841 spin_unlock(&proc->asts_spin);
842
843 dlm_put_lkb(lkb);
844 goto try_another;
845 }
846 if (!resid)
847 list_del_init(&lkb->lkb_cb_list);
848 spin_unlock(&proc->asts_spin);
849
850 if (cb.flags & DLM_CB_SKIP) {
851
852 if (!resid)
853 dlm_put_lkb(lkb);
854 goto try_another;
855 }
856
857 if (cb.flags & DLM_CB_CAST) {
858 int old_mode, new_mode;
859
860 old_mode = lkb->lkb_last_cast.mode;
861 new_mode = cb.mode;
862
863 if (!cb.sb_status && lkb->lkb_lksb->sb_lvbptr &&
864 dlm_lvb_operations[old_mode + 1][new_mode + 1])
865 copy_lvb = 1;
866
867 lkb->lkb_lksb->sb_status = cb.sb_status;
868 lkb->lkb_lksb->sb_flags = cb.sb_flags;
869 }
870
871 rv = copy_result_to_user(lkb->lkb_ua,
872 test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
873 cb.flags, cb.mode, copy_lvb, buf, count);
874
875
876 if (!resid)
877 dlm_put_lkb(lkb);
878
879 return rv;
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 .llseek = noop_llseek,
950};
951
952static const struct file_operations ctl_device_fops = {
953 .open = ctl_device_open,
954 .release = ctl_device_close,
955 .read = device_read,
956 .write = device_write,
957 .owner = THIS_MODULE,
958 .llseek = noop_llseek,
959};
960
961static struct miscdevice ctl_device = {
962 .name = "dlm-control",
963 .fops = &ctl_device_fops,
964 .minor = MISC_DYNAMIC_MINOR,
965};
966
967static const struct file_operations monitor_device_fops = {
968 .open = monitor_device_open,
969 .release = monitor_device_close,
970 .owner = THIS_MODULE,
971 .llseek = noop_llseek,
972};
973
974static struct miscdevice monitor_device = {
975 .name = "dlm-monitor",
976 .fops = &monitor_device_fops,
977 .minor = MISC_DYNAMIC_MINOR,
978};
979
980int __init dlm_user_init(void)
981{
982 int error;
983
984 atomic_set(&dlm_monitor_opened, 0);
985
986 error = misc_register(&ctl_device);
987 if (error) {
988 log_print("misc_register failed for control device");
989 goto out;
990 }
991
992 error = misc_register(&monitor_device);
993 if (error) {
994 log_print("misc_register failed for monitor device");
995 misc_deregister(&ctl_device);
996 }
997 out:
998 return error;
999}
1000
1001void dlm_user_exit(void)
1002{
1003 misc_deregister(&ctl_device);
1004 misc_deregister(&monitor_device);
1005}
1006
1007