ffs_balloc.c revision 302408
132785Speter/* $NetBSD: ffs_balloc.c,v 1.13 2004/06/20 22:20:18 jmc Exp $ */ 244852Speter/* From NetBSD: ffs_balloc.c,v 1.25 2001/08/08 08:36:36 lukem Exp */ 332785Speter 432785Speter/* 532785Speter * Copyright (c) 1982, 1986, 1989, 1993 632785Speter * The Regents of the University of California. All rights reserved. 732785Speter * 832785Speter * Redistribution and use in source and binary forms, with or without 932785Speter * modification, are permitted provided that the following conditions 1032785Speter * are met: 1132785Speter * 1. Redistributions of source code must retain the above copyright 1232785Speter * notice, this list of conditions and the following disclaimer. 1332785Speter * 2. Redistributions in binary form must reproduce the above copyright 1432785Speter * notice, this list of conditions and the following disclaimer in the 1532785Speter * documentation and/or other materials provided with the distribution. 1632785Speter * 3. Neither the name of the University nor the names of its contributors 1732785Speter * may be used to endorse or promote products derived from this software 1832785Speter * without specific prior written permission. 1932785Speter * 2032785Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2132785Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2232785Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2332785Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2432785Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2532785Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2632785Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2732785Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2832785Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2932785Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3032785Speter * SUCH DAMAGE. 3132785Speter * 3232785Speter * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95 3332785Speter */ 3432785Speter 3532785Speter#include <sys/cdefs.h> 3632785Speter__FBSDID("$FreeBSD: stable/11/usr.sbin/makefs/ffs/ffs_balloc.c 186334 2008-12-19 18:45:43Z sam $"); 3732785Speter 3832785Speter#include <sys/param.h> 3932785Speter#include <sys/time.h> 4032785Speter 4132785Speter#include <assert.h> 4232785Speter#include <errno.h> 4332785Speter#include <stdio.h> 4432785Speter#include <stdlib.h> 4532785Speter#include <string.h> 4632785Speter 4732785Speter#include "makefs.h" 4832785Speter 4932785Speter#include <ufs/ufs/dinode.h> 5032785Speter#include <ufs/ffs/fs.h> 5132785Speter 5232785Speter#include "ffs/ufs_bswap.h" 5332785Speter#include "ffs/buf.h" 5432785Speter#include "ffs/ufs_inode.h" 5532785Speter#include "ffs/ffs_extern.h" 5632785Speter 5732785Speterstatic int ffs_balloc_ufs1(struct inode *, off_t, int, struct buf **); 5832785Speterstatic int ffs_balloc_ufs2(struct inode *, off_t, int, struct buf **); 5932785Speter 6032785Speter/* 6132785Speter * Balloc defines the structure of file system storage 6232785Speter * by allocating the physical blocks on a device given 6332785Speter * the inode and the logical block number in a file. 6432785Speter * 6532785Speter * Assume: flags == B_SYNC | B_CLRBUF 6632785Speter */ 6732785Speter 6832785Speterint 6932785Speterffs_balloc(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) 7032785Speter{ 7132785Speter if (ip->i_fs->fs_magic == FS_UFS2_MAGIC) 7232785Speter return ffs_balloc_ufs2(ip, offset, bufsize, bpp); 7332785Speter else 7432785Speter return ffs_balloc_ufs1(ip, offset, bufsize, bpp); 7532785Speter} 7632785Speter 7732785Speterstatic int 7832785Speterffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) 7932785Speter{ 8032785Speter daddr_t lbn, lastlbn; 8132785Speter int size; 8232785Speter int32_t nb; 8332785Speter struct buf *bp, *nbp; 8432785Speter struct fs *fs = ip->i_fs; 8532785Speter struct indir indirs[NIADDR + 2]; 8632785Speter daddr_t newb, pref; 8732785Speter int32_t *bap; 8832785Speter int osize, nsize, num, i, error; 8932785Speter int32_t *allocblk, allociblk[NIADDR + 1]; 9032785Speter int32_t *allocib; 9132785Speter const int needswap = UFS_FSNEEDSWAP(fs); 9232785Speter 9332785Speter lbn = lblkno(fs, offset); 9432785Speter size = blkoff(fs, offset) + bufsize; 9532785Speter if (bpp != NULL) { 9632785Speter *bpp = NULL; 9732785Speter } 9832785Speter 9932785Speter assert(size <= fs->fs_bsize); 10032785Speter if (lbn < 0) 10132785Speter return (EFBIG); 10232785Speter 10332785Speter /* 10432785Speter * If the next write will extend the file into a new block, 10532785Speter * and the file is currently composed of a fragment 10632785Speter * this fragment has to be extended to be a full block. 10732785Speter */ 10832785Speter 10932785Speter lastlbn = lblkno(fs, ip->i_ffs1_size); 11032785Speter if (lastlbn < NDADDR && lastlbn < lbn) { 11132785Speter nb = lastlbn; 11232785Speter osize = blksize(fs, ip, nb); 11332785Speter if (osize < fs->fs_bsize && osize > 0) { 11432785Speter warnx("need to ffs_realloccg; not supported!"); 11532785Speter abort(); 11632785Speter } 11732785Speter } 11832785Speter 11932785Speter /* 12032785Speter * The first NDADDR blocks are direct blocks 12132785Speter */ 12232785Speter 12332785Speter if (lbn < NDADDR) { 12432785Speter nb = ufs_rw32(ip->i_ffs1_db[lbn], needswap); 12532785Speter if (nb != 0 && ip->i_ffs1_size >= lblktosize(fs, lbn + 1)) { 12632785Speter 12732785Speter /* 12832785Speter * The block is an already-allocated direct block 12932785Speter * and the file already extends past this block, 13032785Speter * thus this must be a whole block. 13132785Speter * Just read the block (if requested). 13232785Speter */ 13332785Speter 13432785Speter if (bpp != NULL) { 13532785Speter error = bread(ip->i_fd, ip->i_fs, lbn, 13632785Speter fs->fs_bsize, bpp); 13732785Speter if (error) { 13832785Speter brelse(*bpp); 13932785Speter return (error); 14032785Speter } 14132785Speter } 14232785Speter return (0); 14332785Speter } 14432785Speter if (nb != 0) { 14532785Speter 14632785Speter /* 14732785Speter * Consider need to reallocate a fragment. 14832785Speter */ 14932785Speter 15032785Speter osize = fragroundup(fs, blkoff(fs, ip->i_ffs1_size)); 15132785Speter nsize = fragroundup(fs, size); 15232785Speter if (nsize <= osize) { 15332785Speter 15432785Speter /* 15532785Speter * The existing block is already 15632785Speter * at least as big as we want. 15732785Speter * Just read the block (if requested). 15832785Speter */ 15932785Speter 16032785Speter if (bpp != NULL) { 16132785Speter error = bread(ip->i_fd, ip->i_fs, lbn, 16232785Speter osize, bpp); 16332785Speter if (error) { 16432785Speter brelse(*bpp); 16532785Speter return (error); 16632785Speter } 16732785Speter } 16832785Speter return 0; 16932785Speter } else { 17032785Speter warnx("need to ffs_realloccg; not supported!"); 17132785Speter abort(); 17232785Speter } 17332785Speter } else { 17432785Speter 17532785Speter /* 17632785Speter * the block was not previously allocated, 17732785Speter * allocate a new block or fragment. 17832785Speter */ 17932785Speter 18032785Speter if (ip->i_ffs1_size < lblktosize(fs, lbn + 1)) 18132785Speter nsize = fragroundup(fs, size); 18232785Speter else 18332785Speter nsize = fs->fs_bsize; 18432785Speter error = ffs_alloc(ip, lbn, 18532785Speter ffs_blkpref_ufs1(ip, lbn, (int)lbn, 18632785Speter &ip->i_ffs1_db[0]), 18732785Speter nsize, &newb); 18832785Speter if (error) 18932785Speter return (error); 19032785Speter if (bpp != NULL) { 19132785Speter bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize); 19232785Speter bp->b_blkno = fsbtodb(fs, newb); 19332785Speter clrbuf(bp); 19432785Speter *bpp = bp; 19532785Speter } 19632785Speter } 19732785Speter ip->i_ffs1_db[lbn] = ufs_rw32((int32_t)newb, needswap); 19832785Speter return (0); 19932785Speter } 20032785Speter 20132785Speter /* 20232785Speter * Determine the number of levels of indirection. 20332785Speter */ 20432785Speter 20532785Speter pref = 0; 20632785Speter if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0) 20732785Speter return (error); 20832785Speter 20932785Speter if (num < 1) { 21032785Speter warnx("ffs_balloc: ufs_getlbns returned indirect block"); 21132785Speter abort(); 21232785Speter } 21332785Speter 21432785Speter /* 21532785Speter * Fetch the first indirect block allocating if necessary. 21632785Speter */ 21732785Speter 21832785Speter --num; 21932785Speter nb = ufs_rw32(ip->i_ffs1_ib[indirs[0].in_off], needswap); 22032785Speter allocib = NULL; 22132785Speter allocblk = allociblk; 22232785Speter if (nb == 0) { 22332785Speter pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0); 22432785Speter error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 22532785Speter if (error) 22632785Speter return error; 22732785Speter nb = newb; 22832785Speter *allocblk++ = nb; 22932785Speter bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize); 23032785Speter bp->b_blkno = fsbtodb(fs, nb); 23132785Speter clrbuf(bp); 23232785Speter /* 23332785Speter * Write synchronously so that indirect blocks 23444852Speter * never point at garbage. 23532785Speter */ 23632785Speter if ((error = bwrite(bp)) != 0) 23732785Speter return error; 23844852Speter allocib = &ip->i_ffs1_ib[indirs[0].in_off]; 23932785Speter *allocib = ufs_rw32((int32_t)nb, needswap); 24032785Speter } 24132785Speter 24232785Speter /* 24332785Speter * Fetch through the indirect blocks, allocating as necessary. 24432785Speter */ 24532785Speter 24644852Speter for (i = 1;;) { 24732785Speter error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn, 24844852Speter fs->fs_bsize, &bp); 24944852Speter if (error) { 25032785Speter brelse(bp); 25132785Speter return error; 25232785Speter } 25332785Speter bap = (int32_t *)bp->b_data; 25432785Speter nb = ufs_rw32(bap[indirs[i].in_off], needswap); 25532785Speter if (i == num) 25632785Speter break; 25732785Speter i++; 25832785Speter if (nb != 0) { 25932785Speter brelse(bp); 26032785Speter continue; 26132785Speter } 26232785Speter if (pref == 0) 26332785Speter pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0); 26432785Speter error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 26532785Speter if (error) { 26632785Speter brelse(bp); 26732785Speter return error; 26832785Speter } 26932785Speter nb = newb; 27032785Speter *allocblk++ = nb; 27132785Speter nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn, 27232785Speter fs->fs_bsize); 27332785Speter nbp->b_blkno = fsbtodb(fs, nb); 27432785Speter clrbuf(nbp); 27532785Speter /* 27632785Speter * Write synchronously so that indirect blocks 27732785Speter * never point at garbage. 27832785Speter */ 27932785Speter 28032785Speter if ((error = bwrite(nbp)) != 0) { 28132785Speter brelse(bp); 28232785Speter return error; 28332785Speter } 28432785Speter bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap); 28532785Speter 28632785Speter bwrite(bp); 28732785Speter } 28832785Speter 28932785Speter /* 29032785Speter * Get the data block, allocating if necessary. 29132785Speter */ 29232785Speter 29332785Speter if (nb == 0) { 29432785Speter pref = ffs_blkpref_ufs1(ip, lbn, indirs[num].in_off, &bap[0]); 29532785Speter error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 29632785Speter if (error) { 29732785Speter brelse(bp); 29832785Speter return error; 29932785Speter } 30032785Speter nb = newb; 30132785Speter *allocblk++ = nb; 30232785Speter if (bpp != NULL) { 30332785Speter nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize); 30432785Speter nbp->b_blkno = fsbtodb(fs, nb); 30532785Speter clrbuf(nbp); 30632785Speter *bpp = nbp; 30732785Speter } 30832785Speter bap[indirs[num].in_off] = ufs_rw32(nb, needswap); 30932785Speter 31032785Speter /* 31132785Speter * If required, write synchronously, otherwise use 31232785Speter * delayed write. 31332785Speter */ 31432785Speter bwrite(bp); 31532785Speter return (0); 31632785Speter } 31732785Speter brelse(bp); 31832785Speter if (bpp != NULL) { 31932785Speter error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp); 32032785Speter if (error) { 32132785Speter brelse(nbp); 32232785Speter return error; 32332785Speter } 32432785Speter *bpp = nbp; 32532785Speter } 32632785Speter return (0); 32732785Speter} 32832785Speter 32932785Speterstatic int 33032785Speterffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) 33132785Speter{ 33232785Speter daddr_t lbn, lastlbn; 33332785Speter int size; 33432785Speter struct buf *bp, *nbp; 33532785Speter struct fs *fs = ip->i_fs; 33632785Speter struct indir indirs[NIADDR + 2]; 33732785Speter daddr_t newb, pref, nb; 33832785Speter int64_t *bap; 33932785Speter int osize, nsize, num, i, error; 34032785Speter int64_t *allocblk, allociblk[NIADDR + 1]; 34132785Speter int64_t *allocib; 34232785Speter const int needswap = UFS_FSNEEDSWAP(fs); 34332785Speter 34432785Speter lbn = lblkno(fs, offset); 34532785Speter size = blkoff(fs, offset) + bufsize; 34632785Speter if (bpp != NULL) { 34732785Speter *bpp = NULL; 34832785Speter } 34932785Speter 35032785Speter assert(size <= fs->fs_bsize); 35132785Speter if (lbn < 0) 35232785Speter return (EFBIG); 35332785Speter 35432785Speter /* 35532785Speter * If the next write will extend the file into a new block, 35632785Speter * and the file is currently composed of a fragment 35732785Speter * this fragment has to be extended to be a full block. 35832785Speter */ 35932785Speter 36032785Speter lastlbn = lblkno(fs, ip->i_ffs2_size); 36132785Speter if (lastlbn < NDADDR && lastlbn < lbn) { 36232785Speter nb = lastlbn; 36332785Speter osize = blksize(fs, ip, nb); 36432785Speter if (osize < fs->fs_bsize && osize > 0) { 36532785Speter warnx("need to ffs_realloccg; not supported!"); 36632785Speter abort(); 36732785Speter } 36832785Speter } 36932785Speter 37032785Speter /* 37132785Speter * The first NDADDR blocks are direct blocks 37232785Speter */ 37332785Speter 37432785Speter if (lbn < NDADDR) { 37532785Speter nb = ufs_rw64(ip->i_ffs2_db[lbn], needswap); 37632785Speter if (nb != 0 && ip->i_ffs2_size >= lblktosize(fs, lbn + 1)) { 37732785Speter 37832785Speter /* 37932785Speter * The block is an already-allocated direct block 38032785Speter * and the file already extends past this block, 38132785Speter * thus this must be a whole block. 38232785Speter * Just read the block (if requested). 38332785Speter */ 38432785Speter 38532785Speter if (bpp != NULL) { 38632785Speter error = bread(ip->i_fd, ip->i_fs, lbn, 38732785Speter fs->fs_bsize, bpp); 38832785Speter if (error) { 38932785Speter brelse(*bpp); 39032785Speter return (error); 39132785Speter } 39232785Speter } 39332785Speter return (0); 39432785Speter } 39532785Speter if (nb != 0) { 39632785Speter 39732785Speter /* 39832785Speter * Consider need to reallocate a fragment. 39932785Speter */ 40032785Speter 40132785Speter osize = fragroundup(fs, blkoff(fs, ip->i_ffs2_size)); 40232785Speter nsize = fragroundup(fs, size); 40332785Speter if (nsize <= osize) { 40432785Speter 40532785Speter /* 40632785Speter * The existing block is already 40732785Speter * at least as big as we want. 40832785Speter * Just read the block (if requested). 40932785Speter */ 41032785Speter 41132785Speter if (bpp != NULL) { 41232785Speter error = bread(ip->i_fd, ip->i_fs, lbn, 41332785Speter osize, bpp); 41432785Speter if (error) { 41532785Speter brelse(*bpp); 41632785Speter return (error); 41732785Speter } 41832785Speter } 41932785Speter return 0; 42032785Speter } else { 42132785Speter warnx("need to ffs_realloccg; not supported!"); 42232785Speter abort(); 42332785Speter } 42432785Speter } else { 42532785Speter 42632785Speter /* 42732785Speter * the block was not previously allocated, 42832785Speter * allocate a new block or fragment. 42932785Speter */ 43032785Speter 43132785Speter if (ip->i_ffs2_size < lblktosize(fs, lbn + 1)) 43232785Speter nsize = fragroundup(fs, size); 43332785Speter else 43432785Speter nsize = fs->fs_bsize; 43532785Speter error = ffs_alloc(ip, lbn, 43632785Speter ffs_blkpref_ufs2(ip, lbn, (int)lbn, 43732785Speter &ip->i_ffs2_db[0]), 43832785Speter nsize, &newb); 43932785Speter if (error) 44032785Speter return (error); 44132785Speter if (bpp != NULL) { 44232785Speter bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize); 44332785Speter bp->b_blkno = fsbtodb(fs, newb); 44432785Speter clrbuf(bp); 44532785Speter *bpp = bp; 44632785Speter } 44732785Speter } 44832785Speter ip->i_ffs2_db[lbn] = ufs_rw64(newb, needswap); 44932785Speter return (0); 45032785Speter } 45132785Speter 45232785Speter /* 45332785Speter * Determine the number of levels of indirection. 45432785Speter */ 45532785Speter 45632785Speter pref = 0; 45732785Speter if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0) 45832785Speter return (error); 45932785Speter 46032785Speter if (num < 1) { 46132785Speter warnx("ffs_balloc: ufs_getlbns returned indirect block"); 46232785Speter abort(); 46332785Speter } 46432785Speter 46532785Speter /* 46632785Speter * Fetch the first indirect block allocating if necessary. 46732785Speter */ 46832785Speter 46932785Speter --num; 47032785Speter nb = ufs_rw64(ip->i_ffs2_ib[indirs[0].in_off], needswap); 47132785Speter allocib = NULL; 47232785Speter allocblk = allociblk; 47332785Speter if (nb == 0) { 47432785Speter pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0); 47532785Speter error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 47632785Speter if (error) 47732785Speter return error; 47832785Speter nb = newb; 47932785Speter *allocblk++ = nb; 48032785Speter bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize); 48132785Speter bp->b_blkno = fsbtodb(fs, nb); 48232785Speter clrbuf(bp); 48344852Speter /* 48444852Speter * Write synchronously so that indirect blocks 48544852Speter * never point at garbage. 48644852Speter */ 48744852Speter if ((error = bwrite(bp)) != 0) 48844852Speter return error; 48944852Speter allocib = &ip->i_ffs2_ib[indirs[0].in_off]; 49044852Speter *allocib = ufs_rw64(nb, needswap); 49132785Speter } 49232785Speter 49332785Speter /* 49432785Speter * Fetch through the indirect blocks, allocating as necessary. 49532785Speter */ 49632785Speter 49732785Speter for (i = 1;;) { 49832785Speter error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn, 49932785Speter fs->fs_bsize, &bp); 50032785Speter if (error) { 50132785Speter brelse(bp); 50232785Speter return error; 50332785Speter } 50432785Speter bap = (int64_t *)bp->b_data; 50532785Speter nb = ufs_rw64(bap[indirs[i].in_off], needswap); 50632785Speter if (i == num) 50732785Speter break; 50832785Speter i++; 50932785Speter if (nb != 0) { 51032785Speter brelse(bp); 51132785Speter continue; 51232785Speter } 51332785Speter if (pref == 0) 51432785Speter pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0); 51532785Speter error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 51632785Speter if (error) { 51732785Speter brelse(bp); 51832785Speter return error; 51932785Speter } 52032785Speter nb = newb; 52132785Speter *allocblk++ = nb; 52232785Speter nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn, 52332785Speter fs->fs_bsize); 52432785Speter nbp->b_blkno = fsbtodb(fs, nb); 52532785Speter clrbuf(nbp); 52632785Speter /* 52732785Speter * Write synchronously so that indirect blocks 52832785Speter * never point at garbage. 52932785Speter */ 53032785Speter 53132785Speter if ((error = bwrite(nbp)) != 0) { 53232785Speter brelse(bp); 53332785Speter return error; 53432785Speter } 53532785Speter bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap); 53632785Speter 53732785Speter bwrite(bp); 53832785Speter } 53932785Speter 54032785Speter /* 54132785Speter * Get the data block, allocating if necessary. 54232785Speter */ 54332785Speter 54432785Speter if (nb == 0) { 54532785Speter pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, &bap[0]); 54632785Speter error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 54732785Speter if (error) { 54832785Speter brelse(bp); 54932785Speter return error; 55032785Speter } 55132785Speter nb = newb; 55232785Speter *allocblk++ = nb; 55332785Speter if (bpp != NULL) { 55432785Speter nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize); 55532785Speter nbp->b_blkno = fsbtodb(fs, nb); 55632785Speter clrbuf(nbp); 55732785Speter *bpp = nbp; 55832785Speter } 55932785Speter bap[indirs[num].in_off] = ufs_rw64(nb, needswap); 56032785Speter 56132785Speter /* 56232785Speter * If required, write synchronously, otherwise use 56332785Speter * delayed write. 56432785Speter */ 56532785Speter bwrite(bp); 56632785Speter return (0); 56732785Speter } 56832785Speter brelse(bp); 56944852Speter if (bpp != NULL) { 57044852Speter error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp); 57132785Speter if (error) { 57232785Speter brelse(nbp); 57332785Speter return error; 57432785Speter } 57532785Speter *bpp = nbp; 57632785Speter } 57732785Speter return (0); 57832785Speter} 57932785Speter