X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/43866e378188c25dd1e2208016ab3cbeb086ae6c..89b3af67bb32e691275bf6fa803d1834b2284115:/bsd/ufs/ffs/ffs_inode.c diff --git a/bsd/ufs/ffs/ffs_inode.c b/bsd/ufs/ffs/ffs_inode.c index 0ffc112e2..b04128754 100644 --- a/bsd/ufs/ffs/ffs_inode.c +++ b/bsd/ufs/ffs/ffs_inode.c @@ -1,16 +1,19 @@ /* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER @@ -20,7 +23,7 @@ * Please see the License for the specific language governing rights and * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ /* @@ -63,11 +66,11 @@ #include #include -#include -#include +#include +#include /* for accessing p_stats */ #include -#include -#include +#include +#include #include #include #include @@ -87,11 +90,11 @@ #if REV_ENDIAN_FS #include -#include +#include #endif /* REV_ENDIAN_FS */ -static int ffs_indirtrunc __P((struct inode *, ufs_daddr_t, ufs_daddr_t, - ufs_daddr_t, int, long *)); +static int ffs_indirtrunc(struct inode *, ufs_daddr_t, ufs_daddr_t, + ufs_daddr_t, int, long *); /* * Update the access, modified, and inode change times as specified by the @@ -103,25 +106,20 @@ static int ffs_indirtrunc __P((struct inode *, ufs_daddr_t, ufs_daddr_t, * complete. */ int -ffs_update(ap) - struct vop_update_args /* { - struct vnode *a_vp; - struct timeval *a_access; - struct timeval *a_modify; - int a_waitfor; - } */ *ap; +ffs_update(struct vnode *vp, struct timeval *access, struct timeval *modify, int waitfor) { register struct fs *fs; struct buf *bp; struct inode *ip; - int error; + struct timeval tv; + errno_t error; #if REV_ENDIAN_FS - struct mount *mp=(ap->a_vp)->v_mount; + struct mount *mp=(vp)->v_mount; int rev_endian=(mp->mnt_flag & MNT_REVEND); #endif /* REV_ENDIAN_FS */ - ip = VTOI(ap->a_vp); - if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) { + ip = VTOI(vp); + if (vp->v_mount->mnt_flag & MNT_RDONLY) { ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE); return (0); @@ -130,13 +128,15 @@ ffs_update(ap) (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) return (0); if (ip->i_flag & IN_ACCESS) - ip->i_atime = ap->a_access->tv_sec; + ip->i_atime = access->tv_sec; if (ip->i_flag & IN_UPDATE) { - ip->i_mtime = ap->a_modify->tv_sec; + ip->i_mtime = modify->tv_sec; ip->i_modrev++; } - if (ip->i_flag & IN_CHANGE) - ip->i_ctime = time.tv_sec; + if (ip->i_flag & IN_CHANGE) { + microtime(&tv); + ip->i_ctime = tv.tv_sec; + } ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE); fs = ip->i_fs; /* @@ -147,62 +147,50 @@ ffs_update(ap) ip->i_din.di_ouid = ip->i_uid; /* XXX */ ip->i_din.di_ogid = ip->i_gid; /* XXX */ } /* XXX */ - if (error = bread(ip->i_devvp, - fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), + if (error = buf_bread(ip->i_devvp, + (daddr64_t)((unsigned)fsbtodb(fs, ino_to_fsba(fs, ip->i_number))), (int)fs->fs_bsize, NOCRED, &bp)) { - brelse(bp); - return (error); + buf_brelse(bp); + return ((int)error); } #if REV_ENDIAN_FS if (rev_endian) - byte_swap_inode_out(ip, ((struct dinode *)bp->b_data + ino_to_fsbo(fs, ip->i_number))); + byte_swap_inode_out(ip, ((struct dinode *)buf_dataptr(bp) + ino_to_fsbo(fs, ip->i_number))); else { #endif /* REV_ENDIAN_FS */ - *((struct dinode *)bp->b_data + - ino_to_fsbo(fs, ip->i_number)) = ip->i_din; + *((struct dinode *)buf_dataptr(bp) + ino_to_fsbo(fs, ip->i_number)) = ip->i_din; #if REV_ENDIAN_FS } #endif /* REV_ENDIAN_FS */ - if (ap->a_waitfor && (ap->a_vp->v_mount->mnt_flag & MNT_ASYNC) == 0) - return (bwrite(bp)); + if (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0) + return ((int)buf_bwrite(bp)); else { - bdwrite(bp); + buf_bdwrite(bp); return (0); } } + #define SINGLE 0 /* index of single indirect block */ #define DOUBLE 1 /* index of double indirect block */ #define TRIPLE 2 /* index of triple indirect block */ -/* - * Truncate the inode oip to at most length size, freeing the - * disk blocks. - */ -ffs_truncate(ap) - struct vop_truncate_args /* { - struct vnode *a_vp; - off_t a_length; - int a_flags; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; + +int +ffs_truncate_internal(vnode_t ovp, off_t length, int flags, ucred_t cred) { - register struct vnode *ovp = ap->a_vp; + struct inode *oip; + struct fs *fs; ufs_daddr_t lastblock; - register struct inode *oip; ufs_daddr_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR]; ufs_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR]; - off_t length = ap->a_length; - register struct fs *fs; - struct buf *bp; - int offset, size, level; - long count, nblocks, vflags, blocksreleased = 0; - struct timeval tv; - register int i; - int aflags, error, allerror; - off_t osize; - int devBlockSize=0; + buf_t bp; + int offset, size, level, i; + long count, nblocks, vflags, blocksreleased = 0; + struct timeval tv; + int aflags, error, allerror; + off_t osize; + int devBlockSize=0; #if QUOTA int64_t change; /* in bytes */ #endif /* QUOTA */ @@ -216,7 +204,7 @@ ffs_truncate(ap) if (length > fs->fs_maxfilesize) return (EFBIG); - tv = time; + microtime(&tv); if (ovp->v_type == VLNK && oip->i_size < ovp->v_mount->mnt_maxsymlinklen) { #if DIAGNOSTIC @@ -226,12 +214,12 @@ ffs_truncate(ap) bzero((char *)&oip->i_shortlink, (u_int)oip->i_size); oip->i_size = 0; oip->i_flag |= IN_CHANGE | IN_UPDATE; - return (VOP_UPDATE(ovp, &tv, &tv, 1)); + return (ffs_update(ovp, &tv, &tv, 1)); } if (oip->i_size == length) { oip->i_flag |= IN_CHANGE | IN_UPDATE; - return (VOP_UPDATE(ovp, &tv, &tv, 0)); + return (ffs_update(ovp, &tv, &tv, 0)); } #if QUOTA if (error = getinoquota(oip)) @@ -248,25 +236,24 @@ ffs_truncate(ap) offset = blkoff(fs, length - 1); lbn = lblkno(fs, length - 1); aflags = B_CLRBUF; - if (ap->a_flags & IO_SYNC) + if (flags & IO_SYNC) aflags |= B_SYNC; - if (error = ffs_balloc(oip, lbn, offset + 1, ap->a_cred, &bp, - aflags , 0)) + if (error = ffs_balloc(oip, lbn, offset + 1, cred, &bp, aflags, 0)) return (error); oip->i_size = length; if (UBCINFOEXISTS(ovp)) { - bp->b_flags |= B_INVAL; - bwrite(bp); + buf_markinvalid(bp); + buf_bwrite(bp); ubc_setsize(ovp, (off_t)length); } else { if (aflags & B_SYNC) - bwrite(bp); + buf_bwrite(bp); else - bawrite(bp); + buf_bawrite(bp); } oip->i_flag |= IN_CHANGE | IN_UPDATE; - return (VOP_UPDATE(ovp, &tv, &tv, 1)); + return (ffs_update(ovp, &tv, &tv, 1)); } /* * Shorten the size of the file. If the file is not being @@ -278,33 +265,34 @@ ffs_truncate(ap) if (UBCINFOEXISTS(ovp)) ubc_setsize(ovp, (off_t)length); - vflags = ((length > 0) ? V_SAVE : 0) | V_SAVEMETA; - allerror = vinvalbuf(ovp, vflags, ap->a_cred, ap->a_p, 0, 0); - + vflags = ((length > 0) ? BUF_WRITE_DATA : 0) | BUF_SKIP_META; + if (vflags & BUF_WRITE_DATA) + ffs_fsync_internal(ovp, MNT_WAIT); + allerror = buf_invalidateblks(ovp, vflags, 0, 0); + offset = blkoff(fs, length); if (offset == 0) { oip->i_size = length; } else { lbn = lblkno(fs, length); aflags = B_CLRBUF; - if (ap->a_flags & IO_SYNC) + if (flags & IO_SYNC) aflags |= B_SYNC; - if (error = ffs_balloc(oip, lbn, offset, ap->a_cred, &bp, - aflags, 0)) + if (error = ffs_balloc(oip, lbn, offset, cred, &bp, aflags, 0)) return (error); oip->i_size = length; size = blksize(fs, oip, lbn); - bzero((char *)bp->b_data + offset, (u_int)(size - offset)); + bzero((char *)buf_dataptr(bp) + offset, (u_int)(size - offset)); allocbuf(bp, size); if (UBCINFOEXISTS(ovp)) { - bp->b_flags |= B_INVAL; - bwrite(bp); + buf_markinvalid(bp); + buf_bwrite(bp); } else { if (aflags & B_SYNC) - bwrite(bp); + buf_bwrite(bp); else - bawrite(bp); + buf_bawrite(bp); } } /* @@ -317,7 +305,8 @@ ffs_truncate(ap) lastiblock[SINGLE] = lastblock - NDADDR; lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs); lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs); - VOP_DEVBLOCKSIZE(oip->i_devvp,&devBlockSize); + + devBlockSize = vfs_devblocksize(vnode_mount(ovp)); nblocks = btodb(fs->fs_bsize, devBlockSize); /* @@ -335,7 +324,7 @@ ffs_truncate(ap) for (i = NDADDR - 1; i > lastblock; i--) oip->i_db[i] = 0; oip->i_flag |= IN_CHANGE | IN_UPDATE; - if (error = VOP_UPDATE(ovp, &tv, &tv, MNT_WAIT)) + if (error = ffs_update(ovp, &tv, &tv, MNT_WAIT)) allerror = error; /* * Having written the new inode to disk, save its new configuration @@ -346,8 +335,12 @@ ffs_truncate(ap) bcopy((caddr_t)&oip->i_db[0], (caddr_t)newblks, sizeof newblks); bcopy((caddr_t)oldblks, (caddr_t)&oip->i_db[0], sizeof oldblks); oip->i_size = osize; - vflags = ((length > 0) ? V_SAVE : 0) | V_SAVEMETA; - allerror = vinvalbuf(ovp, vflags, ap->a_cred, ap->a_p, 0, 0); + + vflags = ((length > 0) ? BUF_WRITE_DATA : 0) | BUF_SKIP_META; + + if (vflags & BUF_WRITE_DATA) + ffs_fsync_internal(ovp, MNT_WAIT); + allerror = buf_invalidateblks(ovp, vflags, 0, 0); /* * Indirect blocks first. @@ -427,7 +420,7 @@ done: if (newblks[i] != oip->i_db[i]) panic("itrunc2"); if (length == 0 && - (ovp->v_dirtyblkhd.lh_first || ovp->v_cleanblkhd.lh_first)) + (vnode_hasdirtyblks(ovp) || vnode_hascleanblks(ovp))) panic("itrunc3"); #endif /* DIAGNOSTIC */ /* @@ -471,10 +464,10 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) ufs_daddr_t *copy, nb, nlbn, last; long blkcount, factor; int nblocks, blocksreleased = 0; - int error = 0, allerror = 0; + errno_t error = 0, allerror = 0; int devBlockSize=0; -#if REV_ENDIAN_FS struct mount *mp=vp->v_mount; +#if REV_ENDIAN_FS int rev_endian=(mp->mnt_flag & MNT_REVEND); #endif /* REV_ENDIAN_FS */ @@ -489,7 +482,8 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) last = lastbn; if (lastbn > 0) last /= factor; - VOP_DEVBLOCKSIZE(ip->i_devvp,&devBlockSize); + + devBlockSize = vfs_devblocksize(mp); nblocks = btodb(fs->fs_bsize, devBlockSize); /* Doing a MALLOC here is asking for trouble. We can still @@ -497,49 +491,55 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) * low on memory and block in MALLOC */ - tbp = geteblk(fs->fs_bsize); - copy = (ufs_daddr_t *)tbp->b_data; + tbp = buf_geteblk(fs->fs_bsize); + copy = (ufs_daddr_t *)buf_dataptr(tbp); /* * Get buffer of block pointers, zero those entries corresponding * to blocks to be free'd, and update on disk copy first. Since * double(triple) indirect before single(double) indirect, calls * to bmap on these blocks will fail. However, we already have - * the on disk address, so we have to set the b_blkno field - * explicitly instead of letting bread do everything for us. + * the on disk address, so we have to set the blkno field + * explicitly instead of letting buf_bread do everything for us. */ vp = ITOV(ip); - bp = getblk(vp, lbn, (int)fs->fs_bsize, 0, 0, BLK_META); - if (bp->b_flags & (B_DONE | B_DELWRI)) { + bp = buf_getblk(vp, (daddr64_t)((unsigned)lbn), (int)fs->fs_bsize, 0, 0, BLK_META); + + if (buf_valid(bp)) { /* Braces must be here in case trace evaluates to nothing. */ trace(TR_BREADHIT, pack(vp, fs->fs_bsize), lbn); } else { trace(TR_BREADMISS, pack(vp, fs->fs_bsize), lbn); current_proc()->p_stats->p_ru.ru_inblock++; /* pay for read */ - bp->b_flags |= B_READ; - if (bp->b_bcount > bp->b_bufsize) + buf_setflags(bp, B_READ); + if (buf_count(bp) > buf_size(bp)) panic("ffs_indirtrunc: bad buffer size"); - bp->b_blkno = dbn; - VOP_STRATEGY(bp); - error = biowait(bp); + buf_setblkno(bp, (daddr64_t)((unsigned)dbn)); + VNOP_STRATEGY(bp); + error = buf_biowait(bp); } if (error) { - brelse(bp); + buf_brelse(bp); *countp = 0; - brelse(tbp); - return (error); + buf_brelse(tbp); + return ((int)error); } - bap = (ufs_daddr_t *)bp->b_data; + bap = (ufs_daddr_t *)buf_dataptr(bp); bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize); bzero((caddr_t)&bap[last + 1], (u_int)(NINDIR(fs) - (last + 1)) * sizeof (ufs_daddr_t)); if (last == -1) - bp->b_flags |= B_INVAL; - error = bwrite(bp); - if (error) - allerror = error; + buf_markinvalid(bp); + if (last != -1 && (vp)->v_mount->mnt_flag & MNT_ASYNC) { + error = 0; + buf_bdwrite(bp); + } else { + error = buf_bwrite(bp); + if (error) + allerror = error; + } bap = copy; /* @@ -549,7 +549,7 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) i--, nlbn += factor) { #if REV_ENDIAN_FS if (rev_endian) - nb = NXSwapLong(bap[i]); + nb = OSSwapInt32(bap[i]); else { #endif /* REV_ENDIAN_FS */ nb = bap[i]; @@ -575,7 +575,7 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) last = lastbn % factor; #if REV_ENDIAN_FS if (rev_endian) - nb = NXSwapLong(bap[i]); + nb = OSSwapInt32(bap[i]); else { #endif /* REV_ENDIAN_FS */ nb = bap[i]; @@ -589,8 +589,8 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) blocksreleased += blkcount; } } - brelse(tbp); + buf_brelse(tbp); *countp = blocksreleased; - return (allerror); + return ((int)allerror); }