X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/1c79356b52d46aa6b508fb032f5ae709b1f2897b..8ad349bb6ed4a0be06e34c92be0d98b92e078db4:/bsd/ufs/ffs/ffs_alloc.c diff --git a/bsd/ufs/ffs/ffs_alloc.c b/bsd/ufs/ffs/ffs_alloc.c index c6e462097..e74e7423c 100644 --- a/bsd/ufs/ffs/ffs_alloc.c +++ b/bsd/ufs/ffs/ffs_alloc.c @@ -1,23 +1,31 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ + * 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. 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 + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ */ /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ /* @@ -59,12 +67,14 @@ #include #include -#include +#include #include -#include -#include +#include +#include +#include #include #include +#include #include @@ -81,18 +91,18 @@ extern u_long nextgennumber; -static ufs_daddr_t ffs_alloccg __P((struct inode *, int, ufs_daddr_t, int)); -static ufs_daddr_t ffs_alloccgblk __P((struct fs *, struct cg *, ufs_daddr_t)); -static ufs_daddr_t ffs_clusteralloc __P((struct inode *, int, ufs_daddr_t, - int)); -static ino_t ffs_dirpref __P((struct fs *)); -static ufs_daddr_t ffs_fragextend __P((struct inode *, int, long, int, int)); -static void ffs_fserr __P((struct fs *, u_int, char *)); +static ufs_daddr_t ffs_alloccg(struct inode *, int, ufs_daddr_t, int); +static ufs_daddr_t ffs_alloccgblk(struct fs *, struct cg *, ufs_daddr_t); +static ufs_daddr_t ffs_clusteralloc(struct inode *, int, ufs_daddr_t, int); +static ino_t ffs_dirpref(struct inode *); +static ufs_daddr_t ffs_fragextend(struct inode *, int, long, int, int); +static void ffs_fserr(struct fs *, u_int, char *); static u_long ffs_hashalloc - __P((struct inode *, int, long, int, u_int32_t (*)())); -static ino_t ffs_nodealloccg __P((struct inode *, int, ufs_daddr_t, int)); -static ufs_daddr_t ffs_mapsearch __P((struct fs *, struct cg *, ufs_daddr_t, - int)); + (struct inode *, int, long, int, u_int32_t (*)()); +static ino_t ffs_nodealloccg(struct inode *, int, ufs_daddr_t, int); +static ufs_daddr_t ffs_mapsearch(struct fs *, struct cg *, ufs_daddr_t, int); +static void ffs_clusteracct + (struct fs *fs, struct cg *cgp, ufs_daddr_t blkno, int cnt); /* * Allocate a block in the file system. @@ -117,7 +127,7 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) register struct inode *ip; ufs_daddr_t lbn, bpref; int size; - struct ucred *cred; + kauth_cred_t cred; ufs_daddr_t *bnp; { register struct fs *fs; @@ -137,11 +147,11 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) #endif /* DIAGNOSTIC */ if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) goto nospace; - if (cred->cr_uid != 0 && freespace(fs, fs->fs_minfree) <= 0) + if (suser(cred, NULL) && freespace(fs, fs->fs_minfree) <= 0) goto nospace; - VOP_DEVBLOCKSIZE(ip->i_devvp,&devBlockSize); + devBlockSize = vfs_devblocksize(vnode_mount(ITOV(ip))); #if QUOTA - if (error = chkdq(ip, (long)btodb(size, devBlockSize), cred, 0)) + if (error = chkdq(ip, (int64_t)size, cred, 0)) return (error); #endif /* QUOTA */ if (bpref >= fs->fs_size) @@ -162,10 +172,10 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) /* * Restore user's disk quota because allocation failed. */ - (void) chkdq(ip, (long)-btodb(size, devBlockSize), cred, FORCE); + (void) chkdq(ip, (int64_t)-size, cred, FORCE); #endif /* QUOTA */ nospace: - ffs_fserr(fs, cred->cr_uid, "file system full"); + ffs_fserr(fs, kauth_cred_getuid(cred), "file system full"); uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); return (ENOSPC); } @@ -183,7 +193,7 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) ufs_daddr_t lbprev; ufs_daddr_t bpref; int osize, nsize; - struct ucred *cred; + kauth_cred_t cred; struct buf **bpp; { register struct fs *fs; @@ -205,7 +215,7 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) if (cred == NOCRED) panic("ffs_realloccg: missing credential\n"); #endif /* DIAGNOSTIC */ - if (cred->cr_uid != 0 && freespace(fs, fs->fs_minfree) <= 0) + if (suser(cred, NULL) != 0 && freespace(fs, fs->fs_minfree) <= 0) goto nospace; if ((bprev = ip->i_db[lbprev]) == 0) { printf("dev = 0x%x, bsize = %d, bprev = %d, fs = %s\n", @@ -215,16 +225,16 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) /* * Allocate the extra space in the buffer. */ - if (error = bread(ITOV(ip), lbprev, osize, NOCRED, &bp)) { - brelse(bp); + if (error = (int)buf_bread(ITOV(ip), (daddr64_t)((unsigned)lbprev), osize, NOCRED, &bp)) { + buf_brelse(bp); return (error); } - VOP_DEVBLOCKSIZE(ip->i_devvp,&devBlockSize); + devBlockSize = vfs_devblocksize(vnode_mount(ITOV(ip))); #if QUOTA - if (error = chkdq(ip, (long)btodb(nsize - osize, devBlockSize), cred, 0)) + if (error = chkdq(ip, (int64_t)(nsize - osize), cred, 0)) { - brelse(bp); + buf_brelse(bp); return (error); } #endif /* QUOTA */ @@ -233,13 +243,13 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) */ cg = dtog(fs, bprev); if (bno = ffs_fragextend(ip, cg, (long)bprev, osize, nsize)) { - if (bp->b_blkno != fsbtodb(fs, bno)) + if ((ufs_daddr_t)buf_blkno(bp) != fsbtodb(fs, bno)) panic("bad blockno"); ip->i_blocks += btodb(nsize - osize, devBlockSize); ip->i_flag |= IN_CHANGE | IN_UPDATE; allocbuf(bp, nsize); - bp->b_flags |= B_DONE; - bzero((char *)bp->b_data + osize, (u_int)nsize - osize); + buf_setflags(bp, B_DONE); + bzero((char *)buf_dataptr(bp) + osize, (u_int)buf_size(bp) - osize); *bpp = bp; return (0); } @@ -294,7 +304,7 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) bno = (ufs_daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request, (u_int32_t (*)())ffs_alloccg); if (bno > 0) { - bp->b_blkno = fsbtodb(fs, bno); + buf_setblkno(bp, (daddr64_t)((unsigned)fsbtodb(fs, bno))); ffs_blkfree(ip, bprev, (long)osize); if (nsize < request) ffs_blkfree(ip, bno + numfrags(fs, nsize), @@ -302,8 +312,8 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) ip->i_blocks += btodb(nsize - osize, devBlockSize); ip->i_flag |= IN_CHANGE | IN_UPDATE; allocbuf(bp, nsize); - bp->b_flags |= B_DONE; - bzero((char *)bp->b_data + osize, (u_int)nsize - osize); + buf_setflags(bp, B_DONE); + bzero((char *)buf_dataptr(bp) + osize, (u_int)buf_size(bp) - osize); *bpp = bp; return (0); } @@ -311,14 +321,14 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) /* * Restore user's disk quota because allocation failed. */ - (void) chkdq(ip, (long)-btodb(nsize - osize, devBlockSize), cred, FORCE); + (void) chkdq(ip, (int64_t)-(nsize - osize), cred, FORCE); #endif /* QUOTA */ - brelse(bp); + buf_brelse(bp); nospace: /* * no space available */ - ffs_fserr(fs, cred->cr_uid, "file system full"); + ffs_fserr(fs, kauth_cred_getuid(cred), "file system full"); uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); return (ENOSPC); } @@ -342,12 +352,6 @@ nospace: int doasyncfree = 1; int doreallocblks = 1; -int -ffs_reallocblks(ap) - struct vop_reallocblks_args *ap; -{ - return (ENOSPC); -} /* * Allocate an inode in the file system. @@ -365,44 +369,55 @@ ffs_reallocblks(ap) * available inode is located. */ int -ffs_valloc(ap) - struct vop_valloc_args /* { - struct vnode *a_pvp; - int a_mode; - struct ucred *a_cred; - struct vnode **a_vpp; - } */ *ap; +ffs_valloc( + struct vnode *pvp, + mode_t mode, + kauth_cred_t cred, + struct vnode **vpp) + { - register struct vnode *pvp = ap->a_pvp; register struct inode *pip; register struct fs *fs; register struct inode *ip; - mode_t mode = ap->a_mode; + struct timeval tv; ino_t ino, ipref; int cg, error; - *ap->a_vpp = NULL; + *vpp = NULL; pip = VTOI(pvp); fs = pip->i_fs; if (fs->fs_cstotal.cs_nifree == 0) goto noinodes; if ((mode & IFMT) == IFDIR) - ipref = ffs_dirpref(fs); + ipref = ffs_dirpref(pip); else ipref = pip->i_number; if (ipref >= fs->fs_ncg * fs->fs_ipg) ipref = 0; cg = ino_to_cg(fs, ipref); + /* + * Track the number of dirs created one after another + * in a cg without intervening files. + */ + if ((mode & IFMT) == IFDIR) { + if (fs->fs_contigdirs[cg] < 255) + fs->fs_contigdirs[cg]++; + } else { + if (fs->fs_contigdirs[cg] > 0) + fs->fs_contigdirs[cg]--; + } ino = (ino_t)ffs_hashalloc(pip, cg, (long)ipref, mode, ffs_nodealloccg); if (ino == 0) goto noinodes; - error = VFS_VGET(pvp->v_mount, ino, ap->a_vpp); + + error = ffs_vget_internal(pvp->v_mount, ino, vpp, NULL, NULL, mode, 0); if (error) { - VOP_VFREE(pvp, ino, mode); + ffs_vfree(pvp, ino, mode); return (error); } - ip = VTOI(*ap->a_vpp); + ip = VTOI(*vpp); + if (ip->i_mode) { printf("mode = 0%o, inum = %d, fs = %s\n", ip->i_mode, ip->i_number, fs->fs_fsmnt); @@ -417,39 +432,124 @@ ffs_valloc(ap) /* * Set up a new generation number for this inode. */ - if (++nextgennumber < (u_long)time.tv_sec) - nextgennumber = time.tv_sec; + microtime(&tv); + if (++nextgennumber < (u_long)tv.tv_sec) + nextgennumber = tv.tv_sec; ip->i_gen = nextgennumber; return (0); noinodes: - ffs_fserr(fs, ap->a_cred->cr_uid, "out of inodes"); + ffs_fserr(fs, kauth_cred_getuid(cred), "out of inodes"); uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); return (ENOSPC); } /* - * Find a cylinder to place a directory. + * Find a cylinder group to place a directory. * - * The policy implemented by this algorithm is to select from - * among those cylinder groups with above the average number of - * free inodes, the one with the smallest number of directories. + * The policy implemented by this algorithm is to allocate a + * directory inode in the same cylinder group as its parent + * directory, but also to reserve space for its files inodes + * and data. Restrict the number of directories which may be + * allocated one after another in the same cylinder group + * without intervening allocation of files. */ static ino_t -ffs_dirpref(fs) - register struct fs *fs; +ffs_dirpref(pip) + struct inode *pip; { - int cg, minndir, mincg, avgifree; + register struct fs *fs; + int cg, prefcg, dirsize, cgsize; + int avgifree, avgbfree, avgndir, curdirsize; + int minifree, minbfree, maxndir; + int mincg, minndir; + int maxcontigdirs; + fs = pip->i_fs; avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg; - minndir = fs->fs_ipg; - mincg = 0; - for (cg = 0; cg < fs->fs_ncg; cg++) - if (fs->fs_cs(fs, cg).cs_ndir < minndir && - fs->fs_cs(fs, cg).cs_nifree >= avgifree) { - mincg = cg; - minndir = fs->fs_cs(fs, cg).cs_ndir; + avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; + avgndir = fs->fs_cstotal.cs_ndir / fs->fs_ncg; + + /* + * Force allocation in another cg if creating a first level dir. + */ + if (ITOV(pip)->v_flag & VROOT) { +#ifdef __APPLE__ + prefcg = random() % fs->fs_ncg; +#else + prefcg = arc4random() % fs->fs_ncg; +#endif + mincg = prefcg; + minndir = fs->fs_ipg; + for (cg = prefcg; cg < fs->fs_ncg; cg++) + if (fs->fs_cs(fs, cg).cs_ndir < minndir && + fs->fs_cs(fs, cg).cs_nifree >= avgifree && + fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { + mincg = cg; + minndir = fs->fs_cs(fs, cg).cs_ndir; + } + for (cg = 0; cg < prefcg; cg++) + if (fs->fs_cs(fs, cg).cs_ndir < minndir && + fs->fs_cs(fs, cg).cs_nifree >= avgifree && + fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { + mincg = cg; + minndir = fs->fs_cs(fs, cg).cs_ndir; + } + return ((ino_t)(fs->fs_ipg * mincg)); + } + + /* + * Count various limits which used for + * optimal allocation of a directory inode. + */ + maxndir = min(avgndir + fs->fs_ipg / 16, fs->fs_ipg); + minifree = avgifree - fs->fs_ipg / 4; + if (minifree < 0) + minifree = 0; + minbfree = avgbfree - fs->fs_fpg / fs->fs_frag / 4; + if (minbfree < 0) + minbfree = 0; + cgsize = fs->fs_fsize * fs->fs_fpg; + dirsize = fs->fs_avgfilesize * fs->fs_avgfpdir; + curdirsize = avgndir ? (cgsize - avgbfree * fs->fs_bsize) / avgndir : 0; + if (dirsize < curdirsize) + dirsize = curdirsize; + maxcontigdirs = min(cgsize / dirsize, 255); + if (fs->fs_avgfpdir > 0) + maxcontigdirs = min(maxcontigdirs, + fs->fs_ipg / fs->fs_avgfpdir); + if (maxcontigdirs == 0) + maxcontigdirs = 1; + + /* + * Limit number of dirs in one cg and reserve space for + * regular files, but only if we have no deficit in + * inodes or space. + */ + prefcg = ino_to_cg(fs, pip->i_number); + for (cg = prefcg; cg < fs->fs_ncg; cg++) + if (fs->fs_cs(fs, cg).cs_ndir < maxndir && + fs->fs_cs(fs, cg).cs_nifree >= minifree && + fs->fs_cs(fs, cg).cs_nbfree >= minbfree) { + if (fs->fs_contigdirs[cg] < maxcontigdirs) + return ((ino_t)(fs->fs_ipg * cg)); } - return ((ino_t)(fs->fs_ipg * mincg)); + for (cg = 0; cg < prefcg; cg++) + if (fs->fs_cs(fs, cg).cs_ndir < maxndir && + fs->fs_cs(fs, cg).cs_nifree >= minifree && + fs->fs_cs(fs, cg).cs_nbfree >= minbfree) { + if (fs->fs_contigdirs[cg] < maxcontigdirs) + return ((ino_t)(fs->fs_ipg * cg)); + } + /* + * This is a backstop when we have deficit in space. + */ + for (cg = prefcg; cg < fs->fs_ncg; cg++) + if (fs->fs_cs(fs, cg).cs_nifree >= avgifree) + return ((ino_t)(fs->fs_ipg * cg)); + for (cg = 0; cg < prefcg; cg++) + if (fs->fs_cs(fs, cg).cs_nifree >= avgifree) + break; + return ((ino_t)(fs->fs_ipg * cg)); } /* @@ -657,6 +757,7 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) register struct fs *fs; register struct cg *cgp; struct buf *bp; + struct timeval tv; long bno; int frags, bbase; int i, error; @@ -676,13 +777,13 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) return (NULL); } /* read corresponding cylinder group info */ - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); + error = (int)buf_bread(ip->i_devvp, (daddr64_t)((unsigned)fsbtodb(fs, cgtod(fs, cg))), + (int)fs->fs_cgsize, NOCRED, &bp); if (error) { - brelse(bp); + buf_brelse(bp); return (NULL); } - cgp = (struct cg *)bp->b_data; + cgp = (struct cg *)buf_dataptr(bp); #if REV_ENDIAN_FS if (rev_endian) { byte_swap_cgin(cgp, fs); @@ -694,10 +795,11 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - brelse(bp); + buf_brelse(bp); return (NULL); } - cgp->cg_time = time.tv_sec; + microtime(&tv); + cgp->cg_time = tv.tv_sec; bno = dtogd(fs, bprev); for (i = numfrags(fs, osize); i < frags; i++) if (isclr(cg_blksfree(cgp), bno + i)) { @@ -705,7 +807,7 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - brelse(bp); + buf_brelse(bp); return (NULL); } /* @@ -731,7 +833,7 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - bdwrite(bp); + buf_bdwrite(bp); return (bprev); } @@ -751,6 +853,7 @@ ffs_alloccg(ip, cg, bpref, size) register struct fs *fs; register struct cg *cgp; struct buf *bp; + struct timeval tv; register int i; int error, bno, frags, allocsiz; #if REV_ENDIAN_FS @@ -762,13 +865,13 @@ ffs_alloccg(ip, cg, bpref, size) fs = ip->i_fs; if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize) return (NULL); - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); + error = (int)buf_bread(ip->i_devvp, (daddr64_t)((unsigned)fsbtodb(fs, cgtod(fs, cg))), + (int)fs->fs_cgsize, NOCRED, &bp); if (error) { - brelse(bp); + buf_brelse(bp); return (NULL); } - cgp = (struct cg *)bp->b_data; + cgp = (struct cg *)buf_dataptr(bp); #if REV_ENDIAN_FS if (rev_endian) byte_swap_cgin(cgp,fs); @@ -779,17 +882,18 @@ ffs_alloccg(ip, cg, bpref, size) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - brelse(bp); + buf_brelse(bp); return (NULL); } - cgp->cg_time = time.tv_sec; + microtime(&tv); + cgp->cg_time = tv.tv_sec; if (size == fs->fs_bsize) { bno = ffs_alloccgblk(fs, cgp, bpref); #if REV_ENDIAN_FS if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - bdwrite(bp); + buf_bdwrite(bp); return (bno); } /* @@ -811,7 +915,7 @@ ffs_alloccg(ip, cg, bpref, size) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - brelse(bp); + buf_brelse(bp); return (NULL); } bno = ffs_alloccgblk(fs, cgp, bpref); @@ -828,7 +932,7 @@ ffs_alloccg(ip, cg, bpref, size) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - bdwrite(bp); + buf_bdwrite(bp); return (bno); } bno = ffs_mapsearch(fs, cgp, bpref, allocsiz); @@ -837,7 +941,7 @@ ffs_alloccg(ip, cg, bpref, size) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - brelse(bp); + buf_brelse(bp); return (NULL); } for (i = 0; i < frags; i++) @@ -853,7 +957,7 @@ ffs_alloccg(ip, cg, bpref, size) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - bdwrite(bp); + buf_bdwrite(bp); return (cg * fs->fs_fpg + bno); } @@ -1001,10 +1105,10 @@ ffs_clusteralloc(ip, cg, bpref, len) fs = ip->i_fs; if (fs->fs_maxcluster[cg] < len) return (NULL); - if (bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, - NOCRED, &bp)) + if (buf_bread(ip->i_devvp, (daddr64_t)((unsigned)fsbtodb(fs, cgtod(fs, cg))), (int)fs->fs_cgsize, + NOCRED, &bp)) goto fail; - cgp = (struct cg *)bp->b_data; + cgp = (struct cg *)buf_dataptr(bp); #if REV_ENDIAN_FS if (rev_endian) byte_swap_cgin(cgp,fs); @@ -1100,11 +1204,11 @@ ffs_clusteralloc(ip, cg, bpref, len) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - bdwrite(bp); + buf_bdwrite(bp); return (bno); fail: - brelse(bp); + buf_brelse(bp); return (0); } @@ -1127,6 +1231,7 @@ ffs_nodealloccg(ip, cg, ipref, mode) register struct fs *fs; register struct cg *cgp; struct buf *bp; + struct timeval tv; int error, start, len, loc, map, i; #if REV_ENDIAN_FS struct vnode *vp=ITOV(ip); @@ -1137,13 +1242,13 @@ ffs_nodealloccg(ip, cg, ipref, mode) fs = ip->i_fs; if (fs->fs_cs(fs, cg).cs_nifree == 0) return (NULL); - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); + error = (int)buf_bread(ip->i_devvp, (daddr64_t)((unsigned)fsbtodb(fs, cgtod(fs, cg))), + (int)fs->fs_cgsize, NOCRED, &bp); if (error) { - brelse(bp); + buf_brelse(bp); return (NULL); } - cgp = (struct cg *)bp->b_data; + cgp = (struct cg *)buf_dataptr(bp); #if REV_ENDIAN_FS if (rev_endian) byte_swap_cgin(cgp,fs); @@ -1153,11 +1258,12 @@ ffs_nodealloccg(ip, cg, ipref, mode) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - brelse(bp); + buf_brelse(bp); return (NULL); } - cgp->cg_time = time.tv_sec; + microtime(&tv); + cgp->cg_time = tv.tv_sec; if (ipref) { ipref %= fs->fs_ipg; if (isclr(cg_inosused(cgp), ipref)) @@ -1204,7 +1310,7 @@ gotit: if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - bdwrite(bp); + buf_bdwrite(bp); return (cg * fs->fs_ipg + ipref); } @@ -1215,6 +1321,7 @@ gotit: * free map. If a fragment is deallocated, a possible * block reassembly is checked. */ +void ffs_blkfree(ip, bno, size) register struct inode *ip; ufs_daddr_t bno; @@ -1223,6 +1330,7 @@ ffs_blkfree(ip, bno, size) register struct fs *fs; register struct cg *cgp; struct buf *bp; + struct timeval tv; ufs_daddr_t blkno; int i, error, cg, blk, frags, bbase; #if REV_ENDIAN_FS @@ -1230,6 +1338,7 @@ ffs_blkfree(ip, bno, size) struct mount *mp=vp->v_mount; int rev_endian=(mp->mnt_flag & MNT_REVEND); #endif /* REV_ENDIAN_FS */ + fs = ip->i_fs; if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) { printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", @@ -1242,13 +1351,13 @@ ffs_blkfree(ip, bno, size) ffs_fserr(fs, ip->i_uid, "bad block"); return; } - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); + error = (int)buf_bread(ip->i_devvp, (daddr64_t)((unsigned)fsbtodb(fs, cgtod(fs, cg))), + (int)fs->fs_cgsize, NOCRED, &bp); if (error) { - brelse(bp); + buf_brelse(bp); return; } - cgp = (struct cg *)bp->b_data; + cgp = (struct cg *)buf_dataptr(bp); #if REV_ENDIAN_FS if (rev_endian) byte_swap_cgin(cgp,fs); @@ -1258,10 +1367,11 @@ ffs_blkfree(ip, bno, size) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - brelse(bp); + buf_brelse(bp); return; } - cgp->cg_time = time.tv_sec; + microtime(&tv); + cgp->cg_time = tv.tv_sec; bno = dtogd(fs, bno); if (size == fs->fs_bsize) { blkno = fragstoblks(fs, bno); @@ -1327,7 +1437,7 @@ ffs_blkfree(ip, bno, size) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - bdwrite(bp); + buf_bdwrite(bp); } #if DIAGNOSTIC @@ -1358,13 +1468,13 @@ ffs_checkblk(ip, bno, size) } if ((u_int)bno >= fs->fs_size) panic("checkblk: bad block %d", bno); - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, dtog(fs, bno))), - (int)fs->fs_cgsize, NOCRED, &bp); + error = (int)buf_bread(ip->i_devvp, (daddr64_t)((unsigned)fsbtodb(fs, cgtod(fs, dtog(fs, bno)))), + (int)fs->fs_cgsize, NOCRED, &bp); if (error) { - brelse(bp); + buf_brelse(bp); return; } - cgp = (struct cg *)bp->b_data; + cgp = (struct cg *)buf_dataptr(bp); #if REV_ENDIAN_FS if (rev_endian) byte_swap_cgin(cgp,fs); @@ -1374,7 +1484,7 @@ ffs_checkblk(ip, bno, size) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - brelse(bp); + buf_brelse(bp); return; } bno = dtogd(fs, bno); @@ -1392,7 +1502,7 @@ ffs_checkblk(ip, bno, size) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - brelse(bp); + buf_brelse(bp); return (!free); } #endif /* DIAGNOSTIC */ @@ -1403,38 +1513,32 @@ ffs_checkblk(ip, bno, size) * The specified inode is placed back in the free map. */ int -ffs_vfree(ap) - struct vop_vfree_args /* { - struct vnode *a_pvp; - ino_t a_ino; - int a_mode; - } */ *ap; +ffs_vfree(struct vnode *vp, ino_t ino, int mode) { register struct fs *fs; register struct cg *cgp; register struct inode *pip; - ino_t ino = ap->a_ino; struct buf *bp; + struct timeval tv; int error, cg; #if REV_ENDIAN_FS - struct vnode *vp=ap->a_pvp; struct mount *mp=vp->v_mount; int rev_endian=(mp->mnt_flag & MNT_REVEND); #endif /* REV_ENDIAN_FS */ - pip = VTOI(ap->a_pvp); + pip = VTOI(vp); fs = pip->i_fs; if ((u_int)ino >= fs->fs_ipg * fs->fs_ncg) panic("ifree: range: dev = 0x%x, ino = %d, fs = %s\n", pip->i_dev, ino, fs->fs_fsmnt); cg = ino_to_cg(fs, ino); - error = bread(pip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); + error = (int)buf_bread(pip->i_devvp, (daddr64_t)((unsigned)fsbtodb(fs, cgtod(fs, cg))), + (int)fs->fs_cgsize, NOCRED, &bp); if (error) { - brelse(bp); + buf_brelse(bp); return (0); } - cgp = (struct cg *)bp->b_data; + cgp = (struct cg *)buf_dataptr(bp); #if REV_ENDIAN_FS if (rev_endian) byte_swap_cgin(cgp,fs); @@ -1444,10 +1548,11 @@ ffs_vfree(ap) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - brelse(bp); + buf_brelse(bp); return (0); } - cgp->cg_time = time.tv_sec; + microtime(&tv); + cgp->cg_time = tv.tv_sec; ino %= fs->fs_ipg; if (isclr(cg_inosused(cgp), ino)) { printf("dev = 0x%x, ino = %d, fs = %s\n", @@ -1461,7 +1566,7 @@ ffs_vfree(ap) cgp->cg_cs.cs_nifree++; fs->fs_cstotal.cs_nifree++; fs->fs_cs(fs, cg).cs_nifree++; - if ((ap->a_mode & IFMT) == IFDIR) { + if ((mode & IFMT) == IFDIR) { cgp->cg_cs.cs_ndir--; fs->fs_cstotal.cs_ndir--; fs->fs_cs(fs, cg).cs_ndir--; @@ -1471,7 +1576,7 @@ ffs_vfree(ap) if (rev_endian) byte_swap_cgout(cgp,fs); #endif /* REV_ENDIAN_FS */ - bdwrite(bp); + buf_bdwrite(bp); return (0); } @@ -1545,11 +1650,8 @@ ffs_mapsearch(fs, cgp, bpref, allocsiz) * * Cnt == 1 means free; cnt == -1 means allocating. */ -ffs_clusteracct(fs, cgp, blkno, cnt) - struct fs *fs; - struct cg *cgp; - ufs_daddr_t blkno; - int cnt; +static void +ffs_clusteracct(struct fs *fs, struct cg *cgp, ufs_daddr_t blkno, int cnt) { int32_t *sump; int32_t *lp;