|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* (c) 1997-1998 Apple Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1986, 1989, 1993
28: * The Regents of the University of California. All rights reserved.
29: *
30: * This code is derived from software contributed to Berkeley by
31: * Scooter Morris at Genentech Inc.
32: *
33: * Redistribution and use in source and binary forms, with or without
34: * modification, are permitted provided that the following conditions
35: * are met:
36: * 1. Redistributions of source code must retain the above copyright
37: * notice, this list of conditions and the following disclaimer.
38: * 2. Redistributions in binary form must reproduce the above copyright
39: * notice, this list of conditions and the following disclaimer in the
40: * documentation and/or other materials provided with the distribution.
41: * 3. All advertising materials mentioning features or use of this software
42: * must display the following acknowledgement:
43: * This product includes software developed by the University of
44: * California, Berkeley and its contributors.
45: * 4. Neither the name of the University nor the names of its contributors
46: * may be used to endorse or promote products derived from this software
47: * without specific prior written permission.
48: *
49: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59: * SUCH DAMAGE.
60: *
61: * @(#)hfs_lockf.c 1.0
62: * derived from @(#)ufs_lockf.c 8.4 (Berkeley) 10/26/94
63: */
64:
65: #include "hfs.h"
66: #include "hfs_lockf.h"
67:
68: #include <sys/param.h>
69: #include <sys/systm.h>
70: //#include <sys/kernel.h>
71: #include <sys/file.h>
72: //#include <sys/proc.h>
73: //#include <sys/vnode.h>
74: //#include <sys/malloc.h>
75: #include <sys/fcntl.h>
76: /*
77: * This variable controls the maximum number of processes that will
78: * be checked in doing deadlock detection.
79: */
80: int hfsmaxlockdepth = MAXDEPTH;
81:
82: #ifdef LOCKF_DEBUG
83: #include <vm/vm.h>
84: #include <sys/sysctl.h>
85: int lockf_debug = 0;
86: struct ctldebug debug4 = { "lockf_debug", &lockf_debug };
87: #endif
88:
89: #define NOLOCKF (struct hfslockf *)0
90: #define SELF 0x1
91: #define OTHERS 0x2
92:
93: /*
94: * Set a byte-range lock.
95: */
96: int
97: hfs_setlock(lock)
98: register struct hfslockf *lock;
99: {
100: register struct hfslockf *block;
101: struct hfsnode *hp = lock->lf_hfsnode;
102: struct hfslockf **prev, *overlap, *ltmp;
103: static char lockstr[] = "hfslockf";
104: int ovcase, priority, needtolink, error;
105:
106: #ifdef LOCKF_DEBUG
107: if (lockf_debug & 1)
108: hfs_lprint("hfs_setlock", lock);
109: #endif /* LOCKF_DEBUG */
110:
111: /*
112: * Set the priority
113: */
114: priority = PLOCK;
115: if (lock->lf_type == F_WRLCK)
116: priority += 4;
117: priority |= PCATCH;
118: /*
119: * Scan lock list for this file looking for locks that would block us.
120: */
121: while ((block = hfs_getblock(lock))) {
122: /*
123: * Free the structure and return if nonblocking.
124: */
125: if ((lock->lf_flags & F_WAIT) == 0) {
126: FREE(lock, M_LOCKF);
127: return (EAGAIN);
128: }
129: /*
130: * We are blocked. Since flock style locks cover
131: * the whole file, there is no chance for deadlock.
132: * For byte-range locks we must check for deadlock.
133: *
134: * Deadlock detection is done by looking through the
135: * wait channels to see if there are any cycles that
136: * involve us. MAXDEPTH is set just to make sure we
137: * do not go off into neverland.
138: */
139: if ((lock->lf_flags & F_POSIX) &&
140: (block->lf_flags & F_POSIX)) {
141: register struct proc *wproc;
142: register struct hfslockf *waitblock;
143: int i = 0;
144:
145: /* The block is waiting on something */
146: wproc = (struct proc *)block->lf_id;
147: while (wproc->p_wchan &&
148: (wproc->p_wmesg == lockstr) &&
149: (i++ < hfsmaxlockdepth)) {
150: waitblock = (struct hfslockf *)wproc->p_wchan;
151: /* Get the owner of the blocking lock */
152: waitblock = waitblock->lf_next;
153: if ((waitblock->lf_flags & F_POSIX) == 0)
154: break;
155: wproc = (struct proc *)waitblock->lf_id;
156: if (wproc == (struct proc *)lock->lf_id) {
157: _FREE(lock, M_LOCKF);
158: return (EDEADLK);
159: }
160: }
161: }
162: /*
163: * For flock type locks, we must first remove
164: * any shared locks that we hold before we sleep
165: * waiting for an exclusive lock.
166: */
167: if ((lock->lf_flags & F_FLOCK) &&
168: lock->lf_type == F_WRLCK) {
169: lock->lf_type = F_UNLCK;
170: (void) hfs_clearlock(lock);
171: lock->lf_type = F_WRLCK;
172: }
173: /*
174: * Add our lock to the blocked list and sleep until we're free.
175: * Remember who blocked us (for deadlock detection).
176: */
177: lock->lf_next = block;
178: TAILQ_INSERT_TAIL(&block->lf_blkhd, lock, lf_block);
179: #ifdef LOCKF_DEBUG
180: if (lockf_debug & 1) {
181: hfs_lprint("hfs_setlock: blocking on", block);
182: hfs_lprintlist("hfs_setlock", block);
183: }
184: #endif /* LOCKF_DEBUG */
185: if ((error = tsleep((caddr_t)lock, priority, lockstr, 0))) {
186: /*
187: * We may have been awakened by a signal (in
188: * which case we must remove ourselves from the
189: * blocked list) and/or by another process
190: * releasing a lock (in which case we have already
191: * been removed from the blocked list and our
192: * lf_next field set to NOLOCKF).
193: */
194: if (lock->lf_next)
195: TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock,
196: lf_block);
197: _FREE(lock, M_LOCKF);
198: return (error);
199: }
200: }
201: /*
202: * No blocks!! Add the lock. Note that we will
203: * downgrade or upgrade any overlapping locks this
204: * process already owns.
205: *
206: * Skip over locks owned by other processes.
207: * Handle any locks that overlap and are owned by ourselves.
208: */
209: prev = &hp->h_lockf;
210: block = hp->h_lockf;
211: needtolink = 1;
212: for (;;) {
213: if ((ovcase = hfs_findoverlap(block, lock, SELF, &prev, &overlap)))
214: block = overlap->lf_next;
215: /*
216: * Six cases:
217: * 0) no overlap
218: * 1) overlap == lock
219: * 2) overlap contains lock
220: * 3) lock contains overlap
221: * 4) overlap starts before lock
222: * 5) overlap ends after lock
223: */
224: switch (ovcase) {
225: case 0: /* no overlap */
226: if (needtolink) {
227: *prev = lock;
228: lock->lf_next = overlap;
229: }
230: break;
231:
232: case 1: /* overlap == lock */
233: /*
234: * If downgrading lock, others may be
235: * able to acquire it.
236: */
237: if (lock->lf_type == F_RDLCK &&
238: overlap->lf_type == F_WRLCK)
239: hfs_wakelock(overlap);
240: overlap->lf_type = lock->lf_type;
241: FREE(lock, M_LOCKF);
242: lock = overlap; /* for debug output below */
243: break;
244:
245: case 2: /* overlap contains lock */
246: /*
247: * Check for common starting point and different types.
248: */
249: if (overlap->lf_type == lock->lf_type) {
250: _FREE(lock, M_LOCKF);
251: lock = overlap; /* for debug output below */
252: break;
253: }
254: if (overlap->lf_start == lock->lf_start) {
255: *prev = lock;
256: lock->lf_next = overlap;
257: overlap->lf_start = lock->lf_end + 1;
258: } else
259: hfs_split(overlap, lock);
260: hfs_wakelock(overlap);
261: break;
262:
263: case 3: /* lock contains overlap */
264: /*
265: * If downgrading lock, others may be able to
266: * acquire it, otherwise take the list.
267: */
268: if (lock->lf_type == F_RDLCK &&
269: overlap->lf_type == F_WRLCK) {
270: hfs_wakelock(overlap);
271: } else {
272: while ((ltmp = overlap->lf_blkhd.tqh_first)) {
273: TAILQ_REMOVE(&overlap->lf_blkhd, ltmp,
274: lf_block);
275: TAILQ_INSERT_TAIL(&lock->lf_blkhd,
276: ltmp, lf_block);
277: }
278: }
279: /*
280: * Add the new lock if necessary and delete the overlap.
281: */
282: if (needtolink) {
283: *prev = lock;
284: lock->lf_next = overlap->lf_next;
285: prev = &lock->lf_next;
286: needtolink = 0;
287: } else
288: *prev = overlap->lf_next;
289: _FREE(overlap, M_LOCKF);
290: continue;
291:
292: case 4: /* overlap starts before lock */
293: /*
294: * Add lock after overlap on the list.
295: */
296: lock->lf_next = overlap->lf_next;
297: overlap->lf_next = lock;
298: overlap->lf_end = lock->lf_start - 1;
299: prev = &lock->lf_next;
300: hfs_wakelock(overlap);
301: needtolink = 0;
302: continue;
303:
304: case 5: /* overlap ends after lock */
305: /*
306: * Add the new lock before overlap.
307: */
308: if (needtolink) {
309: *prev = lock;
310: lock->lf_next = overlap;
311: }
312: overlap->lf_start = lock->lf_end + 1;
313: hfs_wakelock(overlap);
314: break;
315: }
316: break;
317: }
318: #ifdef LOCKF_DEBUG
319: if (lockf_debug & 1) {
320: hfs_lprint("hfs_setlock: got the lock", lock);
321: hfs_lprintlist("hfs_setlock", lock);
322: }
323: #endif /* LOCKF_DEBUG */
324: return (0);
325: }
326:
327: /*
328: * Remove a byte-range lock on an hfsnode.
329: *
330: * Generally, find the lock (or an overlap to that lock)
331: * and remove it (or shrink it), then wakeup anyone we can.
332: */
333: int
334: hfs_clearlock(unlock)
335: register struct hfslockf *unlock;
336: {
337: struct hfsnode *hp = unlock->lf_hfsnode;
338: register struct hfslockf *lf = hp->h_lockf;
339: struct hfslockf *overlap, **prev;
340: int ovcase;
341:
342: if (lf == NOLOCKF)
343: return (0);
344: #ifdef LOCKF_DEBUG
345: if (unlock->lf_type != F_UNLCK)
346: panic("hfs_clearlock: bad type");
347: if (lockf_debug & 1)
348: hfs_lprint("hfs_clearlock", unlock);
349: #endif /* LOCKF_DEBUG */
350: prev = &hp->h_lockf;
351: while ((ovcase = hfs_findoverlap(lf, unlock, SELF, &prev, &overlap))) {
352: /*
353: * Wakeup the list of locks to be retried.
354: */
355: hfs_wakelock(overlap);
356:
357: switch (ovcase) {
358:
359: case 1: /* overlap == lock */
360: *prev = overlap->lf_next;
361: FREE(overlap, M_LOCKF);
362: break;
363:
364: case 2: /* overlap contains lock: split it */
365: if (overlap->lf_start == unlock->lf_start) {
366: overlap->lf_start = unlock->lf_end + 1;
367: break;
368: }
369: hfs_split(overlap, unlock);
370: overlap->lf_next = unlock->lf_next;
371: break;
372:
373: case 3: /* lock contains overlap */
374: *prev = overlap->lf_next;
375: lf = overlap->lf_next;
376: _FREE(overlap, M_LOCKF);
377: continue;
378:
379: case 4: /* overlap starts before lock */
380: overlap->lf_end = unlock->lf_start - 1;
381: prev = &overlap->lf_next;
382: lf = overlap->lf_next;
383: continue;
384:
385: case 5: /* overlap ends after lock */
386: overlap->lf_start = unlock->lf_end + 1;
387: break;
388: }
389: break;
390: }
391: #ifdef LOCKF_DEBUG
392: if (lockf_debug & 1)
393: hfs_lprintlist("hfs_clearlock", unlock);
394: #endif /* LOCKF_DEBUG */
395: return (0);
396: }
397:
398: /*
399: * Check whether there is a blocking lock,
400: * and if so return its process identifier.
401: */
402: int
403: hfs_getlock(lock, fl)
404: register struct hfslockf *lock;
405: register struct flock *fl;
406: {
407: register struct hfslockf *block;
408:
409: #ifdef LOCKF_DEBUG
410: if (lockf_debug & 1)
411: hfs_lprint("hfs_getlock", lock);
412: #endif /* LOCKF_DEBUG */
413:
414: if ((block = hfs_getblock(lock))) {
415: fl->l_type = block->lf_type;
416: fl->l_whence = SEEK_SET;
417: fl->l_start = block->lf_start;
418: if (block->lf_end == -1)
419: fl->l_len = 0;
420: else
421: fl->l_len = block->lf_end - block->lf_start + 1;
422: if (block->lf_flags & F_POSIX)
423: fl->l_pid = ((struct proc *)(block->lf_id))->p_pid;
424: else
425: fl->l_pid = -1;
426: } else {
427: fl->l_type = F_UNLCK;
428: }
429: return (0);
430: }
431:
432: /*
433: * Walk the list of locks for an hfsnode and
434: * return the first blocking lock.
435: */
436: struct hfslockf *
437: hfs_getblock(lock)
438: register struct hfslockf *lock;
439: {
440: struct hfslockf **prev, *overlap, *lf = lock->lf_hfsnode->h_lockf;
441: int ovcase;
442:
443: prev = &lock->lf_hfsnode->h_lockf;
444: while ((ovcase = hfs_findoverlap(lf, lock, OTHERS, &prev, &overlap))) {
445: /*
446: * We've found an overlap, see if it blocks us
447: */
448: if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK))
449: return (overlap);
450: /*
451: * Nope, point to the next one on the list and
452: * see if it blocks us
453: */
454: lf = overlap->lf_next;
455: }
456: return (NOLOCKF);
457: }
458:
459: /*
460: * Walk the list of locks for an hfsnode to
461: * find an overlapping lock (if any).
462: *
463: * NOTE: this returns only the FIRST overlapping lock. There
464: * may be more than one.
465: */
466: int
467: hfs_findoverlap(lf, lock, type, prev, overlap)
468: register struct hfslockf *lf;
469: struct hfslockf *lock;
470: int type;
471: struct hfslockf ***prev;
472: struct hfslockf **overlap;
473: {
474: off_t start, end;
475:
476: *overlap = lf;
477: if (lf == NOLOCKF)
478: return (0);
479: #ifdef LOCKF_DEBUG
480: if (lockf_debug & 2)
481: hfs_lprint("hfs_findoverlap: looking for overlap in", lock);
482: #endif /* LOCKF_DEBUG */
483: start = lock->lf_start;
484: end = lock->lf_end;
485: while (lf != NOLOCKF) {
486: if (((type & SELF) && lf->lf_id != lock->lf_id) ||
487: ((type & OTHERS) && lf->lf_id == lock->lf_id)) {
488: *prev = &lf->lf_next;
489: *overlap = lf = lf->lf_next;
490: continue;
491: }
492: #ifdef LOCKF_DEBUG
493: if (lockf_debug & 2)
494: hfs_lprint("\tchecking", lf);
495: #endif /* LOCKF_DEBUG */
496: /*
497: * OK, check for overlap
498: *
499: * Six cases:
500: * 0) no overlap
501: * 1) overlap == lock
502: * 2) overlap contains lock
503: * 3) lock contains overlap
504: * 4) overlap starts before lock
505: * 5) overlap ends after lock
506: */
507: if ((lf->lf_end != -1 && start > lf->lf_end) ||
508: (end != -1 && lf->lf_start > end)) {
509: /* Case 0 */
510: #ifdef LOCKF_DEBUG
511: if (lockf_debug & 2)
512: printf("no overlap\n");
513: #endif /* LOCKF_DEBUG */
514: if ((type & SELF) && end != -1 && lf->lf_start > end)
515: return (0);
516: *prev = &lf->lf_next;
517: *overlap = lf = lf->lf_next;
518: continue;
519: }
520: if ((lf->lf_start == start) && (lf->lf_end == end)) {
521: /* Case 1 */
522: #ifdef LOCKF_DEBUG
523: if (lockf_debug & 2)
524: printf("overlap == lock\n");
525: #endif /* LOCKF_DEBUG */
526: return (1);
527: }
528: if ((lf->lf_start <= start) &&
529: (end != -1) &&
530: ((lf->lf_end >= end) || (lf->lf_end == -1))) {
531: /* Case 2 */
532: #ifdef LOCKF_DEBUG
533: if (lockf_debug & 2)
534: printf("overlap contains lock\n");
535: #endif /* LOCKF_DEBUG */
536: return (2);
537: }
538: if (start <= lf->lf_start &&
539: (end == -1 ||
540: (lf->lf_end != -1 && end >= lf->lf_end))) {
541: /* Case 3 */
542: #ifdef LOCKF_DEBUG
543: if (lockf_debug & 2)
544: printf("lock contains overlap\n");
545: #endif /* LOCKF_DEBUG */
546: return (3);
547: }
548: if ((lf->lf_start < start) &&
549: ((lf->lf_end >= start) || (lf->lf_end == -1))) {
550: /* Case 4 */
551: #ifdef LOCKF_DEBUG
552: if (lockf_debug & 2)
553: printf("overlap starts before lock\n");
554: #endif /* LOCKF_DEBUG */
555: return (4);
556: }
557: if ((lf->lf_start > start) &&
558: (end != -1) &&
559: ((lf->lf_end > end) || (lf->lf_end == -1))) {
560: /* Case 5 */
561: #ifdef LOCKF_DEBUG
562: if (lockf_debug & 2)
563: printf("overlap ends after lock\n");
564: #endif /* LOCKF_DEBUG */
565: return (5);
566: }
567: panic("hfs_findoverlap: default");
568: }
569: return (0);
570: }
571:
572: /*
573: * Split a lock and a contained region into
574: * two or three locks as necessary.
575: */
576: void
577: hfs_split(lock1, lock2)
578: register struct hfslockf *lock1;
579: register struct hfslockf *lock2;
580: {
581: register struct hfslockf *splitlock;
582:
583: #ifdef LOCKF_DEBUG
584: if (lockf_debug & 2) {
585: hfs_lprint("hfs_split", lock1);
586: hfs_lprint("splitting from", lock2);
587: }
588: #endif /* LOCKF_DEBUG */
589: /*
590: * Check to see if spliting into only two pieces.
591: */
592: if (lock1->lf_start == lock2->lf_start) {
593: lock1->lf_start = lock2->lf_end + 1;
594: lock2->lf_next = lock1;
595: return;
596: }
597: if (lock1->lf_end == lock2->lf_end) {
598: lock1->lf_end = lock2->lf_start - 1;
599: lock2->lf_next = lock1->lf_next;
600: lock1->lf_next = lock2;
601: return;
602: }
603: /*
604: * Make a new lock consisting of the last part of
605: * the encompassing lock
606: */
607: MALLOC(splitlock, struct hfslockf *, sizeof *splitlock, M_LOCKF, M_WAITOK);
608: bcopy((caddr_t)lock1, (caddr_t)splitlock, sizeof *splitlock);
609: splitlock->lf_start = lock2->lf_end + 1;
610: TAILQ_INIT(&splitlock->lf_blkhd);
611: lock1->lf_end = lock2->lf_start - 1;
612: /*
613: * OK, now link it in
614: */
615: splitlock->lf_next = lock1->lf_next;
616: lock2->lf_next = splitlock;
617: lock1->lf_next = lock2;
618: }
619:
620: /*
621: * Wakeup a blocklist
622: */
623: void
624: hfs_wakelock(listhead)
625: struct hfslockf *listhead;
626: {
627: register struct hfslockf *wakelock;
628:
629: while ((wakelock = listhead->lf_blkhd.tqh_first)) {
630: TAILQ_REMOVE(&listhead->lf_blkhd, wakelock, lf_block);
631: wakelock->lf_next = NOLOCKF;
632: #ifdef LOCKF_DEBUG
633: if (lockf_debug & 2)
634: hfs_lprint("hfs_wakelock: awakening", wakelock);
635: #endif /* LOCKF_DEBUG */
636: wakeup((caddr_t)wakelock);
637: }
638: }
639:
640: #ifdef LOCKF_DEBUG
641: /*
642: * Print out a lock.
643: */
644: hfs_lprint(tag, lock)
645: char *tag;
646: register struct hfslockf *lock;
647: {
648:
649: printf("%s: lock 0x%lx for ", tag, lock);
650: if (lock->lf_flags & F_POSIX)
651: printf("proc %d", ((struct proc *)(lock->lf_id))->p_pid);
652: else
653: printf("id 0x%x", lock->lf_id);
654: printf(" in ino %d on dev <%d, %d>, %s, start %d, end %d",
655: lock->lf_hfsnode->i_number,
656: major(lock->lf_hfsnode->h_dev),
657: minor(lock->lf_hfsnode->h_dev),
658: lock->lf_type == F_RDLCK ? "shared" :
659: lock->lf_type == F_WRLCK ? "exclusive" :
660: lock->lf_type == F_UNLCK ? "unlock" :
661: "unknown", lock->lf_start, lock->lf_end);
662: if (lock->lf_blkhd.tqh_first)
663: printf(" block 0x%x\n", lock->lf_blkhd.tqh_first);
664: else
665: printf("\n");
666: }
667:
668: hfs_lprintlist(tag, lock)
669: char *tag;
670: struct hfslockf *lock;
671: {
672: register struct hfslockf *lf, *blk;
673:
674: printf("%s: Lock list for ino %d on dev <%d, %d>:\n",
675: tag, lock->lf_hfsnode->i_number,
676: major(lock->lf_hfsnode->h_dev),
677: minor(lock->lf_hfsnode->h_dev));
678: for (lf = lock->lf_hfsnode->h_lockf; lf; lf = lf->lf_next) {
679: printf("\tlock 0x%lx for ", lf);
680: if (lf->lf_flags & F_POSIX)
681: printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid);
682: else
683: printf("id 0x%x", lf->lf_id);
684: printf(", %s, start %d, end %d",
685: lf->lf_type == F_RDLCK ? "shared" :
686: lf->lf_type == F_WRLCK ? "exclusive" :
687: lf->lf_type == F_UNLCK ? "unlock" :
688: "unknown", lf->lf_start, lf->lf_end);
689: for (blk = lf->lf_blkhd.tqh_first; blk;
690: blk = blk->lf_block.tqe_next) {
691: printf("\n\t\tlock request 0x%lx for ", blk);
692: if (blk->lf_flags & F_POSIX)
693: printf("proc %d",
694: ((struct proc *)(blk->lf_id))->p_pid);
695: else
696: printf("id 0x%x", blk->lf_id);
697: printf(", %s, start %d, end %d",
698: blk->lf_type == F_RDLCK ? "shared" :
699: blk->lf_type == F_WRLCK ? "exclusive" :
700: blk->lf_type == F_UNLCK ? "unlock" :
701: "unknown", blk->lf_start, blk->lf_end);
702: if (blk->lf_blkhd.tqh_first)
703: panic("hfs_lprintlist: bad list");
704: }
705: printf("\n");
706: }
707: }
708: #endif /* LOCKF_DEBUG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.