FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_lockf.c
1 /*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Scooter Morris at Genentech Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)ufs_lockf.c 8.3 (Berkeley) 1/6/94
37 * $FreeBSD: releng/5.1/sys/kern/kern_lockf.c 114216 2003-04-29 13:36:06Z kan $
38 */
39
40 #include "opt_debug_lockf.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/limits.h>
46 #include <sys/lock.h>
47 #include <sys/mount.h>
48 #include <sys/mutex.h>
49 #include <sys/proc.h>
50 #include <sys/unistd.h>
51 #include <sys/vnode.h>
52 #include <sys/malloc.h>
53 #include <sys/fcntl.h>
54 #include <sys/lockf.h>
55
56 /*
57 * This variable controls the maximum number of processes that will
58 * be checked in doing deadlock detection.
59 */
60 static int maxlockdepth = MAXDEPTH;
61
62 #ifdef LOCKF_DEBUG
63 #include <sys/sysctl.h>
64
65 #include <ufs/ufs/quota.h>
66 #include <ufs/ufs/inode.h>
67
68
69 static int lockf_debug = 0;
70 SYSCTL_INT(_debug, OID_AUTO, lockf_debug, CTLFLAG_RW, &lockf_debug, 0, "");
71 #endif
72
73 MALLOC_DEFINE(M_LOCKF, "lockf", "Byte-range locking structures");
74
75 #define NOLOCKF (struct lockf *)0
76 #define SELF 0x1
77 #define OTHERS 0x2
78 static int lf_clearlock(struct lockf *);
79 static int lf_findoverlap(struct lockf *,
80 struct lockf *, int, struct lockf ***, struct lockf **);
81 static struct lockf *
82 lf_getblock(struct lockf *);
83 static int lf_getlock(struct lockf *, struct flock *);
84 static int lf_setlock(struct lockf *);
85 static void lf_split(struct lockf *, struct lockf *);
86 static void lf_wakelock(struct lockf *);
87
88 /*
89 * Advisory record locking support
90 */
91 int
92 lf_advlock(ap, head, size)
93 struct vop_advlock_args /* {
94 struct vnode *a_vp;
95 caddr_t a_id;
96 int a_op;
97 struct flock *a_fl;
98 int a_flags;
99 } */ *ap;
100 struct lockf **head;
101 u_quad_t size;
102 {
103 register struct flock *fl = ap->a_fl;
104 register struct lockf *lock;
105 off_t start, end, oadd;
106 int error;
107
108 /*
109 * Convert the flock structure into a start and end.
110 */
111 switch (fl->l_whence) {
112
113 case SEEK_SET:
114 case SEEK_CUR:
115 /*
116 * Caller is responsible for adding any necessary offset
117 * when SEEK_CUR is used.
118 */
119 start = fl->l_start;
120 break;
121
122 case SEEK_END:
123 if (size > OFF_MAX ||
124 (fl->l_start > 0 && size > OFF_MAX - fl->l_start))
125 return (EOVERFLOW);
126 start = size + fl->l_start;
127 break;
128
129 default:
130 return (EINVAL);
131 }
132 if (start < 0)
133 return (EINVAL);
134 if (fl->l_len < 0) {
135 if (start == 0)
136 return (EINVAL);
137 end = start - 1;
138 start += fl->l_len;
139 if (start < 0)
140 return (EINVAL);
141 } else if (fl->l_len == 0)
142 end = -1;
143 else {
144 oadd = fl->l_len - 1;
145 if (oadd > OFF_MAX - start)
146 return (EOVERFLOW);
147 end = start + oadd;
148 }
149 /*
150 * Avoid the common case of unlocking when inode has no locks.
151 */
152 if (*head == (struct lockf *)0) {
153 if (ap->a_op != F_SETLK) {
154 fl->l_type = F_UNLCK;
155 return (0);
156 }
157 }
158 /*
159 * Create the lockf structure
160 */
161 MALLOC(lock, struct lockf *, sizeof *lock, M_LOCKF, M_WAITOK);
162 lock->lf_start = start;
163 lock->lf_end = end;
164 lock->lf_id = ap->a_id;
165 /*
166 * XXX The problem is that VTOI is ufs specific, so it will
167 * break LOCKF_DEBUG for all other FS's other than UFS because
168 * it casts the vnode->data ptr to struct inode *.
169 */
170 /* lock->lf_inode = VTOI(ap->a_vp); */
171 lock->lf_inode = (struct inode *)0;
172 lock->lf_type = fl->l_type;
173 lock->lf_head = head;
174 lock->lf_next = (struct lockf *)0;
175 TAILQ_INIT(&lock->lf_blkhd);
176 lock->lf_flags = ap->a_flags;
177 /*
178 * Do the requested operation.
179 */
180 switch(ap->a_op) {
181 case F_SETLK:
182 return (lf_setlock(lock));
183
184 case F_UNLCK:
185 error = lf_clearlock(lock);
186 FREE(lock, M_LOCKF);
187 return (error);
188
189 case F_GETLK:
190 error = lf_getlock(lock, fl);
191 FREE(lock, M_LOCKF);
192 return (error);
193
194 default:
195 free(lock, M_LOCKF);
196 return (EINVAL);
197 }
198 /* NOTREACHED */
199 }
200
201 /*
202 * Set a byte-range lock.
203 */
204 static int
205 lf_setlock(lock)
206 register struct lockf *lock;
207 {
208 register struct lockf *block;
209 struct lockf **head = lock->lf_head;
210 struct lockf **prev, *overlap, *ltmp;
211 static char lockstr[] = "lockf";
212 int ovcase, priority, needtolink, error;
213
214 #ifdef LOCKF_DEBUG
215 if (lockf_debug & 1)
216 lf_print("lf_setlock", lock);
217 #endif /* LOCKF_DEBUG */
218
219 /*
220 * Set the priority
221 */
222 priority = PLOCK;
223 if (lock->lf_type == F_WRLCK)
224 priority += 4;
225 priority |= PCATCH;
226 /*
227 * Scan lock list for this file looking for locks that would block us.
228 */
229 while ((block = lf_getblock(lock))) {
230 /*
231 * Free the structure and return if nonblocking.
232 */
233 if ((lock->lf_flags & F_WAIT) == 0) {
234 FREE(lock, M_LOCKF);
235 return (EAGAIN);
236 }
237 /*
238 * We are blocked. Since flock style locks cover
239 * the whole file, there is no chance for deadlock.
240 * For byte-range locks we must check for deadlock.
241 *
242 * Deadlock detection is done by looking through the
243 * wait channels to see if there are any cycles that
244 * involve us. MAXDEPTH is set just to make sure we
245 * do not go off into neverland.
246 */
247 if ((lock->lf_flags & F_POSIX) &&
248 (block->lf_flags & F_POSIX)) {
249 register struct proc *wproc;
250 struct thread *td;
251 register struct lockf *waitblock;
252 int i = 0;
253
254 /* The block is waiting on something */
255 /* XXXKSE this is not complete under threads */
256 wproc = (struct proc *)block->lf_id;
257 mtx_lock_spin(&sched_lock);
258 FOREACH_THREAD_IN_PROC(wproc, td) {
259 while (td->td_wchan &&
260 (td->td_wmesg == lockstr) &&
261 (i++ < maxlockdepth)) {
262 waitblock = (struct lockf *)td->td_wchan;
263 /* Get the owner of the blocking lock */
264 waitblock = waitblock->lf_next;
265 if ((waitblock->lf_flags & F_POSIX) == 0)
266 break;
267 wproc = (struct proc *)waitblock->lf_id;
268 if (wproc == (struct proc *)lock->lf_id) {
269 mtx_unlock_spin(&sched_lock);
270 free(lock, M_LOCKF);
271 return (EDEADLK);
272 }
273 }
274 }
275 mtx_unlock_spin(&sched_lock);
276 }
277 /*
278 * For flock type locks, we must first remove
279 * any shared locks that we hold before we sleep
280 * waiting for an exclusive lock.
281 */
282 if ((lock->lf_flags & F_FLOCK) &&
283 lock->lf_type == F_WRLCK) {
284 lock->lf_type = F_UNLCK;
285 (void) lf_clearlock(lock);
286 lock->lf_type = F_WRLCK;
287 }
288 /*
289 * Add our lock to the blocked list and sleep until we're free.
290 * Remember who blocked us (for deadlock detection).
291 */
292 lock->lf_next = block;
293 TAILQ_INSERT_TAIL(&block->lf_blkhd, lock, lf_block);
294 #ifdef LOCKF_DEBUG
295 if (lockf_debug & 1) {
296 lf_print("lf_setlock: blocking on", block);
297 lf_printlist("lf_setlock", block);
298 }
299 #endif /* LOCKF_DEBUG */
300 error = tsleep(lock, priority, lockstr, 0);
301 /*
302 * We may have been awakened by a signal and/or by a
303 * debugger continuing us (in which cases we must remove
304 * ourselves from the blocked list) and/or by another
305 * process releasing a lock (in which case we have
306 * already been removed from the blocked list and our
307 * lf_next field set to NOLOCKF).
308 */
309 if (lock->lf_next) {
310 TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock, lf_block);
311 lock->lf_next = NOLOCKF;
312 }
313 if (error) {
314 free(lock, M_LOCKF);
315 return (error);
316 }
317 }
318 /*
319 * No blocks!! Add the lock. Note that we will
320 * downgrade or upgrade any overlapping locks this
321 * process already owns.
322 *
323 * Skip over locks owned by other processes.
324 * Handle any locks that overlap and are owned by ourselves.
325 */
326 prev = head;
327 block = *head;
328 needtolink = 1;
329 for (;;) {
330 ovcase = lf_findoverlap(block, lock, SELF, &prev, &overlap);
331 if (ovcase)
332 block = overlap->lf_next;
333 /*
334 * Six cases:
335 * 0) no overlap
336 * 1) overlap == lock
337 * 2) overlap contains lock
338 * 3) lock contains overlap
339 * 4) overlap starts before lock
340 * 5) overlap ends after lock
341 */
342 switch (ovcase) {
343 case 0: /* no overlap */
344 if (needtolink) {
345 *prev = lock;
346 lock->lf_next = overlap;
347 }
348 break;
349
350 case 1: /* overlap == lock */
351 /*
352 * If downgrading lock, others may be
353 * able to acquire it.
354 */
355 if (lock->lf_type == F_RDLCK &&
356 overlap->lf_type == F_WRLCK)
357 lf_wakelock(overlap);
358 overlap->lf_type = lock->lf_type;
359 FREE(lock, M_LOCKF);
360 lock = overlap; /* for debug output below */
361 break;
362
363 case 2: /* overlap contains lock */
364 /*
365 * Check for common starting point and different types.
366 */
367 if (overlap->lf_type == lock->lf_type) {
368 free(lock, M_LOCKF);
369 lock = overlap; /* for debug output below */
370 break;
371 }
372 if (overlap->lf_start == lock->lf_start) {
373 *prev = lock;
374 lock->lf_next = overlap;
375 overlap->lf_start = lock->lf_end + 1;
376 } else
377 lf_split(overlap, lock);
378 lf_wakelock(overlap);
379 break;
380
381 case 3: /* lock contains overlap */
382 /*
383 * If downgrading lock, others may be able to
384 * acquire it, otherwise take the list.
385 */
386 if (lock->lf_type == F_RDLCK &&
387 overlap->lf_type == F_WRLCK) {
388 lf_wakelock(overlap);
389 } else {
390 while (!TAILQ_EMPTY(&overlap->lf_blkhd)) {
391 ltmp = TAILQ_FIRST(&overlap->lf_blkhd);
392 TAILQ_REMOVE(&overlap->lf_blkhd, ltmp,
393 lf_block);
394 TAILQ_INSERT_TAIL(&lock->lf_blkhd,
395 ltmp, lf_block);
396 ltmp->lf_next = lock;
397 }
398 }
399 /*
400 * Add the new lock if necessary and delete the overlap.
401 */
402 if (needtolink) {
403 *prev = lock;
404 lock->lf_next = overlap->lf_next;
405 prev = &lock->lf_next;
406 needtolink = 0;
407 } else
408 *prev = overlap->lf_next;
409 free(overlap, M_LOCKF);
410 continue;
411
412 case 4: /* overlap starts before lock */
413 /*
414 * Add lock after overlap on the list.
415 */
416 lock->lf_next = overlap->lf_next;
417 overlap->lf_next = lock;
418 overlap->lf_end = lock->lf_start - 1;
419 prev = &lock->lf_next;
420 lf_wakelock(overlap);
421 needtolink = 0;
422 continue;
423
424 case 5: /* overlap ends after lock */
425 /*
426 * Add the new lock before overlap.
427 */
428 if (needtolink) {
429 *prev = lock;
430 lock->lf_next = overlap;
431 }
432 overlap->lf_start = lock->lf_end + 1;
433 lf_wakelock(overlap);
434 break;
435 }
436 break;
437 }
438 #ifdef LOCKF_DEBUG
439 if (lockf_debug & 1) {
440 lf_print("lf_setlock: got the lock", lock);
441 lf_printlist("lf_setlock", lock);
442 }
443 #endif /* LOCKF_DEBUG */
444 return (0);
445 }
446
447 /*
448 * Remove a byte-range lock on an inode.
449 *
450 * Generally, find the lock (or an overlap to that lock)
451 * and remove it (or shrink it), then wakeup anyone we can.
452 */
453 static int
454 lf_clearlock(unlock)
455 register struct lockf *unlock;
456 {
457 struct lockf **head = unlock->lf_head;
458 register struct lockf *lf = *head;
459 struct lockf *overlap, **prev;
460 int ovcase;
461
462 if (lf == NOLOCKF)
463 return (0);
464 #ifdef LOCKF_DEBUG
465 if (unlock->lf_type != F_UNLCK)
466 panic("lf_clearlock: bad type");
467 if (lockf_debug & 1)
468 lf_print("lf_clearlock", unlock);
469 #endif /* LOCKF_DEBUG */
470 prev = head;
471 while ((ovcase = lf_findoverlap(lf, unlock, SELF, &prev, &overlap))) {
472 /*
473 * Wakeup the list of locks to be retried.
474 */
475 lf_wakelock(overlap);
476
477 switch (ovcase) {
478
479 case 1: /* overlap == lock */
480 *prev = overlap->lf_next;
481 FREE(overlap, M_LOCKF);
482 break;
483
484 case 2: /* overlap contains lock: split it */
485 if (overlap->lf_start == unlock->lf_start) {
486 overlap->lf_start = unlock->lf_end + 1;
487 break;
488 }
489 lf_split(overlap, unlock);
490 overlap->lf_next = unlock->lf_next;
491 break;
492
493 case 3: /* lock contains overlap */
494 *prev = overlap->lf_next;
495 lf = overlap->lf_next;
496 free(overlap, M_LOCKF);
497 continue;
498
499 case 4: /* overlap starts before lock */
500 overlap->lf_end = unlock->lf_start - 1;
501 prev = &overlap->lf_next;
502 lf = overlap->lf_next;
503 continue;
504
505 case 5: /* overlap ends after lock */
506 overlap->lf_start = unlock->lf_end + 1;
507 break;
508 }
509 break;
510 }
511 #ifdef LOCKF_DEBUG
512 if (lockf_debug & 1)
513 lf_printlist("lf_clearlock", unlock);
514 #endif /* LOCKF_DEBUG */
515 return (0);
516 }
517
518 /*
519 * Check whether there is a blocking lock,
520 * and if so return its process identifier.
521 */
522 static int
523 lf_getlock(lock, fl)
524 register struct lockf *lock;
525 register struct flock *fl;
526 {
527 register struct lockf *block;
528
529 #ifdef LOCKF_DEBUG
530 if (lockf_debug & 1)
531 lf_print("lf_getlock", lock);
532 #endif /* LOCKF_DEBUG */
533
534 if ((block = lf_getblock(lock))) {
535 fl->l_type = block->lf_type;
536 fl->l_whence = SEEK_SET;
537 fl->l_start = block->lf_start;
538 if (block->lf_end == -1)
539 fl->l_len = 0;
540 else
541 fl->l_len = block->lf_end - block->lf_start + 1;
542 if (block->lf_flags & F_POSIX)
543 fl->l_pid = ((struct proc *)(block->lf_id))->p_pid;
544 else
545 fl->l_pid = -1;
546 } else {
547 fl->l_type = F_UNLCK;
548 }
549 return (0);
550 }
551
552 /*
553 * Walk the list of locks for an inode and
554 * return the first blocking lock.
555 */
556 static struct lockf *
557 lf_getblock(lock)
558 register struct lockf *lock;
559 {
560 struct lockf **prev, *overlap, *lf = *(lock->lf_head);
561 int ovcase;
562
563 prev = lock->lf_head;
564 while ((ovcase = lf_findoverlap(lf, lock, OTHERS, &prev, &overlap))) {
565 /*
566 * We've found an overlap, see if it blocks us
567 */
568 if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK))
569 return (overlap);
570 /*
571 * Nope, point to the next one on the list and
572 * see if it blocks us
573 */
574 lf = overlap->lf_next;
575 }
576 return (NOLOCKF);
577 }
578
579 /*
580 * Walk the list of locks for an inode to
581 * find an overlapping lock (if any).
582 *
583 * NOTE: this returns only the FIRST overlapping lock. There
584 * may be more than one.
585 */
586 static int
587 lf_findoverlap(lf, lock, type, prev, overlap)
588 register struct lockf *lf;
589 struct lockf *lock;
590 int type;
591 struct lockf ***prev;
592 struct lockf **overlap;
593 {
594 off_t start, end;
595
596 *overlap = lf;
597 if (lf == NOLOCKF)
598 return (0);
599 #ifdef LOCKF_DEBUG
600 if (lockf_debug & 2)
601 lf_print("lf_findoverlap: looking for overlap in", lock);
602 #endif /* LOCKF_DEBUG */
603 start = lock->lf_start;
604 end = lock->lf_end;
605 while (lf != NOLOCKF) {
606 if (((type & SELF) && lf->lf_id != lock->lf_id) ||
607 ((type & OTHERS) && lf->lf_id == lock->lf_id)) {
608 *prev = &lf->lf_next;
609 *overlap = lf = lf->lf_next;
610 continue;
611 }
612 #ifdef LOCKF_DEBUG
613 if (lockf_debug & 2)
614 lf_print("\tchecking", lf);
615 #endif /* LOCKF_DEBUG */
616 /*
617 * OK, check for overlap
618 *
619 * Six cases:
620 * 0) no overlap
621 * 1) overlap == lock
622 * 2) overlap contains lock
623 * 3) lock contains overlap
624 * 4) overlap starts before lock
625 * 5) overlap ends after lock
626 */
627 if ((lf->lf_end != -1 && start > lf->lf_end) ||
628 (end != -1 && lf->lf_start > end)) {
629 /* Case 0 */
630 #ifdef LOCKF_DEBUG
631 if (lockf_debug & 2)
632 printf("no overlap\n");
633 #endif /* LOCKF_DEBUG */
634 if ((type & SELF) && end != -1 && lf->lf_start > end)
635 return (0);
636 *prev = &lf->lf_next;
637 *overlap = lf = lf->lf_next;
638 continue;
639 }
640 if ((lf->lf_start == start) && (lf->lf_end == end)) {
641 /* Case 1 */
642 #ifdef LOCKF_DEBUG
643 if (lockf_debug & 2)
644 printf("overlap == lock\n");
645 #endif /* LOCKF_DEBUG */
646 return (1);
647 }
648 if ((lf->lf_start <= start) &&
649 (end != -1) &&
650 ((lf->lf_end >= end) || (lf->lf_end == -1))) {
651 /* Case 2 */
652 #ifdef LOCKF_DEBUG
653 if (lockf_debug & 2)
654 printf("overlap contains lock\n");
655 #endif /* LOCKF_DEBUG */
656 return (2);
657 }
658 if (start <= lf->lf_start &&
659 (end == -1 ||
660 (lf->lf_end != -1 && end >= lf->lf_end))) {
661 /* Case 3 */
662 #ifdef LOCKF_DEBUG
663 if (lockf_debug & 2)
664 printf("lock contains overlap\n");
665 #endif /* LOCKF_DEBUG */
666 return (3);
667 }
668 if ((lf->lf_start < start) &&
669 ((lf->lf_end >= start) || (lf->lf_end == -1))) {
670 /* Case 4 */
671 #ifdef LOCKF_DEBUG
672 if (lockf_debug & 2)
673 printf("overlap starts before lock\n");
674 #endif /* LOCKF_DEBUG */
675 return (4);
676 }
677 if ((lf->lf_start > start) &&
678 (end != -1) &&
679 ((lf->lf_end > end) || (lf->lf_end == -1))) {
680 /* Case 5 */
681 #ifdef LOCKF_DEBUG
682 if (lockf_debug & 2)
683 printf("overlap ends after lock\n");
684 #endif /* LOCKF_DEBUG */
685 return (5);
686 }
687 panic("lf_findoverlap: default");
688 }
689 return (0);
690 }
691
692 /*
693 * Split a lock and a contained region into
694 * two or three locks as necessary.
695 */
696 static void
697 lf_split(lock1, lock2)
698 register struct lockf *lock1;
699 register struct lockf *lock2;
700 {
701 register struct lockf *splitlock;
702
703 #ifdef LOCKF_DEBUG
704 if (lockf_debug & 2) {
705 lf_print("lf_split", lock1);
706 lf_print("splitting from", lock2);
707 }
708 #endif /* LOCKF_DEBUG */
709 /*
710 * Check to see if spliting into only two pieces.
711 */
712 if (lock1->lf_start == lock2->lf_start) {
713 lock1->lf_start = lock2->lf_end + 1;
714 lock2->lf_next = lock1;
715 return;
716 }
717 if (lock1->lf_end == lock2->lf_end) {
718 lock1->lf_end = lock2->lf_start - 1;
719 lock2->lf_next = lock1->lf_next;
720 lock1->lf_next = lock2;
721 return;
722 }
723 /*
724 * Make a new lock consisting of the last part of
725 * the encompassing lock
726 */
727 MALLOC(splitlock, struct lockf *, sizeof *splitlock, M_LOCKF, M_WAITOK);
728 bcopy(lock1, splitlock, sizeof *splitlock);
729 splitlock->lf_start = lock2->lf_end + 1;
730 TAILQ_INIT(&splitlock->lf_blkhd);
731 lock1->lf_end = lock2->lf_start - 1;
732 /*
733 * OK, now link it in
734 */
735 splitlock->lf_next = lock1->lf_next;
736 lock2->lf_next = splitlock;
737 lock1->lf_next = lock2;
738 }
739
740 /*
741 * Wakeup a blocklist
742 */
743 static void
744 lf_wakelock(listhead)
745 struct lockf *listhead;
746 {
747 register struct lockf *wakelock;
748
749 while (!TAILQ_EMPTY(&listhead->lf_blkhd)) {
750 wakelock = TAILQ_FIRST(&listhead->lf_blkhd);
751 TAILQ_REMOVE(&listhead->lf_blkhd, wakelock, lf_block);
752 wakelock->lf_next = NOLOCKF;
753 #ifdef LOCKF_DEBUG
754 if (lockf_debug & 2)
755 lf_print("lf_wakelock: awakening", wakelock);
756 #endif /* LOCKF_DEBUG */
757 wakeup(wakelock);
758 }
759 }
760
761 #ifdef LOCKF_DEBUG
762 /*
763 * Print out a lock.
764 */
765 void
766 lf_print(tag, lock)
767 char *tag;
768 register struct lockf *lock;
769 {
770
771 printf("%s: lock %p for ", tag, (void *)lock);
772 if (lock->lf_flags & F_POSIX)
773 printf("proc %ld", (long)((struct proc *)lock->lf_id)->p_pid);
774 else
775 printf("id %p", (void *)lock->lf_id);
776 if (lock->lf_inode != (struct inode *)0)
777 printf(" in ino %ju on dev <%d, %d>, %s, start %jd, end %jd",
778 (uintmax_t)lock->lf_inode->i_number,
779 major(lock->lf_inode->i_dev),
780 minor(lock->lf_inode->i_dev),
781 lock->lf_type == F_RDLCK ? "shared" :
782 lock->lf_type == F_WRLCK ? "exclusive" :
783 lock->lf_type == F_UNLCK ? "unlock" : "unknown",
784 (intmax_t)lock->lf_start, (intmax_t)lock->lf_end);
785 else
786 printf(" %s, start %jd, end %jd",
787 lock->lf_type == F_RDLCK ? "shared" :
788 lock->lf_type == F_WRLCK ? "exclusive" :
789 lock->lf_type == F_UNLCK ? "unlock" : "unknown",
790 (intmax_t)lock->lf_start, (intmax_t)lock->lf_end);
791 if (!TAILQ_EMPTY(&lock->lf_blkhd))
792 printf(" block %p\n", (void *)TAILQ_FIRST(&lock->lf_blkhd));
793 else
794 printf("\n");
795 }
796
797 void
798 lf_printlist(tag, lock)
799 char *tag;
800 struct lockf *lock;
801 {
802 register struct lockf *lf, *blk;
803
804 if (lock->lf_inode == (struct inode *)0)
805 return;
806
807 printf("%s: Lock list for ino %ju on dev <%d, %d>:\n",
808 tag, (uintmax_t)lock->lf_inode->i_number,
809 major(lock->lf_inode->i_dev),
810 minor(lock->lf_inode->i_dev));
811 for (lf = lock->lf_inode->i_lockf; lf; lf = lf->lf_next) {
812 printf("\tlock %p for ",(void *)lf);
813 if (lf->lf_flags & F_POSIX)
814 printf("proc %ld",
815 (long)((struct proc *)lf->lf_id)->p_pid);
816 else
817 printf("id %p", (void *)lf->lf_id);
818 printf(", %s, start %jd, end %jd",
819 lf->lf_type == F_RDLCK ? "shared" :
820 lf->lf_type == F_WRLCK ? "exclusive" :
821 lf->lf_type == F_UNLCK ? "unlock" :
822 "unknown", (intmax_t)lf->lf_start, (intmax_t)lf->lf_end);
823 TAILQ_FOREACH(blk, &lf->lf_blkhd, lf_block) {
824 printf("\n\t\tlock request %p for ", (void *)blk);
825 if (blk->lf_flags & F_POSIX)
826 printf("proc %ld",
827 (long)((struct proc *)blk->lf_id)->p_pid);
828 else
829 printf("id %p", (void *)blk->lf_id);
830 printf(", %s, start %jd, end %jd",
831 blk->lf_type == F_RDLCK ? "shared" :
832 blk->lf_type == F_WRLCK ? "exclusive" :
833 blk->lf_type == F_UNLCK ? "unlock" :
834 "unknown", (intmax_t)blk->lf_start,
835 (intmax_t)blk->lf_end);
836 if (!TAILQ_EMPTY(&blk->lf_blkhd))
837 panic("lf_printlist: bad list");
838 }
839 printf("\n");
840 }
841 }
842 #endif /* LOCKF_DEBUG */
Cache object: 39588c3d8ee825c8550b7e890e4dbfd1
|