Annotation of sys/ufs/ffs/ffs_alloc.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ffs_alloc.c,v 1.78 2007/06/22 13:59:12 thib Exp $ */
! 2: /* $NetBSD: ffs_alloc.c,v 1.11 1996/05/11 18:27:09 mycroft Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 2002 Networks Associates Technology, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This software was developed for the FreeBSD Project by Marshall
! 9: * Kirk McKusick and Network Associates Laboratories, the Security
! 10: * Research Division of Network Associates, Inc. under DARPA/SPAWAR
! 11: * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
! 12: * research program.
! 13: *
! 14: * Copyright (c) 1982, 1986, 1989, 1993
! 15: * The Regents of the University of California. All rights reserved.
! 16: *
! 17: * Redistribution and use in source and binary forms, with or without
! 18: * modification, are permitted provided that the following conditions
! 19: * are met:
! 20: * 1. Redistributions of source code must retain the above copyright
! 21: * notice, this list of conditions and the following disclaimer.
! 22: * 2. Redistributions in binary form must reproduce the above copyright
! 23: * notice, this list of conditions and the following disclaimer in the
! 24: * documentation and/or other materials provided with the distribution.
! 25: * 3. Neither the name of the University nor the names of its contributors
! 26: * may be used to endorse or promote products derived from this software
! 27: * without specific prior written permission.
! 28: *
! 29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 39: * SUCH DAMAGE.
! 40: *
! 41: * @(#)ffs_alloc.c 8.11 (Berkeley) 10/27/94
! 42: */
! 43:
! 44: #include <sys/param.h>
! 45: #include <sys/systm.h>
! 46: #include <sys/buf.h>
! 47: #include <sys/proc.h>
! 48: #include <sys/vnode.h>
! 49: #include <sys/mount.h>
! 50: #include <sys/kernel.h>
! 51: #include <sys/syslog.h>
! 52: #include <sys/stdint.h>
! 53:
! 54: #include <uvm/uvm_extern.h>
! 55:
! 56: #include <dev/rndvar.h>
! 57:
! 58: #include <ufs/ufs/quota.h>
! 59: #include <ufs/ufs/inode.h>
! 60: #include <ufs/ufs/ufsmount.h>
! 61: #include <ufs/ufs/ufs_extern.h>
! 62:
! 63: #include <ufs/ffs/fs.h>
! 64: #include <ufs/ffs/ffs_extern.h>
! 65:
! 66: #define ffs_fserr(fs, uid, cp) do { \
! 67: log(LOG_ERR, "uid %u on %s: %s\n", (uid), \
! 68: (fs)->fs_fsmnt, (cp)); \
! 69: } while (0)
! 70:
! 71: daddr_t ffs_alloccg(struct inode *, int, daddr_t, int);
! 72: daddr_t ffs_alloccgblk(struct inode *, struct buf *, daddr_t);
! 73: daddr_t ffs_clusteralloc(struct inode *, int, daddr_t, int);
! 74: ino_t ffs_dirpref(struct inode *);
! 75: daddr_t ffs_fragextend(struct inode *, int, long, int, int);
! 76: u_long ffs_hashalloc(struct inode *, int, long, int,
! 77: daddr_t (*)(struct inode *, int, daddr_t, int));
! 78: daddr_t ffs_nodealloccg(struct inode *, int, daddr_t, int);
! 79: daddr_t ffs_mapsearch(struct fs *, struct cg *, daddr_t, int);
! 80:
! 81: int ffs1_reallocblks(void *);
! 82: #ifdef FFS2
! 83: int ffs2_reallocblks(void *);
! 84: #endif
! 85:
! 86: #ifdef DIAGNOSTIC
! 87: int ffs_checkblk(struct inode *, daddr_t, long);
! 88: #endif
! 89:
! 90: /*
! 91: * Allocate a block in the file system.
! 92: *
! 93: * The size of the requested block is given, which must be some
! 94: * multiple of fs_fsize and <= fs_bsize.
! 95: * A preference may be optionally specified. If a preference is given
! 96: * the following hierarchy is used to allocate a block:
! 97: * 1) allocate the requested block.
! 98: * 2) allocate a rotationally optimal block in the same cylinder.
! 99: * 3) allocate a block in the same cylinder group.
! 100: * 4) quadratically rehash into other cylinder groups, until an
! 101: * available block is located.
! 102: * If no block preference is given the following hierarchy is used
! 103: * to allocate a block:
! 104: * 1) allocate a block in the cylinder group that contains the
! 105: * inode for the file.
! 106: * 2) quadratically rehash into other cylinder groups, until an
! 107: * available block is located.
! 108: */
! 109: int
! 110: ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, int size,
! 111: struct ucred *cred, daddr_t *bnp)
! 112: {
! 113: struct fs *fs;
! 114: daddr_t bno;
! 115: int cg;
! 116: int error;
! 117:
! 118: *bnp = 0;
! 119: fs = ip->i_fs;
! 120: #ifdef DIAGNOSTIC
! 121: if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) {
! 122: printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n",
! 123: ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt);
! 124: panic("ffs_alloc: bad size");
! 125: }
! 126: if (cred == NOCRED)
! 127: panic("ffs_alloc: missing credential");
! 128: #endif /* DIAGNOSTIC */
! 129: if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0)
! 130: goto nospace;
! 131: if (cred->cr_uid != 0 && freespace(fs, fs->fs_minfree) <= 0)
! 132: goto nospace;
! 133:
! 134: if ((error = ufs_quota_alloc_blocks(ip, btodb(size), cred)) != 0)
! 135: return (error);
! 136:
! 137: /*
! 138: * Start allocation in the preferred block's cylinder group or
! 139: * the file's inode's cylinder group if no preferred block was
! 140: * specified.
! 141: */
! 142: if (bpref >= fs->fs_size)
! 143: bpref = 0;
! 144: if (bpref == 0)
! 145: cg = ino_to_cg(fs, ip->i_number);
! 146: else
! 147: cg = dtog(fs, bpref);
! 148:
! 149: /* Try allocating a block. */
! 150: bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, size, ffs_alloccg);
! 151: if (bno > 0) {
! 152: /* allocation successful, update inode data */
! 153: DIP_ADD(ip, blocks, btodb(size));
! 154: ip->i_flag |= IN_CHANGE | IN_UPDATE;
! 155: *bnp = bno;
! 156: return (0);
! 157: }
! 158:
! 159: /* Restore user's disk quota because allocation failed. */
! 160: (void) ufs_quota_free_blocks(ip, btodb(size), cred);
! 161:
! 162: nospace:
! 163: ffs_fserr(fs, cred->cr_uid, "file system full");
! 164: uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
! 165: return (ENOSPC);
! 166: }
! 167:
! 168: /*
! 169: * Reallocate a fragment to a bigger size
! 170: *
! 171: * The number and size of the old block is given, and a preference
! 172: * and new size is also specified. The allocator attempts to extend
! 173: * the original block. Failing that, the regular block allocator is
! 174: * invoked to get an appropriate block.
! 175: */
! 176: int
! 177: ffs_realloccg(struct inode *ip, daddr_t lbprev, daddr_t bpref, int osize,
! 178: int nsize, struct ucred *cred, struct buf **bpp, daddr_t *blknop)
! 179: {
! 180: struct fs *fs;
! 181: struct buf *bp = NULL;
! 182: daddr_t quota_updated = 0;
! 183: int cg, request, error;
! 184: daddr_t bprev, bno;
! 185:
! 186: if (bpp != NULL)
! 187: *bpp = NULL;
! 188: fs = ip->i_fs;
! 189: #ifdef DIAGNOSTIC
! 190: if ((u_int)osize > fs->fs_bsize || fragoff(fs, osize) != 0 ||
! 191: (u_int)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) {
! 192: printf(
! 193: "dev = 0x%x, bsize = %d, osize = %d, nsize = %d, fs = %s\n",
! 194: ip->i_dev, fs->fs_bsize, osize, nsize, fs->fs_fsmnt);
! 195: panic("ffs_realloccg: bad size");
! 196: }
! 197: if (cred == NOCRED)
! 198: panic("ffs_realloccg: missing credential");
! 199: #endif /* DIAGNOSTIC */
! 200: if (cred->cr_uid != 0 && freespace(fs, fs->fs_minfree) <= 0)
! 201: goto nospace;
! 202:
! 203: bprev = DIP(ip, db[lbprev]);
! 204:
! 205: if (bprev == 0) {
! 206: printf("dev = 0x%x, bsize = %d, bprev = %d, fs = %s\n",
! 207: ip->i_dev, fs->fs_bsize, bprev, fs->fs_fsmnt);
! 208: panic("ffs_realloccg: bad bprev");
! 209: }
! 210:
! 211: /*
! 212: * Allocate the extra space in the buffer.
! 213: */
! 214: if (bpp != NULL) {
! 215: if ((error = bread(ITOV(ip), lbprev, fs->fs_bsize,
! 216: NOCRED, &bp)) != 0)
! 217: goto error;
! 218: bp->b_bcount = osize;
! 219: }
! 220:
! 221: if ((error = ufs_quota_alloc_blocks(ip, btodb(nsize - osize), cred))
! 222: != 0)
! 223: goto error;
! 224:
! 225: quota_updated = btodb(nsize - osize);
! 226:
! 227: /*
! 228: * Check for extension in the existing location.
! 229: */
! 230: cg = dtog(fs, bprev);
! 231: if ((bno = ffs_fragextend(ip, cg, (long)bprev, osize, nsize)) != 0) {
! 232: DIP_ADD(ip, blocks, btodb(nsize - osize));
! 233: ip->i_flag |= IN_CHANGE | IN_UPDATE;
! 234: if (bpp != NULL) {
! 235: if (bp->b_blkno != fsbtodb(fs, bno))
! 236: panic("ffs_realloccg: bad blockno");
! 237: #ifdef DIAGNOSTIC
! 238: if (nsize > bp->b_bufsize)
! 239: panic("ffs_realloccg: small buf");
! 240: #endif
! 241: bp->b_bcount = nsize;
! 242: bp->b_flags |= B_DONE;
! 243: bzero(bp->b_data + osize, (u_int)nsize - osize);
! 244: *bpp = bp;
! 245: }
! 246: if (blknop != NULL) {
! 247: *blknop = bno;
! 248: }
! 249: return (0);
! 250: }
! 251: /*
! 252: * Allocate a new disk location.
! 253: */
! 254: if (bpref >= fs->fs_size)
! 255: bpref = 0;
! 256: switch (fs->fs_optim) {
! 257: case FS_OPTSPACE:
! 258: /*
! 259: * Allocate an exact sized fragment. Although this makes
! 260: * best use of space, we will waste time relocating it if
! 261: * the file continues to grow. If the fragmentation is
! 262: * less than half of the minimum free reserve, we choose
! 263: * to begin optimizing for time.
! 264: */
! 265: request = nsize;
! 266: if (fs->fs_minfree < 5 ||
! 267: fs->fs_cstotal.cs_nffree >
! 268: fs->fs_dsize * fs->fs_minfree / (2 * 100))
! 269: break;
! 270: fs->fs_optim = FS_OPTTIME;
! 271: break;
! 272: case FS_OPTTIME:
! 273: /*
! 274: * At this point we have discovered a file that is trying to
! 275: * grow a small fragment to a larger fragment. To save time,
! 276: * we allocate a full sized block, then free the unused portion.
! 277: * If the file continues to grow, the `ffs_fragextend' call
! 278: * above will be able to grow it in place without further
! 279: * copying. If aberrant programs cause disk fragmentation to
! 280: * grow within 2% of the free reserve, we choose to begin
! 281: * optimizing for space.
! 282: */
! 283: request = fs->fs_bsize;
! 284: if (fs->fs_cstotal.cs_nffree <
! 285: fs->fs_dsize * (fs->fs_minfree - 2) / 100)
! 286: break;
! 287: fs->fs_optim = FS_OPTSPACE;
! 288: break;
! 289: default:
! 290: printf("dev = 0x%x, optim = %d, fs = %s\n",
! 291: ip->i_dev, fs->fs_optim, fs->fs_fsmnt);
! 292: panic("ffs_realloccg: bad optim");
! 293: /* NOTREACHED */
! 294: }
! 295: bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request,
! 296: ffs_alloccg);
! 297: if (bno <= 0)
! 298: goto nospace;
! 299:
! 300: (void) uvm_vnp_uncache(ITOV(ip));
! 301: if (!DOINGSOFTDEP(ITOV(ip)))
! 302: ffs_blkfree(ip, bprev, (long)osize);
! 303: if (nsize < request)
! 304: ffs_blkfree(ip, bno + numfrags(fs, nsize),
! 305: (long)(request - nsize));
! 306: DIP_ADD(ip, blocks, btodb(nsize - osize));
! 307: ip->i_flag |= IN_CHANGE | IN_UPDATE;
! 308: if (bpp != NULL) {
! 309: bp->b_blkno = fsbtodb(fs, bno);
! 310: #ifdef DIAGNOSTIC
! 311: if (nsize > bp->b_bufsize)
! 312: panic("ffs_realloccg: small buf 2");
! 313: #endif
! 314: bp->b_bcount = nsize;
! 315: bp->b_flags |= B_DONE;
! 316: bzero(bp->b_data + osize, (u_int)nsize - osize);
! 317: *bpp = bp;
! 318: }
! 319: if (blknop != NULL) {
! 320: *blknop = bno;
! 321: }
! 322: return (0);
! 323:
! 324: nospace:
! 325: /*
! 326: * no space available
! 327: */
! 328: ffs_fserr(fs, cred->cr_uid, "file system full");
! 329: uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
! 330: error = ENOSPC;
! 331:
! 332: error:
! 333: if (bp != NULL) {
! 334: brelse(bp);
! 335: bp = NULL;
! 336: }
! 337:
! 338: /*
! 339: * Restore user's disk quota because allocation failed.
! 340: */
! 341: if (quota_updated != 0)
! 342: (void)ufs_quota_free_blocks(ip, quota_updated, cred);
! 343:
! 344: return error;
! 345: }
! 346:
! 347: /*
! 348: * Reallocate a sequence of blocks into a contiguous sequence of blocks.
! 349: *
! 350: * The vnode and an array of buffer pointers for a range of sequential
! 351: * logical blocks to be made contiguous are given. The allocator attempts
! 352: * to find a range of sequential blocks starting as close as possible to
! 353: * an fs_rotdelay offset from the end of the allocation for the logical
! 354: * block immediately preceding the current range. If successful, the
! 355: * physical block numbers in the buffer pointers and in the inode are
! 356: * changed to reflect the new allocation. If unsuccessful, the allocation
! 357: * is left unchanged. The success in doing the reallocation is returned.
! 358: * Note that the error return is not reflected back to the user. Rather
! 359: * the previous block allocation will be used.
! 360: */
! 361:
! 362: int doasyncfree = 1;
! 363: int doreallocblks = 1;
! 364: int prtrealloc = 0;
! 365:
! 366: int
! 367: ffs1_reallocblks(void *v)
! 368: {
! 369: struct vop_reallocblks_args *ap = v;
! 370: struct fs *fs;
! 371: struct inode *ip;
! 372: struct vnode *vp;
! 373: struct buf *sbp, *ebp;
! 374: daddr_t *bap, *sbap, *ebap = NULL;
! 375: struct cluster_save *buflist;
! 376: daddr_t start_lbn, end_lbn, soff, newblk, blkno;
! 377: struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
! 378: int i, len, start_lvl, end_lvl, pref, ssize;
! 379:
! 380: vp = ap->a_vp;
! 381: ip = VTOI(vp);
! 382: fs = ip->i_fs;
! 383: if (fs->fs_contigsumsize <= 0)
! 384: return (ENOSPC);
! 385: buflist = ap->a_buflist;
! 386: len = buflist->bs_nchildren;
! 387: start_lbn = buflist->bs_children[0]->b_lblkno;
! 388: end_lbn = start_lbn + len - 1;
! 389:
! 390: #ifdef DIAGNOSTIC
! 391: for (i = 0; i < len; i++)
! 392: if (!ffs_checkblk(ip,
! 393: dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
! 394: panic("ffs1_reallocblks: unallocated block 1");
! 395:
! 396: for (i = 1; i < len; i++)
! 397: if (buflist->bs_children[i]->b_lblkno != start_lbn + i)
! 398: panic("ffs1_reallocblks: non-logical cluster");
! 399:
! 400: blkno = buflist->bs_children[0]->b_blkno;
! 401: ssize = fsbtodb(fs, fs->fs_frag);
! 402: for (i = 1; i < len - 1; i++)
! 403: if (buflist->bs_children[i]->b_blkno != blkno + (i * ssize))
! 404: panic("ffs1_reallocblks: non-physical cluster %d", i);
! 405: #endif
! 406: /*
! 407: * If the latest allocation is in a new cylinder group, assume that
! 408: * the filesystem has decided to move and do not force it back to
! 409: * the previous cylinder group.
! 410: */
! 411: if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) !=
! 412: dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno)))
! 413: return (ENOSPC);
! 414: if (ufs_getlbns(vp, start_lbn, start_ap, &start_lvl) ||
! 415: ufs_getlbns(vp, end_lbn, end_ap, &end_lvl))
! 416: return (ENOSPC);
! 417: /*
! 418: * Get the starting offset and block map for the first block.
! 419: */
! 420: if (start_lvl == 0) {
! 421: sbap = &ip->i_ffs1_db[0];
! 422: soff = start_lbn;
! 423: } else {
! 424: idp = &start_ap[start_lvl - 1];
! 425: if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &sbp)) {
! 426: brelse(sbp);
! 427: return (ENOSPC);
! 428: }
! 429: sbap = (daddr_t *)sbp->b_data;
! 430: soff = idp->in_off;
! 431: }
! 432: /*
! 433: * Find the preferred location for the cluster.
! 434: */
! 435: pref = ffs1_blkpref(ip, start_lbn, soff, sbap);
! 436: /*
! 437: * If the block range spans two block maps, get the second map.
! 438: */
! 439: if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) {
! 440: ssize = len;
! 441: } else {
! 442: #ifdef DIAGNOSTIC
! 443: if (start_lvl > 1 &&
! 444: start_ap[start_lvl-1].in_lbn == idp->in_lbn)
! 445: panic("ffs1_reallocblk: start == end");
! 446: #endif
! 447: ssize = len - (idp->in_off + 1);
! 448: if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &ebp))
! 449: goto fail;
! 450: ebap = (daddr_t *)ebp->b_data;
! 451: }
! 452: /*
! 453: * Search the block map looking for an allocation of the desired size.
! 454: */
! 455: if ((newblk = (daddr_t)ffs_hashalloc(ip, dtog(fs, pref), (long)pref,
! 456: len, ffs_clusteralloc)) == 0)
! 457: goto fail;
! 458: /*
! 459: * We have found a new contiguous block.
! 460: *
! 461: * First we have to replace the old block pointers with the new
! 462: * block pointers in the inode and indirect blocks associated
! 463: * with the file.
! 464: */
! 465: #ifdef DEBUG
! 466: if (prtrealloc)
! 467: printf("realloc: ino %d, lbns %d-%d\n\told:", ip->i_number,
! 468: start_lbn, end_lbn);
! 469: #endif
! 470: blkno = newblk;
! 471: for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) {
! 472: if (i == ssize) {
! 473: bap = ebap;
! 474: soff = -i;
! 475: }
! 476: #ifdef DIAGNOSTIC
! 477: if (!ffs_checkblk(ip,
! 478: dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
! 479: panic("ffs1_reallocblks: unallocated block 2");
! 480: if (dbtofsb(fs, buflist->bs_children[i]->b_blkno) != *bap)
! 481: panic("ffs1_reallocblks: alloc mismatch");
! 482: #endif
! 483: #ifdef DEBUG
! 484: if (prtrealloc)
! 485: printf(" %d,", *bap);
! 486: #endif
! 487: if (DOINGSOFTDEP(vp)) {
! 488: if (sbap == &ip->i_ffs1_db[0] && i < ssize)
! 489: softdep_setup_allocdirect(ip, start_lbn + i,
! 490: blkno, *bap, fs->fs_bsize, fs->fs_bsize,
! 491: buflist->bs_children[i]);
! 492: else
! 493: softdep_setup_allocindir_page(ip, start_lbn + i,
! 494: i < ssize ? sbp : ebp, soff + i, blkno,
! 495: *bap, buflist->bs_children[i]);
! 496: }
! 497:
! 498: *bap++ = blkno;
! 499: }
! 500: /*
! 501: * Next we must write out the modified inode and indirect blocks.
! 502: * For strict correctness, the writes should be synchronous since
! 503: * the old block values may have been written to disk. In practise
! 504: * they are almost never written, but if we are concerned about
! 505: * strict correctness, the `doasyncfree' flag should be set to zero.
! 506: *
! 507: * The test on `doasyncfree' should be changed to test a flag
! 508: * that shows whether the associated buffers and inodes have
! 509: * been written. The flag should be set when the cluster is
! 510: * started and cleared whenever the buffer or inode is flushed.
! 511: * We can then check below to see if it is set, and do the
! 512: * synchronous write only when it has been cleared.
! 513: */
! 514: if (sbap != &ip->i_ffs1_db[0]) {
! 515: if (doasyncfree)
! 516: bdwrite(sbp);
! 517: else
! 518: bwrite(sbp);
! 519: } else {
! 520: ip->i_flag |= IN_CHANGE | IN_UPDATE;
! 521: if (!doasyncfree) {
! 522: UFS_UPDATE(ip, MNT_WAIT);
! 523: }
! 524: }
! 525: if (ssize < len) {
! 526: if (doasyncfree)
! 527: bdwrite(ebp);
! 528: else
! 529: bwrite(ebp);
! 530: }
! 531: /*
! 532: * Last, free the old blocks and assign the new blocks to the buffers.
! 533: */
! 534: #ifdef DEBUG
! 535: if (prtrealloc)
! 536: printf("\n\tnew:");
! 537: #endif
! 538: for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) {
! 539: if (!DOINGSOFTDEP(vp))
! 540: ffs_blkfree(ip,
! 541: dbtofsb(fs, buflist->bs_children[i]->b_blkno),
! 542: fs->fs_bsize);
! 543: buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
! 544: #ifdef DIAGNOSTIC
! 545: if (!ffs_checkblk(ip,
! 546: dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
! 547: panic("ffs1_reallocblks: unallocated block 3");
! 548: if (prtrealloc)
! 549: printf(" %d,", blkno);
! 550: #endif
! 551: }
! 552: #ifdef DEBUG
! 553: if (prtrealloc) {
! 554: prtrealloc--;
! 555: printf("\n");
! 556: }
! 557: #endif
! 558: return (0);
! 559:
! 560: fail:
! 561: if (ssize < len)
! 562: brelse(ebp);
! 563: if (sbap != &ip->i_ffs1_db[0])
! 564: brelse(sbp);
! 565: return (ENOSPC);
! 566: }
! 567:
! 568: #ifdef FFS2
! 569: int
! 570: ffs2_reallocblks(void *v)
! 571: {
! 572: struct vop_reallocblks_args *ap = v;
! 573: struct fs *fs;
! 574: struct inode *ip;
! 575: struct vnode *vp;
! 576: struct buf *sbp, *ebp;
! 577: daddr64_t *bap, *sbap, *ebap = 0;
! 578: struct cluster_save *buflist;
! 579: struct ufsmount *ump;
! 580: daddr64_t start_lbn, end_lbn;
! 581: daddr64_t soff, newblk, blkno, pref;
! 582: struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
! 583: int i, len, start_lvl, end_lvl, ssize;
! 584:
! 585: vp = ap->a_vp;
! 586: ip = VTOI(vp);
! 587: fs = ip->i_fs;
! 588: ump = ip->i_ump;
! 589:
! 590: if (fs->fs_contigsumsize <= 0)
! 591: return (ENOSPC);
! 592:
! 593: buflist = ap->a_buflist;
! 594: len = buflist->bs_nchildren;
! 595: start_lbn = buflist->bs_children[0]->b_lblkno;
! 596: end_lbn = start_lbn + len - 1;
! 597:
! 598: #ifdef DIAGNOSTIC
! 599: for (i = 0; i < len; i++)
! 600: if (!ffs_checkblk(ip,
! 601: dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
! 602: panic("ffs2_reallocblks: unallocated block 1");
! 603:
! 604: for (i = 1; i < len; i++)
! 605: if (buflist->bs_children[i]->b_lblkno != start_lbn + i)
! 606: panic("ffs2_reallocblks: non-logical cluster");
! 607:
! 608: blkno = buflist->bs_children[0]->b_blkno;
! 609: ssize = fsbtodb(fs, fs->fs_frag);
! 610:
! 611: for (i = 1; i < len - 1; i++)
! 612: if (buflist->bs_children[i]->b_blkno != blkno + (i * ssize))
! 613: panic("ffs2_reallocblks: non-physical cluster %d", i);
! 614: #endif
! 615:
! 616: /*
! 617: * If the latest allocation is in a new cylinder group, assume that
! 618: * the filesystem has decided to move and do not force it back to
! 619: * the previous cylinder group.
! 620: */
! 621: if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) !=
! 622: dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno)))
! 623: return (ENOSPC);
! 624: if (ufs_getlbns(vp, start_lbn, start_ap, &start_lvl) ||
! 625: ufs_getlbns(vp, end_lbn, end_ap, &end_lvl))
! 626: return (ENOSPC);
! 627:
! 628: /*
! 629: * Get the starting offset and block map for the first block.
! 630: */
! 631: if (start_lvl == 0) {
! 632: sbap = &ip->i_din2->di_db[0];
! 633: soff = start_lbn;
! 634: } else {
! 635: idp = &start_ap[start_lvl - 1];
! 636: if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &sbp)) {
! 637: brelse(sbp);
! 638: return (ENOSPC);
! 639: }
! 640: sbap = (daddr64_t *)sbp->b_data;
! 641: soff = idp->in_off;
! 642: }
! 643:
! 644: /*
! 645: * If the block range spans two block maps, get the second map.
! 646: */
! 647: if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) {
! 648: ssize = len;
! 649: } else {
! 650: #ifdef DIAGNOSTIC
! 651: if (start_ap[start_lvl-1].in_lbn == idp->in_lbn)
! 652: panic("ffs2_reallocblk: start == end");
! 653: #endif
! 654: ssize = len - (idp->in_off + 1);
! 655: if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &ebp))
! 656: goto fail;
! 657: ebap = (daddr64_t *)ebp->b_data;
! 658: }
! 659:
! 660: /*
! 661: * Find the preferred location for the cluster.
! 662: */
! 663: pref = ffs2_blkpref(ip, start_lbn, soff, sbap);
! 664:
! 665: /*
! 666: * Search the block map looking for an allocation of the desired size.
! 667: */
! 668: if ((newblk = ffs_hashalloc(ip, dtog(fs, pref), pref,
! 669: len, ffs_clusteralloc)) == 0)
! 670: goto fail;
! 671:
! 672: /*
! 673: * We have found a new contiguous block.
! 674: *
! 675: * First we have to replace the old block pointers with the new
! 676: * block pointers in the inode and indirect blocks associated
! 677: * with the file.
! 678: */
! 679: #ifdef DEBUG
! 680: if (prtrealloc)
! 681: printf("realloc: ino %d, lbns %jd-%jd\n\told:", ip->i_number,
! 682: (intmax_t)start_lbn, (intmax_t)end_lbn);
! 683: #endif
! 684:
! 685: blkno = newblk;
! 686:
! 687: for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) {
! 688: if (i == ssize) {
! 689: bap = ebap;
! 690: soff = -i;
! 691: }
! 692: #ifdef DIAGNOSTIC
! 693: if (!ffs_checkblk(ip,
! 694: dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
! 695: panic("ffs2_reallocblks: unallocated block 2");
! 696: if (dbtofsb(fs, buflist->bs_children[i]->b_blkno) != *bap)
! 697: panic("ffs2_reallocblks: alloc mismatch");
! 698: #endif
! 699: #ifdef DEBUG
! 700: if (prtrealloc)
! 701: printf(" %jd,", (intmax_t)*bap);
! 702: #endif
! 703: if (DOINGSOFTDEP(vp)) {
! 704: if (sbap == &ip->i_din2->di_db[0] && i < ssize)
! 705: softdep_setup_allocdirect(ip, start_lbn + i,
! 706: blkno, *bap, fs->fs_bsize, fs->fs_bsize,
! 707: buflist->bs_children[i]);
! 708: else
! 709: softdep_setup_allocindir_page(ip, start_lbn + i,
! 710: i < ssize ? sbp : ebp, soff + i, blkno,
! 711: *bap, buflist->bs_children[i]);
! 712: }
! 713: *bap++ = blkno;
! 714: }
! 715:
! 716: /*
! 717: * Next we must write out the modified inode and indirect blocks.
! 718: * For strict correctness, the writes should be synchronous since
! 719: * the old block values may have been written to disk. In practise
! 720: * they are almost never written, but if we are concerned about
! 721: * strict correctness, the `doasyncfree' flag should be set to zero.
! 722: *
! 723: * The test on `doasyncfree' should be changed to test a flag
! 724: * that shows whether the associated buffers and inodes have
! 725: * been written. The flag should be set when the cluster is
! 726: * started and cleared whenever the buffer or inode is flushed.
! 727: * We can then check below to see if it is set, and do the
! 728: * synchronous write only when it has been cleared.
! 729: */
! 730: if (sbap != &ip->i_din2->di_db[0]) {
! 731: if (doasyncfree)
! 732: bdwrite(sbp);
! 733: else
! 734: bwrite(sbp);
! 735: } else {
! 736: ip->i_flag |= IN_CHANGE | IN_UPDATE;
! 737: if (!doasyncfree)
! 738: ffs_update(ip, NULL, NULL, MNT_WAIT);
! 739: }
! 740:
! 741: if (ssize < len) {
! 742: if (doasyncfree)
! 743: bdwrite(ebp);
! 744: else
! 745: bwrite(ebp);
! 746: }
! 747:
! 748: /*
! 749: * Last, free the old blocks and assign the new blocks to the buffers.
! 750: */
! 751: #ifdef DEBUG
! 752: if (prtrealloc)
! 753: printf("\n\tnew:");
! 754: #endif
! 755: for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) {
! 756: if (!DOINGSOFTDEP(vp))
! 757: ffs_blkfree(ip, dbtofsb(fs,
! 758: buflist->bs_children[i]->b_blkno), fs->fs_bsize);
! 759: buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
! 760: #ifdef DIAGNOSTIC
! 761: if (!ffs_checkblk(ip,
! 762: dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
! 763: panic("ffs2_reallocblks: unallocated block 3");
! 764: #endif
! 765: #ifdef DEBUG
! 766: if (prtrealloc)
! 767: printf(" %jd,", (intmax_t)blkno);
! 768: #endif
! 769: }
! 770: #ifdef DEBUG
! 771: if (prtrealloc) {
! 772: prtrealloc--;
! 773: printf("\n");
! 774: }
! 775: #endif
! 776:
! 777: return (0);
! 778:
! 779: fail:
! 780: if (ssize < len)
! 781: brelse(ebp);
! 782:
! 783: if (sbap != &ip->i_din2->di_db[0])
! 784: brelse(sbp);
! 785:
! 786: return (ENOSPC);
! 787: }
! 788: #endif /* FFS2 */
! 789:
! 790: int
! 791: ffs_reallocblks(void *v)
! 792: {
! 793: #ifdef FFS2
! 794: struct vop_reallocblks_args *ap = v;
! 795: #endif
! 796:
! 797: if (!doreallocblks)
! 798: return (ENOSPC);
! 799:
! 800: #ifdef FFS2
! 801: if (VTOI(ap->a_vp)->i_ump->um_fstype == UM_UFS2)
! 802: return (ffs2_reallocblks(v));
! 803: #endif
! 804:
! 805: return (ffs1_reallocblks(v));
! 806: }
! 807:
! 808: /*
! 809: * Allocate an inode in the file system.
! 810: *
! 811: * If allocating a directory, use ffs_dirpref to select the inode.
! 812: * If allocating in a directory, the following hierarchy is followed:
! 813: * 1) allocate the preferred inode.
! 814: * 2) allocate an inode in the same cylinder group.
! 815: * 3) quadratically rehash into other cylinder groups, until an
! 816: * available inode is located.
! 817: * If no inode preference is given the following hierarchy is used
! 818: * to allocate an inode:
! 819: * 1) allocate an inode in cylinder group 0.
! 820: * 2) quadratically rehash into other cylinder groups, until an
! 821: * available inode is located.
! 822: */
! 823: int
! 824: ffs_inode_alloc(struct inode *pip, mode_t mode, struct ucred *cred,
! 825: struct vnode **vpp)
! 826: {
! 827: struct vnode *pvp = ITOV(pip);
! 828: struct fs *fs;
! 829: struct inode *ip;
! 830: ino_t ino, ipref;
! 831: int cg, error;
! 832:
! 833: *vpp = NULL;
! 834: fs = pip->i_fs;
! 835: if (fs->fs_cstotal.cs_nifree == 0)
! 836: goto noinodes;
! 837:
! 838: if ((mode & IFMT) == IFDIR)
! 839: ipref = ffs_dirpref(pip);
! 840: else
! 841: ipref = pip->i_number;
! 842: if (ipref >= fs->fs_ncg * fs->fs_ipg)
! 843: ipref = 0;
! 844: cg = ino_to_cg(fs, ipref);
! 845:
! 846: /*
! 847: * Track number of dirs created one after another
! 848: * in a same cg without intervening by files.
! 849: */
! 850: if ((mode & IFMT) == IFDIR) {
! 851: if (fs->fs_contigdirs[cg] < 255)
! 852: fs->fs_contigdirs[cg]++;
! 853: } else {
! 854: if (fs->fs_contigdirs[cg] > 0)
! 855: fs->fs_contigdirs[cg]--;
! 856: }
! 857: ino = (ino_t)ffs_hashalloc(pip, cg, (long)ipref, mode, ffs_nodealloccg);
! 858: if (ino == 0)
! 859: goto noinodes;
! 860: error = VFS_VGET(pvp->v_mount, ino, vpp);
! 861: if (error) {
! 862: ffs_inode_free(pip, ino, mode);
! 863: return (error);
! 864: }
! 865:
! 866: ip = VTOI(*vpp);
! 867:
! 868: if (DIP(ip, mode)) {
! 869: printf("mode = 0%o, inum = %d, fs = %s\n",
! 870: DIP(ip, mode), ip->i_number, fs->fs_fsmnt);
! 871: panic("ffs_valloc: dup alloc");
! 872: }
! 873:
! 874: if (DIP(ip, blocks)) {
! 875: printf("free inode %s/%d had %d blocks\n",
! 876: fs->fs_fsmnt, ino, DIP(ip, blocks));
! 877: DIP_ASSIGN(ip, blocks, 0);
! 878: }
! 879:
! 880: DIP_ASSIGN(ip, flags, 0);
! 881:
! 882: /*
! 883: * Set up a new generation number for this inode.
! 884: * XXX - just increment for now, this is wrong! (millert)
! 885: * Need a way to preserve randomization.
! 886: */
! 887: if (DIP(ip, gen) == 0 || ++(DIP(ip, gen)) == 0)
! 888: DIP_ASSIGN(ip, gen, arc4random() & INT_MAX);
! 889:
! 890: if (DIP(ip, gen) == 0 || DIP(ip, gen) == -1)
! 891: DIP_ASSIGN(ip, gen, 1); /* Shouldn't happen */
! 892:
! 893: return (0);
! 894:
! 895: noinodes:
! 896: ffs_fserr(fs, cred->cr_uid, "out of inodes");
! 897: uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt);
! 898: return (ENOSPC);
! 899: }
! 900:
! 901: /*
! 902: * Find a cylinder group to place a directory.
! 903: *
! 904: * The policy implemented by this algorithm is to allocate a
! 905: * directory inode in the same cylinder group as its parent
! 906: * directory, but also to reserve space for its files inodes
! 907: * and data. Restrict the number of directories which may be
! 908: * allocated one after another in the same cylinder group
! 909: * without intervening allocation of files.
! 910: *
! 911: * If we allocate a first level directory then force allocation
! 912: * in another cylinder group.
! 913: */
! 914: ino_t
! 915: ffs_dirpref(struct inode *pip)
! 916: {
! 917: struct fs *fs;
! 918: int cg, prefcg, dirsize, cgsize;
! 919: int avgifree, avgbfree, avgndir, curdirsize;
! 920: int minifree, minbfree, maxndir;
! 921: int mincg, minndir;
! 922: int maxcontigdirs;
! 923:
! 924: fs = pip->i_fs;
! 925:
! 926: avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg;
! 927: avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
! 928: avgndir = fs->fs_cstotal.cs_ndir / fs->fs_ncg;
! 929: #if 1
! 930:
! 931: /*
! 932: * Force allocation in another cg if creating a first level dir.
! 933: */
! 934: if (ITOV(pip)->v_flag & VROOT) {
! 935: prefcg = (arc4random() & INT_MAX) % fs->fs_ncg;
! 936: mincg = prefcg;
! 937: minndir = fs->fs_ipg;
! 938: for (cg = prefcg; cg < fs->fs_ncg; cg++)
! 939: if (fs->fs_cs(fs, cg).cs_ndir < minndir &&
! 940: fs->fs_cs(fs, cg).cs_nifree >= avgifree &&
! 941: fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
! 942: mincg = cg;
! 943: minndir = fs->fs_cs(fs, cg).cs_ndir;
! 944: }
! 945: for (cg = 0; cg < prefcg; cg++)
! 946: if (fs->fs_cs(fs, cg).cs_ndir < minndir &&
! 947: fs->fs_cs(fs, cg).cs_nifree >= avgifree &&
! 948: fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
! 949: mincg = cg;
! 950: minndir = fs->fs_cs(fs, cg).cs_ndir;
! 951: }
! 952: cg = mincg;
! 953: goto end;
! 954: } else
! 955: prefcg = ino_to_cg(fs, pip->i_number);
! 956: #else
! 957: prefcg = ino_to_cg(fs, pip->i_number);
! 958: #endif
! 959:
! 960: /*
! 961: * Count various limits which used for
! 962: * optimal allocation of a directory inode.
! 963: */
! 964: #if 1
! 965: maxndir = min(avgndir + fs->fs_ipg / 16, fs->fs_ipg);
! 966: minifree = avgifree - fs->fs_ipg / 4;
! 967: if (minifree < 0)
! 968: minifree = 0;
! 969: minbfree = avgbfree - fs->fs_fpg / fs->fs_frag / 4;
! 970: if (minbfree < 0)
! 971: minbfree = 0;
! 972: #else
! 973: maxndir = avgndir + (fs->fs_ipg - avgndir) / 16;
! 974: minifree = avgifree * 3 / 4;
! 975: minbfree = avgbfree * 3 / 4;
! 976: #endif
! 977: cgsize = fs->fs_fsize * fs->fs_fpg;
! 978: dirsize = fs->fs_avgfilesize * fs->fs_avgfpdir;
! 979: curdirsize = avgndir ? (cgsize - avgbfree * fs->fs_bsize) / avgndir : 0;
! 980: if (dirsize < curdirsize)
! 981: dirsize = curdirsize;
! 982: maxcontigdirs = min(cgsize / dirsize, 255);
! 983: if (fs->fs_avgfpdir > 0)
! 984: maxcontigdirs = min(maxcontigdirs,
! 985: fs->fs_ipg / fs->fs_avgfpdir);
! 986: if (maxcontigdirs == 0)
! 987: maxcontigdirs = 1;
! 988:
! 989: /*
! 990: * Limit number of dirs in one cg and reserve space for
! 991: * regular files, but only if we have no deficit in
! 992: * inodes or space.
! 993: */
! 994: for (cg = prefcg; cg < fs->fs_ncg; cg++)
! 995: if (fs->fs_cs(fs, cg).cs_ndir < maxndir &&
! 996: fs->fs_cs(fs, cg).cs_nifree >= minifree &&
! 997: fs->fs_cs(fs, cg).cs_nbfree >= minbfree) {
! 998: if (fs->fs_contigdirs[cg] < maxcontigdirs)
! 999: goto end;
! 1000: }
! 1001: for (cg = 0; cg < prefcg; cg++)
! 1002: if (fs->fs_cs(fs, cg).cs_ndir < maxndir &&
! 1003: fs->fs_cs(fs, cg).cs_nifree >= minifree &&
! 1004: fs->fs_cs(fs, cg).cs_nbfree >= minbfree) {
! 1005: if (fs->fs_contigdirs[cg] < maxcontigdirs)
! 1006: goto end;
! 1007: }
! 1008: /*
! 1009: * This is a backstop when we have deficit in space.
! 1010: */
! 1011: for (cg = prefcg; cg < fs->fs_ncg; cg++)
! 1012: if (fs->fs_cs(fs, cg).cs_nifree >= avgifree)
! 1013: goto end;
! 1014: for (cg = 0; cg < prefcg; cg++)
! 1015: if (fs->fs_cs(fs, cg).cs_nifree >= avgifree)
! 1016: goto end;
! 1017: end:
! 1018: return ((ino_t)(fs->fs_ipg * cg));
! 1019: }
! 1020:
! 1021: /*
! 1022: * Select the desired position for the next block in a file. The file is
! 1023: * logically divided into sections. The first section is composed of the
! 1024: * direct blocks. Each additional section contains fs_maxbpg blocks.
! 1025: *
! 1026: * If no blocks have been allocated in the first section, the policy is to
! 1027: * request a block in the same cylinder group as the inode that describes
! 1028: * the file. If no blocks have been allocated in any other section, the
! 1029: * policy is to place the section in a cylinder group with a greater than
! 1030: * average number of free blocks. An appropriate cylinder group is found
! 1031: * by using a rotor that sweeps the cylinder groups. When a new group of
! 1032: * blocks is needed, the sweep begins in the cylinder group following the
! 1033: * cylinder group from which the previous allocation was made. The sweep
! 1034: * continues until a cylinder group with greater than the average number
! 1035: * of free blocks is found. If the allocation is for the first block in an
! 1036: * indirect block, the information on the previous allocation is unavailable;
! 1037: * here a best guess is made based upon the logical block number being
! 1038: * allocated.
! 1039: */
! 1040: int32_t
! 1041: ffs1_blkpref(struct inode *ip, daddr_t lbn, int indx, int32_t *bap)
! 1042: {
! 1043: struct fs *fs;
! 1044: int cg, avgbfree, startcg;
! 1045:
! 1046: fs = ip->i_fs;
! 1047: if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
! 1048: if (lbn < NDADDR + NINDIR(fs)) {
! 1049: cg = ino_to_cg(fs, ip->i_number);
! 1050: return (fs->fs_fpg * cg + fs->fs_frag);
! 1051: }
! 1052: /*
! 1053: * Find a cylinder with greater than average number of
! 1054: * unused data blocks.
! 1055: */
! 1056: if (indx == 0 || bap[indx - 1] == 0)
! 1057: startcg =
! 1058: ino_to_cg(fs, ip->i_number) + lbn / fs->fs_maxbpg;
! 1059: else
! 1060: startcg = dtog(fs, bap[indx - 1]) + 1;
! 1061: startcg %= fs->fs_ncg;
! 1062: avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
! 1063: for (cg = startcg; cg < fs->fs_ncg; cg++)
! 1064: if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
! 1065: fs->fs_cgrotor = cg;
! 1066: return (fs->fs_fpg * cg + fs->fs_frag);
! 1067: }
! 1068: for (cg = 0; cg <= startcg; cg++)
! 1069: if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
! 1070: fs->fs_cgrotor = cg;
! 1071: return (fs->fs_fpg * cg + fs->fs_frag);
! 1072: }
! 1073: return (0);
! 1074: }
! 1075:
! 1076: return (bap[indx - 1] + fs->fs_frag);
! 1077: }
! 1078:
! 1079: /*
! 1080: * Same as above, for UFS2.
! 1081: */
! 1082: #ifdef FFS2
! 1083: int64_t
! 1084: ffs2_blkpref(struct inode *ip, daddr_t lbn, int indx, int64_t *bap)
! 1085: {
! 1086: struct fs *fs;
! 1087: int cg, avgbfree, startcg;
! 1088:
! 1089: fs = ip->i_fs;
! 1090:
! 1091: if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
! 1092: if (lbn < NDADDR + NINDIR(fs)) {
! 1093: cg = ino_to_cg(fs, ip->i_number);
! 1094: return (fs->fs_fpg * cg + fs->fs_frag);
! 1095: }
! 1096:
! 1097: /*
! 1098: * Find a cylinder with greater than average number of
! 1099: * unused data blocks.
! 1100: */
! 1101: if (indx == 0 || bap[indx - 1] == 0)
! 1102: startcg = ino_to_cg(fs, ip->i_number) +
! 1103: lbn / fs->fs_maxbpg;
! 1104: else
! 1105: startcg = dtog(fs, bap[indx - 1] + 1);
! 1106:
! 1107: startcg %= fs->fs_ncg;
! 1108: avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
! 1109:
! 1110: for (cg = startcg; cg < fs->fs_ncg; cg++)
! 1111: if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree)
! 1112: return (fs->fs_fpg * cg + fs->fs_frag);
! 1113:
! 1114: for (cg = 0; cg < startcg; cg++)
! 1115: if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree)
! 1116: return (fs->fs_fpg * cg + fs->fs_frag);
! 1117:
! 1118: return (0);
! 1119: }
! 1120:
! 1121: /*
! 1122: * We always just try to lay things out contiguously.
! 1123: */
! 1124: return (bap[indx - 1] + fs->fs_frag);
! 1125: }
! 1126: #endif /* FFS2 */
! 1127:
! 1128: /*
! 1129: * Implement the cylinder overflow algorithm.
! 1130: *
! 1131: * The policy implemented by this algorithm is:
! 1132: * 1) allocate the block in its requested cylinder group.
! 1133: * 2) quadratically rehash on the cylinder group number.
! 1134: * 3) brute force search for a free block.
! 1135: */
! 1136: /*VARARGS5*/
! 1137: u_long
! 1138: ffs_hashalloc(struct inode *ip, int cg, long pref, int size,
! 1139: daddr_t (*allocator)(struct inode *, int, daddr_t, int))
! 1140: {
! 1141: struct fs *fs;
! 1142: long result;
! 1143: int i, icg = cg;
! 1144:
! 1145: fs = ip->i_fs;
! 1146: /*
! 1147: * 1: preferred cylinder group
! 1148: */
! 1149: result = (*allocator)(ip, cg, pref, size);
! 1150: if (result)
! 1151: return (result);
! 1152: /*
! 1153: * 2: quadratic rehash
! 1154: */
! 1155: for (i = 1; i < fs->fs_ncg; i *= 2) {
! 1156: cg += i;
! 1157: if (cg >= fs->fs_ncg)
! 1158: cg -= fs->fs_ncg;
! 1159: result = (*allocator)(ip, cg, 0, size);
! 1160: if (result)
! 1161: return (result);
! 1162: }
! 1163: /*
! 1164: * 3: brute force search
! 1165: * Note that we start at i == 2, since 0 was checked initially,
! 1166: * and 1 is always checked in the quadratic rehash.
! 1167: */
! 1168: cg = (icg + 2) % fs->fs_ncg;
! 1169: for (i = 2; i < fs->fs_ncg; i++) {
! 1170: result = (*allocator)(ip, cg, 0, size);
! 1171: if (result)
! 1172: return (result);
! 1173: cg++;
! 1174: if (cg == fs->fs_ncg)
! 1175: cg = 0;
! 1176: }
! 1177: return (0);
! 1178: }
! 1179:
! 1180: /*
! 1181: * Determine whether a fragment can be extended.
! 1182: *
! 1183: * Check to see if the necessary fragments are available, and
! 1184: * if they are, allocate them.
! 1185: */
! 1186: daddr_t
! 1187: ffs_fragextend(struct inode *ip, int cg, long bprev, int osize, int nsize)
! 1188: {
! 1189: struct fs *fs;
! 1190: struct cg *cgp;
! 1191: struct buf *bp;
! 1192: long bno;
! 1193: int frags, bbase;
! 1194: int i, error;
! 1195:
! 1196: fs = ip->i_fs;
! 1197: if (fs->fs_cs(fs, cg).cs_nffree < numfrags(fs, nsize - osize))
! 1198: return (0);
! 1199: frags = numfrags(fs, nsize);
! 1200: bbase = fragnum(fs, bprev);
! 1201: if (bbase > fragnum(fs, (bprev + frags - 1))) {
! 1202: /* cannot extend across a block boundary */
! 1203: return (0);
! 1204: }
! 1205: error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
! 1206: (int)fs->fs_cgsize, NOCRED, &bp);
! 1207: if (error) {
! 1208: brelse(bp);
! 1209: return (0);
! 1210: }
! 1211: cgp = (struct cg *)bp->b_data;
! 1212: if (!cg_chkmagic(cgp)) {
! 1213: brelse(bp);
! 1214: return (0);
! 1215: }
! 1216:
! 1217: cgp->cg_ffs2_time = cgp->cg_time = time_second;
! 1218:
! 1219: bno = dtogd(fs, bprev);
! 1220: for (i = numfrags(fs, osize); i < frags; i++)
! 1221: if (isclr(cg_blksfree(cgp), bno + i)) {
! 1222: brelse(bp);
! 1223: return (0);
! 1224: }
! 1225: /*
! 1226: * the current fragment can be extended
! 1227: * deduct the count on fragment being extended into
! 1228: * increase the count on the remaining fragment (if any)
! 1229: * allocate the extended piece
! 1230: */
! 1231: for (i = frags; i < fs->fs_frag - bbase; i++)
! 1232: if (isclr(cg_blksfree(cgp), bno + i))
! 1233: break;
! 1234: cgp->cg_frsum[i - numfrags(fs, osize)]--;
! 1235: if (i != frags)
! 1236: cgp->cg_frsum[i - frags]++;
! 1237: for (i = numfrags(fs, osize); i < frags; i++) {
! 1238: clrbit(cg_blksfree(cgp), bno + i);
! 1239: cgp->cg_cs.cs_nffree--;
! 1240: fs->fs_cstotal.cs_nffree--;
! 1241: fs->fs_cs(fs, cg).cs_nffree--;
! 1242: }
! 1243: fs->fs_fmod = 1;
! 1244: if (DOINGSOFTDEP(ITOV(ip)))
! 1245: softdep_setup_blkmapdep(bp, fs, bprev);
! 1246:
! 1247: bdwrite(bp);
! 1248: return (bprev);
! 1249: }
! 1250:
! 1251: /*
! 1252: * Determine whether a block can be allocated.
! 1253: *
! 1254: * Check to see if a block of the appropriate size is available,
! 1255: * and if it is, allocate it.
! 1256: */
! 1257: daddr_t
! 1258: ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size)
! 1259: {
! 1260: struct fs *fs;
! 1261: struct cg *cgp;
! 1262: struct buf *bp;
! 1263: daddr_t bno, blkno;
! 1264: int error, i, frags, allocsiz;
! 1265:
! 1266: fs = ip->i_fs;
! 1267: if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize)
! 1268: return (0);
! 1269: /* read cylinder group block */
! 1270: error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
! 1271: (int)fs->fs_cgsize, NOCRED, &bp);
! 1272: if (error) {
! 1273: brelse(bp);
! 1274: return (0);
! 1275: }
! 1276: cgp = (struct cg *)bp->b_data;
! 1277: if (!cg_chkmagic(cgp) ||
! 1278: (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) {
! 1279: brelse(bp);
! 1280: return (0);
! 1281: }
! 1282:
! 1283: cgp->cg_ffs2_time = cgp->cg_time = time_second;
! 1284:
! 1285: if (size == fs->fs_bsize) {
! 1286: /* allocate and return a complete data block */
! 1287: bno = ffs_alloccgblk(ip, bp, bpref);
! 1288: bdwrite(bp);
! 1289: return (bno);
! 1290: }
! 1291: /*
! 1292: * check to see if any fragments are already available
! 1293: * allocsiz is the size which will be allocated, hacking
! 1294: * it down to a smaller size if necessary
! 1295: */
! 1296: frags = numfrags(fs, size);
! 1297: for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++)
! 1298: if (cgp->cg_frsum[allocsiz] != 0)
! 1299: break;
! 1300: if (allocsiz == fs->fs_frag) {
! 1301: /*
! 1302: * no fragments were available, so a block will be
! 1303: * allocated, and hacked up
! 1304: */
! 1305: if (cgp->cg_cs.cs_nbfree == 0) {
! 1306: brelse(bp);
! 1307: return (0);
! 1308: }
! 1309: bno = ffs_alloccgblk(ip, bp, bpref);
! 1310: bpref = dtogd(fs, bno);
! 1311: for (i = frags; i < fs->fs_frag; i++)
! 1312: setbit(cg_blksfree(cgp), bpref + i);
! 1313: i = fs->fs_frag - frags;
! 1314: cgp->cg_cs.cs_nffree += i;
! 1315: fs->fs_cstotal.cs_nffree += i;
! 1316: fs->fs_cs(fs, cg).cs_nffree += i;
! 1317: fs->fs_fmod = 1;
! 1318: cgp->cg_frsum[i]++;
! 1319: bdwrite(bp);
! 1320: return (bno);
! 1321: }
! 1322: bno = ffs_mapsearch(fs, cgp, bpref, allocsiz);
! 1323: if (bno < 0) {
! 1324: brelse(bp);
! 1325: return (0);
! 1326: }
! 1327:
! 1328: for (i = 0; i < frags; i++)
! 1329: clrbit(cg_blksfree(cgp), bno + i);
! 1330: cgp->cg_cs.cs_nffree -= frags;
! 1331: fs->fs_cstotal.cs_nffree -= frags;
! 1332: fs->fs_cs(fs, cg).cs_nffree -= frags;
! 1333: fs->fs_fmod = 1;
! 1334: cgp->cg_frsum[allocsiz]--;
! 1335: if (frags != allocsiz)
! 1336: cgp->cg_frsum[allocsiz - frags]++;
! 1337:
! 1338: blkno = cg * fs->fs_fpg + bno;
! 1339: if (DOINGSOFTDEP(ITOV(ip)))
! 1340: softdep_setup_blkmapdep(bp, fs, blkno);
! 1341: bdwrite(bp);
! 1342: return ((u_long)blkno);
! 1343: }
! 1344:
! 1345: /*
! 1346: * Allocate a block in a cylinder group.
! 1347: * Note that this routine only allocates fs_bsize blocks; these
! 1348: * blocks may be fragmented by the routine that allocates them.
! 1349: */
! 1350: daddr_t
! 1351: ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref)
! 1352: {
! 1353: struct fs *fs;
! 1354: struct cg *cgp;
! 1355: daddr_t bno, blkno;
! 1356: u_int8_t *blksfree;
! 1357: int cylno;
! 1358:
! 1359: fs = ip->i_fs;
! 1360: cgp = (struct cg *) bp->b_data;
! 1361: blksfree = cg_blksfree(cgp);
! 1362:
! 1363: if (bpref == 0 || dtog(fs, bpref) != cgp->cg_cgx)
! 1364: bpref = cgp->cg_rotor;
! 1365: else {
! 1366: bpref = blknum(fs, bpref);
! 1367: bno = dtogd(fs, bpref);
! 1368: /*
! 1369: * If the requested block is available, use it.
! 1370: */
! 1371: if (ffs_isblock(fs, blksfree, fragstoblks(fs, bno)))
! 1372: goto gotit;
! 1373: }
! 1374:
! 1375: /*
! 1376: * Take the next available block in this cylinder group.
! 1377: */
! 1378: bno = ffs_mapsearch(fs, cgp, bpref, (int) fs->fs_frag);
! 1379: if (bno < 0)
! 1380: return (0);
! 1381:
! 1382: cgp->cg_rotor = bno;
! 1383:
! 1384: gotit:
! 1385: blkno = fragstoblks(fs, bno);
! 1386: ffs_clrblock(fs, blksfree, (long) blkno);
! 1387: ffs_clusteracct(fs, cgp, blkno, -1);
! 1388: cgp->cg_cs.cs_nbfree--;
! 1389: fs->fs_cstotal.cs_nbfree--;
! 1390: fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
! 1391:
! 1392: if (fs->fs_magic != FS_UFS2_MAGIC) {
! 1393: cylno = cbtocylno(fs, bno);
! 1394: cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--;
! 1395: cg_blktot(cgp)[cylno]--;
! 1396: }
! 1397:
! 1398: fs->fs_fmod = 1;
! 1399: blkno = cgp->cg_cgx * fs->fs_fpg + bno;
! 1400:
! 1401: if (DOINGSOFTDEP(ITOV(ip)))
! 1402: softdep_setup_blkmapdep(bp, fs, blkno);
! 1403:
! 1404: return (blkno);
! 1405: }
! 1406:
! 1407: /*
! 1408: * Determine whether a cluster can be allocated.
! 1409: *
! 1410: * We do not currently check for optimal rotational layout if there
! 1411: * are multiple choices in the same cylinder group. Instead we just
! 1412: * take the first one that we find following bpref.
! 1413: */
! 1414: daddr_t
! 1415: ffs_clusteralloc(struct inode *ip, int cg, daddr_t bpref, int len)
! 1416: {
! 1417: struct fs *fs;
! 1418: struct cg *cgp;
! 1419: struct buf *bp;
! 1420: int i, got, run, bno, bit, map;
! 1421: u_char *mapp;
! 1422: int32_t *lp;
! 1423:
! 1424: fs = ip->i_fs;
! 1425: if (fs->fs_maxcluster[cg] < len)
! 1426: return (0);
! 1427: if (bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
! 1428: NOCRED, &bp))
! 1429: goto fail;
! 1430: cgp = (struct cg *)bp->b_data;
! 1431: if (!cg_chkmagic(cgp))
! 1432: goto fail;
! 1433: /*
! 1434: * Check to see if a cluster of the needed size (or bigger) is
! 1435: * available in this cylinder group.
! 1436: */
! 1437: lp = &cg_clustersum(cgp)[len];
! 1438: for (i = len; i <= fs->fs_contigsumsize; i++)
! 1439: if (*lp++ > 0)
! 1440: break;
! 1441: if (i > fs->fs_contigsumsize) {
! 1442: /*
! 1443: * This is the first time looking for a cluster in this
! 1444: * cylinder group. Update the cluster summary information
! 1445: * to reflect the true maximum sized cluster so that
! 1446: * future cluster allocation requests can avoid reading
! 1447: * the cylinder group map only to find no clusters.
! 1448: */
! 1449: lp = &cg_clustersum(cgp)[len - 1];
! 1450: for (i = len - 1; i > 0; i--)
! 1451: if (*lp-- > 0)
! 1452: break;
! 1453: fs->fs_maxcluster[cg] = i;
! 1454: goto fail;
! 1455: }
! 1456: /*
! 1457: * Search the cluster map to find a big enough cluster.
! 1458: * We take the first one that we find, even if it is larger
! 1459: * than we need as we prefer to get one close to the previous
! 1460: * block allocation. We do not search before the current
! 1461: * preference point as we do not want to allocate a block
! 1462: * that is allocated before the previous one (as we will
! 1463: * then have to wait for another pass of the elevator
! 1464: * algorithm before it will be read). We prefer to fail and
! 1465: * be recalled to try an allocation in the next cylinder group.
! 1466: */
! 1467: if (dtog(fs, bpref) != cg)
! 1468: bpref = 0;
! 1469: else
! 1470: bpref = fragstoblks(fs, dtogd(fs, blknum(fs, bpref)));
! 1471: mapp = &cg_clustersfree(cgp)[bpref / NBBY];
! 1472: map = *mapp++;
! 1473: bit = 1 << (bpref % NBBY);
! 1474: for (run = 0, got = bpref; got < cgp->cg_nclusterblks; got++) {
! 1475: if ((map & bit) == 0) {
! 1476: run = 0;
! 1477: } else {
! 1478: run++;
! 1479: if (run == len)
! 1480: break;
! 1481: }
! 1482: if ((got & (NBBY - 1)) != (NBBY - 1)) {
! 1483: bit <<= 1;
! 1484: } else {
! 1485: map = *mapp++;
! 1486: bit = 1;
! 1487: }
! 1488: }
! 1489: if (got >= cgp->cg_nclusterblks)
! 1490: goto fail;
! 1491: /*
! 1492: * Allocate the cluster that we have found.
! 1493: */
! 1494: cgp->cg_ffs2_time = cgp->cg_time = time_second;
! 1495:
! 1496: #ifdef DIAGNOSTIC
! 1497: for (i = 1; i <= len; i++)
! 1498: if (!ffs_isblock(fs, cg_blksfree(cgp), got - run + i))
! 1499: panic("ffs_clusteralloc: map mismatch");
! 1500: #endif
! 1501: bno = cg * fs->fs_fpg + blkstofrags(fs, got - run + 1);
! 1502: #ifdef DIAGNOSTIC
! 1503: if (dtog(fs, bno) != cg)
! 1504: panic("ffs_clusteralloc: allocated out of group");
! 1505: #endif
! 1506:
! 1507: len = blkstofrags(fs, len);
! 1508: for (i = 0; i < len; i += fs->fs_frag)
! 1509: if (ffs_alloccgblk(ip, bp, bno + i) != bno + i)
! 1510: panic("ffs_clusteralloc: lost block");
! 1511: bdwrite(bp);
! 1512: return (bno);
! 1513:
! 1514: fail:
! 1515: brelse(bp);
! 1516: return (0);
! 1517: }
! 1518:
! 1519: /* inode allocation routine */
! 1520: daddr_t
! 1521: ffs_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode)
! 1522: {
! 1523: struct fs *fs;
! 1524: struct cg *cgp;
! 1525: struct buf *bp;
! 1526: int error, start, len, loc, map, i;
! 1527: #ifdef FFS2
! 1528: struct buf *ibp = NULL;
! 1529: struct ufs2_dinode *dp2;
! 1530: #endif
! 1531:
! 1532: /*
! 1533: * For efficiency, before looking at the bitmaps for free inodes,
! 1534: * check the counters kept in the superblock cylinder group summaries,
! 1535: * and in the cylinder group itself.
! 1536: */
! 1537: fs = ip->i_fs;
! 1538: if (fs->fs_cs(fs, cg).cs_nifree == 0)
! 1539: return (0);
! 1540:
! 1541: error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
! 1542: (int)fs->fs_cgsize, NOCRED, &bp);
! 1543: if (error) {
! 1544: brelse(bp);
! 1545: return (0);
! 1546: }
! 1547:
! 1548: cgp = (struct cg *)bp->b_data;
! 1549: if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) {
! 1550: brelse(bp);
! 1551: return (0);
! 1552: }
! 1553:
! 1554: /*
! 1555: * We are committed to the allocation from now on, so update the time
! 1556: * on the cylinder group.
! 1557: */
! 1558: cgp->cg_ffs2_time = cgp->cg_time = time_second;
! 1559:
! 1560: /*
! 1561: * If there was a preferred location for the new inode, try to find it.
! 1562: */
! 1563: if (ipref) {
! 1564: ipref %= fs->fs_ipg;
! 1565: if (isclr(cg_inosused(cgp), ipref))
! 1566: goto gotit; /* inode is free, grab it. */
! 1567: }
! 1568:
! 1569: /*
! 1570: * Otherwise, look for the next available inode, starting at cg_irotor
! 1571: * (the position in the bitmap of the last used inode).
! 1572: */
! 1573: start = cgp->cg_irotor / NBBY;
! 1574: len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY);
! 1575: loc = skpc(0xff, len, &cg_inosused(cgp)[start]);
! 1576: if (loc == 0) {
! 1577: /*
! 1578: * If we didn't find a free inode in the upper part of the
! 1579: * bitmap (from cg_irotor to the end), then look at the bottom
! 1580: * part (from 0 to cg_irotor).
! 1581: */
! 1582: len = start + 1;
! 1583: start = 0;
! 1584: loc = skpc(0xff, len, &cg_inosused(cgp)[0]);
! 1585: if (loc == 0) {
! 1586: /*
! 1587: * If we failed again, then either the bitmap or the
! 1588: * counters kept for the cylinder group are wrong.
! 1589: */
! 1590: printf("cg = %d, irotor = %d, fs = %s\n",
! 1591: cg, cgp->cg_irotor, fs->fs_fsmnt);
! 1592: panic("ffs_nodealloccg: map corrupted");
! 1593: /* NOTREACHED */
! 1594: }
! 1595: }
! 1596:
! 1597: /* skpc() returns the position relative to the end */
! 1598: i = start + len - loc;
! 1599:
! 1600: /*
! 1601: * Okay, so now in 'i' we have the location in the bitmap of a byte
! 1602: * holding a free inode. Find the corresponding bit and set it,
! 1603: * updating cg_irotor as well, accordingly.
! 1604: */
! 1605: map = cg_inosused(cgp)[i];
! 1606: ipref = i * NBBY;
! 1607: for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) {
! 1608: if ((map & i) == 0) {
! 1609: cgp->cg_irotor = ipref;
! 1610: goto gotit;
! 1611: }
! 1612: }
! 1613:
! 1614: printf("fs = %s\n", fs->fs_fsmnt);
! 1615: panic("ffs_nodealloccg: block not in map");
! 1616: /* NOTREACHED */
! 1617:
! 1618: gotit:
! 1619:
! 1620: #ifdef FFS2
! 1621: /*
! 1622: * For FFS2, check if all inodes in this cylinder group have been used
! 1623: * at least once. If they haven't, and we are allocating an inode past
! 1624: * the last allocated block of inodes, read in a block and initialize
! 1625: * all inodes in it.
! 1626: */
! 1627: if (fs->fs_magic == FS_UFS2_MAGIC &&
! 1628: /* Inode is beyond last initialized block of inodes? */
! 1629: ipref + INOPB(fs) > cgp->cg_initediblk &&
! 1630: /* Has any inode not been used at least once? */
! 1631: cgp->cg_initediblk < cgp->cg_ffs2_niblk) {
! 1632:
! 1633: ibp = getblk(ip->i_devvp, fsbtodb(fs,
! 1634: ino_to_fsba(fs, cg * fs->fs_ipg + cgp->cg_initediblk)),
! 1635: (int)fs->fs_bsize, 0, 0);
! 1636:
! 1637: bzero(ibp->b_data, (int)fs->fs_bsize);
! 1638: dp2 = (struct ufs2_dinode *)(ibp->b_data);
! 1639:
! 1640: /* Give each inode a positive generation number */
! 1641: for (i = 0; i < INOPB(fs); i++) {
! 1642: dp2->di_gen = (arc4random() & INT32_MAX) / 2 + 1;
! 1643: dp2++;
! 1644: }
! 1645:
! 1646: /* Update the counter of initialized inodes */
! 1647: cgp->cg_initediblk += INOPB(fs);
! 1648: }
! 1649: #endif /* FFS2 */
! 1650:
! 1651: if (DOINGSOFTDEP(ITOV(ip)))
! 1652: softdep_setup_inomapdep(bp, ip, cg * fs->fs_ipg + ipref);
! 1653:
! 1654: setbit(cg_inosused(cgp), ipref);
! 1655:
! 1656: /* Update the counters we keep on free inodes */
! 1657: cgp->cg_cs.cs_nifree--;
! 1658: fs->fs_cstotal.cs_nifree--;
! 1659: fs->fs_cs(fs, cg).cs_nifree--;
! 1660: fs->fs_fmod = 1; /* file system was modified */
! 1661:
! 1662: /* Update the counters we keep on allocated directories */
! 1663: if ((mode & IFMT) == IFDIR) {
! 1664: cgp->cg_cs.cs_ndir++;
! 1665: fs->fs_cstotal.cs_ndir++;
! 1666: fs->fs_cs(fs, cg).cs_ndir++;
! 1667: }
! 1668:
! 1669: bdwrite(bp);
! 1670:
! 1671: #ifdef FFS2
! 1672: if (ibp != NULL)
! 1673: bawrite(ibp);
! 1674: #endif
! 1675:
! 1676: /* Return the allocated inode number */
! 1677: return (cg * fs->fs_ipg + ipref);
! 1678: }
! 1679:
! 1680: /*
! 1681: * Free a block or fragment.
! 1682: *
! 1683: * The specified block or fragment is placed back in the
! 1684: * free map. If a fragment is deallocated, a possible
! 1685: * block reassembly is checked.
! 1686: */
! 1687: void
! 1688: ffs_blkfree(struct inode *ip, daddr64_t bno, long size)
! 1689: {
! 1690: struct fs *fs;
! 1691: struct cg *cgp;
! 1692: struct buf *bp;
! 1693: daddr_t blkno;
! 1694: int i, error, cg, blk, frags, bbase;
! 1695:
! 1696: fs = ip->i_fs;
! 1697: if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 ||
! 1698: fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) {
! 1699: printf("dev = 0x%x, bsize = %d, size = %ld, fs = %s\n",
! 1700: ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt);
! 1701: panic("ffs_blkfree: bad size");
! 1702: }
! 1703: cg = dtog(fs, bno);
! 1704: if ((u_int)bno >= fs->fs_size) {
! 1705: printf("bad block %d, ino %u\n", bno, ip->i_number);
! 1706: ffs_fserr(fs, DIP(ip, uid), "bad block");
! 1707: return;
! 1708: }
! 1709: error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
! 1710: (int)fs->fs_cgsize, NOCRED, &bp);
! 1711: if (error) {
! 1712: brelse(bp);
! 1713: return;
! 1714: }
! 1715: cgp = (struct cg *)bp->b_data;
! 1716: if (!cg_chkmagic(cgp)) {
! 1717: brelse(bp);
! 1718: return;
! 1719: }
! 1720:
! 1721: cgp->cg_ffs2_time = cgp->cg_time = time_second;
! 1722:
! 1723: bno = dtogd(fs, bno);
! 1724: if (size == fs->fs_bsize) {
! 1725: blkno = fragstoblks(fs, bno);
! 1726: if (!ffs_isfreeblock(fs, cg_blksfree(cgp), blkno)) {
! 1727: printf("dev = 0x%x, block = %d, fs = %s\n",
! 1728: ip->i_dev, bno, fs->fs_fsmnt);
! 1729: panic("ffs_blkfree: freeing free block");
! 1730: }
! 1731: ffs_setblock(fs, cg_blksfree(cgp), blkno);
! 1732: ffs_clusteracct(fs, cgp, blkno, 1);
! 1733: cgp->cg_cs.cs_nbfree++;
! 1734: fs->fs_cstotal.cs_nbfree++;
! 1735: fs->fs_cs(fs, cg).cs_nbfree++;
! 1736:
! 1737: if (fs->fs_magic != FS_UFS2_MAGIC) {
! 1738: i = cbtocylno(fs, bno);
! 1739: cg_blks(fs, cgp, i)[cbtorpos(fs, bno)]++;
! 1740: cg_blktot(cgp)[i]++;
! 1741: }
! 1742:
! 1743: } else {
! 1744: bbase = bno - fragnum(fs, bno);
! 1745: /*
! 1746: * decrement the counts associated with the old frags
! 1747: */
! 1748: blk = blkmap(fs, cg_blksfree(cgp), bbase);
! 1749: ffs_fragacct(fs, blk, cgp->cg_frsum, -1);
! 1750: /*
! 1751: * deallocate the fragment
! 1752: */
! 1753: frags = numfrags(fs, size);
! 1754: for (i = 0; i < frags; i++) {
! 1755: if (isset(cg_blksfree(cgp), bno + i)) {
! 1756: printf("dev = 0x%x, block = %d, fs = %s\n",
! 1757: ip->i_dev, bno + i, fs->fs_fsmnt);
! 1758: panic("ffs_blkfree: freeing free frag");
! 1759: }
! 1760: setbit(cg_blksfree(cgp), bno + i);
! 1761: }
! 1762: cgp->cg_cs.cs_nffree += i;
! 1763: fs->fs_cstotal.cs_nffree += i;
! 1764: fs->fs_cs(fs, cg).cs_nffree += i;
! 1765: /*
! 1766: * add back in counts associated with the new frags
! 1767: */
! 1768: blk = blkmap(fs, cg_blksfree(cgp), bbase);
! 1769: ffs_fragacct(fs, blk, cgp->cg_frsum, 1);
! 1770: /*
! 1771: * if a complete block has been reassembled, account for it
! 1772: */
! 1773: blkno = fragstoblks(fs, bbase);
! 1774: if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) {
! 1775: cgp->cg_cs.cs_nffree -= fs->fs_frag;
! 1776: fs->fs_cstotal.cs_nffree -= fs->fs_frag;
! 1777: fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
! 1778: ffs_clusteracct(fs, cgp, blkno, 1);
! 1779: cgp->cg_cs.cs_nbfree++;
! 1780: fs->fs_cstotal.cs_nbfree++;
! 1781: fs->fs_cs(fs, cg).cs_nbfree++;
! 1782:
! 1783: if (fs->fs_magic != FS_UFS2_MAGIC) {
! 1784: i = cbtocylno(fs, bbase);
! 1785: cg_blks(fs, cgp, i)[cbtorpos(fs, bbase)]++;
! 1786: cg_blktot(cgp)[i]++;
! 1787: }
! 1788: }
! 1789: }
! 1790: fs->fs_fmod = 1;
! 1791: bdwrite(bp);
! 1792: }
! 1793:
! 1794: int
! 1795: ffs_inode_free(struct inode *pip, ino_t ino, mode_t mode)
! 1796: {
! 1797: struct vnode *pvp = ITOV(pip);
! 1798:
! 1799: if (DOINGSOFTDEP(pvp)) {
! 1800: softdep_freefile(pvp, ino, mode);
! 1801: return (0);
! 1802: }
! 1803:
! 1804: return (ffs_freefile(pip, ino, mode));
! 1805: }
! 1806:
! 1807: /*
! 1808: * Do the actual free operation.
! 1809: * The specified inode is placed back in the free map.
! 1810: */
! 1811: int
! 1812: ffs_freefile(struct inode *pip, ino_t ino, mode_t mode)
! 1813: {
! 1814: struct fs *fs;
! 1815: struct cg *cgp;
! 1816: struct buf *bp;
! 1817: int error, cg;
! 1818:
! 1819: fs = pip->i_fs;
! 1820: if ((u_int)ino >= fs->fs_ipg * fs->fs_ncg)
! 1821: panic("ffs_freefile: range: dev = 0x%x, ino = %d, fs = %s",
! 1822: pip->i_dev, ino, fs->fs_fsmnt);
! 1823: cg = ino_to_cg(fs, ino);
! 1824: error = bread(pip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
! 1825: (int)fs->fs_cgsize, NOCRED, &bp);
! 1826: if (error) {
! 1827: brelse(bp);
! 1828: return (error);
! 1829: }
! 1830: cgp = (struct cg *)bp->b_data;
! 1831: if (!cg_chkmagic(cgp)) {
! 1832: brelse(bp);
! 1833: return (0);
! 1834: }
! 1835:
! 1836: cgp->cg_ffs2_time = cgp->cg_time = time_second;
! 1837:
! 1838: ino %= fs->fs_ipg;
! 1839: if (isclr(cg_inosused(cgp), ino)) {
! 1840: printf("dev = 0x%x, ino = %u, fs = %s\n",
! 1841: pip->i_dev, ino, fs->fs_fsmnt);
! 1842: if (fs->fs_ronly == 0)
! 1843: panic("ffs_freefile: freeing free inode");
! 1844: }
! 1845: clrbit(cg_inosused(cgp), ino);
! 1846: if (ino < cgp->cg_irotor)
! 1847: cgp->cg_irotor = ino;
! 1848: cgp->cg_cs.cs_nifree++;
! 1849: fs->fs_cstotal.cs_nifree++;
! 1850: fs->fs_cs(fs, cg).cs_nifree++;
! 1851: if ((mode & IFMT) == IFDIR) {
! 1852: cgp->cg_cs.cs_ndir--;
! 1853: fs->fs_cstotal.cs_ndir--;
! 1854: fs->fs_cs(fs, cg).cs_ndir--;
! 1855: }
! 1856: fs->fs_fmod = 1;
! 1857: bdwrite(bp);
! 1858: return (0);
! 1859: }
! 1860:
! 1861: #ifdef DIAGNOSTIC
! 1862: /*
! 1863: * Verify allocation of a block or fragment. Returns true if block or
! 1864: * fragment is allocated, false if it is free.
! 1865: */
! 1866: int
! 1867: ffs_checkblk(struct inode *ip, daddr_t bno, long size)
! 1868: {
! 1869: struct fs *fs;
! 1870: struct cg *cgp;
! 1871: struct buf *bp;
! 1872: int i, error, frags, free;
! 1873:
! 1874: fs = ip->i_fs;
! 1875: if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) {
! 1876: printf("bsize = %d, size = %ld, fs = %s\n",
! 1877: fs->fs_bsize, size, fs->fs_fsmnt);
! 1878: panic("ffs_checkblk: bad size");
! 1879: }
! 1880: if ((u_int)bno >= fs->fs_size)
! 1881: panic("ffs_checkblk: bad block %d", bno);
! 1882: error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, dtog(fs, bno))),
! 1883: (int)fs->fs_cgsize, NOCRED, &bp);
! 1884: if (error) {
! 1885: brelse(bp);
! 1886: return (0);
! 1887: }
! 1888:
! 1889: cgp = (struct cg *)bp->b_data;
! 1890: if (!cg_chkmagic(cgp)) {
! 1891: brelse(bp);
! 1892: return (0);
! 1893: }
! 1894:
! 1895: bno = dtogd(fs, bno);
! 1896: if (size == fs->fs_bsize) {
! 1897: free = ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno));
! 1898: } else {
! 1899: frags = numfrags(fs, size);
! 1900: for (free = 0, i = 0; i < frags; i++)
! 1901: if (isset(cg_blksfree(cgp), bno + i))
! 1902: free++;
! 1903: if (free != 0 && free != frags)
! 1904: panic("ffs_checkblk: partially free fragment");
! 1905: }
! 1906: brelse(bp);
! 1907: return (!free);
! 1908: }
! 1909: #endif /* DIAGNOSTIC */
! 1910:
! 1911:
! 1912: /*
! 1913: * Find a block of the specified size in the specified cylinder group.
! 1914: *
! 1915: * It is a panic if a request is made to find a block if none are
! 1916: * available.
! 1917: */
! 1918: daddr_t
! 1919: ffs_mapsearch(struct fs *fs, struct cg *cgp, daddr_t bpref, int allocsiz)
! 1920: {
! 1921: daddr_t bno;
! 1922: int start, len, loc, i;
! 1923: int blk, field, subfield, pos;
! 1924:
! 1925: /*
! 1926: * find the fragment by searching through the free block
! 1927: * map for an appropriate bit pattern
! 1928: */
! 1929: if (bpref)
! 1930: start = dtogd(fs, bpref) / NBBY;
! 1931: else
! 1932: start = cgp->cg_frotor / NBBY;
! 1933: len = howmany(fs->fs_fpg, NBBY) - start;
! 1934: loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[start],
! 1935: (u_char *)fragtbl[fs->fs_frag],
! 1936: (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
! 1937: if (loc == 0) {
! 1938: len = start + 1;
! 1939: start = 0;
! 1940: loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[0],
! 1941: (u_char *)fragtbl[fs->fs_frag],
! 1942: (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
! 1943: if (loc == 0) {
! 1944: printf("start = %d, len = %d, fs = %s\n",
! 1945: start, len, fs->fs_fsmnt);
! 1946: panic("ffs_alloccg: map corrupted");
! 1947: /* NOTREACHED */
! 1948: }
! 1949: }
! 1950: bno = (start + len - loc) * NBBY;
! 1951: cgp->cg_frotor = bno;
! 1952: /*
! 1953: * found the byte in the map
! 1954: * sift through the bits to find the selected frag
! 1955: */
! 1956: for (i = bno + NBBY; bno < i; bno += fs->fs_frag) {
! 1957: blk = blkmap(fs, cg_blksfree(cgp), bno);
! 1958: blk <<= 1;
! 1959: field = around[allocsiz];
! 1960: subfield = inside[allocsiz];
! 1961: for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) {
! 1962: if ((blk & field) == subfield)
! 1963: return (bno + pos);
! 1964: field <<= 1;
! 1965: subfield <<= 1;
! 1966: }
! 1967: }
! 1968: printf("bno = %d, fs = %s\n", bno, fs->fs_fsmnt);
! 1969: panic("ffs_alloccg: block not in map");
! 1970: return (-1);
! 1971: }
! 1972:
! 1973: /*
! 1974: * Update the cluster map because of an allocation or free.
! 1975: *
! 1976: * Cnt == 1 means free; cnt == -1 means allocating.
! 1977: */
! 1978: void
! 1979: ffs_clusteracct(struct fs *fs, struct cg *cgp, daddr_t blkno, int cnt)
! 1980: {
! 1981: int32_t *sump;
! 1982: int32_t *lp;
! 1983: u_char *freemapp, *mapp;
! 1984: int i, start, end, forw, back, map, bit;
! 1985:
! 1986: if (fs->fs_contigsumsize <= 0)
! 1987: return;
! 1988: freemapp = cg_clustersfree(cgp);
! 1989: sump = cg_clustersum(cgp);
! 1990: /*
! 1991: * Allocate or clear the actual block.
! 1992: */
! 1993: if (cnt > 0)
! 1994: setbit(freemapp, blkno);
! 1995: else
! 1996: clrbit(freemapp, blkno);
! 1997: /*
! 1998: * Find the size of the cluster going forward.
! 1999: */
! 2000: start = blkno + 1;
! 2001: end = start + fs->fs_contigsumsize;
! 2002: if (end >= cgp->cg_nclusterblks)
! 2003: end = cgp->cg_nclusterblks;
! 2004: mapp = &freemapp[start / NBBY];
! 2005: map = *mapp++;
! 2006: bit = 1 << (start % NBBY);
! 2007: for (i = start; i < end; i++) {
! 2008: if ((map & bit) == 0)
! 2009: break;
! 2010: if ((i & (NBBY - 1)) != (NBBY - 1)) {
! 2011: bit <<= 1;
! 2012: } else {
! 2013: map = *mapp++;
! 2014: bit = 1;
! 2015: }
! 2016: }
! 2017: forw = i - start;
! 2018: /*
! 2019: * Find the size of the cluster going backward.
! 2020: */
! 2021: start = blkno - 1;
! 2022: end = start - fs->fs_contigsumsize;
! 2023: if (end < 0)
! 2024: end = -1;
! 2025: mapp = &freemapp[start / NBBY];
! 2026: map = *mapp--;
! 2027: bit = 1 << (start % NBBY);
! 2028: for (i = start; i > end; i--) {
! 2029: if ((map & bit) == 0)
! 2030: break;
! 2031: if ((i & (NBBY - 1)) != 0) {
! 2032: bit >>= 1;
! 2033: } else {
! 2034: map = *mapp--;
! 2035: bit = 1 << (NBBY - 1);
! 2036: }
! 2037: }
! 2038: back = start - i;
! 2039: /*
! 2040: * Account for old cluster and the possibly new forward and
! 2041: * back clusters.
! 2042: */
! 2043: i = back + forw + 1;
! 2044: if (i > fs->fs_contigsumsize)
! 2045: i = fs->fs_contigsumsize;
! 2046: sump[i] += cnt;
! 2047: if (back > 0)
! 2048: sump[back] -= cnt;
! 2049: if (forw > 0)
! 2050: sump[forw] -= cnt;
! 2051: /*
! 2052: * Update cluster summary information.
! 2053: */
! 2054: lp = &sump[fs->fs_contigsumsize];
! 2055: for (i = fs->fs_contigsumsize; i > 0; i--)
! 2056: if (*lp-- > 0)
! 2057: break;
! 2058: fs->fs_maxcluster[cgp->cg_cgx] = i;
! 2059: }
CVSweb