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