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