Annotation of Net2/ufs/ufs_lockf.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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