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