Annotation of kernel/bsd/ufs/lfs/lfs_inode.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: /*     $NetBSD: lfs_inode.c,v 1.2 1994/06/29 06:46:57 cgd Exp $        */
                     26: 
                     27: /*
                     28:  * Copyright (c) 1986, 1989, 1991, 1993
                     29:  *     The Regents of the University of California.  All rights reserved.
                     30:  *
                     31:  * Redistribution and use in source and binary forms, with or without
                     32:  * modification, are permitted provided that the following conditions
                     33:  * are met:
                     34:  * 1. Redistributions of source code must retain the above copyright
                     35:  *    notice, this list of conditions and the following disclaimer.
                     36:  * 2. Redistributions in binary form must reproduce the above copyright
                     37:  *    notice, this list of conditions and the following disclaimer in the
                     38:  *    documentation and/or other materials provided with the distribution.
                     39:  * 3. All advertising materials mentioning features or use of this software
                     40:  *    must display the following acknowledgement:
                     41:  *     This product includes software developed by the University of
                     42:  *     California, Berkeley and its contributors.
                     43:  * 4. Neither the name of the University nor the names of its contributors
                     44:  *    may be used to endorse or promote products derived from this software
                     45:  *    without specific prior written permission.
                     46:  *
                     47:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     48:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     49:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     50:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     51:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     52:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     53:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     54:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     55:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     56:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     57:  * SUCH DAMAGE.
                     58:  *
                     59:  *     @(#)lfs_inode.c 8.5 (Berkeley) 12/30/93
                     60:  */
                     61: 
                     62: #include <sys/param.h>
                     63: #include <sys/systm.h>
                     64: #include <sys/mount.h>
                     65: #include <sys/proc.h>
                     66: #include <sys/file.h>
                     67: #include <sys/buf.h>
                     68: #include <sys/vnode.h>
                     69: #include <sys/kernel.h>
                     70: #include <sys/malloc.h>
                     71: 
                     72: #include <vm/vm.h>
                     73: 
                     74: #include <ufs/ufs/quota.h>
                     75: #include <ufs/ufs/inode.h>
                     76: #include <ufs/ufs/ufsmount.h>
                     77: #include <ufs/ufs/ufs_extern.h>
                     78: 
                     79: #include <ufs/lfs/lfs.h>
                     80: #include <ufs/lfs/lfs_extern.h>
                     81: 
                     82: int
                     83: lfs_init()
                     84: {
                     85:        return (ufs_init());
                     86: }
                     87: 
                     88: /* Search a block for a specific dinode. */
                     89: struct dinode *
                     90: lfs_ifind(fs, ino, dip)
                     91:        struct lfs *fs;
                     92:        ino_t ino;
                     93:        register struct dinode *dip;
                     94: {
                     95:        register int cnt;
                     96:        register struct dinode *ldip;
                     97: 
                     98:        for (cnt = INOPB(fs), ldip = dip + (cnt - 1); cnt--; --ldip)
                     99:                if (ldip->di_inumber == ino)
                    100:                        return (ldip);
                    101: 
                    102:        panic("lfs_ifind: dinode %u not found", ino);
                    103:        /* NOTREACHED */
                    104: }
                    105: 
                    106: int
                    107: lfs_update(ap)
                    108:        struct vop_update_args /* {
                    109:                struct vnode *a_vp;
                    110:                struct timeval *a_access;
                    111:                struct timeval *a_modify;
                    112:                int a_waitfor;
                    113:        } */ *ap;
                    114: {
                    115:        struct vnode *vp = ap->a_vp;
                    116:        struct inode *ip;
                    117: 
                    118:        if (vp->v_mount->mnt_flag & MNT_RDONLY)
                    119:                return (0);
                    120:        ip = VTOI(vp);
                    121:        if ((ip->i_flag &
                    122:            (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)
                    123:                return (0);
                    124:        if (ip->i_flag & IN_ACCESS)
                    125:                ip->i_atime.tv_sec = ap->a_access->tv_sec;
                    126:        if (ip->i_flag & IN_UPDATE) {
                    127:                ip->i_mtime.tv_sec = ap->a_modify->tv_sec;
                    128:                (ip)->i_modrev++;
                    129:        }
                    130:        if (ip->i_flag & IN_CHANGE)
                    131:                ip->i_ctime.tv_sec = time.tv_sec;
                    132:        ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
                    133: 
                    134:        if (!(ip->i_flag & IN_MODIFIED))
                    135:                ++(VFSTOUFS(vp->v_mount)->um_lfs->lfs_uinodes);
                    136:        ip->i_flag |= IN_MODIFIED;
                    137: 
                    138:        /* If sync, push back the vnode and any dirty blocks it may have. */
                    139:        return (ap->a_waitfor & LFS_SYNC ? lfs_vflush(vp) : 0);
                    140: }
                    141: 
                    142: /* Update segment usage information when removing a block. */
                    143: #define UPDATE_SEGUSE \
                    144:        if (lastseg != -1) { \
                    145:                LFS_SEGENTRY(sup, fs, lastseg, sup_bp); \
                    146:                if ((num << fs->lfs_bshift) > sup->su_nbytes) \
                    147:                        panic("lfs_truncate: negative bytes in segment %d\n", \
                    148:                            lastseg); \
                    149:                sup->su_nbytes -= num << fs->lfs_bshift; \
                    150:                e1 = VOP_BWRITE(sup_bp); \
                    151:                blocksreleased += num; \
                    152:        }
                    153: 
                    154: #define SEGDEC { \
                    155:        if (daddr != 0) { \
                    156:                if (lastseg != (seg = datosn(fs, daddr))) { \
                    157:                        UPDATE_SEGUSE; \
                    158:                        num = 1; \
                    159:                        lastseg = seg; \
                    160:                } else \
                    161:                        ++num; \
                    162:        } \
                    163: }
                    164: 
                    165: /*
                    166:  * Truncate the inode ip to at most length size.  Update segment usage
                    167:  * table information.
                    168:  */
                    169: /* ARGSUSED */
                    170: int
                    171: lfs_truncate(ap)
                    172:        struct vop_truncate_args /* {
                    173:                struct vnode *a_vp;
                    174:                off_t a_length;
                    175:                int a_flags;
                    176:                struct ucred *a_cred;
                    177:                struct proc *a_p;
                    178:        } */ *ap;
                    179: {
                    180:        register struct indir *inp;
                    181:        register int i;
                    182:        register daddr_t *daddrp;
                    183:        register struct vnode *vp = ap->a_vp;
                    184:        off_t length = ap->a_length;
                    185:        struct buf *bp, *sup_bp;
                    186:        struct timeval tv;
                    187:        struct ifile *ifp;
                    188:        struct inode *ip;
                    189:        struct lfs *fs;
                    190:        struct indir a[NIADDR + 2], a_end[NIADDR + 2];
                    191:        SEGUSE *sup;
                    192:        daddr_t daddr, lastblock, lbn, olastblock;
                    193:        long off, a_released, blocksreleased, i_released;
                    194:        int e1, e2, depth, lastseg, num, offset, seg, size;
                    195: 
                    196:        ip = VTOI(vp);
                    197:        tv = time;
                    198:        if (vp->v_type == VLNK && vp->v_mount->mnt_maxsymlinklen > 0) {
                    199: #if DIAGNOSTIC
                    200:                if (length != 0)
                    201:                        panic("lfs_truncate: partial truncate of symlink");
                    202: #endif
                    203:                bzero((char *)&ip->i_shortlink, (u_int)ip->i_size);
                    204:                ip->i_size = 0;
                    205:                ip->i_flag |= IN_CHANGE | IN_UPDATE;
                    206:                return (VOP_UPDATE(vp, &tv, &tv, 0));
                    207:        }
                    208:        vnode_pager_setsize(vp, (u_long)length);
                    209: 
                    210:        fs = ip->i_lfs;
                    211: 
                    212:        /* If length is larger than the file, just update the times. */
                    213:        if (ip->i_size <= length) {
                    214:                ip->i_flag |= IN_CHANGE | IN_UPDATE;
                    215:                return (VOP_UPDATE(vp, &tv, &tv, 0));
                    216:        }
                    217: 
                    218:        /*
                    219:         * Calculate index into inode's block list of last direct and indirect
                    220:         * blocks (if any) which we want to keep.  Lastblock is 0 when the
                    221:         * file is truncated to 0.
                    222:         */
                    223:        lastblock = lblkno(fs, length + fs->lfs_bsize - 1);
                    224:        olastblock = lblkno(fs, ip->i_size + fs->lfs_bsize - 1) - 1;
                    225: 
                    226:        /*
                    227:         * Update the size of the file. If the file is not being truncated to
                    228:         * a block boundry, the contents of the partial block following the end
                    229:         * of the file must be zero'ed in case it ever become accessable again
                    230:         * because of subsequent file growth.
                    231:         */
                    232:        offset = blkoff(fs, length);
                    233:        if (offset == 0)
                    234:                ip->i_size = length;
                    235:        else {
                    236:                lbn = lblkno(fs, length);
                    237: #ifdef QUOTA
                    238:                if (e1 = getinoquota(ip))
                    239:                        return (e1);
                    240: #endif 
                    241:                if (e1 = bread(vp, lbn, fs->lfs_bsize, NOCRED, &bp))
                    242:                        return (e1);
                    243:                ip->i_size = length;
                    244:                size = blksize(fs);
                    245:                (void)vnode_pager_uncache(vp);
                    246:                bzero((char *)bp->b_data + offset, (u_int)(size - offset));
                    247:                allocbuf(bp, size);
                    248:                if (e1 = VOP_BWRITE(bp))
                    249:                        return (e1);
                    250:        }
                    251:        /*
                    252:         * Modify sup->su_nbyte counters for each deleted block; keep track
                    253:         * of number of blocks removed for ip->i_blocks.
                    254:         */
                    255:        blocksreleased = 0;
                    256:        num = 0;
                    257:        lastseg = -1;
                    258: 
                    259:        for (lbn = olastblock; lbn >= lastblock;) {
                    260:                /* XXX use run length from bmap array to make this faster */
                    261:                ufs_bmaparray(vp, lbn, &daddr, a, &depth, NULL);
                    262:                if (lbn == olastblock)
                    263:                        for (i = NIADDR + 2; i--;)
                    264:                                a_end[i] = a[i];
                    265:                switch (depth) {
                    266:                case 0:                         /* Direct block. */
                    267:                        daddr = ip->i_db[lbn];
                    268:                        SEGDEC;
                    269:                        ip->i_db[lbn] = 0;
                    270:                        --lbn;
                    271:                        break;
                    272: #if DIAGNOSTIC
                    273:                case 1:                         /* An indirect block. */
                    274:                        panic("lfs_truncate: ufs_bmaparray returned depth 1");
                    275:                        /* NOTREACHED */
                    276: #endif
                    277:                default:                        /* Chain of indirect blocks. */
                    278:                        inp = a + --depth;
                    279:                        if (inp->in_off > 0 && lbn != lastblock) {
                    280:                                lbn -= inp->in_off < lbn - lastblock ?
                    281:                                    inp->in_off : lbn - lastblock;
                    282:                                break;
                    283:                        }
                    284:                        for (; depth && (inp->in_off == 0 || lbn == lastblock);
                    285:                            --inp, --depth) {
                    286:                                if (bread(vp,
                    287:                                    inp->in_lbn, fs->lfs_bsize, NOCRED, &bp))
                    288:                                        panic("lfs_truncate: bread bno %d",
                    289:                                            inp->in_lbn);
                    290:                                daddrp = (daddr_t *)bp->b_data + inp->in_off;
                    291:                                for (i = inp->in_off;
                    292:                                    i++ <= a_end[depth].in_off;) {
                    293:                                        daddr = *daddrp++;
                    294:                                        SEGDEC;
                    295:                                }
                    296:                                a_end[depth].in_off = NINDIR(fs) - 1;
                    297:                                if (inp->in_off == 0)
                    298:                                        brelse (bp);
                    299:                                else {
                    300:                                        bzero((daddr_t *)bp->b_data +
                    301:                                            inp->in_off, fs->lfs_bsize - 
                    302:                                            inp->in_off * sizeof(daddr_t));
                    303:                                        if (e1 = VOP_BWRITE(bp)) 
                    304:                                                return (e1);
                    305:                                }
                    306:                        }
                    307:                        if (depth == 0 && a[1].in_off == 0) {
                    308:                                off = a[0].in_off;
                    309:                                daddr = ip->i_ib[off];
                    310:                                SEGDEC;
                    311:                                ip->i_ib[off] = 0;
                    312:                        }
                    313:                        if (lbn == lastblock || lbn <= NDADDR)
                    314:                                --lbn;
                    315:                        else {
                    316:                                lbn -= NINDIR(fs);
                    317:                                if (lbn < lastblock)
                    318:                                        lbn = lastblock;
                    319:                        }
                    320:                }
                    321:        }
                    322:        UPDATE_SEGUSE;
                    323: 
                    324:        /* If truncating the file to 0, update the version number. */
                    325:        if (length == 0) {
                    326:                LFS_IENTRY(ifp, fs, ip->i_number, bp);
                    327:                ++ifp->if_version;
                    328:                (void) VOP_BWRITE(bp);
                    329:        }
                    330: 
                    331: #if DIAGNOSTIC
                    332:        if (ip->i_blocks < fsbtodb(fs, blocksreleased)) {
                    333:                printf("lfs_truncate: block count < 0\n");
                    334:                blocksreleased = ip->i_blocks;
                    335:        }
                    336: #endif
                    337:        ip->i_blocks -= fsbtodb(fs, blocksreleased);
                    338:        fs->lfs_bfree +=  fsbtodb(fs, blocksreleased);
                    339:        ip->i_flag |= IN_CHANGE | IN_UPDATE;
                    340:        /*
                    341:         * Traverse dirty block list counting number of dirty buffers
                    342:         * that are being deleted out of the cache, so that the lfs_avail
                    343:         * field can be updated.
                    344:         */
                    345:        a_released = 0;
                    346:        i_released = 0;
                    347:        for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = bp->b_vnbufs.le_next)
                    348:                if (bp->b_flags & B_LOCKED) {
                    349:                        ++a_released;
                    350:                        /*
                    351:                         * XXX
                    352:                         * When buffers are created in the cache, their block
                    353:                         * number is set equal to their logical block number.
                    354:                         * If that is still true, we are assuming that the
                    355:                         * blocks are new (not yet on disk) and weren't
                    356:                         * counted above.  However, there is a slight chance
                    357:                         * that a block's disk address is equal to its logical
                    358:                         * block number in which case, we'll get an overcounting
                    359:                         * here.
                    360:                         */
                    361:                        if (bp->b_blkno == bp->b_lblkno)
                    362:                                ++i_released;
                    363:                }
                    364:        blocksreleased = fsbtodb(fs, i_released);
                    365: #if DIAGNOSTIC
                    366:        if (blocksreleased > ip->i_blocks) {
                    367:                printf("lfs_inode: Warning! %s\n",
                    368:                    "more blocks released from inode than are in inode");
                    369:                blocksreleased = ip->i_blocks;
                    370:        }
                    371: #endif
                    372:        fs->lfs_bfree += blocksreleased;
                    373:        ip->i_blocks -= blocksreleased;
                    374: #if DIAGNOSTIC
                    375:        if (length == 0 && ip->i_blocks != 0)
                    376:                printf("lfs_inode: Warning! %s%d%s\n",
                    377:                    "Truncation to zero, but ", ip->i_blocks,
                    378:                    " blocks left on inode");
                    379: #endif
                    380:        fs->lfs_avail += fsbtodb(fs, a_released);
                    381:        e1 = vinvalbuf(vp, (length > 0) ? V_SAVE : 0, ap->a_cred, ap->a_p,
                    382:            0, 0); 
                    383:        e2 = VOP_UPDATE(vp, &tv, &tv, 0);
                    384:        return (e1 ? e1 : e2 ? e2 : 0);
                    385: }

unix.superglobalmegacorp.com

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