X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/00bff950469f77b3e3eef056168c0e6e25ddbe54..80409bdc15459b1562b1e288e45e7bbad4210deb:/usr/src/sys/ufs/ffs/ffs_alloc.c diff --git a/usr/src/sys/ufs/ffs/ffs_alloc.c b/usr/src/sys/ufs/ffs/ffs_alloc.c index 35657be42a..a601d7d3ba 100644 --- a/usr/src/sys/ufs/ffs/ffs_alloc.c +++ b/usr/src/sys/ufs/ffs/ffs_alloc.c @@ -1,44 +1,40 @@ /* - * Copyright (c) 1982, 1986, 1989 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * %sccs.include.redist.c% * - * @(#)ffs_alloc.c 7.17 (Berkeley) %G% + * @(#)ffs_alloc.c 8.1 (Berkeley) %G% */ -#include "param.h" -#include "systm.h" -#include "mount.h" -#include "buf.h" -#include "user.h" -#include "vnode.h" -#include "kernel.h" -#include "syslog.h" -#include "cmap.h" -#include "../ufs/quota.h" -#include "../ufs/inode.h" -#include "../ufs/fs.h" +#include +#include +#include +#include +#include +#include +#include +#include -extern u_long hashalloc(); -extern ino_t ialloccg(); -extern daddr_t alloccg(); -extern daddr_t alloccgblk(); -extern daddr_t fragextend(); -extern daddr_t blkpref(); -extern daddr_t mapsearch(); -extern int inside[], around[]; -extern unsigned char *fragtbl[]; +#include + +#include +#include + +#include +#include + +extern u_long nextgennumber; + +static daddr_t ffs_alloccg __P((struct inode *, int, daddr_t, int)); +static daddr_t ffs_alloccgblk __P((struct fs *, struct cg *, daddr_t)); +static ino_t ffs_dirpref __P((struct fs *)); +static daddr_t ffs_fragextend __P((struct inode *, int, long, int, int)); +static void ffs_fserr __P((struct fs *, u_int, char *)); +static u_long ffs_hashalloc + __P((struct inode *, int, long, int, u_long (*)())); +static ino_t ffs_ialloccg __P((struct inode *, int, daddr_t, int)); +static daddr_t ffs_mapsearch __P((struct fs *, struct cg *, daddr_t, int)); /* * Allocate a block in the file system. @@ -59,25 +55,29 @@ extern unsigned char *fragtbl[]; * 2) quadradically rehash into other cylinder groups, until an * available block is located. */ -alloc(ip, lbn, bpref, size, bnp) +ffs_alloc(ip, lbn, bpref, size, cred, bnp) register struct inode *ip; daddr_t lbn, bpref; int size; + struct ucred *cred; daddr_t *bnp; { daddr_t bno; register struct fs *fs; register struct buf *bp; int cg, error; - struct ucred *cred = u.u_cred; /* XXX */ *bnp = 0; fs = ip->i_fs; +#ifdef DIAGNOSTIC if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) { printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); - panic("alloc: bad size"); + panic("ffs_alloc: bad size"); } + if (cred == NOCRED) + panic("ffs_alloc: missing credential\n"); +#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) @@ -92,16 +92,22 @@ alloc(ip, lbn, bpref, size, bnp) cg = itog(fs, ip->i_number); else cg = dtog(fs, bpref); - bno = (daddr_t)hashalloc(ip, cg, (long)bpref, size, - (u_long (*)())alloccg); + bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, size, + (u_long (*)())ffs_alloccg); if (bno > 0) { ip->i_blocks += btodb(size); ip->i_flag |= IUPD|ICHG; *bnp = bno; return (0); } +#ifdef QUOTA + /* + * Restore user's disk quota because allocation failed. + */ + (void) chkdq(ip, (long)-btodb(size), cred, FORCE); +#endif nospace: - fserr(fs, "file system full"); + ffs_fserr(fs, cred->cr_uid, "file system full"); uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); return (ENOSPC); } @@ -114,39 +120,39 @@ nospace: * the original block. Failing that, the regular block allocator is * invoked to get an appropriate block. */ -realloccg(ip, lbprev, bpref, osize, nsize, bpp) +ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) register struct inode *ip; - off_t lbprev; + daddr_t lbprev; daddr_t bpref; int osize, nsize; + struct ucred *cred; struct buf **bpp; { register struct fs *fs; struct buf *bp, *obp; - int cg, request; - daddr_t bprev, bno, bn; - int i, error, count; - struct ucred *cred = u.u_cred; /* XXX */ + int cg, request, error; + daddr_t bprev, bno; *bpp = 0; fs = ip->i_fs; +#ifdef DIAGNOSTIC if ((unsigned)osize > fs->fs_bsize || fragoff(fs, osize) != 0 || (unsigned)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) { - printf("dev = 0x%x, bsize = %d, osize = %d, nsize = %d, fs = %s\n", + printf( + "dev = 0x%x, bsize = %d, osize = %d, nsize = %d, fs = %s\n", ip->i_dev, fs->fs_bsize, osize, nsize, fs->fs_fsmnt); - panic("realloccg: bad size"); + panic("ffs_realloccg: bad size"); } + if (cred == NOCRED) + panic("ffs_realloccg: missing credential\n"); +#endif /* DIAGNOSTIC */ if (cred->cr_uid != 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", ip->i_dev, fs->fs_bsize, bprev, fs->fs_fsmnt); - panic("realloccg: bad bprev"); + panic("ffs_realloccg: bad bprev"); } -#ifdef QUOTA - if (error = chkdq(ip, (long)btodb(nsize - osize), cred, 0)) - return (error); -#endif /* * Allocate the extra space in the buffer. */ @@ -154,18 +160,24 @@ realloccg(ip, lbprev, bpref, osize, nsize, bpp) brelse(bp); return (error); } - brealloc(bp, nsize); - bp->b_flags |= B_DONE; - bzero(bp->b_un.b_addr + osize, (unsigned)nsize - osize); +#ifdef QUOTA + if (error = chkdq(ip, (long)btodb(nsize - osize), cred, 0)) { + brelse(bp); + return (error); + } +#endif /* * Check for extension in the existing location. */ cg = dtog(fs, bprev); - if (bno = fragextend(ip, cg, (long)bprev, osize, nsize)) { + if (bno = ffs_fragextend(ip, cg, (long)bprev, osize, nsize)) { if (bp->b_blkno != fsbtodb(fs, bno)) panic("bad blockno"); ip->i_blocks += btodb(nsize - osize); ip->i_flag |= IUPD|ICHG; + allocbuf(bp, nsize); + bp->b_flags |= B_DONE; + bzero(bp->b_un.b_addr + osize, (unsigned)nsize - osize); *bpp = bp; return (0); } @@ -194,14 +206,14 @@ realloccg(ip, lbprev, bpref, osize, nsize, bpp) break; case FS_OPTTIME: /* - * At this point we have discovered a file that is trying - * to grow a small fragment to a larger fragment. To save - * time, we allocate a full sized block, then free the - * unused portion. If the file continues to grow, the - * `fragextend' call above will be able to grow it in place - * without further copying. If aberrant programs cause - * disk fragmentation to grow within 2% of the free reserve, - * we choose to begin optimizing for space. + * At this point we have discovered a file that is trying to + * grow a small fragment to a larger fragment. To save time, + * we allocate a full sized block, then free the unused portion. + * If the file continues to grow, the `ffs_fragextend' call + * above will be able to grow it in place without further + * copying. If aberrant programs cause disk fragmentation to + * grow within 2% of the free reserve, we choose to begin + * optimizing for space. */ request = fs->fs_bsize; if (fs->fs_cstotal.cs_nffree < @@ -214,17 +226,16 @@ realloccg(ip, lbprev, bpref, osize, nsize, bpp) default: printf("dev = 0x%x, optim = %d, fs = %s\n", ip->i_dev, fs->fs_optim, fs->fs_fsmnt); - panic("realloccg: bad optim"); + panic("ffs_realloccg: bad optim"); /* NOTREACHED */ } - bno = (daddr_t)hashalloc(ip, cg, (long)bpref, request, - (u_long (*)())alloccg); + bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request, + (u_long (*)())ffs_alloccg); if (bno > 0) { #ifdef SECSIZE obp = bread(ip->i_dev, fsbtodb(fs, bprev), osize, fs->fs_dbsize); #else SECSIZE - bp->b_blkno = bn = fsbtodb(fs, bno); count = howmany(osize, CLBYTES); for (i = 0; i < count; i++) #ifdef SECSIZE @@ -232,21 +243,30 @@ realloccg(ip, lbprev, bpref, osize, nsize, bpp) #else SECSIZE munhash(ip->i_dev, bn + i * CLBYTES / DEV_BSIZE); #endif SECSIZE - blkfree(ip, bprev, (off_t)osize); + ffs_blkfree(ip, bprev, (long)osize); if (nsize < request) - blkfree(ip, bno + numfrags(fs, nsize), - (off_t)(request - nsize)); + ffs_blkfree(ip, bno + numfrags(fs, nsize), + (long)(request - nsize)); ip->i_blocks += btodb(nsize - osize); ip->i_flag |= IUPD|ICHG; + allocbuf(bp, nsize); + bp->b_flags |= B_DONE; + bzero(bp->b_un.b_addr + osize, (unsigned)nsize - osize); *bpp = bp; return (0); } +#ifdef QUOTA + /* + * Restore user's disk quota because allocation failed. + */ + (void) chkdq(ip, (long)-btodb(nsize - osize), cred, FORCE); +#endif brelse(bp); nospace: /* * no space available */ - fserr(fs, "file system full"); + ffs_fserr(fs, cred->cr_uid, "file system full"); uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); return (ENOSPC); } @@ -254,9 +274,9 @@ nospace: /* * Allocate an inode in the file system. * - * A preference may be optionally specified. If a preference is given - * the following hierarchy is used to allocate an inode: - * 1) allocate the requested inode. + * If allocating a directory, use ffs_dirpref to select the inode. + * If allocating in a directory, the following hierarchy is followed: + * 1) allocate the preferred inode. * 2) allocate an inode in the same cylinder group. * 3) quadradically rehash into other cylinder groups, until an * available inode is located. @@ -266,38 +286,48 @@ nospace: * 2) quadradically rehash into other cylinder groups, until an * available inode is located. */ -ialloc(pip, ipref, mode, cred, ipp) - register struct inode *pip; - ino_t ipref; - int mode; - struct ucred *cred; - struct inode **ipp; +ffs_valloc(ap) + struct vop_valloc_args /* { + struct vnode *a_pvp; + int a_mode; + struct ucred *a_cred; + struct vnode **a_vpp; + } */ *ap; { - ino_t ino; + 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; + ino_t ino, ipref; int cg, error; - *ipp = 0; + *ap->a_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); + else + ipref = pip->i_number; if (ipref >= fs->fs_ncg * fs->fs_ipg) ipref = 0; cg = itog(fs, ipref); - ino = (ino_t)hashalloc(pip, cg, (long)ipref, mode, ialloccg); + ino = (ino_t)ffs_hashalloc(pip, cg, (long)ipref, mode, ffs_ialloccg); if (ino == 0) goto noinodes; - error = iget(pip, ino, ipp); + error = VFS_VGET(pvp->v_mount, ino, ap->a_vpp); if (error) { - ifree(pip, ino, mode); + VOP_VFREE(pvp, ino, mode); return (error); } - ip = *ipp; + ip = VTOI(*ap->a_vpp); if (ip->i_mode) { printf("mode = 0%o, inum = %d, fs = %s\n", ip->i_mode, ip->i_number, fs->fs_fsmnt); - panic("ialloc: dup alloc"); + panic("ffs_valloc: dup alloc"); } if (ip->i_blocks) { /* XXX */ printf("free inode %s/%d had %d blocks\n", @@ -313,7 +343,7 @@ ialloc(pip, ipref, mode, cred, ipp) ip->i_gen = nextgennumber; return (0); noinodes: - fserr(fs, "out of inodes"); + ffs_fserr(fs, ap->a_cred->cr_uid, "out of inodes"); uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); return (ENOSPC); } @@ -325,8 +355,8 @@ noinodes: * among those cylinder groups with above the average number of * free inodes, the one with the smallest number of directories. */ -ino_t -dirpref(fs) +static ino_t +ffs_dirpref(fs) register struct fs *fs; { int cg, minndir, mincg, avgifree; @@ -370,7 +400,7 @@ dirpref(fs) * schedule another I/O transfer. */ daddr_t -blkpref(ip, lbn, indx, bap) +ffs_blkpref(ip, lbn, indx, bap) struct inode *ip; daddr_t lbn; int indx; @@ -416,9 +446,8 @@ blkpref(ip, lbn, indx, bap) * requested rotationally delayed by fs_rotdelay milliseconds. */ nextblk = bap[indx - 1] + fs->fs_frag; - if (indx > fs->fs_maxcontig && - bap[indx - fs->fs_maxcontig] + blkstofrags(fs, fs->fs_maxcontig) - != nextblk) + if (indx < fs->fs_maxcontig || bap[indx - fs->fs_maxcontig] + + blkstofrags(fs, fs->fs_maxcontig) != nextblk) return (nextblk); if (fs->fs_rotdelay != 0) /* @@ -441,8 +470,8 @@ blkpref(ip, lbn, indx, bap) * 3) brute force search for a free block. */ /*VARARGS5*/ -u_long -hashalloc(ip, cg, pref, size, allocator) +static u_long +ffs_hashalloc(ip, cg, pref, size, allocator) struct inode *ip; int cg; long pref; @@ -494,8 +523,8 @@ hashalloc(ip, cg, pref, size, allocator) * Check to see if the necessary fragments are available, and * if they are, allocate them. */ -daddr_t -fragextend(ip, cg, bprev, osize, nsize) +static daddr_t +ffs_fragextend(ip, cg, bprev, osize, nsize) struct inode *ip; int cg; long bprev; @@ -558,7 +587,7 @@ fragextend(ip, cg, bprev, osize, nsize) fs->fs_cstotal.cs_nffree--; fs->fs_cs(fs, cg).cs_nffree--; } - fs->fs_fmod++; + fs->fs_fmod = 1; bdwrite(bp); return (bprev); } @@ -569,8 +598,8 @@ fragextend(ip, cg, bprev, osize, nsize) * Check to see if a block of the apprpriate size is available, * and if it is, allocate it. */ -daddr_t -alloccg(ip, cg, bpref, size) +static daddr_t +ffs_alloccg(ip, cg, bpref, size) struct inode *ip; int cg; daddr_t bpref; @@ -604,7 +633,7 @@ alloccg(ip, cg, bpref, size) } cgp->cg_time = time.tv_sec; if (size == fs->fs_bsize) { - bno = alloccgblk(fs, cgp, bpref); + bno = ffs_alloccgblk(fs, cgp, bpref); bdwrite(bp); return (bno); } @@ -626,7 +655,7 @@ alloccg(ip, cg, bpref, size) brelse(bp); return (NULL); } - bno = alloccgblk(fs, cgp, bpref); + bno = ffs_alloccgblk(fs, cgp, bpref); bpref = dtogd(fs, bno); for (i = frags; i < fs->fs_frag; i++) setbit(cg_blksfree(cgp), bpref + i); @@ -634,12 +663,12 @@ alloccg(ip, cg, bpref, size) cgp->cg_cs.cs_nffree += i; fs->fs_cstotal.cs_nffree += i; fs->fs_cs(fs, cg).cs_nffree += i; - fs->fs_fmod++; + fs->fs_fmod = 1; cgp->cg_frsum[i]++; bdwrite(bp); return (bno); } - bno = mapsearch(fs, cgp, bpref, allocsiz); + bno = ffs_mapsearch(fs, cgp, bpref, allocsiz); if (bno < 0) { brelse(bp); return (NULL); @@ -649,7 +678,7 @@ alloccg(ip, cg, bpref, size) cgp->cg_cs.cs_nffree -= frags; fs->fs_cstotal.cs_nffree -= frags; fs->fs_cs(fs, cg).cs_nffree -= frags; - fs->fs_fmod++; + fs->fs_fmod = 1; cgp->cg_frsum[allocsiz]--; if (frags != allocsiz) cgp->cg_frsum[allocsiz - frags]++; @@ -668,8 +697,8 @@ alloccg(ip, cg, bpref, size) * Note that this routine only allocates fs_bsize blocks; these * blocks may be fragmented by the routine that allocates them. */ -daddr_t -alloccgblk(fs, cgp, bpref) +static daddr_t +ffs_alloccgblk(fs, cgp, bpref) register struct fs *fs; register struct cg *cgp; daddr_t bpref; @@ -688,7 +717,7 @@ alloccgblk(fs, cgp, bpref) /* * if the requested block is available, use it */ - if (isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bpref))) { + if (ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bpref))) { bno = bpref; goto gotit; } @@ -700,10 +729,13 @@ alloccgblk(fs, cgp, bpref) goto norot; if (fs->fs_cpc == 0) { /* - * block layout info is not available, so just have - * to take any block in this cylinder. + * Block layout information is not available. + * Leaving bpref unchanged means we take the + * next available free block following the one + * we just allocated. Hopefully this will at + * least hit a track cache on drives of unknown + * geometry (e.g. SCSI). */ - bpref = howmany(fs->fs_spc * cylno, NSPF(fs)); goto norot; } /* @@ -730,10 +762,10 @@ alloccgblk(fs, cgp, bpref) if (fs_postbl(fs, pos)[i] == -1) { printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt); - panic("alloccgblk: cyl groups corrupted"); + panic("ffs_alloccgblk: cyl groups corrupted"); } for (i = fs_postbl(fs, pos)[i];; ) { - if (isblock(fs, cg_blksfree(cgp), bno + i)) { + if (ffs_isblock(fs, cg_blksfree(cgp), bno + i)) { bno = blkstofrags(fs, (bno + i)); goto gotit; } @@ -744,26 +776,26 @@ alloccgblk(fs, cgp, bpref) i += delta; } printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt); - panic("alloccgblk: can't find blk in cyl"); + panic("ffs_alloccgblk: can't find blk in cyl"); } norot: /* * no blocks in the requested cylinder, so take next * available one in this cylinder group. */ - bno = mapsearch(fs, cgp, bpref, (int)fs->fs_frag); + bno = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag); if (bno < 0) return (NULL); cgp->cg_rotor = bno; gotit: - clrblock(fs, cg_blksfree(cgp), (long)fragstoblks(fs, bno)); + ffs_clrblock(fs, cg_blksfree(cgp), (long)fragstoblks(fs, bno)); cgp->cg_cs.cs_nbfree--; fs->fs_cstotal.cs_nbfree--; fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; cylno = cbtocylno(fs, bno); cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--; cg_blktot(cgp)[cylno]--; - fs->fs_fmod++; + fs->fs_fmod = 1; return (cgp->cg_cgx * fs->fs_fpg + bno); } @@ -776,8 +808,8 @@ gotit: * 2) allocate the next available inode after the requested * inode in the specified cylinder group. */ -ino_t -ialloccg(ip, cg, ipref, mode) +static ino_t +ffs_ialloccg(ip, cg, ipref, mode) struct inode *ip; int cg; daddr_t ipref; @@ -823,7 +855,7 @@ ialloccg(ip, cg, ipref, mode) if (loc == 0) { printf("cg = %s, irotor = %d, fs = %s\n", cg, cgp->cg_irotor, fs->fs_fsmnt); - panic("ialloccg: map corrupted"); + panic("ffs_ialloccg: map corrupted"); /* NOTREACHED */ } } @@ -837,14 +869,14 @@ ialloccg(ip, cg, ipref, mode) } } printf("fs = %s\n", fs->fs_fsmnt); - panic("ialloccg: block not in map"); + panic("ffs_ialloccg: block not in map"); /* NOTREACHED */ gotit: setbit(cg_inosused(cgp), ipref); cgp->cg_cs.cs_nifree--; fs->fs_cstotal.cs_nifree--; fs->fs_cs(fs, cg).cs_nifree--; - fs->fs_fmod++; + fs->fs_fmod = 1; if ((mode & IFMT) == IFDIR) { cgp->cg_cs.cs_ndir++; fs->fs_cstotal.cs_ndir++; @@ -861,10 +893,10 @@ gotit: * free map. If a fragment is deallocated, a possible * block reassembly is checked. */ -blkfree(ip, bno, size) +ffs_blkfree(ip, bno, size) register struct inode *ip; daddr_t bno; - off_t size; + long size; { register struct fs *fs; register struct cg *cgp; @@ -879,8 +911,9 @@ blkfree(ip, bno, size) panic("blkfree: bad size"); } cg = dtog(fs, bno); - if (badblock(fs, bno)) { + if ((unsigned)bno >= fs->fs_size) { printf("bad block %d, ino %d\n", bno, ip->i_number); + ffs_fserr(fs, ip->i_uid, "bad block"); return; } #ifdef SECSIZE @@ -902,12 +935,12 @@ blkfree(ip, bno, size) cgp->cg_time = time.tv_sec; bno = dtogd(fs, bno); if (size == fs->fs_bsize) { - if (isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno))) { + if (ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno))) { printf("dev = 0x%x, block = %d, fs = %s\n", ip->i_dev, bno, fs->fs_fsmnt); panic("blkfree: freeing free block"); } - setblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno)); + ffs_setblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno)); cgp->cg_cs.cs_nbfree++; fs->fs_cstotal.cs_nbfree++; fs->fs_cs(fs, cg).cs_nbfree++; @@ -920,7 +953,7 @@ blkfree(ip, bno, size) * decrement the counts associated with the old frags */ blk = blkmap(fs, cg_blksfree(cgp), bbase); - fragacct(fs, blk, cgp->cg_frsum, -1); + ffs_fragacct(fs, blk, cgp->cg_frsum, -1); /* * deallocate the fragment */ @@ -940,11 +973,11 @@ blkfree(ip, bno, size) * add back in counts associated with the new frags */ blk = blkmap(fs, cg_blksfree(cgp), bbase); - fragacct(fs, blk, cgp->cg_frsum, 1); + ffs_fragacct(fs, blk, cgp->cg_frsum, 1); /* * if a complete block has been reassembled, account for it */ - if (isblock(fs, cg_blksfree(cgp), + if (ffs_isblock(fs, cg_blksfree(cgp), (daddr_t)fragstoblks(fs, bbase))) { cgp->cg_cs.cs_nffree -= fs->fs_frag; fs->fs_cstotal.cs_nffree -= fs->fs_frag; @@ -957,7 +990,7 @@ blkfree(ip, bno, size) cg_blktot(cgp)[i]++; } } - fs->fs_fmod++; + fs->fs_fmod = 1; bdwrite(bp); } @@ -966,45 +999,50 @@ blkfree(ip, bno, size) * * The specified inode is placed back in the free map. */ -ifree(ip, ino, mode) - struct inode *ip; - ino_t ino; - int mode; +int +ffs_vfree(ap) + struct vop_vfree_args /* { + struct vnode *a_pvp; + ino_t a_ino; + int a_mode; + } */ *ap; { register struct fs *fs; register struct cg *cgp; + register struct inode *pip; + ino_t ino = ap->a_ino; struct buf *bp; int error, cg; - fs = ip->i_fs; - if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg) { - printf("dev = 0x%x, ino = %d, fs = %s\n", - ip->i_dev, ino, fs->fs_fsmnt); - panic("ifree: range"); - } + pip = VTOI(ap->a_pvp); + 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 = itog(fs, ino); #ifdef SECSIZE bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, fs->fs_dbsize); #else SECSIZE - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), + error = bread(pip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, NOCRED, &bp); if (error) { brelse(bp); - return; + return (0); } #endif SECSIZE cgp = bp->b_un.b_cg; if (!cg_chkmagic(cgp)) { brelse(bp); - return; + return (0); } cgp->cg_time = time.tv_sec; ino %= fs->fs_ipg; if (isclr(cg_inosused(cgp), ino)) { printf("dev = 0x%x, ino = %d, fs = %s\n", - ip->i_dev, ino, fs->fs_fsmnt); - panic("ifree: freeing free inode"); + pip->i_dev, ino, fs->fs_fsmnt); + if (fs->fs_ronly == 0) + panic("ifree: freeing free inode"); } clrbit(cg_inosused(cgp), ino); if (ino < cgp->cg_irotor) @@ -1012,13 +1050,14 @@ ifree(ip, ino, mode) cgp->cg_cs.cs_nifree++; fs->fs_cstotal.cs_nifree++; fs->fs_cs(fs, cg).cs_nifree++; - if ((mode & IFMT) == IFDIR) { + if ((ap->a_mode & IFMT) == IFDIR) { cgp->cg_cs.cs_ndir--; fs->fs_cstotal.cs_ndir--; fs->fs_cs(fs, cg).cs_ndir--; } - fs->fs_fmod++; + fs->fs_fmod = 1; bdwrite(bp); + return (0); } /* @@ -1027,8 +1066,8 @@ ifree(ip, ino, mode) * It is a panic if a request is made to find a block if none are * available. */ -daddr_t -mapsearch(fs, cgp, bpref, allocsiz) +static daddr_t +ffs_mapsearch(fs, cgp, bpref, allocsiz) register struct fs *fs; register struct cg *cgp; daddr_t bpref; @@ -1059,7 +1098,7 @@ mapsearch(fs, cgp, bpref, allocsiz) if (loc == 0) { printf("start = %d, len = %d, fs = %s\n", start, len, fs->fs_fsmnt); - panic("alloccg: map corrupted"); + panic("ffs_alloccg: map corrupted"); /* NOTREACHED */ } } @@ -1082,36 +1121,22 @@ mapsearch(fs, cgp, bpref, allocsiz) } } printf("bno = %d, fs = %s\n", bno, fs->fs_fsmnt); - panic("alloccg: block not in map"); + panic("ffs_alloccg: block not in map"); return (-1); } -/* - * Check that a specified block number is in range. - */ -badblock(fs, bn) - register struct fs *fs; - daddr_t bn; -{ - - if ((unsigned)bn >= fs->fs_size) { - printf("bad block %d, ", bn); - fserr(fs, "bad block"); - return (1); - } - return (0); -} - /* * Fserr prints the name of a file system with an error diagnostic. * * The form of the error message is: * fs: error message */ -fserr(fs, cp) +static void +ffs_fserr(fs, uid, cp) struct fs *fs; + u_int uid; char *cp; { - log(LOG_ERR, "%s: %s\n", fs->fs_fsmnt, cp); + log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp); }