1185222Ssam/* $NetBSD: ffs_balloc.c,v 1.13 2004/06/20 22:20:18 jmc Exp $ */ 2185222Ssam/* From NetBSD: ffs_balloc.c,v 1.25 2001/08/08 08:36:36 lukem Exp */ 3185222Ssam 4185222Ssam/* 5185222Ssam * Copyright (c) 1982, 1986, 1989, 1993 6185222Ssam * The Regents of the University of California. All rights reserved. 7185222Ssam * 8185222Ssam * Redistribution and use in source and binary forms, with or without 9185222Ssam * modification, are permitted provided that the following conditions 10185222Ssam * are met: 11185222Ssam * 1. Redistributions of source code must retain the above copyright 12185222Ssam * notice, this list of conditions and the following disclaimer. 13185222Ssam * 2. Redistributions in binary form must reproduce the above copyright 14185222Ssam * notice, this list of conditions and the following disclaimer in the 15185222Ssam * documentation and/or other materials provided with the distribution. 16185222Ssam * 3. Neither the name of the University nor the names of its contributors 17185222Ssam * may be used to endorse or promote products derived from this software 18185222Ssam * without specific prior written permission. 19185222Ssam * 20185222Ssam * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21185222Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22185222Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23185222Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24185222Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25185222Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26185222Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27185222Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28185222Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29185222Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30185222Ssam * SUCH DAMAGE. 31185222Ssam * 32185222Ssam * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95 33185222Ssam */ 34185222Ssam 35185222Ssam#include <sys/cdefs.h> 36186334Ssam__FBSDID("$FreeBSD$"); 37185222Ssam 38185222Ssam#include <sys/param.h> 39185222Ssam#include <sys/time.h> 40185222Ssam 41185222Ssam#include <assert.h> 42185222Ssam#include <errno.h> 43185222Ssam#include <stdio.h> 44185222Ssam#include <stdlib.h> 45185222Ssam#include <string.h> 46185222Ssam 47185222Ssam#include "makefs.h" 48185222Ssam 49185222Ssam#include <ufs/ufs/dinode.h> 50185222Ssam#include <ufs/ffs/fs.h> 51185222Ssam 52186261Ssam#include "ffs/ufs_bswap.h" 53185222Ssam#include "ffs/buf.h" 54185222Ssam#include "ffs/ufs_inode.h" 55185222Ssam#include "ffs/ffs_extern.h" 56185222Ssam 57185222Ssamstatic int ffs_balloc_ufs1(struct inode *, off_t, int, struct buf **); 58185222Ssamstatic int ffs_balloc_ufs2(struct inode *, off_t, int, struct buf **); 59185222Ssam 60185222Ssam/* 61185222Ssam * Balloc defines the structure of file system storage 62185222Ssam * by allocating the physical blocks on a device given 63185222Ssam * the inode and the logical block number in a file. 64185222Ssam * 65185222Ssam * Assume: flags == B_SYNC | B_CLRBUF 66185222Ssam */ 67185222Ssam 68185222Ssamint 69185222Ssamffs_balloc(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) 70185222Ssam{ 71185222Ssam if (ip->i_fs->fs_magic == FS_UFS2_MAGIC) 72185222Ssam return ffs_balloc_ufs2(ip, offset, bufsize, bpp); 73185222Ssam else 74185222Ssam return ffs_balloc_ufs1(ip, offset, bufsize, bpp); 75185222Ssam} 76185222Ssam 77185222Ssamstatic int 78185222Ssamffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) 79185222Ssam{ 80185222Ssam daddr_t lbn, lastlbn; 81185222Ssam int size; 82185222Ssam int32_t nb; 83185222Ssam struct buf *bp, *nbp; 84185222Ssam struct fs *fs = ip->i_fs; 85185222Ssam struct indir indirs[NIADDR + 2]; 86185222Ssam daddr_t newb, pref; 87185222Ssam int32_t *bap; 88185222Ssam int osize, nsize, num, i, error; 89185222Ssam int32_t *allocblk, allociblk[NIADDR + 1]; 90185222Ssam int32_t *allocib; 91185222Ssam const int needswap = UFS_FSNEEDSWAP(fs); 92185222Ssam 93185222Ssam lbn = lblkno(fs, offset); 94185222Ssam size = blkoff(fs, offset) + bufsize; 95185222Ssam if (bpp != NULL) { 96185222Ssam *bpp = NULL; 97185222Ssam } 98185222Ssam 99185222Ssam assert(size <= fs->fs_bsize); 100185222Ssam if (lbn < 0) 101185222Ssam return (EFBIG); 102185222Ssam 103185222Ssam /* 104185222Ssam * If the next write will extend the file into a new block, 105185222Ssam * and the file is currently composed of a fragment 106185222Ssam * this fragment has to be extended to be a full block. 107185222Ssam */ 108185222Ssam 109185222Ssam lastlbn = lblkno(fs, ip->i_ffs1_size); 110185222Ssam if (lastlbn < NDADDR && lastlbn < lbn) { 111185222Ssam nb = lastlbn; 112185222Ssam osize = blksize(fs, ip, nb); 113185222Ssam if (osize < fs->fs_bsize && osize > 0) { 114185222Ssam warnx("need to ffs_realloccg; not supported!"); 115185222Ssam abort(); 116185222Ssam } 117185222Ssam } 118185222Ssam 119185222Ssam /* 120185222Ssam * The first NDADDR blocks are direct blocks 121185222Ssam */ 122185222Ssam 123185222Ssam if (lbn < NDADDR) { 124185222Ssam nb = ufs_rw32(ip->i_ffs1_db[lbn], needswap); 125185222Ssam if (nb != 0 && ip->i_ffs1_size >= lblktosize(fs, lbn + 1)) { 126185222Ssam 127185222Ssam /* 128185222Ssam * The block is an already-allocated direct block 129185222Ssam * and the file already extends past this block, 130185222Ssam * thus this must be a whole block. 131185222Ssam * Just read the block (if requested). 132185222Ssam */ 133185222Ssam 134185222Ssam if (bpp != NULL) { 135185222Ssam error = bread(ip->i_fd, ip->i_fs, lbn, 136185222Ssam fs->fs_bsize, bpp); 137185222Ssam if (error) { 138185222Ssam brelse(*bpp); 139185222Ssam return (error); 140185222Ssam } 141185222Ssam } 142185222Ssam return (0); 143185222Ssam } 144185222Ssam if (nb != 0) { 145185222Ssam 146185222Ssam /* 147185222Ssam * Consider need to reallocate a fragment. 148185222Ssam */ 149185222Ssam 150185222Ssam osize = fragroundup(fs, blkoff(fs, ip->i_ffs1_size)); 151185222Ssam nsize = fragroundup(fs, size); 152185222Ssam if (nsize <= osize) { 153185222Ssam 154185222Ssam /* 155185222Ssam * The existing block is already 156185222Ssam * at least as big as we want. 157185222Ssam * Just read the block (if requested). 158185222Ssam */ 159185222Ssam 160185222Ssam if (bpp != NULL) { 161185222Ssam error = bread(ip->i_fd, ip->i_fs, lbn, 162185222Ssam osize, bpp); 163185222Ssam if (error) { 164185222Ssam brelse(*bpp); 165185222Ssam return (error); 166185222Ssam } 167185222Ssam } 168185222Ssam return 0; 169185222Ssam } else { 170185222Ssam warnx("need to ffs_realloccg; not supported!"); 171185222Ssam abort(); 172185222Ssam } 173185222Ssam } else { 174185222Ssam 175185222Ssam /* 176185222Ssam * the block was not previously allocated, 177185222Ssam * allocate a new block or fragment. 178185222Ssam */ 179185222Ssam 180185222Ssam if (ip->i_ffs1_size < lblktosize(fs, lbn + 1)) 181185222Ssam nsize = fragroundup(fs, size); 182185222Ssam else 183185222Ssam nsize = fs->fs_bsize; 184185222Ssam error = ffs_alloc(ip, lbn, 185185222Ssam ffs_blkpref_ufs1(ip, lbn, (int)lbn, 186185222Ssam &ip->i_ffs1_db[0]), 187185222Ssam nsize, &newb); 188185222Ssam if (error) 189185222Ssam return (error); 190185222Ssam if (bpp != NULL) { 191185222Ssam bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize); 192185222Ssam bp->b_blkno = fsbtodb(fs, newb); 193185222Ssam clrbuf(bp); 194185222Ssam *bpp = bp; 195185222Ssam } 196185222Ssam } 197185222Ssam ip->i_ffs1_db[lbn] = ufs_rw32((int32_t)newb, needswap); 198185222Ssam return (0); 199185222Ssam } 200185222Ssam 201185222Ssam /* 202185222Ssam * Determine the number of levels of indirection. 203185222Ssam */ 204185222Ssam 205185222Ssam pref = 0; 206185222Ssam if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0) 207185222Ssam return (error); 208185222Ssam 209185222Ssam if (num < 1) { 210185222Ssam warnx("ffs_balloc: ufs_getlbns returned indirect block"); 211185222Ssam abort(); 212185222Ssam } 213185222Ssam 214185222Ssam /* 215185222Ssam * Fetch the first indirect block allocating if necessary. 216185222Ssam */ 217185222Ssam 218185222Ssam --num; 219185222Ssam nb = ufs_rw32(ip->i_ffs1_ib[indirs[0].in_off], needswap); 220185222Ssam allocib = NULL; 221185222Ssam allocblk = allociblk; 222185222Ssam if (nb == 0) { 223185222Ssam pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0); 224185222Ssam error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 225185222Ssam if (error) 226185222Ssam return error; 227185222Ssam nb = newb; 228185222Ssam *allocblk++ = nb; 229185222Ssam bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize); 230185222Ssam bp->b_blkno = fsbtodb(fs, nb); 231185222Ssam clrbuf(bp); 232185222Ssam /* 233185222Ssam * Write synchronously so that indirect blocks 234185222Ssam * never point at garbage. 235185222Ssam */ 236185222Ssam if ((error = bwrite(bp)) != 0) 237185222Ssam return error; 238185222Ssam allocib = &ip->i_ffs1_ib[indirs[0].in_off]; 239185222Ssam *allocib = ufs_rw32((int32_t)nb, needswap); 240185222Ssam } 241185222Ssam 242185222Ssam /* 243185222Ssam * Fetch through the indirect blocks, allocating as necessary. 244185222Ssam */ 245185222Ssam 246185222Ssam for (i = 1;;) { 247185222Ssam error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn, 248185222Ssam fs->fs_bsize, &bp); 249185222Ssam if (error) { 250185222Ssam brelse(bp); 251185222Ssam return error; 252185222Ssam } 253185222Ssam bap = (int32_t *)bp->b_data; 254185222Ssam nb = ufs_rw32(bap[indirs[i].in_off], needswap); 255185222Ssam if (i == num) 256185222Ssam break; 257185222Ssam i++; 258185222Ssam if (nb != 0) { 259185222Ssam brelse(bp); 260185222Ssam continue; 261185222Ssam } 262185222Ssam if (pref == 0) 263185222Ssam pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0); 264185222Ssam error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 265185222Ssam if (error) { 266185222Ssam brelse(bp); 267185222Ssam return error; 268185222Ssam } 269185222Ssam nb = newb; 270185222Ssam *allocblk++ = nb; 271185222Ssam nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn, 272185222Ssam fs->fs_bsize); 273185222Ssam nbp->b_blkno = fsbtodb(fs, nb); 274185222Ssam clrbuf(nbp); 275185222Ssam /* 276185222Ssam * Write synchronously so that indirect blocks 277185222Ssam * never point at garbage. 278185222Ssam */ 279185222Ssam 280185222Ssam if ((error = bwrite(nbp)) != 0) { 281185222Ssam brelse(bp); 282185222Ssam return error; 283185222Ssam } 284185222Ssam bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap); 285185222Ssam 286185222Ssam bwrite(bp); 287185222Ssam } 288185222Ssam 289185222Ssam /* 290185222Ssam * Get the data block, allocating if necessary. 291185222Ssam */ 292185222Ssam 293185222Ssam if (nb == 0) { 294185222Ssam pref = ffs_blkpref_ufs1(ip, lbn, indirs[num].in_off, &bap[0]); 295185222Ssam error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 296185222Ssam if (error) { 297185222Ssam brelse(bp); 298185222Ssam return error; 299185222Ssam } 300185222Ssam nb = newb; 301185222Ssam *allocblk++ = nb; 302185222Ssam if (bpp != NULL) { 303185222Ssam nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize); 304185222Ssam nbp->b_blkno = fsbtodb(fs, nb); 305185222Ssam clrbuf(nbp); 306185222Ssam *bpp = nbp; 307185222Ssam } 308185222Ssam bap[indirs[num].in_off] = ufs_rw32(nb, needswap); 309185222Ssam 310185222Ssam /* 311185222Ssam * If required, write synchronously, otherwise use 312185222Ssam * delayed write. 313185222Ssam */ 314185222Ssam bwrite(bp); 315185222Ssam return (0); 316185222Ssam } 317185222Ssam brelse(bp); 318185222Ssam if (bpp != NULL) { 319185222Ssam error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp); 320185222Ssam if (error) { 321185222Ssam brelse(nbp); 322185222Ssam return error; 323185222Ssam } 324185222Ssam *bpp = nbp; 325185222Ssam } 326185222Ssam return (0); 327185222Ssam} 328185222Ssam 329185222Ssamstatic int 330185222Ssamffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) 331185222Ssam{ 332185222Ssam daddr_t lbn, lastlbn; 333185222Ssam int size; 334185222Ssam struct buf *bp, *nbp; 335185222Ssam struct fs *fs = ip->i_fs; 336185222Ssam struct indir indirs[NIADDR + 2]; 337185222Ssam daddr_t newb, pref, nb; 338185222Ssam int64_t *bap; 339185222Ssam int osize, nsize, num, i, error; 340185222Ssam int64_t *allocblk, allociblk[NIADDR + 1]; 341185222Ssam int64_t *allocib; 342185222Ssam const int needswap = UFS_FSNEEDSWAP(fs); 343185222Ssam 344185222Ssam lbn = lblkno(fs, offset); 345185222Ssam size = blkoff(fs, offset) + bufsize; 346185222Ssam if (bpp != NULL) { 347185222Ssam *bpp = NULL; 348185222Ssam } 349185222Ssam 350185222Ssam assert(size <= fs->fs_bsize); 351185222Ssam if (lbn < 0) 352185222Ssam return (EFBIG); 353185222Ssam 354185222Ssam /* 355185222Ssam * If the next write will extend the file into a new block, 356185222Ssam * and the file is currently composed of a fragment 357185222Ssam * this fragment has to be extended to be a full block. 358185222Ssam */ 359185222Ssam 360185222Ssam lastlbn = lblkno(fs, ip->i_ffs2_size); 361185222Ssam if (lastlbn < NDADDR && lastlbn < lbn) { 362185222Ssam nb = lastlbn; 363185222Ssam osize = blksize(fs, ip, nb); 364185222Ssam if (osize < fs->fs_bsize && osize > 0) { 365185222Ssam warnx("need to ffs_realloccg; not supported!"); 366185222Ssam abort(); 367185222Ssam } 368185222Ssam } 369185222Ssam 370185222Ssam /* 371185222Ssam * The first NDADDR blocks are direct blocks 372185222Ssam */ 373185222Ssam 374185222Ssam if (lbn < NDADDR) { 375185222Ssam nb = ufs_rw64(ip->i_ffs2_db[lbn], needswap); 376185222Ssam if (nb != 0 && ip->i_ffs2_size >= lblktosize(fs, lbn + 1)) { 377185222Ssam 378185222Ssam /* 379185222Ssam * The block is an already-allocated direct block 380185222Ssam * and the file already extends past this block, 381185222Ssam * thus this must be a whole block. 382185222Ssam * Just read the block (if requested). 383185222Ssam */ 384185222Ssam 385185222Ssam if (bpp != NULL) { 386185222Ssam error = bread(ip->i_fd, ip->i_fs, lbn, 387185222Ssam fs->fs_bsize, bpp); 388185222Ssam if (error) { 389185222Ssam brelse(*bpp); 390185222Ssam return (error); 391185222Ssam } 392185222Ssam } 393185222Ssam return (0); 394185222Ssam } 395185222Ssam if (nb != 0) { 396185222Ssam 397185222Ssam /* 398185222Ssam * Consider need to reallocate a fragment. 399185222Ssam */ 400185222Ssam 401185222Ssam osize = fragroundup(fs, blkoff(fs, ip->i_ffs2_size)); 402185222Ssam nsize = fragroundup(fs, size); 403185222Ssam if (nsize <= osize) { 404185222Ssam 405185222Ssam /* 406185222Ssam * The existing block is already 407185222Ssam * at least as big as we want. 408185222Ssam * Just read the block (if requested). 409185222Ssam */ 410185222Ssam 411185222Ssam if (bpp != NULL) { 412185222Ssam error = bread(ip->i_fd, ip->i_fs, lbn, 413185222Ssam osize, bpp); 414185222Ssam if (error) { 415185222Ssam brelse(*bpp); 416185222Ssam return (error); 417185222Ssam } 418185222Ssam } 419185222Ssam return 0; 420185222Ssam } else { 421185222Ssam warnx("need to ffs_realloccg; not supported!"); 422185222Ssam abort(); 423185222Ssam } 424185222Ssam } else { 425185222Ssam 426185222Ssam /* 427185222Ssam * the block was not previously allocated, 428185222Ssam * allocate a new block or fragment. 429185222Ssam */ 430185222Ssam 431185222Ssam if (ip->i_ffs2_size < lblktosize(fs, lbn + 1)) 432185222Ssam nsize = fragroundup(fs, size); 433185222Ssam else 434185222Ssam nsize = fs->fs_bsize; 435185222Ssam error = ffs_alloc(ip, lbn, 436185222Ssam ffs_blkpref_ufs2(ip, lbn, (int)lbn, 437185222Ssam &ip->i_ffs2_db[0]), 438185222Ssam nsize, &newb); 439185222Ssam if (error) 440185222Ssam return (error); 441185222Ssam if (bpp != NULL) { 442185222Ssam bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize); 443185222Ssam bp->b_blkno = fsbtodb(fs, newb); 444185222Ssam clrbuf(bp); 445185222Ssam *bpp = bp; 446185222Ssam } 447185222Ssam } 448185222Ssam ip->i_ffs2_db[lbn] = ufs_rw64(newb, needswap); 449185222Ssam return (0); 450185222Ssam } 451185222Ssam 452185222Ssam /* 453185222Ssam * Determine the number of levels of indirection. 454185222Ssam */ 455185222Ssam 456185222Ssam pref = 0; 457185222Ssam if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0) 458185222Ssam return (error); 459185222Ssam 460185222Ssam if (num < 1) { 461185222Ssam warnx("ffs_balloc: ufs_getlbns returned indirect block"); 462185222Ssam abort(); 463185222Ssam } 464185222Ssam 465185222Ssam /* 466185222Ssam * Fetch the first indirect block allocating if necessary. 467185222Ssam */ 468185222Ssam 469185222Ssam --num; 470185222Ssam nb = ufs_rw64(ip->i_ffs2_ib[indirs[0].in_off], needswap); 471185222Ssam allocib = NULL; 472185222Ssam allocblk = allociblk; 473185222Ssam if (nb == 0) { 474185222Ssam pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0); 475185222Ssam error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 476185222Ssam if (error) 477185222Ssam return error; 478185222Ssam nb = newb; 479185222Ssam *allocblk++ = nb; 480185222Ssam bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize); 481185222Ssam bp->b_blkno = fsbtodb(fs, nb); 482185222Ssam clrbuf(bp); 483185222Ssam /* 484185222Ssam * Write synchronously so that indirect blocks 485185222Ssam * never point at garbage. 486185222Ssam */ 487185222Ssam if ((error = bwrite(bp)) != 0) 488185222Ssam return error; 489185222Ssam allocib = &ip->i_ffs2_ib[indirs[0].in_off]; 490185222Ssam *allocib = ufs_rw64(nb, needswap); 491185222Ssam } 492185222Ssam 493185222Ssam /* 494185222Ssam * Fetch through the indirect blocks, allocating as necessary. 495185222Ssam */ 496185222Ssam 497185222Ssam for (i = 1;;) { 498185222Ssam error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn, 499185222Ssam fs->fs_bsize, &bp); 500185222Ssam if (error) { 501185222Ssam brelse(bp); 502185222Ssam return error; 503185222Ssam } 504185222Ssam bap = (int64_t *)bp->b_data; 505185222Ssam nb = ufs_rw64(bap[indirs[i].in_off], needswap); 506185222Ssam if (i == num) 507185222Ssam break; 508185222Ssam i++; 509185222Ssam if (nb != 0) { 510185222Ssam brelse(bp); 511185222Ssam continue; 512185222Ssam } 513185222Ssam if (pref == 0) 514185222Ssam pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0); 515185222Ssam error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 516185222Ssam if (error) { 517185222Ssam brelse(bp); 518185222Ssam return error; 519185222Ssam } 520185222Ssam nb = newb; 521185222Ssam *allocblk++ = nb; 522185222Ssam nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn, 523185222Ssam fs->fs_bsize); 524185222Ssam nbp->b_blkno = fsbtodb(fs, nb); 525185222Ssam clrbuf(nbp); 526185222Ssam /* 527185222Ssam * Write synchronously so that indirect blocks 528185222Ssam * never point at garbage. 529185222Ssam */ 530185222Ssam 531185222Ssam if ((error = bwrite(nbp)) != 0) { 532185222Ssam brelse(bp); 533185222Ssam return error; 534185222Ssam } 535185222Ssam bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap); 536185222Ssam 537185222Ssam bwrite(bp); 538185222Ssam } 539185222Ssam 540185222Ssam /* 541185222Ssam * Get the data block, allocating if necessary. 542185222Ssam */ 543185222Ssam 544185222Ssam if (nb == 0) { 545185222Ssam pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, &bap[0]); 546185222Ssam error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 547185222Ssam if (error) { 548185222Ssam brelse(bp); 549185222Ssam return error; 550185222Ssam } 551185222Ssam nb = newb; 552185222Ssam *allocblk++ = nb; 553185222Ssam if (bpp != NULL) { 554185222Ssam nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize); 555185222Ssam nbp->b_blkno = fsbtodb(fs, nb); 556185222Ssam clrbuf(nbp); 557185222Ssam *bpp = nbp; 558185222Ssam } 559185222Ssam bap[indirs[num].in_off] = ufs_rw64(nb, needswap); 560185222Ssam 561185222Ssam /* 562185222Ssam * If required, write synchronously, otherwise use 563185222Ssam * delayed write. 564185222Ssam */ 565185222Ssam bwrite(bp); 566185222Ssam return (0); 567185222Ssam } 568185222Ssam brelse(bp); 569185222Ssam if (bpp != NULL) { 570185222Ssam error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp); 571185222Ssam if (error) { 572185222Ssam brelse(nbp); 573185222Ssam return error; 574185222Ssam } 575185222Ssam *bpp = nbp; 576185222Ssam } 577185222Ssam return (0); 578185222Ssam} 579