Annotation of 43BSDReno/sys/ufs/ufs_inode.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution is only permitted until one year after the first shipment
                      6:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                      7:  * binary forms are permitted provided that: (1) source distributions retain
                      8:  * this entire copyright notice and comment, and (2) distributions including
                      9:  * binaries display the following acknowledgement:  This product includes
                     10:  * software developed by the University of California, Berkeley and its
                     11:  * contributors'' in the documentation or other materials provided with the
                     12:  * distribution and in all advertising materials mentioning features or use
                     13:  * of this software.  Neither the name of the University nor the names of
                     14:  * its contributors may be used to endorse or promote products derived from
                     15:  * this software without specific prior written permission.
                     16:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     17:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     19:  *
                     20:  *     @(#)ufs_inode.c 7.34 (Berkeley) 7/3/90
                     21:  */
                     22: 
                     23: #include "param.h"
                     24: #include "systm.h"
                     25: #include "mount.h"
                     26: #include "user.h"
                     27: #include "proc.h"
                     28: #include "file.h"
                     29: #include "buf.h"
                     30: #include "cmap.h"
                     31: #include "vnode.h"
                     32: #include "../ufs/quota.h"
                     33: #include "../ufs/inode.h"
                     34: #include "../ufs/fs.h"
                     35: #include "../ufs/ufsmount.h"
                     36: #include "kernel.h"
                     37: #include "malloc.h"
                     38: 
                     39: #define        INOHSZ  512
                     40: #if    ((INOHSZ&(INOHSZ-1)) == 0)
                     41: #define        INOHASH(dev,ino)        (((dev)+(ino))&(INOHSZ-1))
                     42: #else
                     43: #define        INOHASH(dev,ino)        (((unsigned)((dev)+(ino)))%INOHSZ)
                     44: #endif
                     45: 
                     46: union ihead {
                     47:        union  ihead *ih_head[2];
                     48:        struct inode *ih_chain[2];
                     49: } ihead[INOHSZ];
                     50: 
                     51: int prtactive; /* 1 => print out reclaim of active vnodes */
                     52: 
                     53: /*
                     54:  * Initialize hash links for inodes.
                     55:  */
                     56: ufs_init()
                     57: {
                     58:        register int i;
                     59:        register union ihead *ih = ihead;
                     60: 
                     61: #ifndef lint
                     62:        if (VN_MAXPRIVATE < sizeof(struct inode))
                     63:                panic("ihinit: too small");
                     64: #endif /* not lint */
                     65:        for (i = INOHSZ; --i >= 0; ih++) {
                     66:                ih->ih_head[0] = ih;
                     67:                ih->ih_head[1] = ih;
                     68:        }
                     69: #ifdef QUOTA
                     70:        dqinit();
                     71: #endif /* QUOTA */
                     72: }
                     73: 
                     74: /*
                     75:  * Look up an vnode/inode by device,inumber.
                     76:  * If it is in core (in the inode structure),
                     77:  * honor the locking protocol.
                     78:  * If it is not in core, read it in from the
                     79:  * specified device.
                     80:  * Callers must check for mount points!!
                     81:  * In all cases, a pointer to a locked
                     82:  * inode structure is returned.
                     83:  */
                     84: iget(xp, ino, ipp)
                     85:        struct inode *xp;
                     86:        ino_t ino;
                     87:        struct inode **ipp;
                     88: {
                     89:        dev_t dev = xp->i_dev;
                     90:        struct mount *mntp = ITOV(xp)->v_mount;
                     91:        register struct fs *fs = VFSTOUFS(mntp)->um_fs;
                     92:        extern struct vnodeops ufs_vnodeops, spec_inodeops;
                     93:        register struct inode *ip, *iq;
                     94:        register struct vnode *vp;
                     95:        struct vnode *nvp;
                     96:        struct buf *bp;
                     97:        struct dinode *dp;
                     98:        union ihead *ih;
                     99:        int i, error;
                    100: 
                    101:        ih = &ihead[INOHASH(dev, ino)];
                    102: loop:
                    103:        for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) {
                    104:                if (ino != ip->i_number || dev != ip->i_dev)
                    105:                        continue;
                    106:                if ((ip->i_flag&ILOCKED) != 0) {
                    107:                        ip->i_flag |= IWANT;
                    108:                        sleep((caddr_t)ip, PINOD);
                    109:                        goto loop;
                    110:                }
                    111:                if (vget(ITOV(ip)))
                    112:                        goto loop;
                    113:                *ipp = ip;
                    114:                return(0);
                    115:        }
                    116:        /*
                    117:         * Allocate a new inode.
                    118:         */
                    119:        if (error = getnewvnode(VT_UFS, mntp, &ufs_vnodeops, &nvp)) {
                    120:                *ipp = 0;
                    121:                return (error);
                    122:        }
                    123:        ip = VTOI(nvp);
                    124:        ip->i_vnode = nvp;
                    125:        ip->i_flag = 0;
                    126:        ip->i_devvp = 0;
                    127:        ip->i_mode = 0;
                    128:        ip->i_diroff = 0;
                    129: #ifdef QUOTA
                    130:        for (i = 0; i < MAXQUOTAS; i++)
                    131:                ip->i_dquot[i] = NODQUOT;
                    132: #endif
                    133:        /*
                    134:         * Put it onto its hash chain and lock it so that other requests for
                    135:         * this inode will block if they arrive while we are sleeping waiting
                    136:         * for old data structures to be purged or for the contents of the
                    137:         * disk portion of this inode to be read.
                    138:         */
                    139:        ip->i_dev = dev;
                    140:        ip->i_number = ino;
                    141:        insque(ip, ih);
                    142:        ILOCK(ip);
                    143:        /*
                    144:         * Read in the disk contents for the inode.
                    145:         */
                    146:        if (error = bread(VFSTOUFS(mntp)->um_devvp, fsbtodb(fs, itod(fs, ino)),
                    147:            (int)fs->fs_bsize, NOCRED, &bp)) {
                    148:                /*
                    149:                 * The inode does not contain anything useful, so it would
                    150:                 * be misleading to leave it on its hash chain.
                    151:                 * Iput() will take care of putting it back on the free list.
                    152:                 */
                    153:                remque(ip);
                    154:                ip->i_forw = ip;
                    155:                ip->i_back = ip;
                    156:                /*
                    157:                 * Unlock and discard unneeded inode.
                    158:                 */
                    159:                iput(ip);
                    160:                brelse(bp);
                    161:                *ipp = 0;
                    162:                return (error);
                    163:        }
                    164:        dp = bp->b_un.b_dino;
                    165:        dp += itoo(fs, ino);
                    166:        ip->i_din = *dp;
                    167:        brelse(bp);
                    168:        /*
                    169:         * Initialize the associated vnode
                    170:         */
                    171:        vp = ITOV(ip);
                    172:        vp->v_type = IFTOVT(ip->i_mode);
                    173:        if (vp->v_type == VFIFO) {
                    174: #ifdef FIFO
                    175:                extern struct vnodeops fifo_inodeops;
                    176:                vp->v_op = &fifo_inodeops;
                    177: #else
                    178:                iput(ip);
                    179:                *ipp = 0;
                    180:                return (EOPNOTSUPP);
                    181: #endif /* FIFO */
                    182:        }
                    183:        if (vp->v_type == VCHR || vp->v_type == VBLK) {
                    184:                vp->v_op = &spec_inodeops;
                    185:                if (nvp = checkalias(vp, ip->i_rdev, mntp)) {
                    186:                        /*
                    187:                         * Reinitialize aliased inode.
                    188:                         */
                    189:                        vp = nvp;
                    190:                        iq = VTOI(vp);
                    191:                        iq->i_vnode = vp;
                    192:                        iq->i_flag = 0;
                    193:                        ILOCK(iq);
                    194:                        iq->i_din = ip->i_din;
                    195:                        iq->i_dev = dev;
                    196:                        iq->i_number = ino;
                    197:                        insque(iq, ih);
                    198:                        /*
                    199:                         * Discard unneeded vnode
                    200:                         */
                    201:                        ip->i_mode = 0;
                    202:                        iput(ip);
                    203:                        ip = iq;
                    204:                }
                    205:        }
                    206:        if (ino == ROOTINO)
                    207:                vp->v_flag |= VROOT;
                    208:        /*
                    209:         * Finish inode initialization.
                    210:         */
                    211:        ip->i_fs = fs;
                    212:        ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
                    213:        VREF(ip->i_devvp);
                    214:        /*
                    215:         * Set up a generation number for this inode if it does not
                    216:         * already have one. This should only happen on old filesystems.
                    217:         */
                    218:        if (ip->i_gen == 0) {
                    219:                if (++nextgennumber < (u_long)time.tv_sec)
                    220:                        nextgennumber = time.tv_sec;
                    221:                ip->i_gen = nextgennumber;
                    222:                if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
                    223:                        ip->i_flag |= IMOD;
                    224:        }
                    225:        *ipp = ip;
                    226:        return (0);
                    227: }
                    228: 
                    229: /*
                    230:  * Unlock and decrement the reference count of an inode structure.
                    231:  */
                    232: iput(ip)
                    233:        register struct inode *ip;
                    234: {
                    235: 
                    236:        if ((ip->i_flag & ILOCKED) == 0)
                    237:                panic("iput");
                    238:        IUNLOCK(ip);
                    239:        vrele(ITOV(ip));
                    240: }
                    241: 
                    242: /*
                    243:  * Last reference to an inode, write the inode out and if necessary,
                    244:  * truncate and deallocate the file.
                    245:  */
                    246: ufs_inactive(vp)
                    247:        struct vnode *vp;
                    248: {
                    249:        register struct inode *ip = VTOI(vp);
                    250:        int mode, error = 0;
                    251: 
                    252:        if (prtactive && vp->v_usecount != 0)
                    253:                vprint("ufs_inactive: pushing active", vp);
                    254:        /*
                    255:         * Get rid of inodes related to stale file handles.
                    256:         */
                    257:        if (ip->i_mode == 0) {
                    258:                if ((vp->v_flag & VXLOCK) == 0)
                    259:                        vgone(vp);
                    260:                return (0);
                    261:        }
                    262:        ILOCK(ip);
                    263:        if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
                    264: #ifdef QUOTA
                    265:                if (!getinoquota(ip))
                    266:                        (void) chkiq(ip, -1, NOCRED, 0);
                    267: #endif
                    268:                error = itrunc(ip, (u_long)0, 0);
                    269:                mode = ip->i_mode;
                    270:                ip->i_mode = 0;
                    271:                ip->i_rdev = 0;
                    272:                ip->i_flag |= IUPD|ICHG;
                    273:                ifree(ip, ip->i_number, mode);
                    274:        }
                    275:        IUPDAT(ip, &time, &time, 0);
                    276:        IUNLOCK(ip);
                    277:        ip->i_flag = 0;
                    278:        /*
                    279:         * If we are done with the inode, reclaim it
                    280:         * so that it can be reused immediately.
                    281:         */
                    282:        if (vp->v_usecount == 0 && ip->i_mode == 0)
                    283:                vgone(vp);
                    284:        return (error);
                    285: }
                    286: 
                    287: /*
                    288:  * Reclaim an inode so that it can be used for other purposes.
                    289:  */
                    290: ufs_reclaim(vp)
                    291:        register struct vnode *vp;
                    292: {
                    293:        register struct inode *ip = VTOI(vp);
                    294:        int i;
                    295: 
                    296:        if (prtactive && vp->v_usecount != 0)
                    297:                vprint("ufs_reclaim: pushing active", vp);
                    298:        /*
                    299:         * Remove the inode from its hash chain.
                    300:         */
                    301:        remque(ip);
                    302:        ip->i_forw = ip;
                    303:        ip->i_back = ip;
                    304:        /*
                    305:         * Purge old data structures associated with the inode.
                    306:         */
                    307:        cache_purge(vp);
                    308:        if (ip->i_devvp) {
                    309:                vrele(ip->i_devvp);
                    310:                ip->i_devvp = 0;
                    311:        }
                    312: #ifdef QUOTA
                    313:        for (i = 0; i < MAXQUOTAS; i++) {
                    314:                if (ip->i_dquot[i] != NODQUOT) {
                    315:                        dqrele(vp, ip->i_dquot[i]);
                    316:                        ip->i_dquot[i] = NODQUOT;
                    317:                }
                    318:        }
                    319: #endif
                    320:        ip->i_flag = 0;
                    321:        return (0);
                    322: }
                    323: 
                    324: /*
                    325:  * Check accessed and update flags on an inode structure.
                    326:  * If any is on, update the inode with the current time.
                    327:  * If waitfor is given, then must ensure I/O order,
                    328:  * so wait for write to complete.
                    329:  */
                    330: iupdat(ip, ta, tm, waitfor)
                    331:        register struct inode *ip;
                    332:        struct timeval *ta, *tm;
                    333:        int waitfor;
                    334: {
                    335:        struct buf *bp;
                    336:        struct vnode *vp = ITOV(ip);
                    337:        struct dinode *dp;
                    338:        register struct fs *fs;
                    339:        int error;
                    340: 
                    341:        fs = ip->i_fs;
                    342:        if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0)
                    343:                return (0);
                    344:        if (vp->v_mount->mnt_flag & MNT_RDONLY)
                    345:                return (0);
                    346:        error = bread(ip->i_devvp, fsbtodb(fs, itod(fs, ip->i_number)),
                    347:                (int)fs->fs_bsize, NOCRED, &bp);
                    348:        if (error) {
                    349:                brelse(bp);
                    350:                return (error);
                    351:        }
                    352:        if (ip->i_flag&IACC)
                    353:                ip->i_atime = ta->tv_sec;
                    354:        if (ip->i_flag&IUPD)
                    355:                ip->i_mtime = tm->tv_sec;
                    356:        if (ip->i_flag&ICHG)
                    357:                ip->i_ctime = time.tv_sec;
                    358:        ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD);
                    359:        dp = bp->b_un.b_dino + itoo(fs, ip->i_number);
                    360:        *dp = ip->i_din;
                    361:        if (waitfor) {
                    362:                return (bwrite(bp));
                    363:        } else {
                    364:                bdwrite(bp);
                    365:                return (0);
                    366:        }
                    367: }
                    368: 
                    369: #define        SINGLE  0       /* index of single indirect block */
                    370: #define        DOUBLE  1       /* index of double indirect block */
                    371: #define        TRIPLE  2       /* index of triple indirect block */
                    372: /*
                    373:  * Truncate the inode ip to at most length size.  Free affected disk
                    374:  * blocks -- the blocks of the file are removed in reverse order.
                    375:  *
                    376:  * NB: triple indirect blocks are untested.
                    377:  */
                    378: itrunc(oip, length, flags)
                    379:        register struct inode *oip;
                    380:        u_long length;
                    381:        int flags;
                    382: {
                    383:        register daddr_t lastblock;
                    384:        daddr_t bn, lbn, lastiblock[NIADDR];
                    385:        register struct fs *fs;
                    386:        register struct inode *ip;
                    387:        struct buf *bp;
                    388:        int offset, osize, size, level;
                    389:        long count, nblocks, blocksreleased = 0;
                    390:        register int i;
                    391:        int aflags, error, allerror;
                    392:        struct inode tip;
                    393: 
                    394:        if (oip->i_size <= length) {
                    395:                oip->i_flag |= ICHG|IUPD;
                    396:                error = iupdat(oip, &time, &time, 1);
                    397:                return (error);
                    398:        }
                    399:        /*
                    400:         * Calculate index into inode's block list of
                    401:         * last direct and indirect blocks (if any)
                    402:         * which we want to keep.  Lastblock is -1 when
                    403:         * the file is truncated to 0.
                    404:         */
                    405:        fs = oip->i_fs;
                    406:        lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1;
                    407:        lastiblock[SINGLE] = lastblock - NDADDR;
                    408:        lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
                    409:        lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
                    410:        nblocks = btodb(fs->fs_bsize);
                    411:        /*
                    412:         * Update the size of the file. If the file is not being
                    413:         * truncated to a block boundry, the contents of the
                    414:         * partial block following the end of the file must be
                    415:         * zero'ed in case it ever become accessable again because
                    416:         * of subsequent file growth.
                    417:         */
                    418:        osize = oip->i_size;
                    419:        offset = blkoff(fs, length);
                    420:        if (offset == 0) {
                    421:                oip->i_size = length;
                    422:        } else {
                    423:                lbn = lblkno(fs, length);
                    424:                aflags = B_CLRBUF;
                    425:                if (flags & IO_SYNC)
                    426:                        aflags |= B_SYNC;
                    427: #ifdef QUOTA
                    428:                if (error = getinoquota(oip))
                    429:                        return (error);
                    430: #endif
                    431:                if (error = balloc(oip, lbn, offset, &bp, aflags))
                    432:                        return (error);
                    433:                oip->i_size = length;
                    434:                size = blksize(fs, oip, lbn);
                    435:                bn = bp->b_blkno;
                    436:                count = howmany(size, CLBYTES);
                    437:                for (i = 0; i < count; i++)
                    438:                        munhash(oip->i_devvp, bn + i * CLBYTES / DEV_BSIZE);
                    439:                bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
                    440:                brealloc(bp, size);
                    441:                if (flags & IO_SYNC)
                    442:                        bwrite(bp);
                    443:                else
                    444:                        bdwrite(bp);
                    445:        }
                    446:        /*
                    447:         * Update file and block pointers
                    448:         * on disk before we start freeing blocks.
                    449:         * If we crash before free'ing blocks below,
                    450:         * the blocks will be returned to the free list.
                    451:         * lastiblock values are also normalized to -1
                    452:         * for calls to indirtrunc below.
                    453:         */
                    454:        tip = *oip;
                    455:        tip.i_size = osize;
                    456:        for (level = TRIPLE; level >= SINGLE; level--)
                    457:                if (lastiblock[level] < 0) {
                    458:                        oip->i_ib[level] = 0;
                    459:                        lastiblock[level] = -1;
                    460:                }
                    461:        for (i = NDADDR - 1; i > lastblock; i--)
                    462:                oip->i_db[i] = 0;
                    463:        oip->i_flag |= ICHG|IUPD;
                    464:        vinvalbuf(ITOV(oip), (length > 0));
                    465:        allerror = iupdat(oip, &time, &time, MNT_WAIT);
                    466: 
                    467:        /*
                    468:         * Indirect blocks first.
                    469:         */
                    470:        ip = &tip;
                    471:        for (level = TRIPLE; level >= SINGLE; level--) {
                    472:                bn = ip->i_ib[level];
                    473:                if (bn != 0) {
                    474:                        error = indirtrunc(ip, bn, lastiblock[level], level,
                    475:                                &count);
                    476:                        if (error)
                    477:                                allerror = error;
                    478:                        blocksreleased += count;
                    479:                        if (lastiblock[level] < 0) {
                    480:                                ip->i_ib[level] = 0;
                    481:                                blkfree(ip, bn, (off_t)fs->fs_bsize);
                    482:                                blocksreleased += nblocks;
                    483:                        }
                    484:                }
                    485:                if (lastiblock[level] >= 0)
                    486:                        goto done;
                    487:        }
                    488: 
                    489:        /*
                    490:         * All whole direct blocks or frags.
                    491:         */
                    492:        for (i = NDADDR - 1; i > lastblock; i--) {
                    493:                register off_t bsize;
                    494: 
                    495:                bn = ip->i_db[i];
                    496:                if (bn == 0)
                    497:                        continue;
                    498:                ip->i_db[i] = 0;
                    499:                bsize = (off_t)blksize(fs, ip, i);
                    500:                blkfree(ip, bn, bsize);
                    501:                blocksreleased += btodb(bsize);
                    502:        }
                    503:        if (lastblock < 0)
                    504:                goto done;
                    505: 
                    506:        /*
                    507:         * Finally, look for a change in size of the
                    508:         * last direct block; release any frags.
                    509:         */
                    510:        bn = ip->i_db[lastblock];
                    511:        if (bn != 0) {
                    512:                off_t oldspace, newspace;
                    513: 
                    514:                /*
                    515:                 * Calculate amount of space we're giving
                    516:                 * back as old block size minus new block size.
                    517:                 */
                    518:                oldspace = blksize(fs, ip, lastblock);
                    519:                ip->i_size = length;
                    520:                newspace = blksize(fs, ip, lastblock);
                    521:                if (newspace == 0)
                    522:                        panic("itrunc: newspace");
                    523:                if (oldspace - newspace > 0) {
                    524:                        /*
                    525:                         * Block number of space to be free'd is
                    526:                         * the old block # plus the number of frags
                    527:                         * required for the storage we're keeping.
                    528:                         */
                    529:                        bn += numfrags(fs, newspace);
                    530:                        blkfree(ip, bn, oldspace - newspace);
                    531:                        blocksreleased += btodb(oldspace - newspace);
                    532:                }
                    533:        }
                    534: done:
                    535: /* BEGIN PARANOIA */
                    536:        for (level = SINGLE; level <= TRIPLE; level++)
                    537:                if (ip->i_ib[level] != oip->i_ib[level])
                    538:                        panic("itrunc1");
                    539:        for (i = 0; i < NDADDR; i++)
                    540:                if (ip->i_db[i] != oip->i_db[i])
                    541:                        panic("itrunc2");
                    542: /* END PARANOIA */
                    543:        oip->i_blocks -= blocksreleased;
                    544:        if (oip->i_blocks < 0)                  /* sanity */
                    545:                oip->i_blocks = 0;
                    546:        oip->i_flag |= ICHG;
                    547: #ifdef QUOTA
                    548:        if (!getinoquota(oip))
                    549:                (void) chkdq(oip, -blocksreleased, NOCRED, 0);
                    550: #endif
                    551:        return (allerror);
                    552: }
                    553: 
                    554: /*
                    555:  * Release blocks associated with the inode ip and
                    556:  * stored in the indirect block bn.  Blocks are free'd
                    557:  * in LIFO order up to (but not including) lastbn.  If
                    558:  * level is greater than SINGLE, the block is an indirect
                    559:  * block and recursive calls to indirtrunc must be used to
                    560:  * cleanse other indirect blocks.
                    561:  *
                    562:  * NB: triple indirect blocks are untested.
                    563:  */
                    564: indirtrunc(ip, bn, lastbn, level, countp)
                    565:        register struct inode *ip;
                    566:        daddr_t bn, lastbn;
                    567:        int level;
                    568:        long *countp;
                    569: {
                    570:        register int i;
                    571:        struct buf *bp;
                    572:        register struct fs *fs = ip->i_fs;
                    573:        register daddr_t *bap;
                    574:        daddr_t *copy, nb, last;
                    575:        long blkcount, factor;
                    576:        int nblocks, blocksreleased = 0;
                    577:        int error, allerror = 0;
                    578: 
                    579:        /*
                    580:         * Calculate index in current block of last
                    581:         * block to be kept.  -1 indicates the entire
                    582:         * block so we need not calculate the index.
                    583:         */
                    584:        factor = 1;
                    585:        for (i = SINGLE; i < level; i++)
                    586:                factor *= NINDIR(fs);
                    587:        last = lastbn;
                    588:        if (lastbn > 0)
                    589:                last /= factor;
                    590:        nblocks = btodb(fs->fs_bsize);
                    591:        /*
                    592:         * Get buffer of block pointers, zero those 
                    593:         * entries corresponding to blocks to be free'd,
                    594:         * and update on disk copy first.
                    595:         */
                    596:        error = bread(ip->i_devvp, fsbtodb(fs, bn), (int)fs->fs_bsize,
                    597:                NOCRED, &bp);
                    598:        if (error) {
                    599:                brelse(bp);
                    600:                *countp = 0;
                    601:                return (error);
                    602:        }
                    603:        bap = bp->b_un.b_daddr;
                    604:        MALLOC(copy, daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK);
                    605:        bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize);
                    606:        bzero((caddr_t)&bap[last + 1],
                    607:          (u_int)(NINDIR(fs) - (last + 1)) * sizeof (daddr_t));
                    608:        if (last == -1)
                    609:                bp->b_flags |= B_INVAL;
                    610:        error = bwrite(bp);
                    611:        if (error)
                    612:                allerror = error;
                    613:        bap = copy;
                    614: 
                    615:        /*
                    616:         * Recursively free totally unused blocks.
                    617:         */
                    618:        for (i = NINDIR(fs) - 1; i > last; i--) {
                    619:                nb = bap[i];
                    620:                if (nb == 0)
                    621:                        continue;
                    622:                if (level > SINGLE) {
                    623:                        error = indirtrunc(ip, nb, (daddr_t)-1, level - 1,
                    624:                                &blkcount);
                    625:                        if (error)
                    626:                                allerror = error;
                    627:                        blocksreleased += blkcount;
                    628:                }
                    629:                blkfree(ip, nb, (off_t)fs->fs_bsize);
                    630:                blocksreleased += nblocks;
                    631:        }
                    632: 
                    633:        /*
                    634:         * Recursively free last partial block.
                    635:         */
                    636:        if (level > SINGLE && lastbn >= 0) {
                    637:                last = lastbn % factor;
                    638:                nb = bap[i];
                    639:                if (nb != 0) {
                    640:                        error = indirtrunc(ip, nb, last, level - 1, &blkcount);
                    641:                        if (error)
                    642:                                allerror = error;
                    643:                        blocksreleased += blkcount;
                    644:                }
                    645:        }
                    646:        FREE(copy, M_TEMP);
                    647:        *countp = blocksreleased;
                    648:        return (allerror);
                    649: }
                    650: 
                    651: /*
                    652:  * Lock an inode. If its already locked, set the WANT bit and sleep.
                    653:  */
                    654: ilock(ip)
                    655:        register struct inode *ip;
                    656: {
                    657: 
                    658:        while (ip->i_flag & ILOCKED) {
                    659:                ip->i_flag |= IWANT;
                    660:                if (ip->i_spare0 == u.u_procp->p_pid)
                    661:                        panic("locking against myself");
                    662:                ip->i_spare1 = u.u_procp->p_pid;
                    663:                (void) sleep((caddr_t)ip, PINOD);
                    664:        }
                    665:        ip->i_spare1 = 0;
                    666:        ip->i_spare0 = u.u_procp->p_pid;
                    667:        u.u_spare[0]++;
                    668:        ip->i_flag |= ILOCKED;
                    669: }
                    670: 
                    671: /*
                    672:  * Unlock an inode.  If WANT bit is on, wakeup.
                    673:  */
                    674: iunlock(ip)
                    675:        register struct inode *ip;
                    676: {
                    677: 
                    678:        if ((ip->i_flag & ILOCKED) == 0)
                    679:                vprint("iunlock: unlocked inode", ITOV(ip));
                    680:        ip->i_spare0 = 0;
                    681:        u.u_spare[0]--;
                    682:        ip->i_flag &= ~ILOCKED;
                    683:        if (ip->i_flag&IWANT) {
                    684:                ip->i_flag &= ~IWANT;
                    685:                wakeup((caddr_t)ip);
                    686:        }
                    687: }

unix.superglobalmegacorp.com

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