[DLM] fix coverity-spotted stupidity
[deliverable/linux.git] / fs / dlm / user.c
CommitLineData
597d0cae
DT
1/*
2 * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
3 *
4 * This copyrighted material is made available to anyone wishing to use,
5 * modify, copy, or redistribute it subject to the terms and conditions
6 * of the GNU General Public License v.2.
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"
84c6e8cd 25#include "user.h"
597d0cae
DT
26
27static const char *name_prefix="dlm";
28static struct miscdevice ctl_device;
00977a59 29static const struct file_operations device_fops;
597d0cae
DT
30
31#ifdef CONFIG_COMPAT
32
33struct dlm_lock_params32 {
34 __u8 mode;
35 __u8 namelen;
36 __u16 flags;
37 __u32 lkid;
38 __u32 parent;
39
40 __u32 castparam;
41 __u32 castaddr;
42 __u32 bastparam;
43 __u32 bastaddr;
44 __u32 lksb;
45
46 char lvb[DLM_USER_LVB_LEN];
47 char name[0];
48};
49
50struct dlm_write_request32 {
51 __u32 version[3];
52 __u8 cmd;
53 __u8 is64bit;
54 __u8 unused[2];
55
56 union {
57 struct dlm_lock_params32 lock;
58 struct dlm_lspace_params lspace;
59 } i;
60};
61
62struct dlm_lksb32 {
63 __u32 sb_status;
64 __u32 sb_lkid;
65 __u8 sb_flags;
66 __u32 sb_lvbptr;
67};
68
69struct dlm_lock_result32 {
70 __u32 length;
71 __u32 user_astaddr;
72 __u32 user_astparam;
73 __u32 user_lksb;
74 struct dlm_lksb32 lksb;
75 __u8 bast_mode;
76 __u8 unused[3];
77 /* Offsets may be zero if no data is present */
78 __u32 lvb_offset;
79};
80
81static void compat_input(struct dlm_write_request *kb,
82 struct dlm_write_request32 *kb32)
83{
84 kb->version[0] = kb32->version[0];
85 kb->version[1] = kb32->version[1];
86 kb->version[2] = kb32->version[2];
87
88 kb->cmd = kb32->cmd;
89 kb->is64bit = kb32->is64bit;
90 if (kb->cmd == DLM_USER_CREATE_LOCKSPACE ||
91 kb->cmd == DLM_USER_REMOVE_LOCKSPACE) {
92 kb->i.lspace.flags = kb32->i.lspace.flags;
93 kb->i.lspace.minor = kb32->i.lspace.minor;
94 strcpy(kb->i.lspace.name, kb32->i.lspace.name);
95 } else {
96 kb->i.lock.mode = kb32->i.lock.mode;
97 kb->i.lock.namelen = kb32->i.lock.namelen;
98 kb->i.lock.flags = kb32->i.lock.flags;
99 kb->i.lock.lkid = kb32->i.lock.lkid;
100 kb->i.lock.parent = kb32->i.lock.parent;
101 kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
102 kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
103 kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
104 kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr;
105 kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb;
106 memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN);
107 memcpy(kb->i.lock.name, kb32->i.lock.name, kb->i.lock.namelen);
108 }
109}
110
111static void compat_output(struct dlm_lock_result *res,
112 struct dlm_lock_result32 *res32)
113{
114 res32->length = res->length - (sizeof(struct dlm_lock_result) -
115 sizeof(struct dlm_lock_result32));
116 res32->user_astaddr = (__u32)(long)res->user_astaddr;
117 res32->user_astparam = (__u32)(long)res->user_astparam;
118 res32->user_lksb = (__u32)(long)res->user_lksb;
119 res32->bast_mode = res->bast_mode;
120
121 res32->lvb_offset = res->lvb_offset;
122 res32->length = res->length;
123
124 res32->lksb.sb_status = res->lksb.sb_status;
125 res32->lksb.sb_flags = res->lksb.sb_flags;
126 res32->lksb.sb_lkid = res->lksb.sb_lkid;
127 res32->lksb.sb_lvbptr = (__u32)(long)res->lksb.sb_lvbptr;
128}
129#endif
130
131
132void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
133{
134 struct dlm_ls *ls;
135 struct dlm_user_args *ua;
136 struct dlm_user_proc *proc;
34e22bed 137 int remove_ownqueue = 0;
597d0cae
DT
138
139 /* dlm_clear_proc_locks() sets ORPHAN/DEAD flag on each
140 lkb before dealing with it. We need to check this
141 flag before taking ls_clear_proc_locks mutex because if
142 it's set, dlm_clear_proc_locks() holds the mutex. */
143
144 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) {
145 /* log_print("user_add_ast skip1 %x", lkb->lkb_flags); */
146 return;
147 }
148
149 ls = lkb->lkb_resource->res_ls;
150 mutex_lock(&ls->ls_clear_proc_locks);
151
152 /* If ORPHAN/DEAD flag is set, it means the process is dead so an ast
153 can't be delivered. For ORPHAN's, dlm_clear_proc_locks() freed
154 lkb->ua so we can't try to use it. */
155
156 if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) {
157 /* log_print("user_add_ast skip2 %x", lkb->lkb_flags); */
158 goto out;
159 }
160
161 DLM_ASSERT(lkb->lkb_astparam, dlm_print_lkb(lkb););
162 ua = (struct dlm_user_args *)lkb->lkb_astparam;
163 proc = ua->proc;
164
165 if (type == AST_BAST && ua->bastaddr == NULL)
166 goto out;
167
168 spin_lock(&proc->asts_spin);
169 if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) {
170 kref_get(&lkb->lkb_ref);
171 list_add_tail(&lkb->lkb_astqueue, &proc->asts);
172 lkb->lkb_ast_type |= type;
173 wake_up_interruptible(&proc->wait);
174 }
175
34e22bed
DT
176 /* noqueue requests that fail may need to be removed from the
177 proc's locks list, there should be a better way of detecting
178 this situation than checking all these things... */
36098198 179
34e22bed
DT
180 if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV &&
181 ua->lksb.sb_status == -EAGAIN && !list_empty(&lkb->lkb_ownqueue))
182 remove_ownqueue = 1;
183
a1bc86e6
DT
184 /* unlocks or cancels of waiting requests need to be removed from the
185 proc's unlocking list, again there must be a better way... */
186
187 if (ua->lksb.sb_status == -DLM_EUNLOCK ||
188 (ua->lksb.sb_status == -DLM_ECANCEL &&
189 lkb->lkb_grmode == DLM_LOCK_IV))
190 remove_ownqueue = 1;
191
597d0cae
DT
192 /* We want to copy the lvb to userspace when the completion
193 ast is read if the status is 0, the lock has an lvb and
194 lvb_ops says we should. We could probably have set_lvb_lock()
195 set update_user_lvb instead and not need old_mode */
196
197 if ((lkb->lkb_ast_type & AST_COMP) &&
198 (lkb->lkb_lksb->sb_status == 0) &&
199 lkb->lkb_lksb->sb_lvbptr &&
200 dlm_lvb_operations[ua->old_mode + 1][lkb->lkb_grmode + 1])
201 ua->update_user_lvb = 1;
202 else
203 ua->update_user_lvb = 0;
204
205 spin_unlock(&proc->asts_spin);
34e22bed
DT
206
207 if (remove_ownqueue) {
208 spin_lock(&ua->proc->locks_spin);
209 list_del_init(&lkb->lkb_ownqueue);
210 spin_unlock(&ua->proc->locks_spin);
211 dlm_put_lkb(lkb);
212 }
597d0cae
DT
213 out:
214 mutex_unlock(&ls->ls_clear_proc_locks);
215}
216
217static int device_user_lock(struct dlm_user_proc *proc,
218 struct dlm_lock_params *params)
219{
220 struct dlm_ls *ls;
221 struct dlm_user_args *ua;
222 int error = -ENOMEM;
223
224 ls = dlm_find_lockspace_local(proc->lockspace);
225 if (!ls)
226 return -ENOENT;
227
228 if (!params->castaddr || !params->lksb) {
229 error = -EINVAL;
230 goto out;
231 }
232
233 ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL);
234 if (!ua)
235 goto out;
236 ua->proc = proc;
237 ua->user_lksb = params->lksb;
238 ua->castparam = params->castparam;
239 ua->castaddr = params->castaddr;
240 ua->bastparam = params->bastparam;
241 ua->bastaddr = params->bastaddr;
242
243 if (params->flags & DLM_LKF_CONVERT)
244 error = dlm_user_convert(ls, ua,
245 params->mode, params->flags,
246 params->lkid, params->lvb);
247 else {
248 error = dlm_user_request(ls, ua,
249 params->mode, params->flags,
250 params->name, params->namelen,
251 params->parent);
252 if (!error)
253 error = ua->lksb.sb_lkid;
254 }
255 out:
256 dlm_put_lockspace(ls);
257 return error;
258}
259
260static int device_user_unlock(struct dlm_user_proc *proc,
261 struct dlm_lock_params *params)
262{
263 struct dlm_ls *ls;
264 struct dlm_user_args *ua;
265 int error = -ENOMEM;
266
267 ls = dlm_find_lockspace_local(proc->lockspace);
268 if (!ls)
269 return -ENOENT;
270
271 ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL);
272 if (!ua)
273 goto out;
274 ua->proc = proc;
275 ua->user_lksb = params->lksb;
276 ua->castparam = params->castparam;
277 ua->castaddr = params->castaddr;
278
279 if (params->flags & DLM_LKF_CANCEL)
280 error = dlm_user_cancel(ls, ua, params->flags, params->lkid);
281 else
282 error = dlm_user_unlock(ls, ua, params->flags, params->lkid,
283 params->lvb);
284 out:
285 dlm_put_lockspace(ls);
286 return error;
287}
288
254da030
PC
289static int create_misc_device(struct dlm_ls *ls, char *name)
290{
291 int error, len;
292
293 error = -ENOMEM;
294 len = strlen(name) + strlen(name_prefix) + 2;
295 ls->ls_device.name = kzalloc(len, GFP_KERNEL);
296 if (!ls->ls_device.name)
297 goto fail;
298
299 snprintf((char *)ls->ls_device.name, len, "%s_%s", name_prefix,
300 name);
301 ls->ls_device.fops = &device_fops;
302 ls->ls_device.minor = MISC_DYNAMIC_MINOR;
303
304 error = misc_register(&ls->ls_device);
305 if (error) {
306 kfree(ls->ls_device.name);
307 }
308fail:
309 return error;
310}
311
597d0cae
DT
312static int device_create_lockspace(struct dlm_lspace_params *params)
313{
314 dlm_lockspace_t *lockspace;
315 struct dlm_ls *ls;
254da030 316 int error;
597d0cae
DT
317
318 if (!capable(CAP_SYS_ADMIN))
319 return -EPERM;
320
321 error = dlm_new_lockspace(params->name, strlen(params->name),
322 &lockspace, 0, DLM_USER_LVB_LEN);
323 if (error)
324 return error;
325
326 ls = dlm_find_lockspace_local(lockspace);
327 if (!ls)
328 return -ENOENT;
329
254da030 330 error = create_misc_device(ls, params->name);
597d0cae 331 dlm_put_lockspace(ls);
597d0cae 332
254da030
PC
333 if (error)
334 dlm_release_lockspace(lockspace, 0);
335 else
336 error = ls->ls_device.minor;
337
597d0cae
DT
338 return error;
339}
340
341static int device_remove_lockspace(struct dlm_lspace_params *params)
342{
343 dlm_lockspace_t *lockspace;
344 struct dlm_ls *ls;
c6e6f0ba 345 int error, force = 0;
597d0cae
DT
346
347 if (!capable(CAP_SYS_ADMIN))
348 return -EPERM;
349
350 ls = dlm_find_lockspace_device(params->minor);
351 if (!ls)
352 return -ENOENT;
353
254da030
PC
354 /* Deregister the misc device first, so we don't have
355 * a device that's not attached to a lockspace. If
356 * dlm_release_lockspace fails then we can recreate it
357 */
597d0cae
DT
358 error = misc_deregister(&ls->ls_device);
359 if (error) {
360 dlm_put_lockspace(ls);
361 goto out;
362 }
363 kfree(ls->ls_device.name);
364
c6e6f0ba
DT
365 if (params->flags & DLM_USER_LSFLG_FORCEFREE)
366 force = 2;
367
597d0cae
DT
368 lockspace = ls->ls_local_handle;
369
370 /* dlm_release_lockspace waits for references to go to zero,
371 so all processes will need to close their device for the ls
372 before the release will procede */
373
374 dlm_put_lockspace(ls);
c6e6f0ba 375 error = dlm_release_lockspace(lockspace, force);
254da030
PC
376 if (error)
377 create_misc_device(ls, ls->ls_name);
c6e6f0ba 378 out:
597d0cae
DT
379 return error;
380}
381
382/* Check the user's version matches ours */
383static int check_version(struct dlm_write_request *req)
384{
385 if (req->version[0] != DLM_DEVICE_VERSION_MAJOR ||
386 (req->version[0] == DLM_DEVICE_VERSION_MAJOR &&
387 req->version[1] > DLM_DEVICE_VERSION_MINOR)) {
388
389 printk(KERN_DEBUG "dlm: process %s (%d) version mismatch "
390 "user (%d.%d.%d) kernel (%d.%d.%d)\n",
391 current->comm,
392 current->pid,
393 req->version[0],
394 req->version[1],
395 req->version[2],
396 DLM_DEVICE_VERSION_MAJOR,
397 DLM_DEVICE_VERSION_MINOR,
398 DLM_DEVICE_VERSION_PATCH);
399 return -EINVAL;
400 }
401 return 0;
402}
403
404/*
405 * device_write
406 *
407 * device_user_lock
408 * dlm_user_request -> request_lock
409 * dlm_user_convert -> convert_lock
410 *
411 * device_user_unlock
412 * dlm_user_unlock -> unlock_lock
413 * dlm_user_cancel -> cancel_lock
414 *
415 * device_create_lockspace
416 * dlm_new_lockspace
417 *
418 * device_remove_lockspace
419 * dlm_release_lockspace
420 */
421
422/* a write to a lockspace device is a lock or unlock request, a write
423 to the control device is to create/remove a lockspace */
424
425static ssize_t device_write(struct file *file, const char __user *buf,
426 size_t count, loff_t *ppos)
427{
428 struct dlm_user_proc *proc = file->private_data;
429 struct dlm_write_request *kbuf;
430 sigset_t tmpsig, allsigs;
431 int error;
432
433#ifdef CONFIG_COMPAT
434 if (count < sizeof(struct dlm_write_request32))
435#else
436 if (count < sizeof(struct dlm_write_request))
437#endif
438 return -EINVAL;
439
440 kbuf = kmalloc(count, GFP_KERNEL);
441 if (!kbuf)
442 return -ENOMEM;
443
444 if (copy_from_user(kbuf, buf, count)) {
445 error = -EFAULT;
446 goto out_free;
447 }
448
449 if (check_version(kbuf)) {
450 error = -EBADE;
451 goto out_free;
452 }
453
454#ifdef CONFIG_COMPAT
455 if (!kbuf->is64bit) {
456 struct dlm_write_request32 *k32buf;
457 k32buf = (struct dlm_write_request32 *)kbuf;
458 kbuf = kmalloc(count + (sizeof(struct dlm_write_request) -
459 sizeof(struct dlm_write_request32)), GFP_KERNEL);
460 if (!kbuf)
461 return -ENOMEM;
462
463 if (proc)
464 set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
465 compat_input(kbuf, k32buf);
466 kfree(k32buf);
467 }
468#endif
469
470 /* do we really need this? can a write happen after a close? */
471 if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) &&
472 test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
473 return -EINVAL;
474
475 sigfillset(&allsigs);
476 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
477
478 error = -EINVAL;
479
480 switch (kbuf->cmd)
481 {
482 case DLM_USER_LOCK:
483 if (!proc) {
484 log_print("no locking on control device");
485 goto out_sig;
486 }
487 error = device_user_lock(proc, &kbuf->i.lock);
488 break;
489
490 case DLM_USER_UNLOCK:
491 if (!proc) {
492 log_print("no locking on control device");
493 goto out_sig;
494 }
495 error = device_user_unlock(proc, &kbuf->i.lock);
496 break;
497
498 case DLM_USER_CREATE_LOCKSPACE:
499 if (proc) {
500 log_print("create/remove only on control device");
501 goto out_sig;
502 }
503 error = device_create_lockspace(&kbuf->i.lspace);
504 break;
505
506 case DLM_USER_REMOVE_LOCKSPACE:
507 if (proc) {
508 log_print("create/remove only on control device");
509 goto out_sig;
510 }
511 error = device_remove_lockspace(&kbuf->i.lspace);
512 break;
513
514 default:
515 log_print("Unknown command passed to DLM device : %d\n",
516 kbuf->cmd);
517 }
518
519 out_sig:
520 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
521 recalc_sigpending();
522 out_free:
523 kfree(kbuf);
524 return error;
525}
526
527/* Every process that opens the lockspace device has its own "proc" structure
528 hanging off the open file that's used to keep track of locks owned by the
529 process and asts that need to be delivered to the process. */
530
531static int device_open(struct inode *inode, struct file *file)
532{
533 struct dlm_user_proc *proc;
534 struct dlm_ls *ls;
535
536 ls = dlm_find_lockspace_device(iminor(inode));
537 if (!ls)
538 return -ENOENT;
539
540 proc = kzalloc(sizeof(struct dlm_user_proc), GFP_KERNEL);
541 if (!proc) {
542 dlm_put_lockspace(ls);
543 return -ENOMEM;
544 }
545
546 proc->lockspace = ls->ls_local_handle;
547 INIT_LIST_HEAD(&proc->asts);
548 INIT_LIST_HEAD(&proc->locks);
a1bc86e6 549 INIT_LIST_HEAD(&proc->unlocking);
597d0cae
DT
550 spin_lock_init(&proc->asts_spin);
551 spin_lock_init(&proc->locks_spin);
552 init_waitqueue_head(&proc->wait);
553 file->private_data = proc;
554
555 return 0;
556}
557
558static int device_close(struct inode *inode, struct file *file)
559{
560 struct dlm_user_proc *proc = file->private_data;
561 struct dlm_ls *ls;
562 sigset_t tmpsig, allsigs;
563
564 ls = dlm_find_lockspace_local(proc->lockspace);
565 if (!ls)
566 return -ENOENT;
567
568 sigfillset(&allsigs);
569 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
570
571 set_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags);
572
573 dlm_clear_proc_locks(ls, proc);
574
575 /* at this point no more lkb's should exist for this lockspace,
576 so there's no chance of dlm_user_add_ast() being called and
577 looking for lkb->ua->proc */
578
579 kfree(proc);
580 file->private_data = NULL;
581
582 dlm_put_lockspace(ls);
583 dlm_put_lockspace(ls); /* for the find in device_open() */
584
585 /* FIXME: AUTOFREE: if this ls is no longer used do
586 device_remove_lockspace() */
587
588 sigprocmask(SIG_SETMASK, &tmpsig, NULL);
589 recalc_sigpending();
590
591 return 0;
592}
593
594static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
595 int bmode, char __user *buf, size_t count)
596{
597#ifdef CONFIG_COMPAT
598 struct dlm_lock_result32 result32;
599#endif
600 struct dlm_lock_result result;
601 void *resultptr;
602 int error=0;
603 int len;
604 int struct_len;
605
606 memset(&result, 0, sizeof(struct dlm_lock_result));
607 memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
608 result.user_lksb = ua->user_lksb;
609
610 /* FIXME: dlm1 provides for the user's bastparam/addr to not be updated
611 in a conversion unless the conversion is successful. See code
612 in dlm_user_convert() for updating ua from ua_tmp. OpenVMS, though,
613 notes that a new blocking AST address and parameter are set even if
614 the conversion fails, so maybe we should just do that. */
615
616 if (type == AST_BAST) {
617 result.user_astaddr = ua->bastaddr;
618 result.user_astparam = ua->bastparam;
619 result.bast_mode = bmode;
620 } else {
621 result.user_astaddr = ua->castaddr;
622 result.user_astparam = ua->castparam;
623 }
624
625#ifdef CONFIG_COMPAT
626 if (compat)
627 len = sizeof(struct dlm_lock_result32);
628 else
629#endif
630 len = sizeof(struct dlm_lock_result);
631 struct_len = len;
632
633 /* copy lvb to userspace if there is one, it's been updated, and
634 the user buffer has space for it */
635
636 if (ua->update_user_lvb && ua->lksb.sb_lvbptr &&
637 count >= len + DLM_USER_LVB_LEN) {
638 if (copy_to_user(buf+len, ua->lksb.sb_lvbptr,
639 DLM_USER_LVB_LEN)) {
640 error = -EFAULT;
641 goto out;
642 }
643
644 result.lvb_offset = len;
645 len += DLM_USER_LVB_LEN;
646 }
647
648 result.length = len;
649 resultptr = &result;
650#ifdef CONFIG_COMPAT
651 if (compat) {
652 compat_output(&result, &result32);
653 resultptr = &result32;
654 }
655#endif
656
657 if (copy_to_user(buf, resultptr, struct_len))
658 error = -EFAULT;
659 else
660 error = len;
661 out:
662 return error;
663}
664
665/* a read returns a single ast described in a struct dlm_lock_result */
666
667static ssize_t device_read(struct file *file, char __user *buf, size_t count,
668 loff_t *ppos)
669{
670 struct dlm_user_proc *proc = file->private_data;
671 struct dlm_lkb *lkb;
672 struct dlm_user_args *ua;
673 DECLARE_WAITQUEUE(wait, current);
674 int error, type=0, bmode=0, removed = 0;
675
676#ifdef CONFIG_COMPAT
677 if (count < sizeof(struct dlm_lock_result32))
678#else
679 if (count < sizeof(struct dlm_lock_result))
680#endif
681 return -EINVAL;
682
683 /* do we really need this? can a read happen after a close? */
684 if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
685 return -EINVAL;
686
687 spin_lock(&proc->asts_spin);
688 if (list_empty(&proc->asts)) {
689 if (file->f_flags & O_NONBLOCK) {
690 spin_unlock(&proc->asts_spin);
691 return -EAGAIN;
692 }
693
694 add_wait_queue(&proc->wait, &wait);
695
696 repeat:
697 set_current_state(TASK_INTERRUPTIBLE);
698 if (list_empty(&proc->asts) && !signal_pending(current)) {
699 spin_unlock(&proc->asts_spin);
700 schedule();
701 spin_lock(&proc->asts_spin);
702 goto repeat;
703 }
704 set_current_state(TASK_RUNNING);
705 remove_wait_queue(&proc->wait, &wait);
706
707 if (signal_pending(current)) {
708 spin_unlock(&proc->asts_spin);
709 return -ERESTARTSYS;
710 }
711 }
712
713 if (list_empty(&proc->asts)) {
714 spin_unlock(&proc->asts_spin);
715 return -EAGAIN;
716 }
717
718 /* there may be both completion and blocking asts to return for
719 the lkb, don't remove lkb from asts list unless no asts remain */
720
721 lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue);
722
723 if (lkb->lkb_ast_type & AST_COMP) {
724 lkb->lkb_ast_type &= ~AST_COMP;
725 type = AST_COMP;
726 } else if (lkb->lkb_ast_type & AST_BAST) {
727 lkb->lkb_ast_type &= ~AST_BAST;
728 type = AST_BAST;
729 bmode = lkb->lkb_bastmode;
730 }
731
732 if (!lkb->lkb_ast_type) {
733 list_del(&lkb->lkb_astqueue);
734 removed = 1;
735 }
736 spin_unlock(&proc->asts_spin);
737
738 ua = (struct dlm_user_args *)lkb->lkb_astparam;
739 error = copy_result_to_user(ua,
740 test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
741 type, bmode, buf, count);
742
743 /* removes reference for the proc->asts lists added by
744 dlm_user_add_ast() and may result in the lkb being freed */
745 if (removed)
746 dlm_put_lkb(lkb);
747
748 return error;
749}
750
751static unsigned int device_poll(struct file *file, poll_table *wait)
752{
753 struct dlm_user_proc *proc = file->private_data;
754
755 poll_wait(file, &proc->wait, wait);
756
757 spin_lock(&proc->asts_spin);
758 if (!list_empty(&proc->asts)) {
759 spin_unlock(&proc->asts_spin);
760 return POLLIN | POLLRDNORM;
761 }
762 spin_unlock(&proc->asts_spin);
763 return 0;
764}
765
766static int ctl_device_open(struct inode *inode, struct file *file)
767{
768 file->private_data = NULL;
769 return 0;
770}
771
772static int ctl_device_close(struct inode *inode, struct file *file)
773{
774 return 0;
775}
776
00977a59 777static const struct file_operations device_fops = {
597d0cae
DT
778 .open = device_open,
779 .release = device_close,
780 .read = device_read,
781 .write = device_write,
782 .poll = device_poll,
783 .owner = THIS_MODULE,
784};
785
00977a59 786static const struct file_operations ctl_device_fops = {
597d0cae
DT
787 .open = ctl_device_open,
788 .release = ctl_device_close,
789 .write = device_write,
790 .owner = THIS_MODULE,
791};
792
793int dlm_user_init(void)
794{
795 int error;
796
797 ctl_device.name = "dlm-control";
798 ctl_device.fops = &ctl_device_fops;
799 ctl_device.minor = MISC_DYNAMIC_MINOR;
800
801 error = misc_register(&ctl_device);
802 if (error)
803 log_print("misc_register failed for control device");
804
805 return error;
806}
807
808void dlm_user_exit(void)
809{
810 misc_deregister(&ctl_device);
811}
812
This page took 0.13425 seconds and 5 git commands to generate.