From 2b40767b8a493e25f0d7214f6fc72f5ecdc57732 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 26 May 1994 18:10:27 +0000 Subject: Initial revision --- ufs/alloc.c | 1053 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1053 insertions(+) create mode 100644 ufs/alloc.c (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c new file mode 100644 index 00000000..161edcb8 --- /dev/null +++ b/ufs/alloc.c @@ -0,0 +1,1053 @@ +/* Disk allocation routines + Copyright (C) 1993, 1994 Free Software Foundation + +This file is part of the GNU Hurd. + +The GNU Hurd is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +The GNU Hurd is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the GNU Hurd; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Modified from UCB by Michael I. Bushnell. */ + +/* + * Copyright (c) 1982, 1986, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution is only permitted until one year after the first shipment + * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and + * binary forms are permitted provided that: (1) source distributions retain + * this entire copyright notice and comment, and (2) distributions including + * binaries display the following acknowledgement: This product includes + * software developed by the University of California, Berkeley and its + * contributors'' in the documentation or other materials provided with the + * distribution and in all advertising materials mentioning features or use + * of this software. Neither the name of the University nor the names of + * its contributors may 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 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)ufs_alloc.c 7.20 (Berkeley) 6/28/90 + */ + +#include "ufs.h" +#include "fs.h" +#include "dinode.h" + +#include + +static u_long alloccg (int, daddr_t, int); +static u_long ialloccg (int, daddr_t, int); +static u_long hashalloc (int, long, int, u_long(*)(int, daddr_t, int)); +static daddr_t fragextend (int, long, int, int); +static daddr_t alloccgblk (struct cg *, daddr_t); +static daddr_t mapsearch (struct cg *, daddr_t, int); +static ino_t dirpref (); + +/* These are in tables.c. */ +extern int inside[], around[]; +extern unsigned char *fragtbl[]; + +static spin_lock_t alloclock = SPIN_LOCK_INITIALIZER; + +/* + * Allocate a block in the file system. + * + * The size of the requested block is given, which must be some + * multiple of fs_fsize and <= fs_bsize. + * A preference may be optionally specified. If a preference is given + * the following hierarchy is used to allocate a block: + * 1) allocate the requested block. + * 2) allocate a rotationally optimal block in the same cylinder. + * 3) allocate a block in the same cylinder group. + * 4) quadradically rehash into other cylinder groups, until an + * available block is located. + * If no block preference is given the following heirarchy is used + * to allocate a block: + * 1) allocate a block in the cylinder group that contains the + * inode for the file. + * 2) quadradically rehash into other cylinder groups, until an + * available block is located. + */ +error_t +alloc(struct node *np, + daddr_t lbn, + daddr_t bpref, + int size, + daddr_t *bnp, + struct protid *cred) +{ + int cg; + daddr_t bno; + + *bnp = 0; + assert ("Alloc of bad sized block" && (unsigned) size <= sblock->fs_bsize + && !fragoff(size)); + + spin_lock (&alloclock); + + if (size == sblock->fs_bsize && sblock->fs_cstotal.cs_nbfree == 0) + goto nospace; + if (cred && !diskfs_isuid (0, cred) && freespace(sblock->fs_minfree) <= 0) + goto nospace; + + if (bpref >= sblock->fs_size) + bpref = 0; + if (bpref == 0) + cg = itog(np->dn->number); + else + cg = dtog(bpref); + bno = (daddr_t)hashalloc(cg, (long)bpref, size, alloccg); + + spin_unlock (&alloclock); + + if (bno > 0) + { + np->dn_stat.st_blocks += btodb(size); + np->dn_set_mtime = 1; + np->dn_set_ctime = 1; + *bnp = bno; + return 0; + } + + nospace: + spin_unlock (&alloclock); + printf("file system full\n"); + return (ENOSPC); +} + +/* + * Reallocate a fragment to a bigger size + * + * The number and size of the old block is given, and a preference + * and new size is also specified. The allocator attempts to extend + * the original block. Failing that, the regular block allocator is + * invoked to get an appropriate block. + */ +error_t +realloccg(struct node *np, + daddr_t lbprev, + volatile daddr_t bpref, + int osize, + int nsize, + daddr_t *pbn, + struct protid *cred) +{ + volatile int cg, request; + daddr_t bprev, bno; + error_t error; + + *pbn = 0; + assert ("bad old size" && (unsigned) osize <= sblock->fs_bsize + && !fragoff (osize)); + assert ("bad new size" && (unsigned) nsize <= sblock->fs_bsize + && !fragoff (nsize)); + + spin_lock (&alloclock); + + if (cred && !diskfs_isuid (0, cred) && freespace(sblock->fs_minfree) <= 0) + { + spin_unlock (&alloclock); + goto nospace; + } + + if (error = diskfs_catch_exception ()) + return error; + bprev = dinodes[np->dn->number].di_db[lbprev]; + diskfs_end_catch_exception (); + assert ("old block not allocated" && bprev); + + /* + * Check for extension in the existing location. + */ + cg = dtog(bprev); + if (bno = fragextend(cg, (long)bprev, osize, nsize)) + { + spin_unlock (&alloclock); + assert ("fragextend behaved incorrectly" && bprev == bno); + np->dn_stat.st_blocks += btodb(nsize - osize); + np->dn_set_mtime = 1; + np->dn_set_ctime = 1; + *pbn = bno; + return (0); + } + /* + * Allocate a new disk location. + */ + if (bpref >= sblock->fs_size) + bpref = 0; + switch ((int)sblock->fs_optim) + { + case FS_OPTSPACE: + /* + * Allocate an exact sized fragment. Although this makes + * best use of space, we will waste time relocating it if + * the file continues to grow. If the fragmentation is + * less than half of the minimum free reserve, we choose + * to begin optimizing for time. + */ + request = nsize; + if (sblock->fs_minfree < 5 || + sblock->fs_cstotal.cs_nffree > + sblock->fs_dsize * sblock->fs_minfree / (2 * 100)) + break; + printf("optimization changed from SPACE to TIME\n"); + sblock->fs_optim = FS_OPTTIME; + 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. + */ + request = sblock->fs_bsize; + if (sblock->fs_cstotal.cs_nffree < + sblock->fs_dsize * (sblock->fs_minfree - 2) / 100) + break; + printf("%s: optimization changed from TIME to SPACE\n", + sblock->fs_fsmnt); + sblock->fs_optim = FS_OPTSPACE; + break; + default: + assert ("filesystem opitimazation bad value" && 0); + } + + bno = (daddr_t)hashalloc(cg, (long)bpref, request, + (u_long (*)())alloccg); + + spin_unlock (&alloclock); + + if (bno > 0) + { + blkfree(bprev, (off_t)osize); + if (nsize < request) + blkfree(bno + numfrags(nsize), (off_t)(request - nsize)); + np->dn_stat.st_blocks += btodb (nsize - osize); + np->dn_set_mtime = 1; + np->dn_set_ctime = 1; + *pbn = bno; + return (0); + } + nospace: + /* + * no space available + */ + printf("file system full\n"); + return (ENOSPC); +} + + +/* Implement the diskfs_alloc_node callback from the diskfs library. + See for the interface description. */ +error_t +diskfs_alloc_node(struct node *dir, + mode_t mode, + struct node **npp) +{ + int ino; + struct node *np; + int cg; + error_t error; + int ipref; + + if (S_ISDIR (mode)) + ipref = dirpref (); + else + ipref = dir->dn->number; + + *npp = 0; + + if (sblock->fs_cstotal.cs_nifree == 0) + goto noinodes; + if (ipref >= sblock->fs_ncg * sblock->fs_ipg) + ipref = 0; + cg = itog(ipref); + spin_lock (&alloclock); + ino = (int)hashalloc(cg, (long)ipref, mode, ialloccg); + spin_unlock (&alloclock); + if (ino == 0) + goto noinodes; + if (error = iget(ino, &np)) + return error; + *npp = np; + assert ("duplicate allocation" && !np->dn_stat.st_mode); + if (np->dn_stat.st_blocks) + { + printf("free inode %d had %d blocks\n", ino, np->dn_stat.st_blocks); + np->dn_stat.st_blocks = 0; + np->dn_set_ctime = 1; + } + /* + * Set up a new generation number for this inode. + */ + spin_lock (&gennumberlock); + if (++nextgennumber < (u_long)diskfs_mtime->seconds) + nextgennumber = diskfs_mtime->seconds; + np->dn_stat.st_gen = nextgennumber; + spin_unlock (&gennumberlock); + return (0); + noinodes: + printf("out of inodes\n"); + return (ENOSPC); +} + +/* + * Find a cylinder 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. + */ +static ino_t +dirpref() +{ + int cg, minndir, mincg, avgifree; + + spin_lock (&alloclock); + avgifree = sblock->fs_cstotal.cs_nifree / sblock->fs_ncg; + minndir = sblock->fs_ipg; + mincg = 0; + for (cg = 0; cg < sblock->fs_ncg; cg++) + if (csum[cg].cs_ndir < minndir && csum[cg].cs_nifree >= avgifree) + { + mincg = cg; + minndir = csum[cg].cs_ndir; + } + spin_unlock (&alloclock); + return ((int)(sblock->fs_ipg * mincg)); +} + +/* + * Select the desired position for the next block in a file. The file is + * logically divided into sections. The first section is composed of the + * direct blocks. Each additional section contains fs_maxbpg blocks. + * + * If no blocks have been allocated in the first section, the policy is to + * request a block in the same cylinder group as the inode that describes + * the file. If no blocks have been allocated in any other section, the + * policy is to place the section in a cylinder group with a greater than + * average number of free blocks. An appropriate cylinder group is found + * by using a rotor that sweeps the cylinder groups. When a new group of + * blocks is needed, the sweep begins in the cylinder group following the + * cylinder group from which the previous allocation was made. The sweep + * continues until a cylinder group with greater than the average number + * of free blocks is found. If the allocation is for the first block in an + * indirect block, the information on the previous allocation is unavailable; + * here a best guess is made based upon the logical block number being + * allocated. + * + * If a section is already partially allocated, the policy is to + * contiguously allocate fs_maxcontig blocks. The end of one of these + * contiguous blocks and the beginning of the next is physically separated + * so that the disk head will be in transit between them for at least + * fs_rotdelay milliseconds. This is to allow time for the processor to + * schedule another I/O transfer. + */ +daddr_t +blkpref(struct node *np, + daddr_t lbn, + int indx, + daddr_t *bap) +{ + int cg; + int avgbfree, startcg; + daddr_t nextblk; + + spin_lock (&alloclock); + if (indx % sblock->fs_maxbpg == 0 || bap[indx - 1] == 0) + { + if (lbn < NDADDR) + { + spin_unlock (&alloclock); + cg = itog(np->dn->number); + return (sblock->fs_fpg * cg + sblock->fs_frag); + } + /* + * Find a cylinder with greater than average number of + * unused data blocks. + */ + if (indx == 0 || bap[indx - 1] == 0) + startcg = itog(np->dn->number) + lbn / sblock->fs_maxbpg; + else + startcg = dtog(bap[indx - 1]) + 1; + startcg %= sblock->fs_ncg; + avgbfree = sblock->fs_cstotal.cs_nbfree / sblock->fs_ncg; + for (cg = startcg; cg < sblock->fs_ncg; cg++) + if (csum[cg].cs_nbfree >= avgbfree) + { + spin_unlock (&alloclock); + sblock->fs_cgrotor = cg; + return (sblock->fs_fpg * cg + sblock->fs_frag); + } + for (cg = 0; cg <= startcg; cg++) + if (csum[cg].cs_nbfree >= avgbfree) + { + spin_unlock (&alloclock); + sblock->fs_cgrotor = cg; + return (sblock->fs_fpg * cg + sblock->fs_frag); + } + spin_unlock (&alloclock); + return 0; + } + + spin_unlock (&alloclock); + + /* + * One or more previous blocks have been laid out. If less + * than fs_maxcontig previous blocks are contiguous, the + * next block is requested contiguously, otherwise it is + * requested rotationally delayed by fs_rotdelay milliseconds. + */ + nextblk = bap[indx - 1] + sblock->fs_frag; + if (indx > sblock->fs_maxcontig && + bap[indx - sblock->fs_maxcontig] + blkstofrags(sblock->fs_maxcontig) + != nextblk) + return (nextblk); + if (sblock->fs_rotdelay != 0) + /* + * Here we convert ms of delay to frags as: + * (frags) = (ms) * (rev/sec) * (sect/rev) / + * ((sect/frag) * (ms/sec)) + * then round up to the next block. + */ + nextblk += roundup(sblock->fs_rotdelay * sblock->fs_rps + * sblock->fs_nsect / (NSPF * 1000), sblock->fs_frag); + return (nextblk); +} + +/* + * Implement the cylinder overflow algorithm. + * + * The policy implemented by this algorithm is: + * 1) allocate the block in its requested cylinder group. + * 2) quadradically rehash on the cylinder group number. + * 3) brute force search for a free block. + */ +/*VARARGS5*/ +static u_long +hashalloc(int cg, + long pref, + int size, /* size for data blocks, mode for inodes */ + u_long (*allocator)(int, daddr_t, int)) +{ + long result; + int i, icg = cg; + + /* + * 1: preferred cylinder group + */ + result = (*allocator)(cg, pref, size); + if (result) + return (result); + /* + * 2: quadratic rehash + */ + for (i = 1; i < sblock->fs_ncg; i *= 2) + { + cg += i; + if (cg >= sblock->fs_ncg) + cg -= sblock->fs_ncg; + result = (*allocator)(cg, 0, size); + if (result) + return (result); + } + /* + * 3: brute force search + * Note that we start at i == 2, since 0 was checked initially, + * and 1 is always checked in the quadratic rehash. + */ + cg = (icg + 2) % sblock->fs_ncg; + for (i = 2; i < sblock->fs_ncg; i++) + { + result = (*allocator)(cg, 0, size); + if (result) + return (result); + cg++; + if (cg == sblock->fs_ncg) + cg = 0; + } + return 0; +} + +/* + * Determine whether a fragment can be extended. + * + * Check to see if the necessary fragments are available, and + * if they are, allocate them. + */ +static daddr_t +fragextend(int cg, + long bprev, + int osize, + int nsize) +{ + struct cg *cgp; + long bno; + int frags, bbase; + int i; + + if (csum[cg].cs_nffree < numfrags(nsize - osize)) + return 0; + frags = numfrags(nsize); + bbase = fragnum(bprev); + if (bbase > fragnum((bprev + frags - 1))) + /* cannot extend across a block boundary */ + return 0; + + cgp = (struct cg *) (cgs + sblock->fs_bsize * cg); + + if (diskfs_catch_exception ()) + return 0; /* bogus, but that's what BSD does... */ + + if (!cg_chkmagic(cgp)) + { + printf ("Cylinder group %d bad magic number: %ld/%ld\n", + cg, cgp->cg_magic, ((struct ocg *)(cgp))->cg_magic); + diskfs_end_catch_exception (); + return 0; + } + cgp->cg_time = diskfs_mtime->seconds; + bno = dtogd(bprev); + for (i = numfrags(osize); i < frags; i++) + if (isclr(cg_blksfree(cgp), bno + i)) + { + diskfs_end_catch_exception (); + return 0; + } + + /* + * the current fragment can be extended + * deduct the count on fragment being extended into + * increase the count on the remaining fragment (if any) + * allocate the extended piece + */ + for (i = frags; i < sblock->fs_frag - bbase; i++) + if (isclr(cg_blksfree(cgp), bno + i)) + break; + cgp->cg_frsum[i - numfrags(osize)]--; + if (i != frags) + cgp->cg_frsum[i - frags]++; + for (i = numfrags(osize); i < frags; i++) + { + clrbit(cg_blksfree(cgp), bno + i); + cgp->cg_cs.cs_nffree--; + sblock->fs_cstotal.cs_nffree--; + csum[cg].cs_nffree--; + } + diskfs_end_catch_exception (); + return (bprev); +} + +/* + * Determine whether a block can be allocated. + * + * Check to see if a block of the apprpriate size is available, + * and if it is, allocate it. + */ +static u_long +alloccg(int cg, + volatile daddr_t bpref, + int size) +{ + struct cg *cgp; + int i; + int bno, frags, allocsiz; + + if (csum[cg].cs_nbfree == 0 && size == sblock->fs_bsize) + return 0; + cgp = (struct cg *) (cgs + sblock->fs_bsize * cg); + + if (diskfs_catch_exception ()) + return 0; + + if (!cg_chkmagic(cgp) || + (cgp->cg_cs.cs_nbfree == 0 && size == sblock->fs_bsize)) + { + printf ("Cylinder group %d bad magic number: %ld/%ld\n", + cg, cgp->cg_magic, ((struct ocg *)(cgp))->cg_magic); + diskfs_end_catch_exception (); + return 0; + } + cgp->cg_time = diskfs_mtime->seconds; + if (size == sblock->fs_bsize) + { + bno = alloccgblk(cgp, bpref); + diskfs_end_catch_exception (); + return (u_long) (bno); + } + /* + * check to see if any fragments are already available + * allocsiz is the size which will be allocated, hacking + * it down to a smaller size if necessary + */ + frags = numfrags(size); + for (allocsiz = frags; allocsiz < sblock->fs_frag; allocsiz++) + if (cgp->cg_frsum[allocsiz] != 0) + break; + if (allocsiz == sblock->fs_frag) + { + /* + * no fragments were available, so a block will be + * allocated, and hacked up + */ + if (cgp->cg_cs.cs_nbfree == 0) + { + diskfs_end_catch_exception (); + return 0; + } + + bno = alloccgblk(cgp, bpref); + bpref = dtogd(bno); + for (i = frags; i < sblock->fs_frag; i++) + setbit(cg_blksfree(cgp), bpref + i); + i = sblock->fs_frag - frags; + cgp->cg_cs.cs_nffree += i; + sblock->fs_cstotal.cs_nffree += i; + csum[cg].cs_nffree += i; + cgp->cg_frsum[i]++; + return (u_long)(bno); + } + bno = mapsearch(cgp, bpref, allocsiz); + if (bno < 0) + { + diskfs_end_catch_exception (); + return 0; + } + + for (i = 0; i < frags; i++) + clrbit(cg_blksfree(cgp), bno + i); + cgp->cg_cs.cs_nffree -= frags; + sblock->fs_cstotal.cs_nffree -= frags; + csum[cg].cs_nffree -= frags; + cgp->cg_frsum[allocsiz]--; + if (frags != allocsiz) + cgp->cg_frsum[allocsiz - frags]++; + diskfs_end_catch_exception (); + return (u_long) (cg * sblock->fs_fpg + bno); +} + +/* + * Allocate a block in a cylinder group. + * + * This algorithm implements the following policy: + * 1) allocate the requested block. + * 2) allocate a rotationally optimal block in the same cylinder. + * 3) allocate the next available block on the block rotor for the + * specified cylinder group. + * Note that this routine only allocates fs_bsize blocks; these + * blocks may be fragmented by the routine that allocates them. + */ +static daddr_t +alloccgblk(struct cg *cgp, + volatile daddr_t bpref) +{ + daddr_t bno; + int cylno, pos, delta; + short *cylbp; + int i; + daddr_t ret; + + if (diskfs_catch_exception ()) + return 0; + + if (bpref == 0) + { + bpref = cgp->cg_rotor; + goto norot; + } + bpref = blknum(bpref); + bpref = dtogd(bpref); + /* + * if the requested block is available, use it + */ + if (isblock(cg_blksfree(cgp), fragstoblks(bpref))) + { + bno = bpref; + goto gotit; + } + /* + * check for a block available on the same cylinder + */ + cylno = cbtocylno(bpref); + if (cg_blktot(cgp)[cylno] == 0) + goto norot; + if (sblock->fs_cpc == 0) + { + /* + * block layout info is not available, so just have + * to take any block in this cylinder. + */ + bpref = howmany(sblock->fs_spc * cylno, NSPF); + goto norot; + } + /* + * check the summary information to see if a block is + * available in the requested cylinder starting at the + * requested rotational position and proceeding around. + */ + cylbp = cg_blks(cgp, cylno); + pos = cbtorpos(bpref); + for (i = pos; i < sblock->fs_nrpos; i++) + if (cylbp[i] > 0) + break; + if (i == sblock->fs_nrpos) + for (i = 0; i < pos; i++) + if (cylbp[i] > 0) + break; + if (cylbp[i] > 0) + { + /* + * found a rotational position, now find the actual + * block. A panic if none is actually there. + */ + pos = cylno % sblock->fs_cpc; + bno = (cylno - pos) * sblock->fs_spc / NSPB; + assert ("postbl table bad" &&fs_postbl(pos)[i] != -1); + for (i = fs_postbl(pos)[i];; ) + { + if (isblock(cg_blksfree(cgp), bno + i)) + { + bno = blkstofrags(bno + i); + goto gotit; + } + delta = fs_rotbl[i]; + if (delta <= 0 || + delta + i > fragstoblks(sblock->fs_fpg)) + break; + i += delta; + } + assert ("Inconsistent rotbl table" && 0); + } + norot: + /* + * no blocks in the requested cylinder, so take next + * available one in this cylinder group. + */ + bno = mapsearch(cgp, bpref, (int)sblock->fs_frag); + if (bno < 0) + { + diskfs_end_catch_exception (); + return 0; + } + cgp->cg_rotor = bno; + gotit: + clrblock(cg_blksfree(cgp), (long)fragstoblks(bno)); + cgp->cg_cs.cs_nbfree--; + sblock->fs_cstotal.cs_nbfree--; + csum[cgp->cg_cgx].cs_nbfree--; + cylno = cbtocylno(bno); + cg_blks(cgp, cylno)[cbtorpos(bno)]--; + cg_blktot(cgp)[cylno]--; + ret = cgp->cg_cgx * sblock->fs_fpg + bno; + diskfs_end_catch_exception (); + return ret; +} + +/* + * Determine whether an inode can be allocated. + * + * Check to see if an inode is available, and if it is, + * allocate it using the following policy: + * 1) allocate the requested inode. + * 2) allocate the next available inode after the requested + * inode in the specified cylinder group. + */ +static u_long +ialloccg(int cg, + volatile daddr_t ipref, + int modein) +{ + struct cg *cgp; + int start, len, loc, map, i; + mode_t mode = (mode_t) modein; + + if (csum[cg].cs_nifree == 0) + return 0; + + cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); + + if (diskfs_catch_exception ()) + return 0; + + if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) + { + printf ("Cylinder group %d bad magic number: %ld/%ld\n", + cg, cgp->cg_magic, ((struct ocg *)(cgp))->cg_magic); + diskfs_end_catch_exception (); + return 0; + } + cgp->cg_time = diskfs_mtime->seconds; + if (ipref) + { + ipref %= sblock->fs_ipg; + if (isclr(cg_inosused(cgp), ipref)) + goto gotit; + } + start = cgp->cg_irotor / NBBY; + len = howmany(sblock->fs_ipg - cgp->cg_irotor, NBBY); + loc = skpc(0xff, len, (u_char *) &cg_inosused(cgp)[start]); + if (loc == 0) + { + len = start + 1; + start = 0; + loc = skpc(0xff, len, (u_char *) &cg_inosused(cgp)[0]); + assert ("inconsistent cg_inosused table" && loc); + } + i = start + len - loc; + map = cg_inosused(cgp)[i]; + ipref = i * NBBY; + for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) + { + if ((map & i) == 0) + { + cgp->cg_irotor = ipref; + goto gotit; + } + } + assert ("inconsistent cg_inosused table" && 0); + gotit: + setbit(cg_inosused(cgp), ipref); + cgp->cg_cs.cs_nifree--; + sblock->fs_cstotal.cs_nifree--; + csum[cg].cs_nifree--; + if ((mode & IFMT) == IFDIR) + { + cgp->cg_cs.cs_ndir++; + sblock->fs_cstotal.cs_ndir++; + csum[cg].cs_ndir++; + } + diskfs_end_catch_exception (); + return (u_long)(cg * sblock->fs_ipg + ipref); +} + +/* + * Free a block or fragment. + * + * The specified block or fragment is placed back in the + * free map. If a fragment is deallocated, a possible + * block reassembly is checked. + */ +void +blkfree(volatile daddr_t bno, + int size) +{ + struct cg *cgp; + int cg, blk, frags, bbase; + int i; + + assert ("free of bad sized block" &&(unsigned) size <= sblock->fs_bsize + && !fragoff (size)); + cg = dtog(bno); + if ((unsigned)bno >= sblock->fs_size) + { + printf("bad block %ld\n", bno); + return; + } + + cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); + + spin_lock (&alloclock); + + if (diskfs_catch_exception ()) + { + spin_unlock (&alloclock); + return; + } + + if (!cg_chkmagic(cgp)) + { + spin_unlock (&alloclock); + printf ("Cylinder group %d bad magic number: %ld/%ld\n", + cg, cgp->cg_magic, ((struct ocg *)(cgp))->cg_magic); + diskfs_end_catch_exception (); + return; + } + cgp->cg_time = diskfs_mtime->seconds; + bno = dtogd(bno); + if (size == sblock->fs_bsize) + { + assert ("inconsistent cg_blskfree table" + && !isblock (cg_blksfree (cgp), fragstoblks (bno))); + setblock(cg_blksfree(cgp), fragstoblks(bno)); + cgp->cg_cs.cs_nbfree++; + sblock->fs_cstotal.cs_nbfree++; + csum[cg].cs_nbfree++; + i = cbtocylno(bno); + cg_blks(cgp, i)[cbtorpos(bno)]++; + cg_blktot(cgp)[i]++; + } + else + { + bbase = bno - fragnum(bno); + /* + * decrement the counts associated with the old frags + */ + blk = blkmap(cg_blksfree(cgp), bbase); + fragacct(blk, cgp->cg_frsum, -1); + /* + * deallocate the fragment + */ + frags = numfrags(size); + for (i = 0; i < frags; i++) + { + assert ("inconsistent cg_blksfree table" + && !isset (cg_blksfree (cgp), bno + i)); + setbit(cg_blksfree(cgp), bno + i); + } + cgp->cg_cs.cs_nffree += i; + sblock->fs_cstotal.cs_nffree += i; + csum[cg].cs_nffree += i; + /* + * add back in counts associated with the new frags + */ + blk = blkmap(cg_blksfree(cgp), bbase); + fragacct(blk, cgp->cg_frsum, 1); + /* + * if a complete block has been reassembled, account for it + */ + if (isblock(cg_blksfree(cgp), (daddr_t)fragstoblks(bbase))) + { + cgp->cg_cs.cs_nffree -= sblock->fs_frag; + sblock->fs_cstotal.cs_nffree -= sblock->fs_frag; + csum[cg].cs_nffree -= sblock->fs_frag; + cgp->cg_cs.cs_nbfree++; + sblock->fs_cstotal.cs_nbfree++; + csum[cg].cs_nbfree++; + i = cbtocylno(bbase); + cg_blks(cgp, i)[cbtorpos(bbase)]++; + cg_blktot(cgp)[i]++; + } + } + spin_unlock (&alloclock); + diskfs_end_catch_exception (); +} + +/* + * Free an inode. + * + * The specified inode is placed back in the free map. + */ +void +diskfs_free_node(struct node *np, mode_t mode) +{ + struct cg *cgp; + int cg; + volatile int ino = np->dn->number; + + assert ("invalid inode number" && ino < sblock->fs_ipg * sblock->fs_ncg); + + cg = itog(ino); + cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); + + spin_lock (&alloclock); + if (diskfs_catch_exception ()) + { + spin_unlock (&alloclock); + return; + } + + if (!cg_chkmagic(cgp)) + { + spin_unlock (&alloclock); + printf ("Cylinder group %d bad magic number: %ld/%ld\n", + cg, cgp->cg_magic, ((struct ocg *)(cgp))->cg_magic); + diskfs_end_catch_exception (); + return; + } + cgp->cg_time = diskfs_mtime->seconds; + ino %= sblock->fs_ipg; + assert ("inconsistent cg_inosused table" && !isclr (cg_inosused (cgp), ino)); + clrbit(cg_inosused(cgp), ino); + if (ino < cgp->cg_irotor) + cgp->cg_irotor = ino; + cgp->cg_cs.cs_nifree++; + sblock->fs_cstotal.cs_nifree++; + csum[cg].cs_nifree++; + if ((mode & IFMT) == IFDIR) + { + cgp->cg_cs.cs_ndir--; + sblock->fs_cstotal.cs_ndir--; + csum[cg].cs_ndir--; + } + spin_unlock (&alloclock); + diskfs_end_catch_exception (); +} + + +/* + * Find a block of the specified size in the specified cylinder group. + * + * It is a panic if a request is made to find a block if none are + * available. + */ +/* This routine expects to be called from inside a diskfs_catch_exception */ +static daddr_t +mapsearch(struct cg *cgp, + daddr_t bpref, + int allocsiz) +{ + daddr_t bno; + int start, len, loc, i; + int blk, field, subfield, pos; + + /* + * find the fragment by searching through the free block + * map for an appropriate bit pattern + */ + if (bpref) + start = dtogd(bpref) / NBBY; + else + start = cgp->cg_frotor / NBBY; + len = howmany(sblock->fs_fpg, NBBY) - start; + loc = scanc((unsigned)len, (u_char *)&cg_blksfree(cgp)[start], + (u_char *)fragtbl[sblock->fs_frag], + (u_char)(1 << (allocsiz - 1 + (sblock->fs_frag % NBBY)))); + if (loc == 0) + { + len = start + 1; + start = 0; + loc = scanc((unsigned)len, (u_char *)&cg_blksfree(cgp)[0], + (u_char *)fragtbl[sblock->fs_frag], + (u_char)(1 << (allocsiz - 1 + (sblock->fs_frag % NBBY)))); + assert ("incosistent cg_blksfree table" && loc); + } + bno = (start + len - loc) * NBBY; + cgp->cg_frotor = bno; + /* + * found the byte in the map + * sift through the bits to find the selected frag + */ + for (i = bno + NBBY; bno < i; bno += sblock->fs_frag) + { + blk = blkmap(cg_blksfree(cgp), bno); + blk <<= 1; + field = around[allocsiz]; + subfield = inside[allocsiz]; + for (pos = 0; pos <= sblock->fs_frag - allocsiz; pos++) + { + if ((blk & field) == subfield) + return (bno + pos); + field <<= 1; + subfield <<= 1; + } + } + assert ("inconsistent cg_blksfree table" && 0); +} + + -- cgit v1.2.3 From 890a81fa732f4c1e654ca492ef1fdae170c7bdf3 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Wed, 1 Jun 1994 18:02:51 +0000 Subject: Formerly alloc.c.~10~ --- ufs/alloc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 161edcb8..193e0f31 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -93,7 +93,7 @@ alloc(struct node *np, *bnp = 0; assert ("Alloc of bad sized block" && (unsigned) size <= sblock->fs_bsize - && !fragoff(size)); + && !fragoff(size) && size != 0); spin_lock (&alloclock); @@ -150,9 +150,9 @@ realloccg(struct node *np, *pbn = 0; assert ("bad old size" && (unsigned) osize <= sblock->fs_bsize - && !fragoff (osize)); + && !fragoff (osize) && osize != 0 ); assert ("bad new size" && (unsigned) nsize <= sblock->fs_bsize - && !fragoff (nsize)); + && !fragoff (nsize) && nsize != 0); spin_lock (&alloclock); @@ -273,12 +273,15 @@ diskfs_alloc_node(struct node *dir, *npp = 0; + spin_lock (&alloclock); if (sblock->fs_cstotal.cs_nifree == 0) - goto noinodes; + { + spin_unlock (&alloclock); + goto noinodes; + } if (ipref >= sblock->fs_ncg * sblock->fs_ipg) ipref = 0; cg = itog(ipref); - spin_lock (&alloclock); ino = (int)hashalloc(cg, (long)ipref, mode, ialloccg); spin_unlock (&alloclock); if (ino == 0) @@ -852,7 +855,7 @@ blkfree(volatile daddr_t bno, int i; assert ("free of bad sized block" &&(unsigned) size <= sblock->fs_bsize - && !fragoff (size)); + && !fragoff (size) && size != 0); cg = dtog(bno); if ((unsigned)bno >= sblock->fs_size) { -- cgit v1.2.3 From 021e49868b745d1c0d20bca96fab3b5ed3decfc2 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 14 Jul 1994 20:09:50 +0000 Subject: Formerly alloc.c.~11~ --- ufs/alloc.c | 2150 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 1284 insertions(+), 866 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 193e0f31..cdd2e4b2 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -1,65 +1,67 @@ -/* Disk allocation routines - Copyright (C) 1993, 1994 Free Software Foundation - -This file is part of the GNU Hurd. - -The GNU Hurd is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -The GNU Hurd is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with the GNU Hurd; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* Modified from UCB by Michael I. Bushnell. */ - /* - * 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 is only permitted until one year after the first shipment - * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and - * binary forms are permitted provided that: (1) source distributions retain - * this entire copyright notice and comment, and (2) distributions including - * binaries display the following acknowledgement: This product includes - * software developed by the University of California, Berkeley and its - * contributors'' in the documentation or other materials provided with the - * distribution and in all advertising materials mentioning features or use - * of this software. Neither the name of the University nor the names of - * its contributors may 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 - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * @(#)ufs_alloc.c 7.20 (Berkeley) 6/28/90 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94 */ -#include "ufs.h" -#include "fs.h" -#include "dinode.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include -#include +#include +#include -static u_long alloccg (int, daddr_t, int); -static u_long ialloccg (int, daddr_t, int); -static u_long hashalloc (int, long, int, u_long(*)(int, daddr_t, int)); -static daddr_t fragextend (int, long, int, int); -static daddr_t alloccgblk (struct cg *, daddr_t); -static daddr_t mapsearch (struct cg *, daddr_t, int); -static ino_t dirpref (); +#include +#include -/* These are in tables.c. */ -extern int inside[], around[]; -extern unsigned char *fragtbl[]; +extern u_long nextgennumber; -static spin_lock_t alloclock = SPIN_LOCK_INITIALIZER; +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 daddr_t ffs_clusteralloc __P((struct inode *, int, daddr_t, int)); +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_nodealloccg __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. @@ -80,51 +82,60 @@ static spin_lock_t alloclock = SPIN_LOCK_INITIALIZER; * 2) quadradically rehash into other cylinder groups, until an * available block is located. */ -error_t -alloc(struct node *np, - daddr_t lbn, - daddr_t bpref, - int size, - daddr_t *bnp, - struct protid *cred) +ffs_alloc(ip, lbn, bpref, size, cred, bnp) + register struct inode *ip; + daddr_t lbn, bpref; + int size; + struct ucred *cred; + daddr_t *bnp; { - int cg; - daddr_t bno; - - *bnp = 0; - assert ("Alloc of bad sized block" && (unsigned) size <= sblock->fs_bsize - && !fragoff(size) && size != 0); - - spin_lock (&alloclock); - - if (size == sblock->fs_bsize && sblock->fs_cstotal.cs_nbfree == 0) - goto nospace; - if (cred && !diskfs_isuid (0, cred) && freespace(sblock->fs_minfree) <= 0) - goto nospace; - - if (bpref >= sblock->fs_size) - bpref = 0; - if (bpref == 0) - cg = itog(np->dn->number); - else - cg = dtog(bpref); - bno = (daddr_t)hashalloc(cg, (long)bpref, size, alloccg); - - spin_unlock (&alloclock); - - if (bno > 0) - { - np->dn_stat.st_blocks += btodb(size); - np->dn_set_mtime = 1; - np->dn_set_ctime = 1; - *bnp = bno; - return 0; - } - - nospace: - spin_unlock (&alloclock); - printf("file system full\n"); - return (ENOSPC); + register struct fs *fs; + daddr_t bno; + int cg, error; + + *bnp = 0; + fs = ip->i_fs; +#ifdef DIAGNOSTIC + if ((u_int)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("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) + goto nospace; +#ifdef QUOTA + if (error = chkdq(ip, (long)btodb(size), cred, 0)) + return (error); +#endif + if (bpref >= fs->fs_size) + bpref = 0; + if (bpref == 0) + cg = ino_to_cg(fs, ip->i_number); + else + cg = dtog(fs, bpref); + 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 |= IN_CHANGE | IN_UPDATE; + *bnp = bno; + return (0); + } +#ifdef QUOTA + /* + * Restore user's disk quota because allocation failed. + */ + (void) chkdq(ip, (long)-btodb(size), cred, FORCE); +#endif +nospace: + ffs_fserr(fs, cred->cr_uid, "file system full"); + uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); + return (ENOSPC); } /* @@ -135,179 +146,386 @@ alloc(struct node *np, * the original block. Failing that, the regular block allocator is * invoked to get an appropriate block. */ -error_t -realloccg(struct node *np, - daddr_t lbprev, - volatile daddr_t bpref, - int osize, - int nsize, - daddr_t *pbn, - struct protid *cred) +ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) + register struct inode *ip; + daddr_t lbprev; + daddr_t bpref; + int osize, nsize; + struct ucred *cred; + struct buf **bpp; { - volatile int cg, request; - daddr_t bprev, bno; - error_t error; - - *pbn = 0; - assert ("bad old size" && (unsigned) osize <= sblock->fs_bsize - && !fragoff (osize) && osize != 0 ); - assert ("bad new size" && (unsigned) nsize <= sblock->fs_bsize - && !fragoff (nsize) && nsize != 0); - - spin_lock (&alloclock); - - if (cred && !diskfs_isuid (0, cred) && freespace(sblock->fs_minfree) <= 0) - { - spin_unlock (&alloclock); - goto nospace; - } - - if (error = diskfs_catch_exception ()) - return error; - bprev = dinodes[np->dn->number].di_db[lbprev]; - diskfs_end_catch_exception (); - assert ("old block not allocated" && bprev); + register struct fs *fs; + struct buf *bp; + int cg, request, error; + daddr_t bprev, bno; + + *bpp = 0; + fs = ip->i_fs; +#ifdef DIAGNOSTIC + if ((u_int)osize > fs->fs_bsize || fragoff(fs, osize) != 0 || + (u_int)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) { + 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("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("ffs_realloccg: bad bprev"); + } + /* + * Allocate the extra space in the buffer. + */ + if (error = bread(ITOV(ip), lbprev, osize, NOCRED, &bp)) { + brelse(bp); + return (error); + } +#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 = 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 |= IN_CHANGE | IN_UPDATE; + allocbuf(bp, nsize); + bp->b_flags |= B_DONE; + bzero((char *)bp->b_data + osize, (u_int)nsize - osize); + *bpp = bp; + return (0); + } + /* + * Allocate a new disk location. + */ + if (bpref >= fs->fs_size) + bpref = 0; + switch ((int)fs->fs_optim) { + case FS_OPTSPACE: + /* + * Allocate an exact sized fragment. Although this makes + * best use of space, we will waste time relocating it if + * the file continues to grow. If the fragmentation is + * less than half of the minimum free reserve, we choose + * to begin optimizing for time. + */ + request = nsize; + if (fs->fs_minfree < 5 || + fs->fs_cstotal.cs_nffree > + fs->fs_dsize * fs->fs_minfree / (2 * 100)) + break; + log(LOG_NOTICE, "%s: optimization changed from SPACE to TIME\n", + fs->fs_fsmnt); + fs->fs_optim = FS_OPTTIME; + 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 `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 < + fs->fs_dsize * (fs->fs_minfree - 2) / 100) + break; + log(LOG_NOTICE, "%s: optimization changed from TIME to SPACE\n", + fs->fs_fsmnt); + fs->fs_optim = FS_OPTSPACE; + break; + default: + printf("dev = 0x%x, optim = %d, fs = %s\n", + ip->i_dev, fs->fs_optim, fs->fs_fsmnt); + panic("ffs_realloccg: bad optim"); + /* NOTREACHED */ + } + bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request, + (u_long (*)())ffs_alloccg); + if (bno > 0) { + bp->b_blkno = fsbtodb(fs, bno); + (void) vnode_pager_uncache(ITOV(ip)); + ffs_blkfree(ip, bprev, (long)osize); + if (nsize < request) + ffs_blkfree(ip, bno + numfrags(fs, nsize), + (long)(request - nsize)); + ip->i_blocks += btodb(nsize - osize); + 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); + *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 + */ + ffs_fserr(fs, cred->cr_uid, "file system full"); + uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); + return (ENOSPC); +} - /* - * Check for extension in the existing location. - */ - cg = dtog(bprev); - if (bno = fragextend(cg, (long)bprev, osize, nsize)) - { - spin_unlock (&alloclock); - assert ("fragextend behaved incorrectly" && bprev == bno); - np->dn_stat.st_blocks += btodb(nsize - osize); - np->dn_set_mtime = 1; - np->dn_set_ctime = 1; - *pbn = bno; - return (0); - } - /* - * Allocate a new disk location. - */ - if (bpref >= sblock->fs_size) - bpref = 0; - switch ((int)sblock->fs_optim) - { - case FS_OPTSPACE: - /* - * Allocate an exact sized fragment. Although this makes - * best use of space, we will waste time relocating it if - * the file continues to grow. If the fragmentation is - * less than half of the minimum free reserve, we choose - * to begin optimizing for time. - */ - request = nsize; - if (sblock->fs_minfree < 5 || - sblock->fs_cstotal.cs_nffree > - sblock->fs_dsize * sblock->fs_minfree / (2 * 100)) - break; - printf("optimization changed from SPACE to TIME\n"); - sblock->fs_optim = FS_OPTTIME; - 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. - */ - request = sblock->fs_bsize; - if (sblock->fs_cstotal.cs_nffree < - sblock->fs_dsize * (sblock->fs_minfree - 2) / 100) - break; - printf("%s: optimization changed from TIME to SPACE\n", - sblock->fs_fsmnt); - sblock->fs_optim = FS_OPTSPACE; - break; - default: - assert ("filesystem opitimazation bad value" && 0); - } - - bno = (daddr_t)hashalloc(cg, (long)bpref, request, - (u_long (*)())alloccg); +/* + * Reallocate a sequence of blocks into a contiguous sequence of blocks. + * + * The vnode and an array of buffer pointers for a range of sequential + * logical blocks to be made contiguous is given. The allocator attempts + * to find a range of sequential blocks starting as close as possible to + * an fs_rotdelay offset from the end of the allocation for the logical + * block immediately preceeding the current range. If successful, the + * physical block numbers in the buffer pointers and in the inode are + * changed to reflect the new allocation. If unsuccessful, the allocation + * is left unchanged. The success in doing the reallocation is returned. + * Note that the error return is not reflected back to the user. Rather + * the previous block allocation will be used. + */ +#include +int doasyncfree = 1; +struct ctldebug debug14 = { "doasyncfree", &doasyncfree }; +int +ffs_reallocblks(ap) + struct vop_reallocblks_args /* { + struct vnode *a_vp; + struct cluster_save *a_buflist; + } */ *ap; +{ + struct fs *fs; + struct inode *ip; + struct vnode *vp; + struct buf *sbp, *ebp; + daddr_t *bap, *sbap, *ebap; + struct cluster_save *buflist; + daddr_t start_lbn, end_lbn, soff, eoff, newblk, blkno; + struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp; + int i, len, start_lvl, end_lvl, pref, ssize; - spin_unlock (&alloclock); + vp = ap->a_vp; + ip = VTOI(vp); + fs = ip->i_fs; + if (fs->fs_contigsumsize <= 0) + return (ENOSPC); + buflist = ap->a_buflist; + len = buflist->bs_nchildren; + start_lbn = buflist->bs_children[0]->b_lblkno; + end_lbn = start_lbn + len - 1; +#ifdef DIAGNOSTIC + for (i = 1; i < len; i++) + if (buflist->bs_children[i]->b_lblkno != start_lbn + i) + panic("ffs_reallocblks: non-cluster"); +#endif + /* + * If the latest allocation is in a new cylinder group, assume that + * the filesystem has decided to move and do not force it back to + * the previous cylinder group. + */ + if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) != + dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno))) + return (ENOSPC); + if (ufs_getlbns(vp, start_lbn, start_ap, &start_lvl) || + ufs_getlbns(vp, end_lbn, end_ap, &end_lvl)) + return (ENOSPC); + /* + * Get the starting offset and block map for the first block. + */ + if (start_lvl == 0) { + sbap = &ip->i_db[0]; + soff = start_lbn; + } else { + idp = &start_ap[start_lvl - 1]; + if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &sbp)) { + brelse(sbp); + return (ENOSPC); + } + sbap = (daddr_t *)sbp->b_data; + soff = idp->in_off; + } + /* + * Find the preferred location for the cluster. + */ + pref = ffs_blkpref(ip, start_lbn, soff, sbap); + /* + * If the block range spans two block maps, get the second map. + */ + if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) { + ssize = len; + } else { +#ifdef DIAGNOSTIC + if (start_ap[start_lvl-1].in_lbn == idp->in_lbn) + panic("ffs_reallocblk: start == end"); +#endif + ssize = len - (idp->in_off + 1); + if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &ebp)) + goto fail; + ebap = (daddr_t *)ebp->b_data; + } + /* + * Search the block map looking for an allocation of the desired size. + */ + if ((newblk = (daddr_t)ffs_hashalloc(ip, dtog(fs, pref), (long)pref, + len, (u_long (*)())ffs_clusteralloc)) == 0) + goto fail; + /* + * We have found a new contiguous block. + * + * First we have to replace the old block pointers with the new + * block pointers in the inode and indirect blocks associated + * with the file. + */ + blkno = newblk; + for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) { + if (i == ssize) + bap = ebap; +#ifdef DIAGNOSTIC + if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap)) + panic("ffs_reallocblks: alloc mismatch"); +#endif + *bap++ = blkno; + } + /* + * Next we must write out the modified inode and indirect blocks. + * For strict correctness, the writes should be synchronous since + * the old block values may have been written to disk. In practise + * they are almost never written, but if we are concerned about + * strict correctness, the `doasyncfree' flag should be set to zero. + * + * The test on `doasyncfree' should be changed to test a flag + * that shows whether the associated buffers and inodes have + * been written. The flag should be set when the cluster is + * started and cleared whenever the buffer or inode is flushed. + * We can then check below to see if it is set, and do the + * synchronous write only when it has been cleared. + */ + if (sbap != &ip->i_db[0]) { + if (doasyncfree) + bdwrite(sbp); + else + bwrite(sbp); + } else { + ip->i_flag |= IN_CHANGE | IN_UPDATE; + if (!doasyncfree) + VOP_UPDATE(vp, &time, &time, MNT_WAIT); + } + if (ssize < len) + if (doasyncfree) + bdwrite(ebp); + else + bwrite(ebp); + /* + * Last, free the old blocks and assign the new blocks to the buffers. + */ + for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) { + ffs_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno), + fs->fs_bsize); + buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); + } + return (0); - if (bno > 0) - { - blkfree(bprev, (off_t)osize); - if (nsize < request) - blkfree(bno + numfrags(nsize), (off_t)(request - nsize)); - np->dn_stat.st_blocks += btodb (nsize - osize); - np->dn_set_mtime = 1; - np->dn_set_ctime = 1; - *pbn = bno; - return (0); - } - nospace: - /* - * no space available - */ - printf("file system full\n"); - return (ENOSPC); +fail: + if (ssize < len) + brelse(ebp); + if (sbap != &ip->i_db[0]) + brelse(sbp); + return (ENOSPC); } - -/* Implement the diskfs_alloc_node callback from the diskfs library. - See for the interface description. */ -error_t -diskfs_alloc_node(struct node *dir, - mode_t mode, - struct node **npp) +/* + * Allocate an inode in the file system. + * + * 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. + * If no inode preference is given the following heirarchy is used + * to allocate an inode: + * 1) allocate an inode in cylinder group 0. + * 2) quadradically rehash into other cylinder groups, until an + * available inode is located. + */ +ffs_valloc(ap) + struct vop_valloc_args /* { + struct vnode *a_pvp; + int a_mode; + struct ucred *a_cred; + struct vnode **a_vpp; + } */ *ap; { - int ino; - struct node *np; - int cg; - error_t error; - int ipref; - - if (S_ISDIR (mode)) - ipref = dirpref (); - else - ipref = dir->dn->number; - - *npp = 0; + 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; + + *ap->a_vpp = NULL; + pip = VTOI(pvp); + fs = pip->i_fs; + if (fs->fs_cstotal.cs_nifree == 0) + goto noinodes; - spin_lock (&alloclock); - if (sblock->fs_cstotal.cs_nifree == 0) - { - spin_unlock (&alloclock); - goto noinodes; - } - if (ipref >= sblock->fs_ncg * sblock->fs_ipg) - ipref = 0; - cg = itog(ipref); - ino = (int)hashalloc(cg, (long)ipref, mode, ialloccg); - spin_unlock (&alloclock); - if (ino == 0) - goto noinodes; - if (error = iget(ino, &np)) - return error; - *npp = np; - assert ("duplicate allocation" && !np->dn_stat.st_mode); - if (np->dn_stat.st_blocks) - { - printf("free inode %d had %d blocks\n", ino, np->dn_stat.st_blocks); - np->dn_stat.st_blocks = 0; - np->dn_set_ctime = 1; - } - /* - * Set up a new generation number for this inode. - */ - spin_lock (&gennumberlock); - if (++nextgennumber < (u_long)diskfs_mtime->seconds) - nextgennumber = diskfs_mtime->seconds; - np->dn_stat.st_gen = nextgennumber; - spin_unlock (&gennumberlock); - return (0); - noinodes: - printf("out of inodes\n"); - return (ENOSPC); + if ((mode & IFMT) == IFDIR) + ipref = ffs_dirpref(fs); + else + ipref = pip->i_number; + if (ipref >= fs->fs_ncg * fs->fs_ipg) + ipref = 0; + cg = ino_to_cg(fs, ipref); + 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); + if (error) { + VOP_VFREE(pvp, ino, mode); + return (error); + } + 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("ffs_valloc: dup alloc"); + } + if (ip->i_blocks) { /* XXX */ + printf("free inode %s/%d had %d blocks\n", + fs->fs_fsmnt, ino, ip->i_blocks); + ip->i_blocks = 0; + } + ip->i_flags = 0; + /* + * Set up a new generation number for this inode. + */ + if (++nextgennumber < (u_long)time.tv_sec) + nextgennumber = time.tv_sec; + ip->i_gen = nextgennumber; + return (0); +noinodes: + 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); } /* @@ -318,22 +536,21 @@ diskfs_alloc_node(struct node *dir, * free inodes, the one with the smallest number of directories. */ static ino_t -dirpref() +ffs_dirpref(fs) + register struct fs *fs; { - int cg, minndir, mincg, avgifree; - - spin_lock (&alloclock); - avgifree = sblock->fs_cstotal.cs_nifree / sblock->fs_ncg; - minndir = sblock->fs_ipg; - mincg = 0; - for (cg = 0; cg < sblock->fs_ncg; cg++) - if (csum[cg].cs_ndir < minndir && csum[cg].cs_nifree >= avgifree) - { - mincg = cg; - minndir = csum[cg].cs_ndir; - } - spin_unlock (&alloclock); - return ((int)(sblock->fs_ipg * mincg)); + int cg, minndir, mincg, avgifree; + + 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; + } + return ((ino_t)(fs->fs_ipg * mincg)); } /* @@ -363,75 +580,66 @@ dirpref() * schedule another I/O transfer. */ daddr_t -blkpref(struct node *np, - daddr_t lbn, - int indx, - daddr_t *bap) +ffs_blkpref(ip, lbn, indx, bap) + struct inode *ip; + daddr_t lbn; + int indx; + daddr_t *bap; { - int cg; - int avgbfree, startcg; - daddr_t nextblk; - - spin_lock (&alloclock); - if (indx % sblock->fs_maxbpg == 0 || bap[indx - 1] == 0) - { - if (lbn < NDADDR) - { - spin_unlock (&alloclock); - cg = itog(np->dn->number); - return (sblock->fs_fpg * cg + sblock->fs_frag); - } - /* - * Find a cylinder with greater than average number of - * unused data blocks. - */ - if (indx == 0 || bap[indx - 1] == 0) - startcg = itog(np->dn->number) + lbn / sblock->fs_maxbpg; - else - startcg = dtog(bap[indx - 1]) + 1; - startcg %= sblock->fs_ncg; - avgbfree = sblock->fs_cstotal.cs_nbfree / sblock->fs_ncg; - for (cg = startcg; cg < sblock->fs_ncg; cg++) - if (csum[cg].cs_nbfree >= avgbfree) - { - spin_unlock (&alloclock); - sblock->fs_cgrotor = cg; - return (sblock->fs_fpg * cg + sblock->fs_frag); - } - for (cg = 0; cg <= startcg; cg++) - if (csum[cg].cs_nbfree >= avgbfree) - { - spin_unlock (&alloclock); - sblock->fs_cgrotor = cg; - return (sblock->fs_fpg * cg + sblock->fs_frag); - } - spin_unlock (&alloclock); - return 0; - } + register struct fs *fs; + register int cg; + int avgbfree, startcg; + daddr_t nextblk; - spin_unlock (&alloclock); - - /* - * One or more previous blocks have been laid out. If less - * than fs_maxcontig previous blocks are contiguous, the - * next block is requested contiguously, otherwise it is - * requested rotationally delayed by fs_rotdelay milliseconds. - */ - nextblk = bap[indx - 1] + sblock->fs_frag; - if (indx > sblock->fs_maxcontig && - bap[indx - sblock->fs_maxcontig] + blkstofrags(sblock->fs_maxcontig) - != nextblk) - return (nextblk); - if (sblock->fs_rotdelay != 0) - /* - * Here we convert ms of delay to frags as: - * (frags) = (ms) * (rev/sec) * (sect/rev) / - * ((sect/frag) * (ms/sec)) - * then round up to the next block. - */ - nextblk += roundup(sblock->fs_rotdelay * sblock->fs_rps - * sblock->fs_nsect / (NSPF * 1000), sblock->fs_frag); - return (nextblk); + fs = ip->i_fs; + if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) { + if (lbn < NDADDR) { + cg = ino_to_cg(fs, ip->i_number); + return (fs->fs_fpg * cg + fs->fs_frag); + } + /* + * Find a cylinder with greater than average number of + * unused data blocks. + */ + if (indx == 0 || bap[indx - 1] == 0) + startcg = + ino_to_cg(fs, ip->i_number) + lbn / fs->fs_maxbpg; + else + startcg = dtog(fs, bap[indx - 1]) + 1; + startcg %= fs->fs_ncg; + avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; + for (cg = startcg; cg < fs->fs_ncg; cg++) + if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { + fs->fs_cgrotor = cg; + return (fs->fs_fpg * cg + fs->fs_frag); + } + for (cg = 0; cg <= startcg; cg++) + if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { + fs->fs_cgrotor = cg; + return (fs->fs_fpg * cg + fs->fs_frag); + } + return (NULL); + } + /* + * One or more previous blocks have been laid out. If less + * than fs_maxcontig previous blocks are contiguous, the + * next block is requested contiguously, otherwise it is + * 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) + return (nextblk); + if (fs->fs_rotdelay != 0) + /* + * Here we convert ms of delay to frags as: + * (frags) = (ms) * (rev/sec) * (sect/rev) / + * ((sect/frag) * (ms/sec)) + * then round up to the next block. + */ + nextblk += roundup(fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect / + (NSPF(fs) * 1000), fs->fs_frag); + return (nextblk); } /* @@ -444,48 +652,50 @@ blkpref(struct node *np, */ /*VARARGS5*/ static u_long -hashalloc(int cg, - long pref, - int size, /* size for data blocks, mode for inodes */ - u_long (*allocator)(int, daddr_t, int)) +ffs_hashalloc(ip, cg, pref, size, allocator) + struct inode *ip; + int cg; + long pref; + int size; /* size for data blocks, mode for inodes */ + u_long (*allocator)(); { - long result; - int i, icg = cg; - - /* - * 1: preferred cylinder group - */ - result = (*allocator)(cg, pref, size); - if (result) - return (result); - /* - * 2: quadratic rehash - */ - for (i = 1; i < sblock->fs_ncg; i *= 2) - { - cg += i; - if (cg >= sblock->fs_ncg) - cg -= sblock->fs_ncg; - result = (*allocator)(cg, 0, size); - if (result) - return (result); - } - /* - * 3: brute force search - * Note that we start at i == 2, since 0 was checked initially, - * and 1 is always checked in the quadratic rehash. - */ - cg = (icg + 2) % sblock->fs_ncg; - for (i = 2; i < sblock->fs_ncg; i++) - { - result = (*allocator)(cg, 0, size); - if (result) - return (result); - cg++; - if (cg == sblock->fs_ncg) - cg = 0; - } - return 0; + register struct fs *fs; + long result; + int i, icg = cg; + + fs = ip->i_fs; + /* + * 1: preferred cylinder group + */ + result = (*allocator)(ip, cg, pref, size); + if (result) + return (result); + /* + * 2: quadratic rehash + */ + for (i = 1; i < fs->fs_ncg; i *= 2) { + cg += i; + if (cg >= fs->fs_ncg) + cg -= fs->fs_ncg; + result = (*allocator)(ip, cg, 0, size); + if (result) + return (result); + } + /* + * 3: brute force search + * Note that we start at i == 2, since 0 was checked initially, + * and 1 is always checked in the quadratic rehash. + */ + cg = (icg + 2) % fs->fs_ncg; + for (i = 2; i < fs->fs_ncg; i++) { + result = (*allocator)(ip, cg, 0, size); + if (result) + return (result); + cg++; + if (cg == fs->fs_ncg) + cg = 0; + } + return (NULL); } /* @@ -495,154 +705,156 @@ hashalloc(int cg, * if they are, allocate them. */ static daddr_t -fragextend(int cg, - long bprev, - int osize, - int nsize) +ffs_fragextend(ip, cg, bprev, osize, nsize) + struct inode *ip; + int cg; + long bprev; + int osize, nsize; { - struct cg *cgp; - long bno; - int frags, bbase; - int i; - - if (csum[cg].cs_nffree < numfrags(nsize - osize)) - return 0; - frags = numfrags(nsize); - bbase = fragnum(bprev); - if (bbase > fragnum((bprev + frags - 1))) - /* cannot extend across a block boundary */ - return 0; + register struct fs *fs; + register struct cg *cgp; + struct buf *bp; + long bno; + int frags, bbase; + int i, error; - cgp = (struct cg *) (cgs + sblock->fs_bsize * cg); - - if (diskfs_catch_exception ()) - return 0; /* bogus, but that's what BSD does... */ - - if (!cg_chkmagic(cgp)) - { - printf ("Cylinder group %d bad magic number: %ld/%ld\n", - cg, cgp->cg_magic, ((struct ocg *)(cgp))->cg_magic); - diskfs_end_catch_exception (); - return 0; - } - cgp->cg_time = diskfs_mtime->seconds; - bno = dtogd(bprev); - for (i = numfrags(osize); i < frags; i++) - if (isclr(cg_blksfree(cgp), bno + i)) - { - diskfs_end_catch_exception (); - return 0; - } - - /* - * the current fragment can be extended - * deduct the count on fragment being extended into - * increase the count on the remaining fragment (if any) - * allocate the extended piece - */ - for (i = frags; i < sblock->fs_frag - bbase; i++) - if (isclr(cg_blksfree(cgp), bno + i)) - break; - cgp->cg_frsum[i - numfrags(osize)]--; - if (i != frags) - cgp->cg_frsum[i - frags]++; - for (i = numfrags(osize); i < frags; i++) - { - clrbit(cg_blksfree(cgp), bno + i); - cgp->cg_cs.cs_nffree--; - sblock->fs_cstotal.cs_nffree--; - csum[cg].cs_nffree--; - } - diskfs_end_catch_exception (); - return (bprev); + fs = ip->i_fs; + if (fs->fs_cs(fs, cg).cs_nffree < numfrags(fs, nsize - osize)) + return (NULL); + frags = numfrags(fs, nsize); + bbase = fragnum(fs, bprev); + if (bbase > fragnum(fs, (bprev + frags - 1))) { + /* cannot extend across a block boundary */ + return (NULL); + } + error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), + (int)fs->fs_cgsize, NOCRED, &bp); + if (error) { + brelse(bp); + return (NULL); + } + cgp = (struct cg *)bp->b_data; + if (!cg_chkmagic(cgp)) { + brelse(bp); + return (NULL); + } + cgp->cg_time = time.tv_sec; + bno = dtogd(fs, bprev); + for (i = numfrags(fs, osize); i < frags; i++) + if (isclr(cg_blksfree(cgp), bno + i)) { + brelse(bp); + return (NULL); + } + /* + * the current fragment can be extended + * deduct the count on fragment being extended into + * increase the count on the remaining fragment (if any) + * allocate the extended piece + */ + for (i = frags; i < fs->fs_frag - bbase; i++) + if (isclr(cg_blksfree(cgp), bno + i)) + break; + cgp->cg_frsum[i - numfrags(fs, osize)]--; + if (i != frags) + cgp->cg_frsum[i - frags]++; + for (i = numfrags(fs, osize); i < frags; i++) { + clrbit(cg_blksfree(cgp), bno + i); + cgp->cg_cs.cs_nffree--; + fs->fs_cstotal.cs_nffree--; + fs->fs_cs(fs, cg).cs_nffree--; + } + fs->fs_fmod = 1; + bdwrite(bp); + return (bprev); } /* * Determine whether a block can be allocated. * - * Check to see if a block of the apprpriate size is available, + * Check to see if a block of the appropriate size is available, * and if it is, allocate it. */ -static u_long -alloccg(int cg, - volatile daddr_t bpref, - int size) +static daddr_t +ffs_alloccg(ip, cg, bpref, size) + struct inode *ip; + int cg; + daddr_t bpref; + int size; { - struct cg *cgp; - int i; - int bno, frags, allocsiz; - - if (csum[cg].cs_nbfree == 0 && size == sblock->fs_bsize) - return 0; - cgp = (struct cg *) (cgs + sblock->fs_bsize * cg); + register struct fs *fs; + register struct cg *cgp; + struct buf *bp; + register int i; + int error, bno, frags, allocsiz; - if (diskfs_catch_exception ()) - return 0; - - if (!cg_chkmagic(cgp) || - (cgp->cg_cs.cs_nbfree == 0 && size == sblock->fs_bsize)) - { - printf ("Cylinder group %d bad magic number: %ld/%ld\n", - cg, cgp->cg_magic, ((struct ocg *)(cgp))->cg_magic); - diskfs_end_catch_exception (); - return 0; - } - cgp->cg_time = diskfs_mtime->seconds; - if (size == sblock->fs_bsize) - { - bno = alloccgblk(cgp, bpref); - diskfs_end_catch_exception (); - return (u_long) (bno); - } - /* - * check to see if any fragments are already available - * allocsiz is the size which will be allocated, hacking - * it down to a smaller size if necessary - */ - frags = numfrags(size); - for (allocsiz = frags; allocsiz < sblock->fs_frag; allocsiz++) - if (cgp->cg_frsum[allocsiz] != 0) - break; - if (allocsiz == sblock->fs_frag) - { - /* - * no fragments were available, so a block will be - * allocated, and hacked up - */ - if (cgp->cg_cs.cs_nbfree == 0) - { - diskfs_end_catch_exception (); - return 0; + 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); + if (error) { + brelse(bp); + return (NULL); } - - bno = alloccgblk(cgp, bpref); - bpref = dtogd(bno); - for (i = frags; i < sblock->fs_frag; i++) - setbit(cg_blksfree(cgp), bpref + i); - i = sblock->fs_frag - frags; - cgp->cg_cs.cs_nffree += i; - sblock->fs_cstotal.cs_nffree += i; - csum[cg].cs_nffree += i; - cgp->cg_frsum[i]++; - return (u_long)(bno); - } - bno = mapsearch(cgp, bpref, allocsiz); - if (bno < 0) - { - diskfs_end_catch_exception (); - return 0; - } - - for (i = 0; i < frags; i++) - clrbit(cg_blksfree(cgp), bno + i); - cgp->cg_cs.cs_nffree -= frags; - sblock->fs_cstotal.cs_nffree -= frags; - csum[cg].cs_nffree -= frags; - cgp->cg_frsum[allocsiz]--; - if (frags != allocsiz) - cgp->cg_frsum[allocsiz - frags]++; - diskfs_end_catch_exception (); - return (u_long) (cg * sblock->fs_fpg + bno); + cgp = (struct cg *)bp->b_data; + if (!cg_chkmagic(cgp) || + (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) { + brelse(bp); + return (NULL); + } + cgp->cg_time = time.tv_sec; + if (size == fs->fs_bsize) { + bno = ffs_alloccgblk(fs, cgp, bpref); + bdwrite(bp); + return (bno); + } + /* + * check to see if any fragments are already available + * allocsiz is the size which will be allocated, hacking + * it down to a smaller size if necessary + */ + frags = numfrags(fs, size); + for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++) + if (cgp->cg_frsum[allocsiz] != 0) + break; + if (allocsiz == fs->fs_frag) { + /* + * no fragments were available, so a block will be + * allocated, and hacked up + */ + if (cgp->cg_cs.cs_nbfree == 0) { + brelse(bp); + return (NULL); + } + bno = ffs_alloccgblk(fs, cgp, bpref); + bpref = dtogd(fs, bno); + for (i = frags; i < fs->fs_frag; i++) + setbit(cg_blksfree(cgp), bpref + i); + i = fs->fs_frag - frags; + cgp->cg_cs.cs_nffree += i; + fs->fs_cstotal.cs_nffree += i; + fs->fs_cs(fs, cg).cs_nffree += i; + fs->fs_fmod = 1; + cgp->cg_frsum[i]++; + bdwrite(bp); + return (bno); + } + bno = ffs_mapsearch(fs, cgp, bpref, allocsiz); + if (bno < 0) { + brelse(bp); + return (NULL); + } + for (i = 0; i < frags; i++) + clrbit(cg_blksfree(cgp), bno + i); + cgp->cg_cs.cs_nffree -= frags; + fs->fs_cstotal.cs_nffree -= frags; + fs->fs_cs(fs, cg).cs_nffree -= frags; + fs->fs_fmod = 1; + cgp->cg_frsum[allocsiz]--; + if (frags != allocsiz) + cgp->cg_frsum[allocsiz - frags]++; + bdwrite(bp); + return (cg * fs->fs_fpg + bno); } /* @@ -657,109 +869,196 @@ alloccg(int cg, * blocks may be fragmented by the routine that allocates them. */ static daddr_t -alloccgblk(struct cg *cgp, - volatile daddr_t bpref) +ffs_alloccgblk(fs, cgp, bpref) + register struct fs *fs; + register struct cg *cgp; + daddr_t bpref; { - daddr_t bno; - int cylno, pos, delta; - short *cylbp; - int i; - daddr_t ret; - - if (diskfs_catch_exception ()) - return 0; - - if (bpref == 0) - { - bpref = cgp->cg_rotor; - goto norot; - } - bpref = blknum(bpref); - bpref = dtogd(bpref); - /* - * if the requested block is available, use it - */ - if (isblock(cg_blksfree(cgp), fragstoblks(bpref))) - { - bno = bpref; - goto gotit; - } - /* - * check for a block available on the same cylinder - */ - cylno = cbtocylno(bpref); - if (cg_blktot(cgp)[cylno] == 0) - goto norot; - if (sblock->fs_cpc == 0) - { - /* - * block layout info is not available, so just have - * to take any block in this cylinder. - */ - bpref = howmany(sblock->fs_spc * cylno, NSPF); - goto norot; - } - /* - * check the summary information to see if a block is - * available in the requested cylinder starting at the - * requested rotational position and proceeding around. - */ - cylbp = cg_blks(cgp, cylno); - pos = cbtorpos(bpref); - for (i = pos; i < sblock->fs_nrpos; i++) - if (cylbp[i] > 0) - break; - if (i == sblock->fs_nrpos) - for (i = 0; i < pos; i++) - if (cylbp[i] > 0) - break; - if (cylbp[i] > 0) - { - /* - * found a rotational position, now find the actual - * block. A panic if none is actually there. - */ - pos = cylno % sblock->fs_cpc; - bno = (cylno - pos) * sblock->fs_spc / NSPB; - assert ("postbl table bad" &&fs_postbl(pos)[i] != -1); - for (i = fs_postbl(pos)[i];; ) - { - if (isblock(cg_blksfree(cgp), bno + i)) - { - bno = blkstofrags(bno + i); - goto gotit; - } - delta = fs_rotbl[i]; - if (delta <= 0 || - delta + i > fragstoblks(sblock->fs_fpg)) - break; - i += delta; + daddr_t bno, blkno; + int cylno, pos, delta; + short *cylbp; + register int i; + + if (bpref == 0 || dtog(fs, bpref) != cgp->cg_cgx) { + bpref = cgp->cg_rotor; + goto norot; } - assert ("Inconsistent rotbl table" && 0); - } - norot: - /* - * no blocks in the requested cylinder, so take next - * available one in this cylinder group. - */ - bno = mapsearch(cgp, bpref, (int)sblock->fs_frag); - if (bno < 0) - { - diskfs_end_catch_exception (); - return 0; - } - cgp->cg_rotor = bno; - gotit: - clrblock(cg_blksfree(cgp), (long)fragstoblks(bno)); - cgp->cg_cs.cs_nbfree--; - sblock->fs_cstotal.cs_nbfree--; - csum[cgp->cg_cgx].cs_nbfree--; - cylno = cbtocylno(bno); - cg_blks(cgp, cylno)[cbtorpos(bno)]--; - cg_blktot(cgp)[cylno]--; - ret = cgp->cg_cgx * sblock->fs_fpg + bno; - diskfs_end_catch_exception (); - return ret; + bpref = blknum(fs, bpref); + bpref = dtogd(fs, bpref); + /* + * if the requested block is available, use it + */ + if (ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bpref))) { + bno = bpref; + goto gotit; + } + /* + * check for a block available on the same cylinder + */ + cylno = cbtocylno(fs, bpref); + if (cg_blktot(cgp)[cylno] == 0) + goto norot; + if (fs->fs_cpc == 0) { + /* + * 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). + */ + goto norot; + } + /* + * check the summary information to see if a block is + * available in the requested cylinder starting at the + * requested rotational position and proceeding around. + */ + cylbp = cg_blks(fs, cgp, cylno); + pos = cbtorpos(fs, bpref); + for (i = pos; i < fs->fs_nrpos; i++) + if (cylbp[i] > 0) + break; + if (i == fs->fs_nrpos) + for (i = 0; i < pos; i++) + if (cylbp[i] > 0) + break; + if (cylbp[i] > 0) { + /* + * found a rotational position, now find the actual + * block. A panic if none is actually there. + */ + pos = cylno % fs->fs_cpc; + bno = (cylno - pos) * fs->fs_spc / NSPB(fs); + if (fs_postbl(fs, pos)[i] == -1) { + printf("pos = %d, i = %d, fs = %s\n", + pos, i, fs->fs_fsmnt); + panic("ffs_alloccgblk: cyl groups corrupted"); + } + for (i = fs_postbl(fs, pos)[i];; ) { + if (ffs_isblock(fs, cg_blksfree(cgp), bno + i)) { + bno = blkstofrags(fs, (bno + i)); + goto gotit; + } + delta = fs_rotbl(fs)[i]; + if (delta <= 0 || + delta + i > fragstoblks(fs, fs->fs_fpg)) + break; + i += delta; + } + printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt); + 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 = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag); + if (bno < 0) + return (NULL); + cgp->cg_rotor = bno; +gotit: + blkno = fragstoblks(fs, bno); + ffs_clrblock(fs, cg_blksfree(cgp), (long)blkno); + ffs_clusteracct(fs, cgp, blkno, -1); + 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 = 1; + return (cgp->cg_cgx * fs->fs_fpg + bno); +} + +/* + * Determine whether a cluster can be allocated. + * + * We do not currently check for optimal rotational layout if there + * are multiple choices in the same cylinder group. Instead we just + * take the first one that we find following bpref. + */ +static daddr_t +ffs_clusteralloc(ip, cg, bpref, len) + struct inode *ip; + int cg; + daddr_t bpref; + int len; +{ + register struct fs *fs; + register struct cg *cgp; + struct buf *bp; + int i, run, bno, bit, map; + u_char *mapp; + + fs = ip->i_fs; + if (fs->fs_cs(fs, cg).cs_nbfree < len) + return (NULL); + if (bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, + NOCRED, &bp)) + goto fail; + cgp = (struct cg *)bp->b_data; + if (!cg_chkmagic(cgp)) + goto fail; + /* + * Check to see if a cluster of the needed size (or bigger) is + * available in this cylinder group. + */ + for (i = len; i <= fs->fs_contigsumsize; i++) + if (cg_clustersum(cgp)[i] > 0) + break; + if (i > fs->fs_contigsumsize) + goto fail; + /* + * Search the cluster map to find a big enough cluster. + * We take the first one that we find, even if it is larger + * than we need as we prefer to get one close to the previous + * block allocation. We do not search before the current + * preference point as we do not want to allocate a block + * that is allocated before the previous one (as we will + * then have to wait for another pass of the elevator + * algorithm before it will be read). We prefer to fail and + * be recalled to try an allocation in the next cylinder group. + */ + if (dtog(fs, bpref) != cg) + bpref = 0; + else + bpref = fragstoblks(fs, dtogd(fs, blknum(fs, bpref))); + mapp = &cg_clustersfree(cgp)[bpref / NBBY]; + map = *mapp++; + bit = 1 << (bpref % NBBY); + for (run = 0, i = bpref; i < cgp->cg_nclusterblks; i++) { + if ((map & bit) == 0) { + run = 0; + } else { + run++; + if (run == len) + break; + } + if ((i & (NBBY - 1)) != (NBBY - 1)) { + bit <<= 1; + } else { + map = *mapp++; + bit = 1; + } + } + if (i == cgp->cg_nclusterblks) + goto fail; + /* + * Allocate the cluster that we have found. + */ + bno = cg * fs->fs_fpg + blkstofrags(fs, i - run + 1); + len = blkstofrags(fs, len); + for (i = 0; i < len; i += fs->fs_frag) + if (ffs_alloccgblk(fs, cgp, bno + i) != bno + i) + panic("ffs_clusteralloc: lost block"); + brelse(bp); + return (bno); + +fail: + brelse(bp); + return (0); } /* @@ -771,72 +1070,77 @@ alloccgblk(struct cg *cgp, * 2) allocate the next available inode after the requested * inode in the specified cylinder group. */ -static u_long -ialloccg(int cg, - volatile daddr_t ipref, - int modein) +static ino_t +ffs_nodealloccg(ip, cg, ipref, mode) + struct inode *ip; + int cg; + daddr_t ipref; + int mode; { - struct cg *cgp; - int start, len, loc, map, i; - mode_t mode = (mode_t) modein; - - if (csum[cg].cs_nifree == 0) - return 0; - - cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); + register struct fs *fs; + register struct cg *cgp; + struct buf *bp; + int error, start, len, loc, map, i; - if (diskfs_catch_exception ()) - return 0; - - if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) - { - printf ("Cylinder group %d bad magic number: %ld/%ld\n", - cg, cgp->cg_magic, ((struct ocg *)(cgp))->cg_magic); - diskfs_end_catch_exception (); - return 0; - } - cgp->cg_time = diskfs_mtime->seconds; - if (ipref) - { - ipref %= sblock->fs_ipg; - if (isclr(cg_inosused(cgp), ipref)) - goto gotit; - } - start = cgp->cg_irotor / NBBY; - len = howmany(sblock->fs_ipg - cgp->cg_irotor, NBBY); - loc = skpc(0xff, len, (u_char *) &cg_inosused(cgp)[start]); - if (loc == 0) - { - len = start + 1; - start = 0; - loc = skpc(0xff, len, (u_char *) &cg_inosused(cgp)[0]); - assert ("inconsistent cg_inosused table" && loc); - } - i = start + len - loc; - map = cg_inosused(cgp)[i]; - ipref = i * NBBY; - for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) - { - if ((map & i) == 0) - { - cgp->cg_irotor = ipref; - goto gotit; + 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); + if (error) { + brelse(bp); + return (NULL); + } + cgp = (struct cg *)bp->b_data; + if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) { + brelse(bp); + return (NULL); + } + cgp->cg_time = time.tv_sec; + if (ipref) { + ipref %= fs->fs_ipg; + if (isclr(cg_inosused(cgp), ipref)) + goto gotit; + } + start = cgp->cg_irotor / NBBY; + len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY); + loc = skpc(0xff, len, &cg_inosused(cgp)[start]); + if (loc == 0) { + len = start + 1; + start = 0; + loc = skpc(0xff, len, &cg_inosused(cgp)[0]); + if (loc == 0) { + printf("cg = %d, irotor = %d, fs = %s\n", + cg, cgp->cg_irotor, fs->fs_fsmnt); + panic("ffs_nodealloccg: map corrupted"); + /* NOTREACHED */ + } + } + i = start + len - loc; + map = cg_inosused(cgp)[i]; + ipref = i * NBBY; + for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) { + if ((map & i) == 0) { + cgp->cg_irotor = ipref; + goto gotit; + } + } + printf("fs = %s\n", fs->fs_fsmnt); + panic("ffs_nodealloccg: 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 = 1; + if ((mode & IFMT) == IFDIR) { + cgp->cg_cs.cs_ndir++; + fs->fs_cstotal.cs_ndir++; + fs->fs_cs(fs, cg).cs_ndir++; } - } - assert ("inconsistent cg_inosused table" && 0); - gotit: - setbit(cg_inosused(cgp), ipref); - cgp->cg_cs.cs_nifree--; - sblock->fs_cstotal.cs_nifree--; - csum[cg].cs_nifree--; - if ((mode & IFMT) == IFDIR) - { - cgp->cg_cs.cs_ndir++; - sblock->fs_cstotal.cs_ndir++; - csum[cg].cs_ndir++; - } - diskfs_end_catch_exception (); - return (u_long)(cg * sblock->fs_ipg + ipref); + bdwrite(bp); + return (cg * fs->fs_ipg + ipref); } /* @@ -846,99 +1150,103 @@ ialloccg(int cg, * free map. If a fragment is deallocated, a possible * block reassembly is checked. */ -void -blkfree(volatile daddr_t bno, - int size) +ffs_blkfree(ip, bno, size) + register struct inode *ip; + daddr_t bno; + long size; { - struct cg *cgp; - int cg, blk, frags, bbase; - int i; - - assert ("free of bad sized block" &&(unsigned) size <= sblock->fs_bsize - && !fragoff (size) && size != 0); - cg = dtog(bno); - if ((unsigned)bno >= sblock->fs_size) - { - printf("bad block %ld\n", bno); - return; - } + register struct fs *fs; + register struct cg *cgp; + struct buf *bp; + daddr_t blkno; + int i, error, cg, blk, frags, bbase; - cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); - - spin_lock (&alloclock); - - if (diskfs_catch_exception ()) - { - spin_unlock (&alloclock); - return; - } - - if (!cg_chkmagic(cgp)) - { - spin_unlock (&alloclock); - printf ("Cylinder group %d bad magic number: %ld/%ld\n", - cg, cgp->cg_magic, ((struct ocg *)(cgp))->cg_magic); - diskfs_end_catch_exception (); - return; - } - cgp->cg_time = diskfs_mtime->seconds; - bno = dtogd(bno); - if (size == sblock->fs_bsize) - { - assert ("inconsistent cg_blskfree table" - && !isblock (cg_blksfree (cgp), fragstoblks (bno))); - setblock(cg_blksfree(cgp), fragstoblks(bno)); - cgp->cg_cs.cs_nbfree++; - sblock->fs_cstotal.cs_nbfree++; - csum[cg].cs_nbfree++; - i = cbtocylno(bno); - cg_blks(cgp, i)[cbtorpos(bno)]++; - cg_blktot(cgp)[i]++; - } - else - { - bbase = bno - fragnum(bno); - /* - * decrement the counts associated with the old frags - */ - blk = blkmap(cg_blksfree(cgp), bbase); - fragacct(blk, cgp->cg_frsum, -1); - /* - * deallocate the fragment - */ - frags = numfrags(size); - for (i = 0; i < frags; i++) - { - assert ("inconsistent cg_blksfree table" - && !isset (cg_blksfree (cgp), bno + i)); - setbit(cg_blksfree(cgp), bno + i); + 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", + ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); + panic("blkfree: bad size"); + } + cg = dtog(fs, bno); + if ((u_int)bno >= fs->fs_size) { + printf("bad block %d, ino %d\n", bno, ip->i_number); + ffs_fserr(fs, ip->i_uid, "bad block"); + return; } - cgp->cg_cs.cs_nffree += i; - sblock->fs_cstotal.cs_nffree += i; - csum[cg].cs_nffree += i; - /* - * add back in counts associated with the new frags - */ - blk = blkmap(cg_blksfree(cgp), bbase); - fragacct(blk, cgp->cg_frsum, 1); - /* - * if a complete block has been reassembled, account for it - */ - if (isblock(cg_blksfree(cgp), (daddr_t)fragstoblks(bbase))) - { - cgp->cg_cs.cs_nffree -= sblock->fs_frag; - sblock->fs_cstotal.cs_nffree -= sblock->fs_frag; - csum[cg].cs_nffree -= sblock->fs_frag; - cgp->cg_cs.cs_nbfree++; - sblock->fs_cstotal.cs_nbfree++; - csum[cg].cs_nbfree++; - i = cbtocylno(bbase); - cg_blks(cgp, i)[cbtorpos(bbase)]++; - cg_blktot(cgp)[i]++; + error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), + (int)fs->fs_cgsize, NOCRED, &bp); + if (error) { + brelse(bp); + return; } - } - spin_unlock (&alloclock); - diskfs_end_catch_exception (); + cgp = (struct cg *)bp->b_data; + if (!cg_chkmagic(cgp)) { + brelse(bp); + return; + } + cgp->cg_time = time.tv_sec; + bno = dtogd(fs, bno); + if (size == fs->fs_bsize) { + blkno = fragstoblks(fs, bno); + if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) { + printf("dev = 0x%x, block = %d, fs = %s\n", + ip->i_dev, bno, fs->fs_fsmnt); + panic("blkfree: freeing free block"); + } + ffs_setblock(fs, cg_blksfree(cgp), blkno); + ffs_clusteracct(fs, cgp, blkno, 1); + cgp->cg_cs.cs_nbfree++; + fs->fs_cstotal.cs_nbfree++; + fs->fs_cs(fs, cg).cs_nbfree++; + i = cbtocylno(fs, bno); + cg_blks(fs, cgp, i)[cbtorpos(fs, bno)]++; + cg_blktot(cgp)[i]++; + } else { + bbase = bno - fragnum(fs, bno); + /* + * decrement the counts associated with the old frags + */ + blk = blkmap(fs, cg_blksfree(cgp), bbase); + ffs_fragacct(fs, blk, cgp->cg_frsum, -1); + /* + * deallocate the fragment + */ + frags = numfrags(fs, size); + for (i = 0; i < frags; i++) { + if (isset(cg_blksfree(cgp), bno + i)) { + printf("dev = 0x%x, block = %d, fs = %s\n", + ip->i_dev, bno + i, fs->fs_fsmnt); + panic("blkfree: freeing free frag"); + } + setbit(cg_blksfree(cgp), bno + i); + } + cgp->cg_cs.cs_nffree += i; + fs->fs_cstotal.cs_nffree += i; + fs->fs_cs(fs, cg).cs_nffree += i; + /* + * add back in counts associated with the new frags + */ + blk = blkmap(fs, cg_blksfree(cgp), bbase); + ffs_fragacct(fs, blk, cgp->cg_frsum, 1); + /* + * if a complete block has been reassembled, account for it + */ + blkno = fragstoblks(fs, bbase); + if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) { + cgp->cg_cs.cs_nffree -= fs->fs_frag; + fs->fs_cstotal.cs_nffree -= fs->fs_frag; + fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; + ffs_clusteracct(fs, cgp, blkno, 1); + cgp->cg_cs.cs_nbfree++; + fs->fs_cstotal.cs_nbfree++; + fs->fs_cs(fs, cg).cs_nbfree++; + i = cbtocylno(fs, bbase); + cg_blks(fs, cgp, i)[cbtorpos(fs, bbase)]++; + cg_blktot(cgp)[i]++; + } + } + fs->fs_fmod = 1; + bdwrite(bp); } /* @@ -946,111 +1254,221 @@ blkfree(volatile daddr_t bno, * * The specified inode is placed back in the free map. */ -void -diskfs_free_node(struct node *np, mode_t mode) +int +ffs_vfree(ap) + struct vop_vfree_args /* { + struct vnode *a_pvp; + ino_t a_ino; + int a_mode; + } */ *ap; { - struct cg *cgp; - int cg; - volatile int ino = np->dn->number; - - assert ("invalid inode number" && ino < sblock->fs_ipg * sblock->fs_ncg); - - cg = itog(ino); - cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); + register struct fs *fs; + register struct cg *cgp; + register struct inode *pip; + ino_t ino = ap->a_ino; + struct buf *bp; + int error, cg; - spin_lock (&alloclock); - if (diskfs_catch_exception ()) - { - spin_unlock (&alloclock); - return; - } - - if (!cg_chkmagic(cgp)) - { - spin_unlock (&alloclock); - printf ("Cylinder group %d bad magic number: %ld/%ld\n", - cg, cgp->cg_magic, ((struct ocg *)(cgp))->cg_magic); - diskfs_end_catch_exception (); - return; - } - cgp->cg_time = diskfs_mtime->seconds; - ino %= sblock->fs_ipg; - assert ("inconsistent cg_inosused table" && !isclr (cg_inosused (cgp), ino)); - clrbit(cg_inosused(cgp), ino); - if (ino < cgp->cg_irotor) - cgp->cg_irotor = ino; - cgp->cg_cs.cs_nifree++; - sblock->fs_cstotal.cs_nifree++; - csum[cg].cs_nifree++; - if ((mode & IFMT) == IFDIR) - { - cgp->cg_cs.cs_ndir--; - sblock->fs_cstotal.cs_ndir--; - csum[cg].cs_ndir--; - } - spin_unlock (&alloclock); - diskfs_end_catch_exception (); + 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 = ino_to_cg(fs, ino); + error = bread(pip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), + (int)fs->fs_cgsize, NOCRED, &bp); + if (error) { + brelse(bp); + return (0); + } + cgp = (struct cg *)bp->b_data; + if (!cg_chkmagic(cgp)) { + brelse(bp); + 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", + 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) + cgp->cg_irotor = ino; + cgp->cg_cs.cs_nifree++; + fs->fs_cstotal.cs_nifree++; + fs->fs_cs(fs, cg).cs_nifree++; + 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 = 1; + bdwrite(bp); + return (0); } - /* * Find a block of the specified size in the specified cylinder group. * * It is a panic if a request is made to find a block if none are * available. */ -/* This routine expects to be called from inside a diskfs_catch_exception */ static daddr_t -mapsearch(struct cg *cgp, - daddr_t bpref, - int allocsiz) +ffs_mapsearch(fs, cgp, bpref, allocsiz) + register struct fs *fs; + register struct cg *cgp; + daddr_t bpref; + int allocsiz; +{ + daddr_t bno; + int start, len, loc, i; + int blk, field, subfield, pos; + + /* + * find the fragment by searching through the free block + * map for an appropriate bit pattern + */ + if (bpref) + start = dtogd(fs, bpref) / NBBY; + else + start = cgp->cg_frotor / NBBY; + len = howmany(fs->fs_fpg, NBBY) - start; + loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[start], + (u_char *)fragtbl[fs->fs_frag], + (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); + if (loc == 0) { + len = start + 1; + start = 0; + loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[0], + (u_char *)fragtbl[fs->fs_frag], + (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); + if (loc == 0) { + printf("start = %d, len = %d, fs = %s\n", + start, len, fs->fs_fsmnt); + panic("ffs_alloccg: map corrupted"); + /* NOTREACHED */ + } + } + bno = (start + len - loc) * NBBY; + cgp->cg_frotor = bno; + /* + * found the byte in the map + * sift through the bits to find the selected frag + */ + for (i = bno + NBBY; bno < i; bno += fs->fs_frag) { + blk = blkmap(fs, cg_blksfree(cgp), bno); + blk <<= 1; + field = around[allocsiz]; + subfield = inside[allocsiz]; + for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) { + if ((blk & field) == subfield) + return (bno + pos); + field <<= 1; + subfield <<= 1; + } + } + printf("bno = %d, fs = %s\n", bno, fs->fs_fsmnt); + panic("ffs_alloccg: block not in map"); + return (-1); +} + +/* + * Update the cluster map because of an allocation or free. + * + * Cnt == 1 means free; cnt == -1 means allocating. + */ +ffs_clusteracct(fs, cgp, blkno, cnt) + struct fs *fs; + struct cg *cgp; + daddr_t blkno; + int cnt; { - daddr_t bno; - int start, len, loc, i; - int blk, field, subfield, pos; - - /* - * find the fragment by searching through the free block - * map for an appropriate bit pattern - */ - if (bpref) - start = dtogd(bpref) / NBBY; - else - start = cgp->cg_frotor / NBBY; - len = howmany(sblock->fs_fpg, NBBY) - start; - loc = scanc((unsigned)len, (u_char *)&cg_blksfree(cgp)[start], - (u_char *)fragtbl[sblock->fs_frag], - (u_char)(1 << (allocsiz - 1 + (sblock->fs_frag % NBBY)))); - if (loc == 0) - { - len = start + 1; - start = 0; - loc = scanc((unsigned)len, (u_char *)&cg_blksfree(cgp)[0], - (u_char *)fragtbl[sblock->fs_frag], - (u_char)(1 << (allocsiz - 1 + (sblock->fs_frag % NBBY)))); - assert ("incosistent cg_blksfree table" && loc); - } - bno = (start + len - loc) * NBBY; - cgp->cg_frotor = bno; - /* - * found the byte in the map - * sift through the bits to find the selected frag - */ - for (i = bno + NBBY; bno < i; bno += sblock->fs_frag) - { - blk = blkmap(cg_blksfree(cgp), bno); - blk <<= 1; - field = around[allocsiz]; - subfield = inside[allocsiz]; - for (pos = 0; pos <= sblock->fs_frag - allocsiz; pos++) - { - if ((blk & field) == subfield) - return (bno + pos); - field <<= 1; - subfield <<= 1; + long *sump; + u_char *freemapp, *mapp; + int i, start, end, forw, back, map, bit; + + if (fs->fs_contigsumsize <= 0) + return; + freemapp = cg_clustersfree(cgp); + sump = cg_clustersum(cgp); + /* + * Allocate or clear the actual block. + */ + if (cnt > 0) + setbit(freemapp, blkno); + else + clrbit(freemapp, blkno); + /* + * Find the size of the cluster going forward. + */ + start = blkno + 1; + end = start + fs->fs_contigsumsize; + if (end >= cgp->cg_nclusterblks) + end = cgp->cg_nclusterblks; + mapp = &freemapp[start / NBBY]; + map = *mapp++; + bit = 1 << (start % NBBY); + for (i = start; i < end; i++) { + if ((map & bit) == 0) + break; + if ((i & (NBBY - 1)) != (NBBY - 1)) { + bit <<= 1; + } else { + map = *mapp++; + bit = 1; + } + } + forw = i - start; + /* + * Find the size of the cluster going backward. + */ + start = blkno - 1; + end = start - fs->fs_contigsumsize; + if (end < 0) + end = -1; + mapp = &freemapp[start / NBBY]; + map = *mapp--; + bit = 1 << (start % NBBY); + for (i = start; i > end; i--) { + if ((map & bit) == 0) + break; + if ((i & (NBBY - 1)) != 0) { + bit >>= 1; + } else { + map = *mapp--; + bit = 1 << (NBBY - 1); + } } - } - assert ("inconsistent cg_blksfree table" && 0); + back = start - i; + /* + * Account for old cluster and the possibly new forward and + * back clusters. + */ + i = back + forw + 1; + if (i > fs->fs_contigsumsize) + i = fs->fs_contigsumsize; + sump[i] += cnt; + if (back > 0) + sump[back] -= cnt; + if (forw > 0) + sump[forw] -= cnt; } +/* + * Fserr prints the name of a file system with an error diagnostic. + * + * The form of the error message is: + * fs: error message + */ +static void +ffs_fserr(fs, uid, cp) + struct fs *fs; + u_int uid; + char *cp; +{ + log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp); +} -- cgit v1.2.3 From 7b0c5fe429fd598011edd4c2c0cae008263b8467 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 14 Jul 1994 21:45:29 +0000 Subject: Formerly alloc.c.~12~ --- ufs/alloc.c | 531 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 275 insertions(+), 256 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index cdd2e4b2..7dfe5785 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -1,3 +1,23 @@ +/* Disk allocation routines + Copyright (C) 1993, 1994 Free Software Foundation + +This file is part of the GNU Hurd. + +The GNU Hurd is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +The GNU Hurd is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the GNU Hurd; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Modified from UCB by Michael I. Bushnell. */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -33,35 +53,18 @@ * @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94 */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include +#include "ufs.h" +#include "fs.h" +#include "dinode.h" +#include -#include -#include - -#include -#include +/* These don't work *at all* here; don't even try setting them. */ +#undef DIAGNOSTIC +#undef QUOTA 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 daddr_t ffs_clusteralloc __P((struct inode *, int, daddr_t, int)); -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_nodealloccg __P((struct inode *, int, daddr_t, int)); -static daddr_t ffs_mapsearch __P((struct fs *, struct cg *, daddr_t, int)); +spin_lock_t alloclock = SPIN_LOCK_INITIALIZER; /* * Allocate a block in the file system. @@ -82,31 +85,32 @@ static daddr_t ffs_mapsearch __P((struct fs *, struct cg *, daddr_t, int)); * 2) quadradically rehash into other cylinder groups, until an * available block is located. */ -ffs_alloc(ip, lbn, bpref, size, cred, bnp) - register struct inode *ip; - daddr_t lbn, bpref; - int size; - struct ucred *cred; - daddr_t *bnp; +ffs_alloc(register struct node *np, + daddr_t lbn, + daddr_t bpref, + int size, + daddr_t *bnp, + struct protid *cred) { register struct fs *fs; daddr_t bno; int cg, error; *bnp = 0; - fs = ip->i_fs; + fs = sblock; #ifdef DIAGNOSTIC if ((u_int)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("ffs_alloc: bad size"); } - if (cred == NOCRED) - panic("ffs_alloc: missing credential\n"); + assert (cred); #endif /* DIAGNOSTIC */ + spin_lock (&alloclock); 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 (cred && !diskfs_isuid (0, cred) + && freespace(fs, fs->fs_minfree) <= 0) goto nospace; #ifdef QUOTA if (error = chkdq(ip, (long)btodb(size), cred, 0)) @@ -115,14 +119,16 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) if (bpref >= fs->fs_size) bpref = 0; if (bpref == 0) - cg = ino_to_cg(fs, ip->i_number); + cg = ino_to_cg(fs, np->dn->number); else cg = dtog(fs, bpref); - bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, size, + bno = (daddr_t)ffs_hashalloc(np, cg, (long)bpref, size, (u_long (*)())ffs_alloccg); if (bno > 0) { - ip->i_blocks += btodb(size); - ip->i_flag |= IN_CHANGE | IN_UPDATE; + spin_unlock (&alloclock); + np->dn_stat.st_blocks += btodb(size); + np->dn_set_ctime = 1; + np->dn_set_mtime = 1; *bnp = bno; return (0); } @@ -133,8 +139,10 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) (void) chkdq(ip, (long)-btodb(size), cred, FORCE); #endif nospace: - ffs_fserr(fs, cred->cr_uid, "file system full"); - uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); + spin_unlock (&alloclock); + printf ("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); } @@ -146,21 +154,20 @@ nospace: * the original block. Failing that, the regular block allocator is * invoked to get an appropriate block. */ -ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) - register struct inode *ip; - daddr_t lbprev; - daddr_t bpref; - int osize, nsize; - struct ucred *cred; - struct buf **bpp; +ffs_realloccg(register struct node *np, + daddr_t lbprev, + daddr_t bpref, + int osize, + int nsize, + daddr_t *pbn, + struct protid *cred) { register struct fs *fs; - struct buf *bp; int cg, request, error; daddr_t bprev, bno; - *bpp = 0; - fs = ip->i_fs; + *pbn = 0; + fs = sblock; #ifdef DIAGNOSTIC if ((u_int)osize > fs->fs_bsize || fragoff(fs, osize) != 0 || (u_int)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) { @@ -172,13 +179,18 @@ 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) + + spin_lock (&alloclock); + + if (!isuid (0, cred) && 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("ffs_realloccg: bad bprev"); - } + if (error = diskfs_catch_exception ()) + return error; + bprev = dinodes[np->dn->number].di_db[lbprev]; + diskfs_end_catch_exception (); + assert ("old block not allocated" && bprev); + +#if 0 /* Not needed in GNU Hurd ufs */ /* * Allocate the extra space in the buffer. */ @@ -192,19 +204,25 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) return (error); } #endif +#endif /* 0 */ + /* * Check for extension in the existing location. */ cg = dtog(fs, bprev); - 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 |= IN_CHANGE | IN_UPDATE; + if (bno = ffs_fragextend(np, cg, (long)bprev, osize, nsize)) { + assert (bno == bprev); + spin_unlock (&alloclock); + np->dn_stat.st_blocks += btodb(nsize - osize); + np->dn_set_ctime = 1; + np->dn_set_mtime = 1; + *pbn = bno; +#if 0 /* Not done this way in GNU Hurd ufs. */ allocbuf(bp, nsize); bp->b_flags |= B_DONE; bzero((char *)bp->b_data + osize, (u_int)nsize - osize); *bpp = bp; +#endif return (0); } /* @@ -252,24 +270,31 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) default: printf("dev = 0x%x, optim = %d, fs = %s\n", ip->i_dev, fs->fs_optim, fs->fs_fsmnt); - panic("ffs_realloccg: bad optim"); + assert (0); /* NOTREACHED */ } - bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request, + bno = (daddr_t)ffs_hashalloc(np, cg, (long)bpref, request, (u_long (*)())ffs_alloccg); if (bno > 0) { +#if 0 /* Not necessary in GNU Hurd ufs */ bp->b_blkno = fsbtodb(fs, bno); (void) vnode_pager_uncache(ITOV(ip)); - ffs_blkfree(ip, bprev, (long)osize); +#endif + ffs_blkfree(np, bprev, (long)osize); if (nsize < request) - ffs_blkfree(ip, bno + numfrags(fs, nsize), + ffs_blkfree(np, bno + numfrags(fs, nsize), (long)(request - nsize)); - ip->i_blocks += btodb(nsize - osize); - ip->i_flag |= IN_CHANGE | IN_UPDATE; + spin_unlock (&alloclock); + np->dn_stat.st_blocks += btodb(nsize - osize); + np->dn_set_mtime = 1; + np->dn_set_ctime = 1; + *pbn = bno; +#if 0 /* Not done this way in GNU Hurd ufs */ allocbuf(bp, nsize); bp->b_flags |= B_DONE; bzero((char *)bp->b_data + osize, (u_int)nsize - osize); *bpp = bp; +#endif /* 0 */ return (0); } #ifdef QUOTA @@ -278,16 +303,21 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) */ (void) chkdq(ip, (long)-btodb(nsize - osize), cred, FORCE); #endif +#if 0 /* Not necesarry in GNU Hurd ufs */ brelse(bp); +#endif nospace: /* * no space available */ - ffs_fserr(fs, cred->cr_uid, "file system full"); - uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); + spin_unlock (&alloclock); + printf ("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); } +#if 0 /* Not used (yet?) in GNU Hurd ufs */ /* * Reallocate a sequence of blocks into a contiguous sequence of blocks. * @@ -450,6 +480,7 @@ fail: brelse(sbp); return (ENOSPC); } +#endif /* 0 */ /* * Allocate an inode in the file system. @@ -466,65 +497,64 @@ fail: * 2) quadradically rehash into other cylinder groups, until an * available inode is located. */ -ffs_valloc(ap) - struct vop_valloc_args /* { - struct vnode *a_pvp; - int a_mode; - struct ucred *a_cred; - struct vnode **a_vpp; - } */ *ap; +/* This is now the diskfs_alloc_node callback from the diskfs library + (described in ). It used to be ffs_valloc in BSD. */ +error_t +diskfs_alloc_node (struct node *dir, + mode_t mode, + struct node **npp) { - 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; + register struct node *np; ino_t ino, ipref; int cg, error; - *ap->a_vpp = NULL; - pip = VTOI(pvp); - fs = pip->i_fs; + fs = sblock; + + + spin_lock (&alloclock); + if (fs->fs_cstotal.cs_nifree == 0) - goto noinodes; + { + spin_unlock (&alloclock); + goto noinodes; + } - if ((mode & IFMT) == IFDIR) + if (S_ISDIR (mode)) ipref = ffs_dirpref(fs); else - ipref = pip->i_number; + ipref = dir->dn->number; + if (ipref >= fs->fs_ncg * fs->fs_ipg) ipref = 0; cg = ino_to_cg(fs, ipref); - ino = (ino_t)ffs_hashalloc(pip, cg, (long)ipref, mode, ffs_nodealloccg); + ino = (ino_t)ffs_hashalloc(dir, cg, (long)ipref, + mode, ffs_nodealloccg); + spin_unlock (&alloclock); if (ino == 0) goto noinodes; - error = VFS_VGET(pvp->v_mount, ino, ap->a_vpp); - if (error) { - VOP_VFREE(pvp, ino, mode); - return (error); - } - 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("ffs_valloc: dup alloc"); - } - if (ip->i_blocks) { /* XXX */ - printf("free inode %s/%d had %d blocks\n", - fs->fs_fsmnt, ino, ip->i_blocks); - ip->i_blocks = 0; + error = iget (ino, &np); + assert ("duplicate allocation" && !np->dn_stat.st_mode); + if (np->dn_stat.st_blocks) { + printf("free inode %d had %d blocks\n", + ino, ip->i_blocks); + np->dn_stat.st_blocks = 0; + np->dn_set_ctime = 1; } ip->i_flags = 0; /* * Set up a new generation number for this inode. */ + spin_lock (&gennumberlock); if (++nextgennumber < (u_long)time.tv_sec) nextgennumber = time.tv_sec; ip->i_gen = nextgennumber; + spin_unlock (&gennumberlock); return (0); noinodes: - ffs_fserr(fs, ap->a_cred->cr_uid, "out of inodes"); - uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); + printf ("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); } @@ -536,8 +566,7 @@ noinodes: * free inodes, the one with the smallest number of directories. */ static ino_t -ffs_dirpref(fs) - register struct fs *fs; +ffs_dirpref(register struct fs *fs) { int cg, minndir, mincg, avgifree; @@ -545,10 +574,10 @@ ffs_dirpref(fs) 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) { + if (csum[cg].cs_ndir < minndir && + csum[cg].cs_nifree >= avgifree) { mincg = cg; - minndir = fs->fs_cs(fs, cg).cs_ndir; + minndir = csum[cg].cs_ndir; } return ((ino_t)(fs->fs_ipg * mincg)); } @@ -580,21 +609,22 @@ ffs_dirpref(fs) * schedule another I/O transfer. */ daddr_t -ffs_blkpref(ip, lbn, indx, bap) - struct inode *ip; - daddr_t lbn; - int indx; - daddr_t *bap; +ffs_blkpref(struct node *np, + daddr_t lbn, + int indx, + daddr_t *bap) { register struct fs *fs; register int cg; int avgbfree, startcg; daddr_t nextblk; - fs = ip->i_fs; + fs = sblock; + spin_lock (&alloclock); if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) { if (lbn < NDADDR) { - cg = ino_to_cg(fs, ip->i_number); + cg = ino_to_cg(fs, np->dn->number); + spin_unlock (&alloclock); return (fs->fs_fpg * cg + fs->fs_frag); } /* @@ -603,23 +633,28 @@ ffs_blkpref(ip, lbn, indx, bap) */ if (indx == 0 || bap[indx - 1] == 0) startcg = - ino_to_cg(fs, ip->i_number) + lbn / fs->fs_maxbpg; + (ino_to_cg(fs, np->dn->number) + + lbn / fs->fs_maxbpg); else startcg = dtog(fs, bap[indx - 1]) + 1; startcg %= fs->fs_ncg; avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; for (cg = startcg; cg < fs->fs_ncg; cg++) - if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { + if (csum[cg].cs_nbfree >= avgbfree) { fs->fs_cgrotor = cg; + spin_unlock (&alloclock); return (fs->fs_fpg * cg + fs->fs_frag); } for (cg = 0; cg <= startcg; cg++) - if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { + if (csum[cg].cs_nbfree >= avgbfree) { fs->fs_cgrotor = cg; + spin_unlock (&alloclock); return (fs->fs_fpg * cg + fs->fs_frag); } + spin_unlock (&alloclock); return (NULL); } + spin_unlock (&alloclock); /* * One or more previous blocks have been laid out. If less * than fs_maxcontig previous blocks are contiguous, the @@ -629,7 +664,9 @@ ffs_blkpref(ip, lbn, indx, bap) nextblk = bap[indx - 1] + fs->fs_frag; if (indx < fs->fs_maxcontig || bap[indx - fs->fs_maxcontig] + blkstofrags(fs, fs->fs_maxcontig) != nextblk) - return (nextblk); + { + return (nextblk); + } if (fs->fs_rotdelay != 0) /* * Here we convert ms of delay to frags as: @@ -652,22 +689,21 @@ ffs_blkpref(ip, lbn, indx, bap) */ /*VARARGS5*/ static u_long -ffs_hashalloc(ip, cg, pref, size, allocator) - struct inode *ip; - int cg; - long pref; - int size; /* size for data blocks, mode for inodes */ - u_long (*allocator)(); +ffs_hashalloc(struct node *np, + int cg, + long pref, + int size, /* size for data blocks, mode for inodes */ + u_long (*allocator)()) { register struct fs *fs; long result; int i, icg = cg; - fs = ip->i_fs; + fs = sblock; /* * 1: preferred cylinder group */ - result = (*allocator)(ip, cg, pref, size); + result = (*allocator)(np, cg, pref, size); if (result) return (result); /* @@ -677,7 +713,7 @@ ffs_hashalloc(ip, cg, pref, size, allocator) cg += i; if (cg >= fs->fs_ncg) cg -= fs->fs_ncg; - result = (*allocator)(ip, cg, 0, size); + result = (*allocator)(np, cg, 0, size); if (result) return (result); } @@ -688,7 +724,7 @@ ffs_hashalloc(ip, cg, pref, size, allocator) */ cg = (icg + 2) % fs->fs_ncg; for (i = 2; i < fs->fs_ncg; i++) { - result = (*allocator)(ip, cg, 0, size); + result = (*allocator)(np, cg, 0, size); if (result) return (result); cg++; @@ -705,11 +741,11 @@ ffs_hashalloc(ip, cg, pref, size, allocator) * if they are, allocate them. */ static daddr_t -ffs_fragextend(ip, cg, bprev, osize, nsize) - struct inode *ip; - int cg; - long bprev; - int osize, nsize; +ffs_fragextend(struct node *np, + int cg, + long bprev, + int osize, + int nsize) { register struct fs *fs; register struct cg *cgp; @@ -718,8 +754,8 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) int frags, bbase; int i, error; - fs = ip->i_fs; - if (fs->fs_cs(fs, cg).cs_nffree < numfrags(fs, nsize - osize)) + fs = sblock; + if (csum[cg].cs_nffree < numfrags(fs, nsize - osize)) return (NULL); frags = numfrags(fs, nsize); bbase = fragnum(fs, bprev); @@ -727,6 +763,7 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) /* cannot extend across a block boundary */ return (NULL); } +#if 0 /* Wrong for GNU Hurd ufs */ error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, NOCRED, &bp); if (error) { @@ -734,15 +771,18 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) return (NULL); } cgp = (struct cg *)bp->b_data; +#else + cgp = (struct cg *) (cgs + sblock->fs_bsize * cg); +#endif if (!cg_chkmagic(cgp)) { - brelse(bp); +/* brelse(bp); */ return (NULL); } - cgp->cg_time = time.tv_sec; + cgp->cg_time = diskfs_mtime->seconds; bno = dtogd(fs, bprev); for (i = numfrags(fs, osize); i < frags; i++) if (isclr(cg_blksfree(cgp), bno + i)) { - brelse(bp); +/* brelse(bp); */ return (NULL); } /* @@ -761,10 +801,10 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) clrbit(cg_blksfree(cgp), bno + i); cgp->cg_cs.cs_nffree--; fs->fs_cstotal.cs_nffree--; - fs->fs_cs(fs, cg).cs_nffree--; + csum[cg].cs_nffree--; } fs->fs_fmod = 1; - bdwrite(bp); +/* bdwrite(bp); */ return (bprev); } @@ -775,11 +815,10 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) * and if it is, allocate it. */ static daddr_t -ffs_alloccg(ip, cg, bpref, size) - struct inode *ip; - int cg; - daddr_t bpref; - int size; +ffs_alloccg(struct node *np, + int cg, + daddr_t bpref, + int size) { register struct fs *fs; register struct cg *cgp; @@ -787,9 +826,10 @@ ffs_alloccg(ip, cg, bpref, size) register int i; int error, bno, frags, allocsiz; - fs = ip->i_fs; - if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize) + fs = sblock; + if (csum[cg].cs_nbfree == 0 && size == fs->fs_bsize) return (NULL); +#if 0 /* Not this way in GNU Hurd ufs */ error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, NOCRED, &bp); if (error) { @@ -797,15 +837,18 @@ ffs_alloccg(ip, cg, bpref, size) return (NULL); } cgp = (struct cg *)bp->b_data; +#else + cgp = (struct cg *) (cgs + sblock->fs_bsize * cg); +#endif if (!cg_chkmagic(cgp) || (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) { - brelse(bp); +/* brelse(bp); */ return (NULL); } - cgp->cg_time = time.tv_sec; + cgp->cg_time = diskfs_mtime->seconds; if (size == fs->fs_bsize) { bno = ffs_alloccgblk(fs, cgp, bpref); - bdwrite(bp); +/* bdwrite(bp); */ return (bno); } /* @@ -823,7 +866,7 @@ ffs_alloccg(ip, cg, bpref, size) * allocated, and hacked up */ if (cgp->cg_cs.cs_nbfree == 0) { - brelse(bp); +/* brelse(bp); */ return (NULL); } bno = ffs_alloccgblk(fs, cgp, bpref); @@ -833,27 +876,27 @@ ffs_alloccg(ip, cg, bpref, size) i = fs->fs_frag - frags; cgp->cg_cs.cs_nffree += i; fs->fs_cstotal.cs_nffree += i; - fs->fs_cs(fs, cg).cs_nffree += i; + csum[cg].cs_nffree += i; fs->fs_fmod = 1; cgp->cg_frsum[i]++; - bdwrite(bp); +/* bdwrite(bp); */ return (bno); } bno = ffs_mapsearch(fs, cgp, bpref, allocsiz); if (bno < 0) { - brelse(bp); +/* brelse(bp);* / return (NULL); } for (i = 0; i < frags; i++) clrbit(cg_blksfree(cgp), bno + i); cgp->cg_cs.cs_nffree -= frags; fs->fs_cstotal.cs_nffree -= frags; - fs->fs_cs(fs, cg).cs_nffree -= frags; + csum[cg].cs_nffree -= frags; fs->fs_fmod = 1; cgp->cg_frsum[allocsiz]--; if (frags != allocsiz) cgp->cg_frsum[allocsiz - frags]++; - bdwrite(bp); +/* bdwrite(bp); */ return (cg * fs->fs_fpg + bno); } @@ -869,10 +912,9 @@ ffs_alloccg(ip, cg, bpref, size) * blocks may be fragmented by the routine that allocates them. */ static daddr_t -ffs_alloccgblk(fs, cgp, bpref) - register struct fs *fs; - register struct cg *cgp; - daddr_t bpref; +ffs_alloccgblk(register struct fs *fs, + register struct cg *cgp, + daddr_t bpref) { daddr_t bno, blkno; int cylno, pos, delta; @@ -930,11 +972,7 @@ ffs_alloccgblk(fs, cgp, bpref) */ pos = cylno % fs->fs_cpc; bno = (cylno - pos) * fs->fs_spc / NSPB(fs); - if (fs_postbl(fs, pos)[i] == -1) { - printf("pos = %d, i = %d, fs = %s\n", - pos, i, fs->fs_fsmnt); - panic("ffs_alloccgblk: cyl groups corrupted"); - } + assert (fs_postbl(fs, pos)[i] != -1); for (i = fs_postbl(fs, pos)[i];; ) { if (ffs_isblock(fs, cg_blksfree(cgp), bno + i)) { bno = blkstofrags(fs, (bno + i)); @@ -947,7 +985,7 @@ ffs_alloccgblk(fs, cgp, bpref) i += delta; } printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt); - panic("ffs_alloccgblk: can't find blk in cyl"); + assert (0); } norot: /* @@ -964,7 +1002,7 @@ gotit: ffs_clusteracct(fs, cgp, blkno, -1); cgp->cg_cs.cs_nbfree--; fs->fs_cstotal.cs_nbfree--; - fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; + csum[cgp->cg_cgx].cs_nbfree--; cylno = cbtocylno(fs, bno); cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--; cg_blktot(cgp)[cylno]--; @@ -972,6 +1010,7 @@ gotit: return (cgp->cg_cgx * fs->fs_fpg + bno); } +#if 0 /* Not needed in GNU Hurd ufs (yet?) */ /* * Determine whether a cluster can be allocated. * @@ -1060,6 +1099,7 @@ fail: brelse(bp); return (0); } +#endif /* * Determine whether an inode can be allocated. @@ -1071,20 +1111,20 @@ fail: * inode in the specified cylinder group. */ static ino_t -ffs_nodealloccg(ip, cg, ipref, mode) - struct inode *ip; - int cg; - daddr_t ipref; - int mode; +ffs_nodealloccg(struct node *np, + int cg, + daddr_t ipref, + int mode) { register struct fs *fs; register struct cg *cgp; struct buf *bp; int error, start, len, loc, map, i; - fs = ip->i_fs; - if (fs->fs_cs(fs, cg).cs_nifree == 0) + fs = sblock; + if (csum[cg].cs_nifree == 0) return (NULL); +#if 0 /* Not this way in GNU Hurd ufs */ error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, NOCRED, &bp); if (error) { @@ -1092,8 +1132,11 @@ ffs_nodealloccg(ip, cg, ipref, mode) return (NULL); } cgp = (struct cg *)bp->b_data; +#else + cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); +#endif if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) { - brelse(bp); +/* brelse(bp); */ return (NULL); } cgp->cg_time = time.tv_sec; @@ -1109,12 +1152,7 @@ ffs_nodealloccg(ip, cg, ipref, mode) len = start + 1; start = 0; loc = skpc(0xff, len, &cg_inosused(cgp)[0]); - if (loc == 0) { - printf("cg = %d, irotor = %d, fs = %s\n", - cg, cgp->cg_irotor, fs->fs_fsmnt); - panic("ffs_nodealloccg: map corrupted"); - /* NOTREACHED */ - } + assert (loc != 0); } i = start + len - loc; map = cg_inosused(cgp)[i]; @@ -1125,21 +1163,20 @@ ffs_nodealloccg(ip, cg, ipref, mode) goto gotit; } } - printf("fs = %s\n", fs->fs_fsmnt); - panic("ffs_nodealloccg: block not in map"); + assort (0); /* NOTREACHED */ gotit: setbit(cg_inosused(cgp), ipref); cgp->cg_cs.cs_nifree--; fs->fs_cstotal.cs_nifree--; - fs->fs_cs(fs, cg).cs_nifree--; + csum[cg].cs_nifree--; fs->fs_fmod = 1; if ((mode & IFMT) == IFDIR) { cgp->cg_cs.cs_ndir++; fs->fs_cstotal.cs_ndir++; - fs->fs_cs(fs, cg).cs_ndir++; + csum[cg].cs_ndir++; } - bdwrite(bp); +/* bdwrite(bp); */ return (cg * fs->fs_ipg + ipref); } @@ -1150,10 +1187,9 @@ gotit: * free map. If a fragment is deallocated, a possible * block reassembly is checked. */ -ffs_blkfree(ip, bno, size) - register struct inode *ip; - daddr_t bno; - long size; +ffs_blkfree(register struct node *np, + daddr_t bno, + long size) { register struct fs *fs; register struct cg *cgp; @@ -1161,18 +1197,15 @@ ffs_blkfree(ip, bno, size) daddr_t blkno; int i, error, cg, blk, frags, bbase; - 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", - ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); - panic("blkfree: bad size"); - } + fs = sblock; + assert ((u_int)size <= fs->fs_bsize && !fragoff (fs, size)); cg = dtog(fs, bno); if ((u_int)bno >= fs->fs_size) { - printf("bad block %d, ino %d\n", bno, ip->i_number); - ffs_fserr(fs, ip->i_uid, "bad block"); + printf("bad block %d, ino %d\n", bno, np->dn->number); +/* ffs_fserr(fs, ip->i_uid, "bad block"); */ return; } +#if 0 /* Not this way in GNU Hurd ufs */ error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, NOCRED, &bp); if (error) { @@ -1180,24 +1213,23 @@ ffs_blkfree(ip, bno, size) return; } cgp = (struct cg *)bp->b_data; +#else + cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); +#endif if (!cg_chkmagic(cgp)) { - brelse(bp); +/* brelse(bp); */ return; } cgp->cg_time = time.tv_sec; bno = dtogd(fs, bno); if (size == fs->fs_bsize) { blkno = fragstoblks(fs, bno); - if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) { - printf("dev = 0x%x, block = %d, fs = %s\n", - ip->i_dev, bno, fs->fs_fsmnt); - panic("blkfree: freeing free block"); - } + assert (!ffs_isblock(fs, cg_blksfree (cgp), blkno)); ffs_setblock(fs, cg_blksfree(cgp), blkno); ffs_clusteracct(fs, cgp, blkno, 1); cgp->cg_cs.cs_nbfree++; fs->fs_cstotal.cs_nbfree++; - fs->fs_cs(fs, cg).cs_nbfree++; + csum[cg].cs_nbfree++; i = cbtocylno(fs, bno); cg_blks(fs, cgp, i)[cbtorpos(fs, bno)]++; cg_blktot(cgp)[i]++; @@ -1213,16 +1245,12 @@ ffs_blkfree(ip, bno, size) */ frags = numfrags(fs, size); for (i = 0; i < frags; i++) { - if (isset(cg_blksfree(cgp), bno + i)) { - printf("dev = 0x%x, block = %d, fs = %s\n", - ip->i_dev, bno + i, fs->fs_fsmnt); - panic("blkfree: freeing free frag"); - } - setbit(cg_blksfree(cgp), bno + i); + assert (!isset (cg_blksfree(cgp, bno + i))); + setbit(cg_blksfree(cgp), bno + i); } cgp->cg_cs.cs_nffree += i; fs->fs_cstotal.cs_nffree += i; - fs->fs_cs(fs, cg).cs_nffree += i; + csum[cg].cs_nffree += i; /* * add back in counts associated with the new frags */ @@ -1235,18 +1263,18 @@ ffs_blkfree(ip, bno, size) if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) { cgp->cg_cs.cs_nffree -= fs->fs_frag; fs->fs_cstotal.cs_nffree -= fs->fs_frag; - fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; + csum[cg].cs_nffree -= fs->fs_frag; ffs_clusteracct(fs, cgp, blkno, 1); cgp->cg_cs.cs_nbfree++; fs->fs_cstotal.cs_nbfree++; - fs->fs_cs(fs, cg).cs_nbfree++; + csum[cg].cs_nbfree++; i = cbtocylno(fs, bbase); cg_blks(fs, cgp, i)[cbtorpos(fs, bbase)]++; cg_blktot(cgp)[i]++; } } fs->fs_fmod = 1; - bdwrite(bp); +/* bdwrite(bp); */ } /* @@ -1254,27 +1282,21 @@ ffs_blkfree(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; +/* Implement diskfs call back diskfs_free_node (described in + . This was called ffs_vfree in BSD. */ +void +diskfs_free_node (struct node *np, mode_t mode) { register struct fs *fs; register struct cg *cgp; - register struct inode *pip; - ino_t ino = ap->a_ino; + ino_t ino = np->dn->number; struct buf *bp; int error, cg; - 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); + fs = sblock; + assert (ino < fs->fs_ipg * fs->fs_ncg); cg = ino_to_cg(fs, ino); +#if 0 /* Not this way in GNU Hurd ufs */ error = bread(pip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, NOCRED, &bp); if (error) { @@ -1282,8 +1304,11 @@ ffs_vfree(ap) return (0); } cgp = (struct cg *)bp->b_data; +#else + cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); +#endif if (!cg_chkmagic(cgp)) { - brelse(bp); +/* brelse(bp); */ return (0); } cgp->cg_time = time.tv_sec; @@ -1291,22 +1316,21 @@ ffs_vfree(ap) if (isclr(cg_inosused(cgp), ino)) { printf("dev = 0x%x, ino = %d, fs = %s\n", pip->i_dev, ino, fs->fs_fsmnt); - if (fs->fs_ronly == 0) - panic("ifree: freeing free inode"); + assert (diskfs_readonly); } clrbit(cg_inosused(cgp), ino); if (ino < cgp->cg_irotor) cgp->cg_irotor = ino; cgp->cg_cs.cs_nifree++; fs->fs_cstotal.cs_nifree++; - fs->fs_cs(fs, cg).cs_nifree++; + csum[cg].cs_nifree++; if ((ap->a_mode & IFMT) == IFDIR) { cgp->cg_cs.cs_ndir--; fs->fs_cstotal.cs_ndir--; - fs->fs_cs(fs, cg).cs_ndir--; + csum[cg].cs_ndir--; } fs->fs_fmod = 1; - bdwrite(bp); +/* bdwrite(bp); */ return (0); } @@ -1317,11 +1341,10 @@ ffs_vfree(ap) * available. */ static daddr_t -ffs_mapsearch(fs, cgp, bpref, allocsiz) - register struct fs *fs; - register struct cg *cgp; - daddr_t bpref; - int allocsiz; +ffs_mapsearch(register struct fs *fs, + register struct cg *cgp, + daddr_t bpref, + int allocsiz) { daddr_t bno; int start, len, loc, i; @@ -1345,12 +1368,8 @@ ffs_mapsearch(fs, cgp, bpref, allocsiz) loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[0], (u_char *)fragtbl[fs->fs_frag], (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); - if (loc == 0) { - printf("start = %d, len = %d, fs = %s\n", - start, len, fs->fs_fsmnt); - panic("ffs_alloccg: map corrupted"); - /* NOTREACHED */ - } + assert (loc); + } bno = (start + len - loc) * NBBY; cgp->cg_frotor = bno; @@ -1370,8 +1389,7 @@ ffs_mapsearch(fs, cgp, bpref, allocsiz) subfield <<= 1; } } - printf("bno = %d, fs = %s\n", bno, fs->fs_fsmnt); - panic("ffs_alloccg: block not in map"); + assert (0); return (-1); } @@ -1380,11 +1398,10 @@ 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; - daddr_t blkno; - int cnt; +ffs_clusteracct(struct fs *fs, + struct cg *cgp, + daddr_t blkno, + int cnt) { long *sump; u_char *freemapp, *mapp; @@ -1457,6 +1474,7 @@ ffs_clusteracct(fs, cgp, blkno, cnt) sump[forw] -= cnt; } +#if 0 /* * Fserr prints the name of a file system with an error diagnostic. * @@ -1472,3 +1490,4 @@ ffs_fserr(fs, uid, cp) log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp); } +#endif -- cgit v1.2.3 From 2cfce87e9a8b27de0eeac18be9fa90b24bda6565 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 15 Jul 1994 17:23:00 +0000 Subject: Formerly alloc.c.~13~ --- ufs/alloc.c | 112 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 61 insertions(+), 51 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 7dfe5785..8afa6aa7 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -66,6 +66,17 @@ extern u_long nextgennumber; spin_lock_t alloclock = SPIN_LOCK_INITIALIZER; +/* Forward declarations */ +static u_long ffs_hashalloc (struct node *, int, long, int, + u_long (*)(struct node *, int, daddr_t, int)); +static u_long ffs_alloccg (struct node *, int, daddr_t, int); +static daddr_t ffs_fragextend (struct node *, int, long, int, int); +static ino_t ffs_dirpref (struct fs *); +static u_long ffs_nodealloccg (struct node *, int, daddr_t, int); +static daddr_t ffs_alloccgblk (struct fs *, struct cg *, daddr_t); +static daddr_t ffs_mapsearch (struct fs *, struct cg *, daddr_t, int); +void ffs_clusteracct (struct fs *, struct cg *, daddr_t, int); + /* * Allocate a block in the file system. * @@ -85,6 +96,7 @@ spin_lock_t alloclock = SPIN_LOCK_INITIALIZER; * 2) quadradically rehash into other cylinder groups, until an * available block is located. */ +error_t ffs_alloc(register struct node *np, daddr_t lbn, daddr_t bpref, @@ -94,7 +106,7 @@ ffs_alloc(register struct node *np, { register struct fs *fs; daddr_t bno; - int cg, error; + int cg; *bnp = 0; fs = sblock; @@ -154,16 +166,18 @@ nospace: * the original block. Failing that, the regular block allocator is * invoked to get an appropriate block. */ +error_t ffs_realloccg(register struct node *np, daddr_t lbprev, - daddr_t bpref, + volatile daddr_t bpref, int osize, int nsize, daddr_t *pbn, struct protid *cred) { register struct fs *fs; - int cg, request, error; + int cg, error; + volatile int request; daddr_t bprev, bno; *pbn = 0; @@ -182,7 +196,7 @@ ffs_realloccg(register struct node *np, spin_lock (&alloclock); - if (!isuid (0, cred) && freespace(fs, fs->fs_minfree) <= 0) + if (!diskfs_isuid (0, cred) && freespace(fs, fs->fs_minfree) <= 0) goto nospace; if (error = diskfs_catch_exception ()) return error; @@ -244,7 +258,7 @@ ffs_realloccg(register struct node *np, fs->fs_cstotal.cs_nffree > fs->fs_dsize * fs->fs_minfree / (2 * 100)) break; - log(LOG_NOTICE, "%s: optimization changed from SPACE to TIME\n", + printf ("%s: optimization changed from SPACE to TIME\n", fs->fs_fsmnt); fs->fs_optim = FS_OPTTIME; break; @@ -263,13 +277,11 @@ ffs_realloccg(register struct node *np, if (fs->fs_cstotal.cs_nffree < fs->fs_dsize * (fs->fs_minfree - 2) / 100) break; - log(LOG_NOTICE, "%s: optimization changed from TIME to SPACE\n", + printf ("%s: optimization changed from TIME to SPACE\n", fs->fs_fsmnt); fs->fs_optim = FS_OPTSPACE; break; default: - printf("dev = 0x%x, optim = %d, fs = %s\n", - ip->i_dev, fs->fs_optim, fs->fs_fsmnt); assert (0); /* NOTREACHED */ } @@ -505,9 +517,10 @@ diskfs_alloc_node (struct node *dir, struct node **npp) { register struct fs *fs; - register struct node *np; + struct node *np; ino_t ino, ipref; int cg, error; + int sex; fs = sblock; @@ -537,18 +550,19 @@ diskfs_alloc_node (struct node *dir, assert ("duplicate allocation" && !np->dn_stat.st_mode); if (np->dn_stat.st_blocks) { printf("free inode %d had %d blocks\n", - ino, ip->i_blocks); + ino, np->dn_stat.st_blocks); np->dn_stat.st_blocks = 0; np->dn_set_ctime = 1; } - ip->i_flags = 0; + np->dn_stat.st_flags = 0; /* * Set up a new generation number for this inode. */ spin_lock (&gennumberlock); - if (++nextgennumber < (u_long)time.tv_sec) - nextgennumber = time.tv_sec; - ip->i_gen = nextgennumber; + sex = diskfs_mtime->seconds; + if (++nextgennumber < (u_long)sex) + nextgennumber = sex; + np->dn_stat.st_gen = nextgennumber; spin_unlock (&gennumberlock); return (0); noinodes: @@ -652,7 +666,7 @@ ffs_blkpref(struct node *np, return (fs->fs_fpg * cg + fs->fs_frag); } spin_unlock (&alloclock); - return (NULL); + return 0; } spin_unlock (&alloclock); /* @@ -731,7 +745,7 @@ ffs_hashalloc(struct node *np, if (cg == fs->fs_ncg) cg = 0; } - return (NULL); + return 0; } /* @@ -749,19 +763,18 @@ ffs_fragextend(struct node *np, { register struct fs *fs; register struct cg *cgp; - struct buf *bp; long bno; int frags, bbase; - int i, error; + int i; fs = sblock; if (csum[cg].cs_nffree < numfrags(fs, nsize - osize)) - return (NULL); + return 0; frags = numfrags(fs, nsize); bbase = fragnum(fs, bprev); if (bbase > fragnum(fs, (bprev + frags - 1))) { /* cannot extend across a block boundary */ - return (NULL); + return 0; } #if 0 /* Wrong for GNU Hurd ufs */ error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), @@ -776,14 +789,14 @@ ffs_fragextend(struct node *np, #endif if (!cg_chkmagic(cgp)) { /* brelse(bp); */ - return (NULL); + return 0; } cgp->cg_time = diskfs_mtime->seconds; bno = dtogd(fs, bprev); for (i = numfrags(fs, osize); i < frags; i++) if (isclr(cg_blksfree(cgp), bno + i)) { /* brelse(bp); */ - return (NULL); + return 0; } /* * the current fragment can be extended @@ -814,7 +827,7 @@ ffs_fragextend(struct node *np, * Check to see if a block of the appropriate size is available, * and if it is, allocate it. */ -static daddr_t +static u_long ffs_alloccg(struct node *np, int cg, daddr_t bpref, @@ -822,13 +835,12 @@ ffs_alloccg(struct node *np, { register struct fs *fs; register struct cg *cgp; - struct buf *bp; register int i; - int error, bno, frags, allocsiz; + int bno, frags, allocsiz; fs = sblock; if (csum[cg].cs_nbfree == 0 && size == fs->fs_bsize) - return (NULL); + return 0; #if 0 /* Not this way in GNU Hurd ufs */ error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, NOCRED, &bp); @@ -843,7 +855,7 @@ ffs_alloccg(struct node *np, if (!cg_chkmagic(cgp) || (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) { /* brelse(bp); */ - return (NULL); + return 0; } cgp->cg_time = diskfs_mtime->seconds; if (size == fs->fs_bsize) { @@ -867,7 +879,7 @@ ffs_alloccg(struct node *np, */ if (cgp->cg_cs.cs_nbfree == 0) { /* brelse(bp); */ - return (NULL); + return 0; } bno = ffs_alloccgblk(fs, cgp, bpref); bpref = dtogd(fs, bno); @@ -884,8 +896,8 @@ ffs_alloccg(struct node *np, } bno = ffs_mapsearch(fs, cgp, bpref, allocsiz); if (bno < 0) { -/* brelse(bp);* / - return (NULL); +/* brelse(bp); */ + return 0; } for (i = 0; i < frags; i++) clrbit(cg_blksfree(cgp), bno + i); @@ -994,7 +1006,7 @@ norot: */ bno = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag); if (bno < 0) - return (NULL); + return 0; cgp->cg_rotor = bno; gotit: blkno = fragstoblks(fs, bno); @@ -1110,7 +1122,7 @@ fail: * 2) allocate the next available inode after the requested * inode in the specified cylinder group. */ -static ino_t +static u_long ffs_nodealloccg(struct node *np, int cg, daddr_t ipref, @@ -1118,12 +1130,11 @@ ffs_nodealloccg(struct node *np, { register struct fs *fs; register struct cg *cgp; - struct buf *bp; - int error, start, len, loc, map, i; + int start, len, loc, map, i; fs = sblock; if (csum[cg].cs_nifree == 0) - return (NULL); + return 0; #if 0 /* Not this way in GNU Hurd ufs */ error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, NOCRED, &bp); @@ -1137,9 +1148,9 @@ ffs_nodealloccg(struct node *np, #endif if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) { /* brelse(bp); */ - return (NULL); + return 0; } - cgp->cg_time = time.tv_sec; + cgp->cg_time = diskfs_mtime->seconds; if (ipref) { ipref %= fs->fs_ipg; if (isclr(cg_inosused(cgp), ipref)) @@ -1163,7 +1174,7 @@ ffs_nodealloccg(struct node *np, goto gotit; } } - assort (0); + assert (0); /* NOTREACHED */ gotit: setbit(cg_inosused(cgp), ipref); @@ -1187,21 +1198,21 @@ gotit: * free map. If a fragment is deallocated, a possible * block reassembly is checked. */ +void ffs_blkfree(register struct node *np, daddr_t bno, long size) { register struct fs *fs; register struct cg *cgp; - struct buf *bp; daddr_t blkno; - int i, error, cg, blk, frags, bbase; + int i, cg, blk, frags, bbase; fs = sblock; assert ((u_int)size <= fs->fs_bsize && !fragoff (fs, size)); cg = dtog(fs, bno); if ((u_int)bno >= fs->fs_size) { - printf("bad block %d, ino %d\n", bno, np->dn->number); + printf("bad block %ld, ino %d\n", bno, np->dn->number); /* ffs_fserr(fs, ip->i_uid, "bad block"); */ return; } @@ -1220,7 +1231,7 @@ ffs_blkfree(register struct node *np, /* brelse(bp); */ return; } - cgp->cg_time = time.tv_sec; + cgp->cg_time = diskfs_mtime->seconds; bno = dtogd(fs, bno); if (size == fs->fs_bsize) { blkno = fragstoblks(fs, bno); @@ -1245,7 +1256,7 @@ ffs_blkfree(register struct node *np, */ frags = numfrags(fs, size); for (i = 0; i < frags; i++) { - assert (!isset (cg_blksfree(cgp, bno + i))); + assert (!isset (cg_blksfree(cgp), bno + i)); setbit(cg_blksfree(cgp), bno + i); } cgp->cg_cs.cs_nffree += i; @@ -1290,8 +1301,7 @@ diskfs_free_node (struct node *np, mode_t mode) register struct fs *fs; register struct cg *cgp; ino_t ino = np->dn->number; - struct buf *bp; - int error, cg; + int cg; fs = sblock; assert (ino < fs->fs_ipg * fs->fs_ncg); @@ -1309,13 +1319,13 @@ diskfs_free_node (struct node *np, mode_t mode) #endif if (!cg_chkmagic(cgp)) { /* brelse(bp); */ - return (0); + return; } - cgp->cg_time = time.tv_sec; + cgp->cg_time = diskfs_mtime->seconds; ino %= fs->fs_ipg; if (isclr(cg_inosused(cgp), ino)) { - printf("dev = 0x%x, ino = %d, fs = %s\n", - pip->i_dev, ino, fs->fs_fsmnt); +/* printf("dev = 0x%x, ino = %d, fs = %s\n", + pip->i_dev, ino, fs->fs_fsmnt); */ assert (diskfs_readonly); } clrbit(cg_inosused(cgp), ino); @@ -1324,14 +1334,13 @@ diskfs_free_node (struct node *np, mode_t mode) cgp->cg_cs.cs_nifree++; fs->fs_cstotal.cs_nifree++; csum[cg].cs_nifree++; - if ((ap->a_mode & IFMT) == IFDIR) { + if ((mode & IFMT) == IFDIR) { cgp->cg_cs.cs_ndir--; fs->fs_cstotal.cs_ndir--; csum[cg].cs_ndir--; } fs->fs_fmod = 1; /* bdwrite(bp); */ - return (0); } /* @@ -1398,6 +1407,7 @@ ffs_mapsearch(register struct fs *fs, * * Cnt == 1 means free; cnt == -1 means allocating. */ +void ffs_clusteracct(struct fs *fs, struct cg *cgp, daddr_t blkno, -- cgit v1.2.3 From 5c1e6655a532185b661a90fd6380b9334575f77e Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 18 Aug 1994 16:40:57 +0000 Subject: Formerly alloc.c.~14~ --- ufs/alloc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 8afa6aa7..19389afe 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -564,6 +564,8 @@ diskfs_alloc_node (struct node *dir, nextgennumber = sex; np->dn_stat.st_gen = nextgennumber; spin_unlock (&gennumberlock); + + *npp = np; return (0); noinodes: printf ("out of inodes"); -- cgit v1.2.3 From 5fbf0f632993ae920b695b2be3585fcd80f5baf1 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 23 Sep 1994 01:29:06 +0000 Subject: Formerly alloc.c.~15~ --- ufs/alloc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 19389afe..2d27c1e7 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -200,7 +200,7 @@ ffs_realloccg(register struct node *np, goto nospace; if (error = diskfs_catch_exception ()) return error; - bprev = dinodes[np->dn->number].di_db[lbprev]; + bprev = (dino (np->dn->number))->di_db[lbprev]; diskfs_end_catch_exception (); assert ("old block not allocated" && bprev); @@ -787,7 +787,7 @@ ffs_fragextend(struct node *np, } cgp = (struct cg *)bp->b_data; #else - cgp = (struct cg *) (cgs + sblock->fs_bsize * cg); + cgp = cg_locate (cg); #endif if (!cg_chkmagic(cgp)) { /* brelse(bp); */ @@ -852,7 +852,7 @@ ffs_alloccg(struct node *np, } cgp = (struct cg *)bp->b_data; #else - cgp = (struct cg *) (cgs + sblock->fs_bsize * cg); + cgp = cg_locate (cg); #endif if (!cg_chkmagic(cgp) || (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) { @@ -1146,7 +1146,7 @@ ffs_nodealloccg(struct node *np, } cgp = (struct cg *)bp->b_data; #else - cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); + cgp = cg_locate (cg); #endif if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) { /* brelse(bp); */ @@ -1227,7 +1227,7 @@ ffs_blkfree(register struct node *np, } cgp = (struct cg *)bp->b_data; #else - cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); + cgp = cg_locate (cg); #endif if (!cg_chkmagic(cgp)) { /* brelse(bp); */ @@ -1317,7 +1317,7 @@ diskfs_free_node (struct node *np, mode_t mode) } cgp = (struct cg *)bp->b_data; #else - cgp = (struct cg *)(cgs + sblock->fs_bsize * cg); + cgp = cg_locate (cg); #endif if (!cg_chkmagic(cgp)) { /* brelse(bp); */ -- cgit v1.2.3 From 7d0599b3ffb4a08bfdcdaf8e0383f05c58517b51 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 23 Sep 1994 21:50:13 +0000 Subject: Formerly alloc.c.~16~ --- ufs/alloc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 2d27c1e7..b7c1ec40 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -54,7 +54,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ */ #include "ufs.h" -#include "fs.h" #include "dinode.h" #include -- cgit v1.2.3 From 6ef59be7e2ab2cdb8a80356ea45e4b1218610c62 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 27 Sep 1994 02:51:54 +0000 Subject: Formerly alloc.c.~17~ --- ufs/alloc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index b7c1ec40..c881454b 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -54,7 +54,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ */ #include "ufs.h" -#include "dinode.h" #include /* These don't work *at all* here; don't even try setting them. */ -- cgit v1.2.3 From da152d2b61bf591ce23d89b40db10a92989159b5 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Wed, 5 Oct 1994 16:58:39 +0000 Subject: Formerly alloc.c.~18~ --- ufs/alloc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index c881454b..4464dfa0 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -546,6 +546,7 @@ diskfs_alloc_node (struct node *dir, goto noinodes; error = iget (ino, &np); assert ("duplicate allocation" && !np->dn_stat.st_mode); + assert (!np->istranslated); if (np->dn_stat.st_blocks) { printf("free inode %d had %d blocks\n", ino, np->dn_stat.st_blocks); -- cgit v1.2.3 From 59fe81bbe11821d0c0f70e3caecb6164437d7ae5 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 25 Oct 1994 16:54:36 +0000 Subject: entered into RCS --- ufs/alloc.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 4464dfa0..b82d6065 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -817,6 +817,9 @@ ffs_fragextend(struct node *np, fs->fs_cstotal.cs_nffree--; csum[cg].cs_nffree--; } + record_poke (cgp, sblock->fs_cgsize); + csum_dirty = 1; + sblock_dirty = 1; fs->fs_fmod = 1; /* bdwrite(bp); */ return (bprev); @@ -892,6 +895,10 @@ ffs_alloccg(struct node *np, csum[cg].cs_nffree += i; fs->fs_fmod = 1; cgp->cg_frsum[i]++; + + record_poke (cgp, sblock->fs_cgsize); + csum_dirty = 1; + sblock_dirty = 1; /* bdwrite(bp); */ return (bno); } @@ -909,6 +916,9 @@ ffs_alloccg(struct node *np, cgp->cg_frsum[allocsiz]--; if (frags != allocsiz) cgp->cg_frsum[allocsiz - frags]++; + record_poke (cgp, sblock->fs_cgsize); + csum_dirty = 1; + sblock_dirty = 1; /* bdwrite(bp); */ return (cg * fs->fs_fpg + bno); } @@ -1020,6 +1030,9 @@ gotit: cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--; cg_blktot(cgp)[cylno]--; fs->fs_fmod = 1; + record_poke (cgp, sblock->fs_cgsize); + csum_dirty = 1; + sblock_dirty = 1; return (cgp->cg_cgx * fs->fs_fpg + bno); } @@ -1188,6 +1201,9 @@ gotit: fs->fs_cstotal.cs_ndir++; csum[cg].cs_ndir++; } + record_poke (cgp, sblock->fs_cgsize); + csum_dirty = 1; + sblock_dirty = 1; /* bdwrite(bp); */ return (cg * fs->fs_ipg + ipref); } @@ -1285,6 +1301,9 @@ ffs_blkfree(register struct node *np, cg_blktot(cgp)[i]++; } } + record_poke (cgp, sblock->fs_cgsize); + csum_dirty = 1; + sblock_dirty = 1; fs->fs_fmod = 1; /* bdwrite(bp); */ } @@ -1340,6 +1359,9 @@ diskfs_free_node (struct node *np, mode_t mode) fs->fs_cstotal.cs_ndir--; csum[cg].cs_ndir--; } + record_poke (cgp, sblock->fs_cgsize); + csum_dirty = 1; + sblock_dirty = 1; fs->fs_fmod = 1; /* bdwrite(bp); */ } -- cgit v1.2.3 From 28d8598ef9e75e22031141cae694ece08af6730e Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 17 Mar 1995 19:31:00 +0000 Subject: (ffs_clusteracct): Make static. (alloc_sync): New function. (ffs_alloc): Call alloc_sync. (ffs_realloccg): Likewise. (diskfs_alloc_node): Likewise. (ffs_blkfree): Likewise. (diskfs_free_node): Likewise. --- ufs/alloc.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index b82d6065..9fa517ed 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -1,5 +1,5 @@ /* Disk allocation routines - Copyright (C) 1993, 1994 Free Software Foundation + Copyright (C) 1993, 1994, 1995 Free Software Foundation This file is part of the GNU Hurd. @@ -73,7 +73,21 @@ static ino_t ffs_dirpref (struct fs *); static u_long ffs_nodealloccg (struct node *, int, daddr_t, int); static daddr_t ffs_alloccgblk (struct fs *, struct cg *, daddr_t); static daddr_t ffs_mapsearch (struct fs *, struct cg *, daddr_t, int); -void ffs_clusteracct (struct fs *, struct cg *, daddr_t, int); +static void ffs_clusteracct (struct fs *, struct cg *, daddr_t, int); + +/* Sync all allocation information and nod eNP if diskfs_synchronous. */ +inline +alloc_sync (struct diskfs_node *np) +{ + if (diskfs_syncronous) + { + if (np) + diskfs_node_update (np, 1); + copy_sblock (); + diskfs_set_dypermetadata (1, 0); + sync_disk (1); + } +} /* * Allocate a block in the file system. @@ -140,6 +154,7 @@ ffs_alloc(register struct node *np, np->dn_set_ctime = 1; np->dn_set_mtime = 1; *bnp = bno; + alloc_sync (np); return (0); } #ifdef QUOTA @@ -235,6 +250,7 @@ ffs_realloccg(register struct node *np, bzero((char *)bp->b_data + osize, (u_int)nsize - osize); *bpp = bp; #endif + alloc_sync (np); return (0); } /* @@ -305,6 +321,7 @@ ffs_realloccg(register struct node *np, bzero((char *)bp->b_data + osize, (u_int)nsize - osize); *bpp = bp; #endif /* 0 */ + alloc_sync (np); return (0); } #ifdef QUOTA @@ -565,6 +582,7 @@ diskfs_alloc_node (struct node *dir, spin_unlock (&gennumberlock); *npp = np; + alloc_sync (np); return (0); noinodes: printf ("out of inodes"); @@ -1305,6 +1323,7 @@ ffs_blkfree(register struct node *np, csum_dirty = 1; sblock_dirty = 1; fs->fs_fmod = 1; + alloc_sync (np); /* bdwrite(bp); */ } @@ -1363,6 +1382,7 @@ diskfs_free_node (struct node *np, mode_t mode) csum_dirty = 1; sblock_dirty = 1; fs->fs_fmod = 1; + alloc_sync (np, 1); /* bdwrite(bp); */ } @@ -1430,7 +1450,7 @@ ffs_mapsearch(register struct fs *fs, * * Cnt == 1 means free; cnt == -1 means allocating. */ -void +static void ffs_clusteracct(struct fs *fs, struct cg *cgp, daddr_t blkno, -- cgit v1.2.3 From 08eb992b1fdc4285ca49b31fb51a0a844ba03c42 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 17 Mar 1995 19:36:46 +0000 Subject: (alloc_sync): Typo. --- ufs/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 9fa517ed..39344501 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -77,7 +77,7 @@ static void ffs_clusteracct (struct fs *, struct cg *, daddr_t, int); /* Sync all allocation information and nod eNP if diskfs_synchronous. */ inline -alloc_sync (struct diskfs_node *np) +alloc_sync (struct node *np) { if (diskfs_syncronous) { -- cgit v1.2.3 From bb2bd7c4d2c7e834529383b0036373faf4cd035d Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 17 Mar 1995 19:37:52 +0000 Subject: More typos. --- ufs/alloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 39344501..87b0b45a 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -76,15 +76,15 @@ static daddr_t ffs_mapsearch (struct fs *, struct cg *, daddr_t, int); static void ffs_clusteracct (struct fs *, struct cg *, daddr_t, int); /* Sync all allocation information and nod eNP if diskfs_synchronous. */ -inline +inline void alloc_sync (struct node *np) { - if (diskfs_syncronous) + if (diskfs_synchronous) { if (np) diskfs_node_update (np, 1); copy_sblock (); - diskfs_set_dypermetadata (1, 0); + diskfs_set_hypermetadata (1, 0); sync_disk (1); } } @@ -1382,7 +1382,7 @@ diskfs_free_node (struct node *np, mode_t mode) csum_dirty = 1; sblock_dirty = 1; fs->fs_fmod = 1; - alloc_sync (np, 1); + alloc_sync (np); /* bdwrite(bp); */ } -- cgit v1.2.3 From 12235ec5d3b87c11782d39732209a39bb1e55381 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 20 Jun 1995 15:48:44 +0000 Subject: (ffs_realloccg): Remove assignments from if tests. --- ufs/alloc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 87b0b45a..add588ee 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -211,7 +211,8 @@ ffs_realloccg(register struct node *np, if (!diskfs_isuid (0, cred) && freespace(fs, fs->fs_minfree) <= 0) goto nospace; - if (error = diskfs_catch_exception ()) + error = diskfs_catch_exception (); + if (error) return error; bprev = (dino (np->dn->number))->di_db[lbprev]; diskfs_end_catch_exception (); @@ -237,7 +238,8 @@ ffs_realloccg(register struct node *np, * Check for extension in the existing location. */ cg = dtog(fs, bprev); - if (bno = ffs_fragextend(np, cg, (long)bprev, osize, nsize)) { + bno = ffs_fragextend(np, cg, (long)bprev, osize, nsize); + if (bno) assert (bno == bprev); spin_unlock (&alloclock); np->dn_stat.st_blocks += btodb(nsize - osize); -- cgit v1.2.3 From 84752530e00bd9cbd7d1864154802b0261a15df5 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 20 Jun 1995 16:02:30 +0000 Subject: (ffs_realloccg): Fix typo. --- ufs/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index add588ee..8f6a5baf 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -239,7 +239,7 @@ ffs_realloccg(register struct node *np, */ cg = dtog(fs, bprev); bno = ffs_fragextend(np, cg, (long)bprev, osize, nsize); - if (bno) + if (bno) { assert (bno == bprev); spin_unlock (&alloclock); np->dn_stat.st_blocks += btodb(nsize - osize); -- cgit v1.2.3 From b69508c00daf432e4d21e72800ac58f950b967d4 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 18 Apr 1996 19:06:20 +0000 Subject: (ffs_realloccg): If we are allocating a new block, don't actually free the old one here. --- ufs/alloc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 8f6a5baf..4cbac331 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -1,5 +1,5 @@ /* Disk allocation routines - Copyright (C) 1993, 1994, 1995 Free Software Foundation + Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation This file is part of the GNU Hurd. @@ -308,7 +308,10 @@ ffs_realloccg(register struct node *np, bp->b_blkno = fsbtodb(fs, bno); (void) vnode_pager_uncache(ITOV(ip)); #endif - ffs_blkfree(np, bprev, (long)osize); +/* Commented out here for Hurd; we don't want to free this until we've + saved the old contents. Callers are responsible for freeing the + block when they are done with it. */ +/* ffs_blkfree(np, bprev, (long)osize); */ if (nsize < request) ffs_blkfree(np, bno + numfrags(fs, nsize), (long)(request - nsize)); @@ -563,7 +566,7 @@ diskfs_alloc_node (struct node *dir, spin_unlock (&alloclock); if (ino == 0) goto noinodes; - error = iget (ino, &np); + error = diskfs_cached_lookup (ino, &np); assert ("duplicate allocation" && !np->dn_stat.st_mode); assert (!np->istranslated); if (np->dn_stat.st_blocks) { -- cgit v1.2.3 From 5f9cfa422098196ff6b98656fe192193d4f699bb Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Apr 1996 17:59:46 +0000 Subject: (ffs_realloccg): Use read/write_disk_entry when reading/writing on-disk inode fields. (ffs_blkpref): Use read_disk_entry when reading from BAP array. (swab_cg, read_cg, release_cg): New functions. (ffs_fragextend, ffs_alloccg, ffs_nodealloccg, ffs_blkfree, diskfs_free_node): Use new cg access functions. --- ufs/alloc.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 158 insertions(+), 10 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 4cbac331..fdd0aa59 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -89,6 +89,117 @@ alloc_sync (struct node *np) } } +/* Byteswap everything in CGP. */ +void +swab_cg (struct cg *cgp) +{ + int i, j; + + if (swab_long (cg->cg_magic) == CG_MAGIC + || cg->cg_magic == CG_MAGIC) + { + cg->cg_magic = swab_long (cg->cg_magic); + cg->cg_time = swab_long (cg->cg_time); + cg->cg_cgx = swab_long (cg->cg_cgx); + cg->cg_ncyl = swab_short (cg->cg_ncyl); + cg->cg_niblk = swab_short (cg->cg_niblk); + cg->cg_cs.cs_ndir = swab_long (cg->cg_cs.cs_ndir); + cg->cg_cs.cs_nbfree = swab_long (cg->cg_cs.cs_nbfree); + cg->cg_cs.cs_nifree = swab_long (cg->cg_cs.cs_nifree); + cg->cg_cs.cs_nffree = swab_long (cg->cg_cs.cs_nffree); + cg->cg_rotor = swab_long (cg->cg_rotor); + cg->cg_irotor = swab_long (cg->cg_irotor); + for (i = 0; i < MAXFRAG; i++) + cg->cg_frsum[i] = swab_long (cg->cg_frsum[i]); + cg->cg_btotoff = swab_long (cg->cg_btotoff); + cg->cg_boff = swab_long (cg->cg_boff); + cg->cg_iusedoff = swab_long (cg->cg_iusedoff); + cg->cg_freeoff = swab_long (cg->cg_freeoff); + cg->cg_nextfreeoff = swab_long (cg->cg_nextfreeoff); + cg->cg_clustersumoff = swab_long (cg->cg_clustersumoff); + cg->cg_clusteroff = swab_long (cg->cg_clusteroff); + cg->cg_nclusterblks = swab_long (cg->cg_nclusterblks); + + /* blktot map */ + for (i = 0; i < cg->cg_ncyl; i++) + cg_blktot(cg)[i] = swab_long (cg_blktot(cg)[i]); + + /* blks map */ + for (i = 0; i < cg->cg_ncyl; i++) + for (j = 0; j < sblock->fs_nrpos; j++) + cg_blks(sblock, cg, i)[j] = swab_short (cg_blks (sblock, cg, i)[j]); + + for (i = 0; i < sblock->fs_contigsumsize; i++) + cg_clustersum(cg)[i] = swab_long (cg_clustersum(cg)[i]); + + /* inosused, blksfree, and cg_clustersfree are char arrays */ + } + else + { + /* Old format cylinder group... */ + struct ocg *ocg = cg; + + if (swab_long (ocg->cg_magic) != CG_MAGIC + && ocg->cg_magic != CG_MAGIC) + return; + + ocg->cg_time = swab_long (ocg->cg_time); + ocg->cg_cgx = swab_long (ocg->cg_cgx); + ocg->cg_ncyl = swab_short (ocg->cg_ncyl); + ocg->cg_niblk = swab_short (ocg->cg_niblk); + ocg->cg_ndblk = swab_long (ocg->cg_ndblk); + ocg->cg_cs.cs_ndir = swab_long (ocg->cg_cs.cs_ndir); + ocg->cg_cs.cs_nbfree = swab_long (ocg->cg_cs.cs_nbfree); + ocg->cg_cs.cs_nifree = swab_long (ocg->cg_cs.cs_nifree); + ocg->cg_cs.cs_nffree = swab_long (ocg->cg_cs.cs_nffree); + ocg->cg_rotor = swab_long (ocg->cg_rotor); + ocg->cg_frotor = swab_long (ocg->cg_frotor); + ocg->cg_irotor = swab_long (ocg->cg_irotor); + for (i = 0; i < 8; i++) + ocg->cg_frsum[i] = swab_long (ocg->cg_frsum[i]); + for (i = 0; i < 32; i++) + ocg->cg_btot[i] = swab_long (ocg->cg_btot[i]); + for (i = 0; i < 32; i++) + for (j = 0; j < 8; j++) + ocg->cg_b[i][j] = swab_short (ocg->cg_b[i][j]); + ocg->cg_magic = swab_long (ocg->cg_magic); + } +} + + +/* Read cylinder group indexed CG. Set *CGPP to point at it. + Return 1 if caller should call release_cgp when we're done with it; + otherwise zero. */ +int +read_cg (int cg, struct cg **cgpp) +{ + struct cg *diskcg = cg_locate (cg); + + if (swab_disk) + { + *cgp = malloc (sblock->fs_cgsize); + bcopy (diskcg, *cgp, sblock->fs_cgsize); + swab_cg (*cgp); + return 1; + } + else + { + *cgp = diskcg; + return 0; + } +} + +/* Caller of read_cg is done with cg; write it back to disk (swapping it + along the way) and free the memory allocated in read_cg. */ +void +release_cgp (struct cg *cgp) +{ + swab_cg (cgp); + bcopy (cgp, cg_locate (cg), sblock->fs_cgsize); + free (cgp); +} + + /* * Allocate a block in the file system. * @@ -214,7 +325,7 @@ ffs_realloccg(register struct node *np, error = diskfs_catch_exception (); if (error) return error; - bprev = (dino (np->dn->number))->di_db[lbprev]; + bprev = read_disk_entry ((dino (np->dn->number))->di_db[lbprev]); diskfs_end_catch_exception (); assert ("old block not allocated" && bprev); @@ -674,7 +785,8 @@ ffs_blkpref(struct node *np, (ino_to_cg(fs, np->dn->number) + lbn / fs->fs_maxbpg); else - startcg = dtog(fs, bap[indx - 1]) + 1; + startcg = dtog(fs, + read_disk_entry (bap[indx - 1])) + 1; startcg %= fs->fs_ncg; avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; for (cg = startcg; cg < fs->fs_ncg; cg++) @@ -699,9 +811,10 @@ ffs_blkpref(struct node *np, * next block is requested contiguously, otherwise it is * 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) + nextblk = read_disk_entry (bap[indx - 1]) + fs->fs_frag; + if (indx < fs->fs_maxcontig + || (read_disk_entry (bap[indx - fs->fs_maxcontig]) + + blkstofrags(fs, fs->fs_maxcontig) != nextblk)) { return (nextblk); } @@ -790,6 +903,7 @@ ffs_fragextend(struct node *np, long bno; int frags, bbase; int i; + int releasecg; fs = sblock; if (csum[cg].cs_nffree < numfrags(fs, nsize - osize)) @@ -809,10 +923,12 @@ ffs_fragextend(struct node *np, } cgp = (struct cg *)bp->b_data; #else - cgp = cg_locate (cg); + releasecg = read_cg (cg, &cgp); #endif if (!cg_chkmagic(cgp)) { /* brelse(bp); */ + if (releasecg) + release_cg (cgp); return 0; } cgp->cg_time = diskfs_mtime->seconds; @@ -820,6 +936,8 @@ ffs_fragextend(struct node *np, for (i = numfrags(fs, osize); i < frags; i++) if (isclr(cg_blksfree(cgp), bno + i)) { /* brelse(bp); */ + if (releasecg) + release_cg (cgp); return 0; } /* @@ -840,6 +958,8 @@ ffs_fragextend(struct node *np, fs->fs_cstotal.cs_nffree--; csum[cg].cs_nffree--; } + if (releasecg) + release_cg (cgp); record_poke (cgp, sblock->fs_cgsize); csum_dirty = 1; sblock_dirty = 1; @@ -864,6 +984,7 @@ ffs_alloccg(struct node *np, register struct cg *cgp; register int i; int bno, frags, allocsiz; + int releasecg; fs = sblock; if (csum[cg].cs_nbfree == 0 && size == fs->fs_bsize) @@ -877,17 +998,21 @@ ffs_alloccg(struct node *np, } cgp = (struct cg *)bp->b_data; #else - cgp = cg_locate (cg); + releasecg = read_cg (cg, &cgp); #endif if (!cg_chkmagic(cgp) || (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) { /* brelse(bp); */ + if (releasecg) + release_cg (cgp); return 0; } cgp->cg_time = diskfs_mtime->seconds; if (size == fs->fs_bsize) { bno = ffs_alloccgblk(fs, cgp, bpref); /* bdwrite(bp); */ + if (releasecg) + release_cg (cgp); return (bno); } /* @@ -906,6 +1031,8 @@ ffs_alloccg(struct node *np, */ if (cgp->cg_cs.cs_nbfree == 0) { /* brelse(bp); */ + if (releasecg) + release_cg (cgp); return 0; } bno = ffs_alloccgblk(fs, cgp, bpref); @@ -919,6 +1046,8 @@ ffs_alloccg(struct node *np, fs->fs_fmod = 1; cgp->cg_frsum[i]++; + if (releasecg) + release_cg (cgp) record_poke (cgp, sblock->fs_cgsize); csum_dirty = 1; sblock_dirty = 1; @@ -928,6 +1057,8 @@ ffs_alloccg(struct node *np, bno = ffs_mapsearch(fs, cgp, bpref, allocsiz); if (bno < 0) { /* brelse(bp); */ + if (releasecg) + release_cg (cgp); return 0; } for (i = 0; i < frags; i++) @@ -939,6 +1070,8 @@ ffs_alloccg(struct node *np, cgp->cg_frsum[allocsiz]--; if (frags != allocsiz) cgp->cg_frsum[allocsiz - frags]++; + if (releasecg) + release_cg (cgp); record_poke (cgp, sblock->fs_cgsize); csum_dirty = 1; sblock_dirty = 1; @@ -1168,6 +1301,7 @@ ffs_nodealloccg(struct node *np, register struct fs *fs; register struct cg *cgp; int start, len, loc, map, i; + int releasecg; fs = sblock; if (csum[cg].cs_nifree == 0) @@ -1181,10 +1315,12 @@ ffs_nodealloccg(struct node *np, } cgp = (struct cg *)bp->b_data; #else - cgp = cg_locate (cg); + releasecg = read_cg (cg, &cgp); #endif if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) { /* brelse(bp); */ + if (releasecg) + release_cg (cg); return 0; } cgp->cg_time = diskfs_mtime->seconds; @@ -1224,6 +1360,8 @@ gotit: fs->fs_cstotal.cs_ndir++; csum[cg].cs_ndir++; } + if (releasecg) + release_cg (cgp); record_poke (cgp, sblock->fs_cgsize); csum_dirty = 1; sblock_dirty = 1; @@ -1247,6 +1385,7 @@ ffs_blkfree(register struct node *np, register struct cg *cgp; daddr_t blkno; int i, cg, blk, frags, bbase; + int releasecg; fs = sblock; assert ((u_int)size <= fs->fs_bsize && !fragoff (fs, size)); @@ -1265,10 +1404,12 @@ ffs_blkfree(register struct node *np, } cgp = (struct cg *)bp->b_data; #else - cgp = cg_locate (cg); + releasecg = cg_read (cg, &cgp); #endif if (!cg_chkmagic(cgp)) { /* brelse(bp); */ + if (releasecg) + release_cg (cgp); return; } cgp->cg_time = diskfs_mtime->seconds; @@ -1324,6 +1465,8 @@ ffs_blkfree(register struct node *np, cg_blktot(cgp)[i]++; } } + if (releasecg) + release_cg (cgp); record_poke (cgp, sblock->fs_cgsize); csum_dirty = 1; sblock_dirty = 1; @@ -1346,6 +1489,7 @@ diskfs_free_node (struct node *np, mode_t mode) register struct cg *cgp; ino_t ino = np->dn->number; int cg; + int releasecg; fs = sblock; assert (ino < fs->fs_ipg * fs->fs_ncg); @@ -1359,10 +1503,12 @@ diskfs_free_node (struct node *np, mode_t mode) } cgp = (struct cg *)bp->b_data; #else - cgp = cg_locate (cg); + releasecg = read_cg (cg, &cgp); #endif if (!cg_chkmagic(cgp)) { /* brelse(bp); */ + if (releasecg) + release_cg (cgp); return; } cgp->cg_time = diskfs_mtime->seconds; @@ -1383,6 +1529,8 @@ diskfs_free_node (struct node *np, mode_t mode) fs->fs_cstotal.cs_ndir--; csum[cg].cs_ndir--; } + if (releasecg) + release_cg (cgp); record_poke (cgp, sblock->fs_cgsize); csum_dirty = 1; sblock_dirty = 1; -- cgit v1.2.3 From 4e2aa139eaca196f8479e52bb73a30029d534a8e Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Apr 1996 18:17:36 +0000 Subject: Include . Fixup. --- ufs/alloc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index fdd0aa59..9efd2eb3 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -55,6 +55,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ufs.h" #include +#include + /* These don't work *at all* here; don't even try setting them. */ #undef DIAGNOSTIC @@ -91,7 +93,7 @@ alloc_sync (struct node *np) /* Byteswap everything in CGP. */ void -swab_cg (struct cg *cgp) +swab_cg (struct cg *cg) { int i, j; @@ -177,14 +179,14 @@ read_cg (int cg, struct cg **cgpp) if (swab_disk) { - *cgp = malloc (sblock->fs_cgsize); - bcopy (diskcg, *cgp, sblock->fs_cgsize); - swab_cg (*cgp); + *cgpp = malloc (sblock->fs_cgsize); + bcopy (diskcg, *cgpp, sblock->fs_cgsize); + swab_cg (*cgpp); return 1; } else { - *cgp = diskcg; + *cgpp = diskcg; return 0; } } @@ -194,8 +196,9 @@ read_cg (int cg, struct cg **cgpp) void release_cgp (struct cg *cgp) { + int cgx = cgp->cg_cgx; swab_cg (cgp); - bcopy (cgp, cg_locate (cg), sblock->fs_cgsize); + bcopy (cgp, cg_locate (cgx), sblock->fs_cgsize); free (cgp); } -- cgit v1.2.3 From 15ec6058ff8a845747c1f59e815806304b7c7e57 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Apr 1996 18:32:36 +0000 Subject: (ffs_blkfree): final fixup. --- ufs/alloc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 9efd2eb3..90ce68f5 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -139,7 +139,7 @@ swab_cg (struct cg *cg) else { /* Old format cylinder group... */ - struct ocg *ocg = cg; + struct ocg *ocg = (struct ocg *) cg; if (swab_long (ocg->cg_magic) != CG_MAGIC && ocg->cg_magic != CG_MAGIC) @@ -194,7 +194,7 @@ read_cg (int cg, struct cg **cgpp) /* Caller of read_cg is done with cg; write it back to disk (swapping it along the way) and free the memory allocated in read_cg. */ void -release_cgp (struct cg *cgp) +release_cg (struct cg *cgp) { int cgx = cgp->cg_cgx; swab_cg (cgp); @@ -902,7 +902,7 @@ ffs_fragextend(struct node *np, int nsize) { register struct fs *fs; - register struct cg *cgp; + struct cg *cgp; long bno; int frags, bbase; int i; @@ -984,7 +984,7 @@ ffs_alloccg(struct node *np, int size) { register struct fs *fs; - register struct cg *cgp; + struct cg *cgp; register int i; int bno, frags, allocsiz; int releasecg; @@ -1050,7 +1050,7 @@ ffs_alloccg(struct node *np, cgp->cg_frsum[i]++; if (releasecg) - release_cg (cgp) + release_cg (cgp); record_poke (cgp, sblock->fs_cgsize); csum_dirty = 1; sblock_dirty = 1; @@ -1302,7 +1302,7 @@ ffs_nodealloccg(struct node *np, int mode) { register struct fs *fs; - register struct cg *cgp; + struct cg *cgp; int start, len, loc, map, i; int releasecg; @@ -1323,7 +1323,7 @@ ffs_nodealloccg(struct node *np, if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) { /* brelse(bp); */ if (releasecg) - release_cg (cg); + release_cg (cgp); return 0; } cgp->cg_time = diskfs_mtime->seconds; @@ -1385,7 +1385,7 @@ ffs_blkfree(register struct node *np, long size) { register struct fs *fs; - register struct cg *cgp; + struct cg *cgp; daddr_t blkno; int i, cg, blk, frags, bbase; int releasecg; @@ -1407,7 +1407,7 @@ ffs_blkfree(register struct node *np, } cgp = (struct cg *)bp->b_data; #else - releasecg = cg_read (cg, &cgp); + releasecg = read_cg (cg, &cgp); #endif if (!cg_chkmagic(cgp)) { /* brelse(bp); */ @@ -1489,7 +1489,7 @@ void diskfs_free_node (struct node *np, mode_t mode) { register struct fs *fs; - register struct cg *cgp; + struct cg *cgp; ino_t ino = np->dn->number; int cg; int releasecg; -- cgit v1.2.3 From 00b56b8817816a221ed49d07c14d5c93a079da4d Mon Sep 17 00:00:00 2001 From: Thomas Bushnell Date: Mon, 18 Nov 1996 23:59:08 +0000 Subject: Sat Nov 16 17:21:40 1996 Thomas Bushnell, n/BSG * inode.c (diskfs_S_fsys_getfile): Delete var `fakecred'. diskfs_access -> fshelp_access. * alloc.c (ffs_alloc): diskfs_isuid -> idvec_contains. (ffs_realloccg): Likewise. Thu Nov 14 16:43:36 1996 Thomas Bushnell, n/BSG * inode.c (diskfs_S_file_getfh): diskfs_isuid -> idvec_contains. (diskfs_S_fsys_getfile): Use idvecs and iousers. --- ufs/ChangeLog | 12 ++++++++++++ ufs/alloc.c | 5 +++-- ufs/inode.c | 27 ++++++++++++++++----------- 3 files changed, 31 insertions(+), 13 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/ChangeLog b/ufs/ChangeLog index 2c81dbc3..4ca29dee 100644 --- a/ufs/ChangeLog +++ b/ufs/ChangeLog @@ -1,3 +1,15 @@ +Sat Nov 16 17:21:40 1996 Thomas Bushnell, n/BSG + + * inode.c (diskfs_S_fsys_getfile): Delete var `fakecred'. + diskfs_access -> fshelp_access. + * alloc.c (ffs_alloc): diskfs_isuid -> idvec_contains. + (ffs_realloccg): Likewise. + +Thu Nov 14 16:43:36 1996 Thomas Bushnell, n/BSG + + * inode.c (diskfs_S_file_getfh): diskfs_isuid -> idvec_contains. + (diskfs_S_fsys_getfile): Use idvecs and iousers. + Thu Oct 24 16:07:17 1996 Miles Bader * main.c (startup_children, runtime_children): New variables. diff --git a/ufs/alloc.c b/ufs/alloc.c index 90ce68f5..15d53180 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -247,7 +247,7 @@ ffs_alloc(register struct node *np, spin_lock (&alloclock); if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) goto nospace; - if (cred && !diskfs_isuid (0, cred) + if (cred && !idvec_contains (cred->user->uids, 0) && freespace(fs, fs->fs_minfree) <= 0) goto nospace; #ifdef QUOTA @@ -323,7 +323,8 @@ ffs_realloccg(register struct node *np, spin_lock (&alloclock); - if (!diskfs_isuid (0, cred) && freespace(fs, fs->fs_minfree) <= 0) + if (!idvec_contains (cred->user->uids, 0) + && freespace(fs, fs->fs_minfree) <= 0) goto nospace; error = diskfs_catch_exception (); if (error) diff --git a/ufs/inode.c b/ufs/inode.c index 47aa6ac9..a0f16642 100644 --- a/ufs/inode.c +++ b/ufs/inode.c @@ -716,7 +716,7 @@ diskfs_S_file_getfh (struct protid *cred, if (!cred) return EOPNOTSUPP; - if (!diskfs_isuid (0, cred)) + if (!idvec_contains (cred->user->uids, 0)) return EPERM; np = cred->po->np; @@ -757,7 +757,9 @@ diskfs_S_fsys_getfile (mach_port_t fsys, struct ufs_fhandle *f; error_t err; int flags; - struct protid fakecred, *newpi; + struct protid *newpi; + struct idvec *uvec, *gvec; + struct iouser *user; if (!pt) return EOPNOTSUPP; @@ -784,24 +786,27 @@ diskfs_S_fsys_getfile (mach_port_t fsys, return ESTALE; } - /* This call should have a flags arg, but until then... */ - fakecred.uids = uids; - fakecred.gids = gids; - fakecred.nuids = nuids; - fakecred.ngids = ngids; + uvec = make_idvec (); + gvec = make_idvec (); + idvec_set_ids (uvec, uids, nuids); + idvec_set_ids (gvec, gids, ngids); + user = iohelp_create_iouser (uvec, gvec); + flags = 0; - if (!diskfs_access (np, S_IREAD, &fakecred)) + if (!fshelp_access (&np->dn_stat, S_IREAD, user)) flags |= O_READ; - if (!diskfs_access (np, S_IEXEC, &fakecred)) + if (!fshelp_access (&np->dn_stat, S_IEXEC, user)) flags |= O_EXEC; - if (!diskfs_access (np, S_IWRITE, &fakecred) + if (!fshelp_access (&np->dn_stat, S_IWRITE, user) && !S_ISDIR (np->dn_stat.st_mode) && !diskfs_check_readonly ()) flags |= O_WRITE; err = diskfs_create_protid (diskfs_make_peropen (np, flags, MACH_PORT_NULL), - uids, nuids, gids, ngids, &newpi); + user, &newpi); + + iohelp_free_iouser (user); diskfs_nput (np); ports_port_deref (pt); -- cgit v1.2.3 From 44015af36f54d4d34fe15a2c8f34179acb979def Mon Sep 17 00:00:00 2001 From: Miles Bader Date: Tue, 19 Nov 1996 23:18:20 +0000 Subject: (ffs_alloc): Use S_IPTRANS in NP->dn_stat.st_mode instead of NP->istranslated. --- ufs/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index 15d53180..ac72c928 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -683,7 +683,7 @@ diskfs_alloc_node (struct node *dir, goto noinodes; error = diskfs_cached_lookup (ino, &np); assert ("duplicate allocation" && !np->dn_stat.st_mode); - assert (!np->istranslated); + assert (! (np->dn_stat.st_mode & S_IPTRANS)); if (np->dn_stat.st_blocks) { printf("free inode %d had %d blocks\n", ino, np->dn_stat.st_blocks); -- cgit v1.2.3 From d2d38a4c423435d8b8fea4630d484cd1dab01bab Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sun, 20 Dec 1998 20:51:02 +0000 Subject: 1998-12-20 Roland McGrath * alloc.c (diskfs_alloc_node): Fix printf format to silence warning. * hyper.c (get_hypermetadata): Likewise. --- ufs/alloc.c | 86 ++++++++++++++++++++++++++++++------------------------------- ufs/hyper.c | 16 ++++++------ 2 files changed, 51 insertions(+), 51 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index ac72c928..e76b7703 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -1,5 +1,5 @@ /* Disk allocation routines - Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation + Copyright (C) 1993, 94, 95, 96, 98 Free Software Foundation, Inc. This file is part of the GNU Hurd. @@ -8,7 +8,7 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. -The GNU Hurd is distributed in the hope that it will be useful, +The GNU Hurd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -67,7 +67,7 @@ extern u_long nextgennumber; spin_lock_t alloclock = SPIN_LOCK_INITIALIZER; /* Forward declarations */ -static u_long ffs_hashalloc (struct node *, int, long, int, +static u_long ffs_hashalloc (struct node *, int, long, int, u_long (*)(struct node *, int, daddr_t, int)); static u_long ffs_alloccg (struct node *, int, daddr_t, int); static daddr_t ffs_fragextend (struct node *, int, long, int, int); @@ -96,7 +96,7 @@ void swab_cg (struct cg *cg) { int i, j; - + if (swab_long (cg->cg_magic) == CG_MAGIC || cg->cg_magic == CG_MAGIC) { @@ -125,12 +125,12 @@ swab_cg (struct cg *cg) /* blktot map */ for (i = 0; i < cg->cg_ncyl; i++) cg_blktot(cg)[i] = swab_long (cg_blktot(cg)[i]); - + /* blks map */ for (i = 0; i < cg->cg_ncyl; i++) for (j = 0; j < sblock->fs_nrpos; j++) cg_blks(sblock, cg, i)[j] = swab_short (cg_blks (sblock, cg, i)[j]); - + for (i = 0; i < sblock->fs_contigsumsize; i++) cg_clustersum(cg)[i] = swab_long (cg_clustersum(cg)[i]); @@ -140,11 +140,11 @@ swab_cg (struct cg *cg) { /* Old format cylinder group... */ struct ocg *ocg = (struct ocg *) cg; - + if (swab_long (ocg->cg_magic) != CG_MAGIC && ocg->cg_magic != CG_MAGIC) return; - + ocg->cg_time = swab_long (ocg->cg_time); ocg->cg_cgx = swab_long (ocg->cg_cgx); ocg->cg_ncyl = swab_short (ocg->cg_ncyl); @@ -176,7 +176,7 @@ int read_cg (int cg, struct cg **cgpp) { struct cg *diskcg = cg_locate (cg); - + if (swab_disk) { *cgpp = malloc (sblock->fs_cgsize); @@ -205,7 +205,7 @@ release_cg (struct cg *cgp) /* * Allocate a block in the file system. - * + * * The size of the requested block is given, which must be some * multiple of fs_fsize and <= fs_bsize. * A preference may be optionally specified. If a preference is given @@ -224,7 +224,7 @@ release_cg (struct cg *cgp) */ error_t ffs_alloc(register struct node *np, - daddr_t lbn, + daddr_t lbn, daddr_t bpref, int size, daddr_t *bnp, @@ -233,7 +233,7 @@ ffs_alloc(register struct node *np, register struct fs *fs; daddr_t bno; int cg; - + *bnp = 0; fs = sblock; #ifdef DIAGNOSTIC @@ -297,7 +297,7 @@ error_t ffs_realloccg(register struct node *np, daddr_t lbprev, volatile daddr_t bpref, - int osize, + int osize, int nsize, daddr_t *pbn, struct protid *cred) @@ -306,7 +306,7 @@ ffs_realloccg(register struct node *np, int cg, error; volatile int request; daddr_t bprev, bno; - + *pbn = 0; fs = sblock; #ifdef DIAGNOSTIC @@ -322,8 +322,8 @@ ffs_realloccg(register struct node *np, #endif /* DIAGNOSTIC */ spin_lock (&alloclock); - - if (!idvec_contains (cred->user->uids, 0) + + if (!idvec_contains (cred->user->uids, 0) && freespace(fs, fs->fs_minfree) <= 0) goto nospace; error = diskfs_catch_exception (); @@ -378,8 +378,8 @@ ffs_realloccg(register struct node *np, switch ((int)fs->fs_optim) { case FS_OPTSPACE: /* - * Allocate an exact sized fragment. Although this makes - * best use of space, we will waste time relocating it if + * Allocate an exact sized fragment. Although this makes + * best use of space, we will waste time relocating it if * the file continues to grow. If the fragmentation is * less than half of the minimum free reserve, we choose * to begin optimizing for time. @@ -419,7 +419,7 @@ ffs_realloccg(register struct node *np, bno = (daddr_t)ffs_hashalloc(np, cg, (long)bpref, request, (u_long (*)())ffs_alloccg); if (bno > 0) { -#if 0 /* Not necessary in GNU Hurd ufs */ +#if 0 /* Not necessary in GNU Hurd ufs */ bp->b_blkno = fsbtodb(fs, bno); (void) vnode_pager_uncache(ITOV(ip)); #endif @@ -585,7 +585,7 @@ ffs_reallocblks(ap) * Next we must write out the modified inode and indirect blocks. * For strict correctness, the writes should be synchronous since * the old block values may have been written to disk. In practise - * they are almost never written, but if we are concerned about + * they are almost never written, but if we are concerned about * strict correctness, the `doasyncfree' flag should be set to zero. * * The test on `doasyncfree' should be changed to test a flag @@ -631,7 +631,7 @@ fail: /* * Allocate an inode in the file system. - * + * * 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. @@ -644,7 +644,7 @@ fail: * 2) quadradically rehash into other cylinder groups, until an * available inode is located. */ -/* This is now the diskfs_alloc_node callback from the diskfs library +/* This is now the diskfs_alloc_node callback from the diskfs library (described in ). It used to be ffs_valloc in BSD. */ error_t diskfs_alloc_node (struct node *dir, @@ -656,7 +656,7 @@ diskfs_alloc_node (struct node *dir, ino_t ino, ipref; int cg, error; int sex; - + fs = sblock; @@ -685,7 +685,7 @@ diskfs_alloc_node (struct node *dir, assert ("duplicate allocation" && !np->dn_stat.st_mode); assert (! (np->dn_stat.st_mode & S_IPTRANS)); if (np->dn_stat.st_blocks) { - printf("free inode %d had %d blocks\n", + printf("free inode %d had %ld blocks\n", ino, np->dn_stat.st_blocks); np->dn_stat.st_blocks = 0; np->dn_set_ctime = 1; @@ -700,7 +700,7 @@ diskfs_alloc_node (struct node *dir, nextgennumber = sex; np->dn_stat.st_gen = nextgennumber; spin_unlock (&gennumberlock); - + *npp = np; alloc_sync (np); return (0); @@ -739,7 +739,7 @@ ffs_dirpref(register struct fs *fs) * Select the desired position for the next block in a file. The file is * logically divided into sections. The first section is composed of the * direct blocks. Each additional section contains fs_maxbpg blocks. - * + * * If no blocks have been allocated in the first section, the policy is to * request a block in the same cylinder group as the inode that describes * the file. If no blocks have been allocated in any other section, the @@ -753,7 +753,7 @@ ffs_dirpref(register struct fs *fs) * indirect block, the information on the previous allocation is unavailable; * here a best guess is made based upon the logical block number being * allocated. - * + * * If a section is already partially allocated, the policy is to * contiguously allocate fs_maxcontig blocks. The end of one of these * contiguous blocks and the beginning of the next is physically separated @@ -786,10 +786,10 @@ ffs_blkpref(struct node *np, */ if (indx == 0 || bap[indx - 1] == 0) startcg = - (ino_to_cg(fs, np->dn->number) + (ino_to_cg(fs, np->dn->number) + lbn / fs->fs_maxbpg); else - startcg = dtog(fs, + startcg = dtog(fs, read_disk_entry (bap[indx - 1])) + 1; startcg %= fs->fs_ncg; avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; @@ -892,14 +892,14 @@ ffs_hashalloc(struct node *np, /* * Determine whether a fragment can be extended. * - * Check to see if the necessary fragments are available, and + * Check to see if the necessary fragments are available, and * if they are, allocate them. */ static daddr_t ffs_fragextend(struct node *np, int cg, long bprev, - int osize, + int osize, int nsize) { register struct fs *fs; @@ -1016,7 +1016,7 @@ ffs_alloccg(struct node *np, bno = ffs_alloccgblk(fs, cgp, bpref); /* bdwrite(bp); */ if (releasecg) - release_cg (cgp); + release_cg (cgp); return (bno); } /* @@ -1030,7 +1030,7 @@ ffs_alloccg(struct node *np, break; if (allocsiz == fs->fs_frag) { /* - * no fragments were available, so a block will be + * no fragments were available, so a block will be * allocated, and hacked up */ if (cgp->cg_cs.cs_nbfree == 0) { @@ -1049,7 +1049,7 @@ ffs_alloccg(struct node *np, csum[cg].cs_nffree += i; fs->fs_fmod = 1; cgp->cg_frsum[i]++; - + if (releasecg) release_cg (cgp); record_poke (cgp, sblock->fs_cgsize); @@ -1127,7 +1127,7 @@ ffs_alloccgblk(register struct fs *fs, /* * Block layout information is not available. * Leaving bpref unchanged means we take the - * next available free block following the one + * 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). @@ -1135,7 +1135,7 @@ ffs_alloccgblk(register struct fs *fs, goto norot; } /* - * check the summary information to see if a block is + * check the summary information to see if a block is * available in the requested cylinder starting at the * requested rotational position and proceeding around. */ @@ -1285,7 +1285,7 @@ fail: brelse(bp); return (0); } -#endif +#endif /* * Determine whether an inode can be allocated. @@ -1377,7 +1377,7 @@ gotit: * Free a block or fragment. * * The specified block or fragment is placed back in the - * free map. If a fragment is deallocated, a possible + * free map. If a fragment is deallocated, a possible * block reassembly is checked. */ void @@ -1409,7 +1409,7 @@ ffs_blkfree(register struct node *np, cgp = (struct cg *)bp->b_data; #else releasecg = read_cg (cg, &cgp); -#endif +#endif if (!cg_chkmagic(cgp)) { /* brelse(bp); */ if (releasecg) @@ -1484,7 +1484,7 @@ ffs_blkfree(register struct node *np, * * The specified inode is placed back in the free map. */ -/* Implement diskfs call back diskfs_free_node (described in +/* Implement diskfs call back diskfs_free_node (described in . This was called ffs_vfree in BSD. */ void diskfs_free_node (struct node *np, mode_t mode) @@ -1508,11 +1508,11 @@ diskfs_free_node (struct node *np, mode_t mode) cgp = (struct cg *)bp->b_data; #else releasecg = read_cg (cg, &cgp); -#endif +#endif if (!cg_chkmagic(cgp)) { /* brelse(bp); */ if (releasecg) - release_cg (cgp); + release_cg (cgp); return; } cgp->cg_time = diskfs_mtime->seconds; @@ -1687,7 +1687,7 @@ ffs_clusteracct(struct fs *fs, #if 0 /* * Fserr prints the name of a file system with an error diagnostic. - * + * * The form of the error message is: * fs: error message */ diff --git a/ufs/hyper.c b/ufs/hyper.c index 500934eb..2a43bfed 100644 --- a/ufs/hyper.c +++ b/ufs/hyper.c @@ -1,5 +1,5 @@ /* Fetching and storing the hypermetadata (superblock and cg summary info). - Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation + Copyright (C) 1994, 95, 96, 97, 98 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -34,7 +34,7 @@ void swab_sblock (struct fs *sblock) { int i, j; - + sblock->fs_sblkno = swab_long (sblock->fs_sblkno); sblock->fs_cblkno = swab_long (sblock->fs_cblkno); sblock->fs_iblkno = swab_long (sblock->fs_iblkno); @@ -108,24 +108,24 @@ swab_sblock (struct fs *sblock) else for (i = 0; i < sblock->fs_cpc; i++) for (j = 0; j < sblock->fs_nrpos; j++) - fs_postbl(sblock, j)[i] + fs_postbl(sblock, j)[i] = swab_short (fs_postbl (sblock, j)[i]); /* The rot table is all chars */ } - + void swab_csums (struct csum *csum) { int i; - + for (i = 0; i < sblock->fs_ncg; i++) { csum[i].cs_ndir = swab_long (csum[i].cs_ndir); csum[i].cs_nbfree = swab_long (csum[i].cs_nbfree); csum[i].cs_nifree = swab_long (csum[i].cs_nifree); csum[i].cs_nffree = swab_long (csum[i].cs_nffree); - } + } } void @@ -252,7 +252,7 @@ get_hypermetadata (void) if (store->size < sblock->fs_size * sblock->fs_fsize) { fprintf (stderr, - "Disk size (%Zd) less than necessary " + "Disk size (%ld) less than necessary " "(superblock says we need %ld)\n", store->size, sblock->fs_size * sblock->fs_fsize); exit (1); @@ -315,7 +315,7 @@ diskfs_set_hypermetadata (int wait, int clean) } vm_deallocate (mach_task_self (), (vm_address_t)buf, read); - + if (err) { spin_unlock (&alloclock); -- cgit v1.2.3 From 0df695e2e07f18089ce49a5bc728dc8643ed871e Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 11 Jun 2002 21:41:03 +0000 Subject: 2002-06-08 Roland McGrath * alloc.c, dir.c: Use %Ld format for ino_t values. * alloc.c (diskfs_alloc_node): Use %Ld format for blkcnt_t values. --- ufs/alloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ufs/alloc.c') diff --git a/ufs/alloc.c b/ufs/alloc.c index e76b7703..48ee60cc 100644 --- a/ufs/alloc.c +++ b/ufs/alloc.c @@ -1,5 +1,5 @@ /* Disk allocation routines - Copyright (C) 1993, 94, 95, 96, 98 Free Software Foundation, Inc. + Copyright (C) 1993,94,95,96,98,2002 Free Software Foundation, Inc. This file is part of the GNU Hurd. @@ -685,7 +685,7 @@ diskfs_alloc_node (struct node *dir, assert ("duplicate allocation" && !np->dn_stat.st_mode); assert (! (np->dn_stat.st_mode & S_IPTRANS)); if (np->dn_stat.st_blocks) { - printf("free inode %d had %ld blocks\n", + printf("free inode %Ld had %Ld blocks\n", ino, np->dn_stat.st_blocks); np->dn_stat.st_blocks = 0; np->dn_set_ctime = 1; @@ -1395,7 +1395,7 @@ ffs_blkfree(register struct node *np, assert ((u_int)size <= fs->fs_bsize && !fragoff (fs, size)); cg = dtog(fs, bno); if ((u_int)bno >= fs->fs_size) { - printf("bad block %ld, ino %d\n", bno, np->dn->number); + printf("bad block %ld, ino %Ld\n", bno, np->dn->number); /* ffs_fserr(fs, ip->i_uid, "bad block"); */ return; } @@ -1518,7 +1518,7 @@ diskfs_free_node (struct node *np, mode_t mode) cgp->cg_time = diskfs_mtime->seconds; ino %= fs->fs_ipg; if (isclr(cg_inosused(cgp), ino)) { -/* printf("dev = 0x%x, ino = %d, fs = %s\n", +/* printf("dev = 0x%x, ino = %Ld, fs = %s\n", pip->i_dev, ino, fs->fs_fsmnt); */ assert (diskfs_readonly); } -- cgit v1.2.3