Annotation of kernel/bsd/hfs/hfs_lockf.c, revision 1.1.1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.