|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1982, 1986, 1989, 1993 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95 ! 59: */ ! 60: ! 61: #include <rev_endian_fs.h> ! 62: #include <mach_nbc.h> ! 63: #include <sys/param.h> ! 64: #include <sys/systm.h> ! 65: #include <sys/buf.h> ! 66: #include <sys/proc.h> ! 67: #include <sys/file.h> ! 68: #include <sys/vnode.h> ! 69: #if REV_ENDIAN_FS ! 70: #include <sys/mount.h> ! 71: #endif /* REV_ENDIAN_FS */ ! 72: ! 73: #include <sys/vm.h> ! 74: ! 75: #include <ufs/ufs/quota.h> ! 76: #include <ufs/ufs/inode.h> ! 77: #include <ufs/ufs/ufs_extern.h> ! 78: ! 79: #include <ufs/ffs/fs.h> ! 80: #include <ufs/ffs/ffs_extern.h> ! 81: ! 82: #if REV_ENDIAN_FS ! 83: #include <ufs/ufs/ufs_byte_order.h> ! 84: #include <architecture/byte_order.h> ! 85: #endif /* REV_ENDIAN_FS */ ! 86: ! 87: #if MACH_NBC ! 88: #include <kern/mapfs.h> ! 89: #endif /* MACH_NBC */ ! 90: /* ! 91: * Balloc defines the structure of file system storage ! 92: * by allocating the physical blocks on a device given ! 93: * the inode and the logical block number in a file. ! 94: */ ! 95: ffs_balloc(ip, lbn, size, cred, bpp, flags) ! 96: register struct inode *ip; ! 97: register ufs_daddr_t lbn; ! 98: int size; ! 99: struct ucred *cred; ! 100: struct buf **bpp; ! 101: int flags; ! 102: { ! 103: register struct fs *fs; ! 104: register ufs_daddr_t nb; ! 105: struct buf *bp, *nbp; ! 106: struct vnode *vp = ITOV(ip); ! 107: struct indir indirs[NIADDR + 2]; ! 108: ufs_daddr_t newb, *bap, pref; ! 109: int deallocated, osize, nsize, num, i, error; ! 110: ufs_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1]; ! 111: #ifdef NeXT ! 112: int devBlockSize=0; ! 113: #endif /* NeXT */ ! 114: #if REV_ENDIAN_FS ! 115: struct mount *mp=vp->v_mount; ! 116: int rev_endian=(mp->mnt_flag & MNT_REVEND); ! 117: #endif /* REV_ENDIAN_FS */ ! 118: ! 119: *bpp = NULL; ! 120: if (lbn < 0) ! 121: return (EFBIG); ! 122: fs = ip->i_fs; ! 123: ! 124: /* ! 125: * If the next write will extend the file into a new block, ! 126: * and the file is currently composed of a fragment ! 127: * this fragment has to be extended to be a full block. ! 128: */ ! 129: nb = lblkno(fs, ip->i_size); ! 130: if (nb < NDADDR && nb < lbn) { ! 131: osize = blksize(fs, ip, nb); ! 132: if (osize < fs->fs_bsize && osize > 0) { ! 133: error = ffs_realloccg(ip, nb, ! 134: ffs_blkpref(ip, nb, (int)nb, &ip->i_db[0]), ! 135: osize, (int)fs->fs_bsize, cred, &bp); ! 136: if (error) ! 137: return (error); ! 138: ip->i_size = (nb + 1) * fs->fs_bsize; ! 139: #if MACH_NBC ! 140: if ((vp->v_type == VREG) && (vp->v_vm_info && !(vp->v_vm_info->mapped))) { ! 141: #endif /* MACH_NBC */ ! 142: vnode_pager_setsize(vp, (u_long)ip->i_size); ! 143: #if MACH_NBC ! 144: } ! 145: #endif /* MACH_NBC */ ! 146: ip->i_db[nb] = dbtofsb(fs, bp->b_blkno); ! 147: ip->i_flag |= IN_CHANGE | IN_UPDATE; ! 148: if (flags & B_SYNC) ! 149: bwrite(bp); ! 150: else ! 151: bawrite(bp); ! 152: } ! 153: } ! 154: /* ! 155: * The first NDADDR blocks are direct blocks ! 156: */ ! 157: if (lbn < NDADDR) { ! 158: nb = ip->i_db[lbn]; ! 159: if (nb != 0 && ip->i_size >= (lbn + 1) * fs->fs_bsize) { ! 160: error = bread(vp, lbn, fs->fs_bsize, NOCRED, &bp); ! 161: if (error) { ! 162: brelse(bp); ! 163: return (error); ! 164: } ! 165: *bpp = bp; ! 166: return (0); ! 167: } ! 168: if (nb != 0) { ! 169: /* ! 170: * Consider need to reallocate a fragment. ! 171: */ ! 172: osize = fragroundup(fs, blkoff(fs, ip->i_size)); ! 173: nsize = fragroundup(fs, size); ! 174: if (nsize <= osize) { ! 175: error = bread(vp, lbn, osize, NOCRED, &bp); ! 176: if (error) { ! 177: brelse(bp); ! 178: return (error); ! 179: } ! 180: } else { ! 181: error = ffs_realloccg(ip, lbn, ! 182: ffs_blkpref(ip, lbn, (int)lbn, ! 183: &ip->i_db[0]), osize, nsize, cred, &bp); ! 184: if (error) ! 185: return (error); ! 186: } ! 187: } else { ! 188: if (ip->i_size < (lbn + 1) * fs->fs_bsize) ! 189: nsize = fragroundup(fs, size); ! 190: else ! 191: nsize = fs->fs_bsize; ! 192: error = ffs_alloc(ip, lbn, ! 193: ffs_blkpref(ip, lbn, (int)lbn, &ip->i_db[0]), ! 194: nsize, cred, &newb); ! 195: if (error) ! 196: return (error); ! 197: bp = getblk(vp, lbn, nsize, 0, 0); ! 198: bp->b_blkno = fsbtodb(fs, newb); ! 199: if (flags & B_CLRBUF) ! 200: clrbuf(bp); ! 201: } ! 202: ip->i_db[lbn] = dbtofsb(fs, bp->b_blkno); ! 203: ip->i_flag |= IN_CHANGE | IN_UPDATE; ! 204: *bpp = bp; ! 205: return (0); ! 206: } ! 207: /* ! 208: * Determine the number of levels of indirection. ! 209: */ ! 210: pref = 0; ! 211: if (error = ufs_getlbns(vp, lbn, indirs, &num)) ! 212: return(error); ! 213: #if DIAGNOSTIC ! 214: if (num < 1) ! 215: panic ("ffs_balloc: ufs_bmaparray returned indirect block\n"); ! 216: #endif ! 217: /* ! 218: * Fetch the first indirect block allocating if necessary. ! 219: */ ! 220: --num; ! 221: nb = ip->i_ib[indirs[0].in_off]; ! 222: allocib = NULL; ! 223: allocblk = allociblk; ! 224: if (nb == 0) { ! 225: pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0); ! 226: if (error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, ! 227: cred, &newb)) ! 228: return (error); ! 229: nb = newb; ! 230: *allocblk++ = nb; ! 231: bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0); ! 232: bp->b_blkno = fsbtodb(fs, nb); ! 233: clrbuf(bp); ! 234: /* ! 235: * Write synchronously so that indirect blocks ! 236: * never point at garbage. ! 237: */ ! 238: if (error = bwrite(bp)) ! 239: goto fail; ! 240: allocib = &ip->i_ib[indirs[0].in_off]; ! 241: *allocib = nb; ! 242: ip->i_flag |= IN_CHANGE | IN_UPDATE; ! 243: } ! 244: /* ! 245: * Fetch through the indirect blocks, allocating as necessary. ! 246: */ ! 247: for (i = 1;;) { ! 248: error = bread(vp, ! 249: indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp); ! 250: if (error) { ! 251: brelse(bp); ! 252: goto fail; ! 253: } ! 254: bap = (ufs_daddr_t *)bp->b_data; ! 255: #if REV_ENDIAN_FS ! 256: if (rev_endian) ! 257: nb = NXSwapLong(bap[indirs[i].in_off]); ! 258: else { ! 259: #endif /* REV_ENDIAN_FS */ ! 260: nb = bap[indirs[i].in_off]; ! 261: #if REV_ENDIAN_FS ! 262: } ! 263: #endif /* REV_ENDIAN_FS */ ! 264: if (i == num) ! 265: break; ! 266: i += 1; ! 267: if (nb != 0) { ! 268: brelse(bp); ! 269: continue; ! 270: } ! 271: if (pref == 0) ! 272: pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0); ! 273: if (error = ! 274: ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) { ! 275: brelse(bp); ! 276: goto fail; ! 277: } ! 278: nb = newb; ! 279: *allocblk++ = nb; ! 280: nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0); ! 281: nbp->b_blkno = fsbtodb(fs, nb); ! 282: clrbuf(nbp); ! 283: /* ! 284: * Write synchronously so that indirect blocks ! 285: * never point at garbage. ! 286: */ ! 287: if (error = bwrite(nbp)) { ! 288: brelse(bp); ! 289: goto fail; ! 290: } ! 291: #if REV_ENDIAN_FS ! 292: if (rev_endian) ! 293: bap[indirs[i - 1].in_off] = NXSwapLong(nb); ! 294: else { ! 295: #endif /* REV_ENDIAN_FS */ ! 296: bap[indirs[i - 1].in_off] = nb; ! 297: #if REV_ENDIAN_FS ! 298: } ! 299: #endif /* REV_ENDIAN_FS */ ! 300: /* ! 301: * If required, write synchronously, otherwise use ! 302: * delayed write. ! 303: */ ! 304: if (flags & B_SYNC) { ! 305: bwrite(bp); ! 306: } else { ! 307: bdwrite(bp); ! 308: } ! 309: } ! 310: /* ! 311: * Get the data block, allocating if necessary. ! 312: */ ! 313: if (nb == 0) { ! 314: pref = ffs_blkpref(ip, lbn, indirs[i].in_off, &bap[0]); ! 315: if (error = ffs_alloc(ip, ! 316: lbn, pref, (int)fs->fs_bsize, cred, &newb)) { ! 317: brelse(bp); ! 318: goto fail; ! 319: } ! 320: nb = newb; ! 321: *allocblk++ = nb; ! 322: nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0); ! 323: nbp->b_blkno = fsbtodb(fs, nb); ! 324: if (flags & B_CLRBUF) ! 325: clrbuf(nbp); ! 326: #if REV_ENDIAN_FS ! 327: if (rev_endian) ! 328: bap[indirs[i].in_off] = NXSwapLong(nb); ! 329: else { ! 330: #endif /* REV_ENDIAN_FS */ ! 331: bap[indirs[i].in_off] = nb; ! 332: #if REV_ENDIAN_FS ! 333: } ! 334: #endif /* REV_ENDIAN_FS */ ! 335: /* ! 336: * If required, write synchronously, otherwise use ! 337: * delayed write. ! 338: */ ! 339: if (flags & B_SYNC) { ! 340: bwrite(bp); ! 341: } else { ! 342: bdwrite(bp); ! 343: } ! 344: *bpp = nbp; ! 345: return (0); ! 346: } ! 347: brelse(bp); ! 348: if (flags & B_CLRBUF) { ! 349: error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp); ! 350: if (error) { ! 351: brelse(nbp); ! 352: goto fail; ! 353: } ! 354: } else { ! 355: nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0); ! 356: nbp->b_blkno = fsbtodb(fs, nb); ! 357: } ! 358: *bpp = nbp; ! 359: return (0); ! 360: fail: ! 361: /* ! 362: * If we have failed part way through block allocation, we ! 363: * have to deallocate any indirect blocks that we have allocated. ! 364: */ ! 365: for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) { ! 366: ffs_blkfree(ip, *blkp, fs->fs_bsize); ! 367: deallocated += fs->fs_bsize; ! 368: } ! 369: if (allocib != NULL) ! 370: *allocib = 0; ! 371: if (deallocated) { ! 372: #ifdef NeXT ! 373: VOP_DEVBLOCKSIZE(ip->i_devvp,&devBlockSize); ! 374: #endif /* NeXT */ ! 375: ! 376: #if QUOTA ! 377: /* ! 378: * Restore user's disk quota because allocation failed. ! 379: */ ! 380: #ifdef NeXT ! 381: (void) chkdq(ip, (long)-btodb(deallocated, devBlockSize), cred, FORCE); ! 382: #else ! 383: (void) chkdq(ip, (long)-btodb(deallocated), cred, FORCE); ! 384: #endif /* NeXT */ ! 385: #endif /* QUOTA */ ! 386: #ifdef NeXT ! 387: ip->i_blocks -= btodb(deallocated, devBlockSize); ! 388: #else ! 389: ip->i_blocks -= btodb(deallocated); ! 390: #endif /* NeXT */ ! 391: ip->i_flag |= IN_CHANGE | IN_UPDATE; ! 392: } ! 393: return (error); ! 394: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.