|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * 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: *
1.1.1.2 ! root 36: * from: @(#)ufs_lockf.c 7.7 (Berkeley) 7/2/91
! 37: * ufs_lockf.c,v 1.4.2.2 1993/07/22 10:50:54 cgd Exp
1.1 root 38: */
39:
40: #include "param.h"
41: #include "systm.h"
42: #include "kernel.h"
43: #include "file.h"
44: #include "proc.h"
45: #include "vnode.h"
46: #include "malloc.h"
47: #include "fcntl.h"
48:
49: #include "lockf.h"
50: #include "quota.h"
51: #include "inode.h"
52:
1.1.1.2 ! root 53:
! 54:
! 55: /*
! 56: * Advisory record locking support
! 57: */
! 58: lf_advlock(head, size, id, op, fl, flags)
! 59: struct lockf **head;
! 60: u_long size;
! 61: caddr_t id;
! 62: int op;
! 63: register struct flock *fl;
! 64: int flags;
! 65: {
! 66: register struct lockf *lock;
! 67: off_t start, end;
! 68: int error;
! 69:
! 70: /*
! 71: * Avoid the common case of unlocking when inode has no locks.
! 72: */
! 73: if (*head == (struct lockf *)0) {
! 74: if (op != F_SETLK) {
! 75: fl->l_type = F_UNLCK;
! 76: return (0);
! 77: }
! 78: }
! 79:
! 80: /*
! 81: * Convert the flock structure into a start and end.
! 82: */
! 83: switch (fl->l_whence) {
! 84:
! 85: case SEEK_SET:
! 86: case SEEK_CUR:
! 87: /*
! 88: * Caller is responsible for adding any necessary offset
! 89: * when SEEK_CUR is used.
! 90: */
! 91: start = fl->l_start;
! 92: break;
! 93:
! 94: case SEEK_END:
! 95: start = size + fl->l_start;
! 96: break;
! 97:
! 98: default:
! 99: return (EINVAL);
! 100: }
! 101: if (start < 0)
! 102: return (EINVAL);
! 103: if (fl->l_len == 0)
! 104: end = -1;
! 105: else
! 106: end = start + fl->l_len - 1;
! 107: /*
! 108: * Create the lockf structure
! 109: */
! 110: MALLOC(lock, struct lockf *, sizeof *lock, M_LOCKF, M_WAITOK);
! 111: lock->lf_start = start;
! 112: lock->lf_end = end;
! 113: lock->lf_id = id;
! 114: lock->lf_head = head;
! 115: lock->lf_type = fl->l_type;
! 116: lock->lf_next = (struct lockf *)0;
! 117: lock->lf_block = (struct lockf *)0;
! 118: lock->lf_flags = flags;
! 119: /*
! 120: * Do the requested operation.
! 121: */
! 122: switch(op) {
! 123: case F_SETLK:
! 124: return (lf_setlock(lock));
! 125:
! 126: case F_UNLCK:
! 127: error = lf_clearlock(lock);
! 128: FREE(lock, M_LOCKF);
! 129: return (error);
! 130:
! 131: case F_GETLK:
! 132: error = lf_getlock(lock, fl);
! 133: FREE(lock, M_LOCKF);
! 134: return (error);
! 135:
! 136: default:
! 137: free(lock, M_LOCKF);
! 138: return (EINVAL);
! 139: }
! 140: /* NOTREACHED */
! 141: }
! 142:
1.1 root 143: /*
144: * This variable controls the maximum number of processes that will
145: * be checked in doing deadlock detection.
146: */
147: int maxlockdepth = MAXDEPTH;
148:
149: #ifdef LOCKF_DEBUG
150: int lockf_debug = 0;
151: #endif /* LOCKF_DEBUG */
152:
153: #define NOLOCKF (struct lockf *)0
154: #define SELF 0x1
155: #define OTHERS 0x2
156:
157: /*
158: * Set a byte-range lock.
159: */
160: lf_setlock(lock)
161: register struct lockf *lock;
162: {
163: register struct lockf *block;
1.1.1.2 ! root 164: struct lockf **head = lock->lf_head;
1.1 root 165: struct lockf **prev, *overlap, *ltmp;
166: static char lockstr[] = "lockf";
167: int ovcase, priority, needtolink, error;
168:
169: #ifdef LOCKF_DEBUG
170: if (lockf_debug & 1)
171: lf_print("lf_setlock", lock);
172: #endif /* LOCKF_DEBUG */
173:
174: /*
175: * Set the priority
176: */
177: priority = PLOCK;
178: if (lock->lf_type == F_WRLCK)
179: priority += 4;
180: priority |= PCATCH;
181: /*
182: * Scan lock list for this file looking for locks that would block us.
183: */
184: while (block = lf_getblock(lock)) {
185: /*
186: * Free the structure and return if nonblocking.
187: */
188: if ((lock->lf_flags & F_WAIT) == 0) {
189: FREE(lock, M_LOCKF);
190: return (EAGAIN);
191: }
192: /*
193: * We are blocked. Since flock style locks cover
194: * the whole file, there is no chance for deadlock.
195: * For byte-range locks we must check for deadlock.
196: *
197: * Deadlock detection is done by looking through the
198: * wait channels to see if there are any cycles that
199: * involve us. MAXDEPTH is set just to make sure we
200: * do not go off into neverland.
201: */
202: if ((lock->lf_flags & F_POSIX) &&
203: (block->lf_flags & F_POSIX)) {
204: register struct proc *wproc;
205: register struct lockf *waitblock;
206: int i = 0;
207:
208: /* The block is waiting on something */
209: wproc = (struct proc *)block->lf_id;
210: while (wproc->p_wchan &&
211: (wproc->p_wmesg == lockstr) &&
212: (i++ < maxlockdepth)) {
213: waitblock = (struct lockf *)wproc->p_wchan;
214: /* Get the owner of the blocking lock */
215: waitblock = waitblock->lf_next;
216: if ((waitblock->lf_flags & F_POSIX) == 0)
217: break;
218: wproc = (struct proc *)waitblock->lf_id;
219: if (wproc == (struct proc *)lock->lf_id) {
220: free(lock, M_LOCKF);
221: return (EDEADLK);
222: }
223: }
224: }
225: /*
226: * For flock type locks, we must first remove
227: * any shared locks that we hold before we sleep
228: * waiting for an exclusive lock.
229: */
230: if ((lock->lf_flags & F_FLOCK) &&
231: lock->lf_type == F_WRLCK) {
232: lock->lf_type = F_UNLCK;
233: (void) lf_clearlock(lock);
234: lock->lf_type = F_WRLCK;
235: }
236: /*
237: * Add our lock to the blocked list and sleep until we're free.
238: * Remember who blocked us (for deadlock detection).
239: */
240: lock->lf_next = block;
241: lf_addblock(block, lock);
242: #ifdef LOCKF_DEBUG
243: if (lockf_debug & 1) {
244: lf_print("lf_setlock: blocking on", block);
245: lf_printlist("lf_setlock", block);
246: }
247: #endif /* LOCKF_DEBUG */
1.1.1.2 ! root 248: if (error = tsleep((caddr_t)lock, priority, lockstr, 0)) {
! 249: /*
! 250: * Delete ourselves from the waiting to lock list.
! 251: */
! 252: for (block = lock->lf_next;
! 253: block != NOLOCKF;
! 254: block = block->lf_block) {
! 255: if (block->lf_block != lock)
! 256: continue;
! 257: block->lf_block = block->lf_block->lf_block;
! 258: free(lock, M_LOCKF);
! 259: return (error);
! 260: }
! 261: panic("lf_setlock: lost lock");
1.1 root 262: }
263: }
264: /*
265: * No blocks!! Add the lock. Note that we will
266: * downgrade or upgrade any overlapping locks this
267: * process already owns.
268: *
269: * Skip over locks owned by other processes.
270: * Handle any locks that overlap and are owned by ourselves.
271: */
1.1.1.2 ! root 272: prev = head;
! 273: block = *head;
1.1 root 274: needtolink = 1;
275: for (;;) {
276: if (ovcase = lf_findoverlap(block, lock, SELF, &prev, &overlap))
277: block = overlap->lf_next;
278: /*
279: * Six cases:
280: * 0) no overlap
281: * 1) overlap == lock
282: * 2) overlap contains lock
283: * 3) lock contains overlap
284: * 4) overlap starts before lock
285: * 5) overlap ends after lock
286: */
287: switch (ovcase) {
288: case 0: /* no overlap */
289: if (needtolink) {
290: *prev = lock;
291: lock->lf_next = overlap;
292: }
293: break;
294:
295: case 1: /* overlap == lock */
296: /*
297: * If downgrading lock, others may be
298: * able to acquire it.
299: */
300: if (lock->lf_type == F_RDLCK &&
301: overlap->lf_type == F_WRLCK)
302: lf_wakelock(overlap);
303: overlap->lf_type = lock->lf_type;
304: FREE(lock, M_LOCKF);
305: lock = overlap; /* for debug output below */
306: break;
307:
308: case 2: /* overlap contains lock */
309: /*
310: * Check for common starting point and different types.
311: */
312: if (overlap->lf_type == lock->lf_type) {
313: free(lock, M_LOCKF);
314: lock = overlap; /* for debug output below */
315: break;
316: }
317: if (overlap->lf_start == lock->lf_start) {
318: *prev = lock;
319: lock->lf_next = overlap;
320: overlap->lf_start = lock->lf_end + 1;
321: } else
322: lf_split(overlap, lock);
323: lf_wakelock(overlap);
324: break;
325:
326: case 3: /* lock contains overlap */
327: /*
328: * If downgrading lock, others may be able to
329: * acquire it, otherwise take the list.
330: */
331: if (lock->lf_type == F_RDLCK &&
332: overlap->lf_type == F_WRLCK) {
333: lf_wakelock(overlap);
334: } else {
335: ltmp = lock->lf_block;
336: lock->lf_block = overlap->lf_block;
337: lf_addblock(lock, ltmp);
338: }
339: /*
340: * Add the new lock if necessary and delete the overlap.
341: */
342: if (needtolink) {
343: *prev = lock;
344: lock->lf_next = overlap->lf_next;
345: prev = &lock->lf_next;
346: needtolink = 0;
347: } else
348: *prev = overlap->lf_next;
349: free(overlap, M_LOCKF);
350: continue;
351:
352: case 4: /* overlap starts before lock */
353: /*
354: * Add lock after overlap on the list.
355: */
356: lock->lf_next = overlap->lf_next;
357: overlap->lf_next = lock;
358: overlap->lf_end = lock->lf_start - 1;
359: prev = &lock->lf_next;
360: lf_wakelock(overlap);
361: needtolink = 0;
362: continue;
363:
364: case 5: /* overlap ends after lock */
365: /*
366: * Add the new lock before overlap.
367: */
368: if (needtolink) {
369: *prev = lock;
370: lock->lf_next = overlap;
371: }
372: overlap->lf_start = lock->lf_end + 1;
373: lf_wakelock(overlap);
374: break;
375: }
376: break;
377: }
378: #ifdef LOCKF_DEBUG
379: if (lockf_debug & 1) {
380: lf_print("lf_setlock: got the lock", lock);
381: lf_printlist("lf_setlock", lock);
382: }
383: #endif /* LOCKF_DEBUG */
384: return (0);
385: }
386:
387: /*
388: * Remove a byte-range lock on an inode.
389: *
390: * Generally, find the lock (or an overlap to that lock)
391: * and remove it (or shrink it), then wakeup anyone we can.
392: */
393: lf_clearlock(unlock)
394: register struct lockf *unlock;
395: {
1.1.1.2 ! root 396: struct lockf **head = unlock->lf_head;
! 397: register struct lockf *lf = *head;
1.1 root 398: struct lockf *overlap, **prev;
399: int ovcase;
400:
401: if (lf == NOLOCKF)
402: return (0);
403: #ifdef LOCKF_DEBUG
404: if (unlock->lf_type != F_UNLCK)
405: panic("lf_clearlock: bad type");
406: if (lockf_debug & 1)
407: lf_print("lf_clearlock", unlock);
408: #endif /* LOCKF_DEBUG */
1.1.1.2 ! root 409: prev = head;
1.1 root 410: while (ovcase = lf_findoverlap(lf, unlock, SELF, &prev, &overlap)) {
411: /*
412: * Wakeup the list of locks to be retried.
413: */
414: lf_wakelock(overlap);
415:
416: switch (ovcase) {
417:
418: case 1: /* overlap == lock */
419: *prev = overlap->lf_next;
420: FREE(overlap, M_LOCKF);
421: break;
422:
423: case 2: /* overlap contains lock: split it */
424: if (overlap->lf_start == unlock->lf_start) {
425: overlap->lf_start = unlock->lf_end + 1;
426: break;
427: }
428: lf_split(overlap, unlock);
429: overlap->lf_next = unlock->lf_next;
430: break;
431:
432: case 3: /* lock contains overlap */
433: *prev = overlap->lf_next;
434: lf = overlap->lf_next;
435: free(overlap, M_LOCKF);
436: continue;
437:
438: case 4: /* overlap starts before lock */
439: overlap->lf_end = unlock->lf_start - 1;
440: prev = &overlap->lf_next;
441: lf = overlap->lf_next;
442: continue;
443:
444: case 5: /* overlap ends after lock */
445: overlap->lf_start = unlock->lf_end + 1;
446: break;
447: }
448: break;
449: }
450: #ifdef LOCKF_DEBUG
451: if (lockf_debug & 1)
452: lf_printlist("lf_clearlock", unlock);
453: #endif /* LOCKF_DEBUG */
454: return (0);
455: }
456:
457: /*
458: * Check whether there is a blocking lock,
459: * and if so return its process identifier.
460: */
461: lf_getlock(lock, fl)
462: register struct lockf *lock;
463: register struct flock *fl;
464: {
465: register struct lockf *block;
466: off_t start, end;
467:
468: #ifdef LOCKF_DEBUG
469: if (lockf_debug & 1)
470: lf_print("lf_getlock", lock);
471: #endif /* LOCKF_DEBUG */
472:
473: if (block = lf_getblock(lock)) {
474: fl->l_type = block->lf_type;
475: fl->l_whence = SEEK_SET;
476: fl->l_start = block->lf_start;
477: if (block->lf_end == -1)
478: fl->l_len = 0;
479: else
480: fl->l_len = block->lf_end - block->lf_start + 1;
481: if (block->lf_flags & F_POSIX)
482: fl->l_pid = ((struct proc *)(block->lf_id))->p_pid;
483: else
484: fl->l_pid = -1;
485: } else {
486: fl->l_type = F_UNLCK;
487: }
488: return (0);
489: }
490:
491: /*
492: * Walk the list of locks for an inode and
493: * return the first blocking lock.
494: */
495: struct lockf *
496: lf_getblock(lock)
497: register struct lockf *lock;
498: {
1.1.1.2 ! root 499: struct lockf **prev, *overlap, *lf = *(lock->lf_head);
1.1 root 500: int ovcase;
501:
1.1.1.2 ! root 502: prev = lock->lf_head;
1.1 root 503: while (ovcase = lf_findoverlap(lf, lock, OTHERS, &prev, &overlap)) {
504: /*
505: * We've found an overlap, see if it blocks us
506: */
507: if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK))
508: return (overlap);
509: /*
510: * Nope, point to the next one on the list and
511: * see if it blocks us
512: */
513: lf = overlap->lf_next;
514: }
515: return (NOLOCKF);
516: }
517:
518: /*
519: * Walk the list of locks for an inode to
520: * find an overlapping lock (if any).
521: *
522: * NOTE: this returns only the FIRST overlapping lock. There
523: * may be more than one.
524: */
525: lf_findoverlap(lf, lock, type, prev, overlap)
526: register struct lockf *lf;
527: struct lockf *lock;
528: int type;
529: struct lockf ***prev;
530: struct lockf **overlap;
531: {
532: off_t start, end;
533:
534: *overlap = lf;
535: if (lf == NOLOCKF)
536: return (0);
537: #ifdef LOCKF_DEBUG
538: if (lockf_debug & 2)
539: lf_print("lf_findoverlap: looking for overlap in", lock);
540: #endif /* LOCKF_DEBUG */
541: start = lock->lf_start;
542: end = lock->lf_end;
543: while (lf != NOLOCKF) {
544: if (((type & SELF) && lf->lf_id != lock->lf_id) ||
545: ((type & OTHERS) && lf->lf_id == lock->lf_id)) {
546: *prev = &lf->lf_next;
547: *overlap = lf = lf->lf_next;
548: continue;
549: }
550: #ifdef LOCKF_DEBUG
551: if (lockf_debug & 2)
552: lf_print("\tchecking", lf);
553: #endif /* LOCKF_DEBUG */
554: /*
555: * OK, check for overlap
556: *
557: * Six cases:
558: * 0) no overlap
559: * 1) overlap == lock
560: * 2) overlap contains lock
561: * 3) lock contains overlap
562: * 4) overlap starts before lock
563: * 5) overlap ends after lock
564: */
565: if ((lf->lf_end != -1 && start > lf->lf_end) ||
566: (end != -1 && lf->lf_start > end)) {
567: /* Case 0 */
568: #ifdef LOCKF_DEBUG
569: if (lockf_debug & 2)
570: printf("no overlap\n");
571: #endif /* LOCKF_DEBUG */
572: if ((type & SELF) && end != -1 && lf->lf_start > end)
573: return (0);
574: *prev = &lf->lf_next;
575: *overlap = lf = lf->lf_next;
576: continue;
577: }
578: if ((lf->lf_start == start) && (lf->lf_end == end)) {
579: /* Case 1 */
580: #ifdef LOCKF_DEBUG
581: if (lockf_debug & 2)
582: printf("overlap == lock\n");
583: #endif /* LOCKF_DEBUG */
584: return (1);
585: }
586: if ((lf->lf_start <= start) &&
587: (end != -1) &&
588: ((lf->lf_end >= end) || (lf->lf_end == -1))) {
589: /* Case 2 */
590: #ifdef LOCKF_DEBUG
591: if (lockf_debug & 2)
592: printf("overlap contains lock\n");
593: #endif /* LOCKF_DEBUG */
594: return (2);
595: }
596: if (start <= lf->lf_start &&
1.1.1.2 ! root 597: (end == -1 ||
1.1 root 598: (lf->lf_end != -1 && end >= lf->lf_end))) {
599: /* Case 3 */
600: #ifdef LOCKF_DEBUG
601: if (lockf_debug & 2)
602: printf("lock contains overlap\n");
603: #endif /* LOCKF_DEBUG */
604: return (3);
605: }
606: if ((lf->lf_start < start) &&
607: ((lf->lf_end >= start) || (lf->lf_end == -1))) {
608: /* Case 4 */
609: #ifdef LOCKF_DEBUG
610: if (lockf_debug & 2)
611: printf("overlap starts before lock\n");
612: #endif /* LOCKF_DEBUG */
613: return (4);
614: }
615: if ((lf->lf_start > start) &&
616: (end != -1) &&
617: ((lf->lf_end > end) || (lf->lf_end == -1))) {
618: /* Case 5 */
619: #ifdef LOCKF_DEBUG
620: if (lockf_debug & 2)
621: printf("overlap ends after lock\n");
622: #endif /* LOCKF_DEBUG */
623: return (5);
624: }
625: panic("lf_findoverlap: default");
626: }
627: return (0);
628: }
629:
630: /*
631: * Add a lock to the end of the blocked list.
632: */
633: lf_addblock(lock, blocked)
634: struct lockf *lock;
635: struct lockf *blocked;
636: {
637: register struct lockf *lf;
638:
639: if (blocked == NOLOCKF)
640: return;
641: #ifdef LOCKF_DEBUG
642: if (lockf_debug & 2) {
643: lf_print("addblock: adding", blocked);
644: lf_print("to blocked list of", lock);
645: }
646: #endif /* LOCKF_DEBUG */
647: if ((lf = lock->lf_block) == NOLOCKF) {
648: lock->lf_block = blocked;
649: return;
650: }
651: while (lf->lf_block != NOLOCKF)
652: lf = lf->lf_block;
653: lf->lf_block = blocked;
654: return;
655: }
656:
657: /*
658: * Split a lock and a contained region into
659: * two or three locks as necessary.
660: */
661: lf_split(lock1, lock2)
662: register struct lockf *lock1;
663: register struct lockf *lock2;
664: {
665: register struct lockf *splitlock;
666:
667: #ifdef LOCKF_DEBUG
668: if (lockf_debug & 2) {
669: lf_print("lf_split", lock1);
670: lf_print("splitting from", lock2);
671: }
672: #endif /* LOCKF_DEBUG */
673: /*
674: * Check to see if spliting into only two pieces.
675: */
676: if (lock1->lf_start == lock2->lf_start) {
677: lock1->lf_start = lock2->lf_end + 1;
678: lock2->lf_next = lock1;
679: return;
680: }
681: if (lock1->lf_end == lock2->lf_end) {
682: lock1->lf_end = lock2->lf_start - 1;
683: lock2->lf_next = lock1->lf_next;
684: lock1->lf_next = lock2;
685: return;
686: }
687: /*
688: * Make a new lock consisting of the last part of
689: * the encompassing lock
690: */
691: MALLOC(splitlock, struct lockf *, sizeof *splitlock, M_LOCKF, M_WAITOK);
692: bcopy((caddr_t)lock1, (caddr_t)splitlock, sizeof *splitlock);
693: splitlock->lf_start = lock2->lf_end + 1;
694: splitlock->lf_block = NOLOCKF;
695: lock1->lf_end = lock2->lf_start - 1;
696: /*
697: * OK, now link it in
698: */
699: splitlock->lf_next = lock1->lf_next;
700: lock2->lf_next = splitlock;
701: lock1->lf_next = lock2;
702: }
703:
704: /*
705: * Wakeup a blocklist
706: */
707: lf_wakelock(listhead)
708: struct lockf *listhead;
709: {
1.1.1.2 ! root 710: register struct lockf *blocklist, *wakelock;
1.1 root 711:
712: blocklist = listhead->lf_block;
713: listhead->lf_block = NOLOCKF;
1.1.1.2 ! root 714: while (blocklist != NOLOCKF) {
! 715: wakelock = blocklist;
! 716: blocklist = blocklist->lf_block;
1.1 root 717: wakelock->lf_block = NOLOCKF;
718: wakelock->lf_next = NOLOCKF;
719: #ifdef LOCKF_DEBUG
720: if (lockf_debug & 2)
721: lf_print("lf_wakelock: awakening", wakelock);
722: #endif /* LOCKF_DEBUG */
1.1.1.2 ! root 723: wakeup((caddr_t)wakelock);
! 724: }
1.1 root 725: }
726:
727: #ifdef LOCKF_DEBUG
728: /*
729: * Print out a lock.
730: */
731: lf_print(tag, lock)
732: char *tag;
733: register struct lockf *lock;
734: {
735:
736: printf("%s: lock 0x%lx for ", tag, lock);
737: if (lock->lf_flags & F_POSIX)
738: printf("proc %d", ((struct proc *)(lock->lf_id))->p_pid);
739: else
740: printf("id 0x%x", lock->lf_id);
741: printf(" in ino %d on dev <%d, %d>, %s, start %d, end %d",
742: lock->lf_inode->i_number,
743: major(lock->lf_inode->i_dev),
744: minor(lock->lf_inode->i_dev),
745: lock->lf_type == F_RDLCK ? "shared" :
746: lock->lf_type == F_WRLCK ? "exclusive" :
747: lock->lf_type == F_UNLCK ? "unlock" :
748: "unknown", lock->lf_start, lock->lf_end);
749: if (lock->lf_block)
750: printf(" block 0x%x\n", lock->lf_block);
751: else
752: printf("\n");
753: }
754:
755: lf_printlist(tag, lock)
756: char *tag;
757: struct lockf *lock;
758: {
759: register struct lockf *lf;
760:
761: printf("%s: Lock list for ino %d on dev <%d, %d>:\n",
762: tag, lock->lf_inode->i_number,
763: major(lock->lf_inode->i_dev),
764: minor(lock->lf_inode->i_dev));
765: for (lf = lock->lf_inode->i_lockf; lf; lf = lf->lf_next) {
766: printf("\tlock 0x%lx for ", lf);
767: if (lf->lf_flags & F_POSIX)
768: printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid);
769: else
770: printf("id 0x%x", lf->lf_id);
771: printf(", %s, start %d, end %d",
772: lf->lf_type == F_RDLCK ? "shared" :
773: lf->lf_type == F_WRLCK ? "exclusive" :
774: lf->lf_type == F_UNLCK ? "unlock" :
775: "unknown", lf->lf_start, lf->lf_end);
776: if (lf->lf_block)
777: printf(" block 0x%x\n", lf->lf_block);
778: else
779: printf("\n");
780: }
781: }
782: #endif /* LOCKF_DEBUG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.