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