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