- if (nb == 0) {
- if (pref == 0)
- if (j < NIADDR)
- pref = blkpref(ip, lbn, 0,
- (daddr_t *)0);
- else
- pref = blkpref(ip, lbn, i, &bap[0]);
- error = alloc(ip, pref, (int)fs->fs_bsize, &nbp,
- (j < NIADDR) ? B_CLRBUF : flags);
- if (error) {
- brelse(bp);
- *bnp = (daddr_t)-1;
- return (error);
- }
- nb = dbtofsb(fs, nbp->b_blkno);
- if (j < NIADDR || (ip->i_mode & IFMT) == IFDIR)
- /*
- * Write synchronously so indirect blocks
- * never point at garbage and blocks
- * in directories never contain garbage.
- *
- * NB: Should free space and return error
- * if bwrite returns an error.
- */
- error = bwrite(nbp);
- else
- bdwrite(nbp);
- bap[i] = nb;
+ if (j == NIADDR)
+ break;
+ if (nb != 0) {
+ brelse(bp);
+ continue;
+ }
+ if (pref == 0)
+ pref = blkpref(ip, lbn, 0, (daddr_t *)0);
+ if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
+ brelse(bp);
+ return (error);
+ }
+ nb = newb;
+ nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
+ clrbuf(nbp);
+ /*
+ * Write synchronously so that indirect blocks
+ * never point at garbage.
+ */
+ if (error = bwrite(nbp)) {
+ blkfree(ip, nb, fs->fs_bsize);
+ brelse(bp);
+ return (error);
+ }
+ bap[i] = nb;
+ /*
+ * If required, write synchronously, otherwise use
+ * delayed write. If this is the first instance of
+ * the delayed write, reassociate the buffer with the
+ * file so it will be written if the file is sync'ed.
+ */
+ if (flags & B_SYNC) {
+ bwrite(bp);
+ } else if (bp->b_flags & B_DELWRI) {
+ bdwrite(bp);
+ } else {