On Sat, Nov 28, 2015 at 03:49:21PM -0700, Bob Beck wrote: > On Fri, Nov 27, 2015 at 02:50:57PM -0200, Walter Neto wrote: > > You have a number of places here where you introduce a line of 8 spaces > after your #endif - please clean up the trailing spaces, they shouldn't be > there. > Ok, cleaned :)
> You also have uses of B_METAONLY that are not inside a #ifdef WAPBL in > ffs_balloc.c > Yeah, but I don't know what is the best way to correct it. Should I use: #ifdef WAPBL foo(..., flags | B_METAONLY, ...); #else foo(..., flags, ...); #endif or foo(..., flags #ifdef WAPBL | B_METAONLY #endif , ...) ? (Waiting this answer to send the fixed diff. > The first one I mostly get - as we are only looking for the first indirect > block > this makes sense. the second usage I'm not sure is correct... is it? > Yes Bob, It is correct! After many hours reading and re-reading the FFS code (it is a dragon) I understood it better, and the socond makes sense too cause it is where other data block is been allocated to store new indirect data-blocks address, so it is a B_METAONLY data-block. I don't know if I was clear, any doubts we can discuss. > I would like some more FFS savvy eyes on this one and not just me. > (This is a large hint to some other people) > > -Bob > > > > After mpi@ review > > > > -- > > Walter Neto > > > > diff --git a/sys/sys/buf.h b/sys/sys/buf.h > > index c47f3f9..fd38c28 100644 > > --- a/sys/sys/buf.h > > +++ b/sys/sys/buf.h > > @@ -254,6 +254,8 @@ struct cluster_save { > > /* Flags to low-level allocation routines. */ > > #define B_CLRBUF 0x01 /* Request allocated buffer be cleared. */ > > #define B_SYNC 0x02 /* Do all allocations synchronously. */ > > +#define B_METAONLY 0x04 /* return indirect block buffer */ > > +#define B_CONTIG 0x08 /* allocate file contiguously */ > > > > struct cluster_info { > > daddr_t ci_lastr; /* last read (read-ahead) */ > > diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c > > index 08961b9..807a2d1 100644 > > --- a/sys/ufs/ffs/ffs_alloc.c > > +++ b/sys/ufs/ffs/ffs_alloc.c > > @@ -63,16 +63,19 @@ > > (fs)->fs_fsmnt, (cp)); \ > > } while (0) > > > > -daddr_t ffs_alloccg(struct inode *, int, daddr_t, int); > > +daddr_t ffs_alloccg(struct inode *, int, daddr_t, int, int); > > struct buf * ffs_cgread(struct fs *, struct inode *, int); > > -daddr_t ffs_alloccgblk(struct inode *, struct buf *, daddr_t); > > -daddr_t ffs_clusteralloc(struct inode *, int, daddr_t, int); > > +daddr_t ffs_alloccgblk(struct inode *, struct buf *, daddr_t, > > int); > > +daddr_t ffs_clusteralloc(struct inode *, int, daddr_t, int, > > int); > > ufsino_t ffs_dirpref(struct inode *); > > daddr_t ffs_fragextend(struct inode *, int, daddr_t, int, int); > > -daddr_t ffs_hashalloc(struct inode *, int, daddr_t, int, > > - daddr_t (*)(struct inode *, int, daddr_t, int)); > > -daddr_t ffs_nodealloccg(struct inode *, int, daddr_t, int); > > +daddr_t ffs_hashalloc(struct inode *, int, daddr_t, int, int, > > + daddr_t (*)(struct inode *, int, daddr_t, int, int)); > > +daddr_t ffs_nodealloccg(struct inode *, int, daddr_t, int, int); > > daddr_t ffs_mapsearch(struct fs *, struct cg *, daddr_t, int); > > +void ffs_blkfree_subr(struct fs *, struct vnode *, > > + struct inode *, daddr_t bno, long size); > > + > > > > int ffs1_reallocblks(void *); > > #ifdef FFS2 > > @@ -106,7 +109,7 @@ static const struct timeval fserr_interval = { 2, 0 > > }; > > * available block is located. > > */ > > int > > -ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, int size, > > +ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, int size, int > > flags, > > struct ucred *cred, daddr_t *bnp) > > { > > static struct timeval fsfull_last; > > @@ -147,7 +150,7 @@ ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, > > int size, > > cg = dtog(fs, bpref); > > > > /* Try allocating a block. */ > > - bno = ffs_hashalloc(ip, cg, bpref, size, ffs_alloccg); > > + bno = ffs_hashalloc(ip, cg, bpref, size, flags, ffs_alloccg); > > if (bno > 0) { > > /* allocation successful, update inode data */ > > DIP_ADD(ip, blocks, btodb(size)); > > @@ -159,6 +162,14 @@ ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t > > bpref, int size, > > /* Restore user's disk quota because allocation failed. */ > > (void) ufs_quota_free_blocks(ip, btodb(size), cred); > > > > +#ifdef WAPBL > > + if (flags & B_CONTIG) { > > + /* > > + * Fail silently -- it's up to our caller to report errors. > > + */ > > + return (ENOSPC); > > + } > > +#endif /* WAPBL */ > > nospace: > > if (ratecheck(&fsfull_last, &fserr_interval)) { > > ffs_fserr(fs, cred->cr_uid, "file system full"); > > @@ -178,7 +189,7 @@ nospace: > > */ > > int > > ffs_realloccg(struct inode *ip, daddr_t lbprev, daddr_t bpref, int osize, > > - int nsize, struct ucred *cred, struct buf **bpp, daddr_t *blknop) > > + int nsize, int flags, struct ucred *cred, struct buf **bpp, daddr_t > > *blknop) > > { > > static struct timeval fsfull_last; > > struct fs *fs; > > @@ -295,7 +306,7 @@ ffs_realloccg(struct inode *ip, daddr_t lbprev, daddr_t > > bpref, int osize, > > panic("ffs_realloccg: bad optim"); > > /* NOTREACHED */ > > } > > - bno = ffs_hashalloc(ip, cg, bpref, request, ffs_alloccg); > > + bno = ffs_hashalloc(ip, cg, bpref, request, flags, ffs_alloccg); > > if (bno <= 0) > > goto nospace; > > > > @@ -434,7 +445,7 @@ ffs1_reallocblks(void *v) > > /* > > * Find the preferred location for the cluster. > > */ > > - pref = ffs1_blkpref(ip, start_lbn, soff, sbap); > > + pref = ffs1_blkpref(ip, start_lbn, soff, 0, sbap); > > /* > > * If the block range spans two block maps, get the second map. > > */ > > @@ -454,7 +465,7 @@ ffs1_reallocblks(void *v) > > /* > > * Search the block map looking for an allocation of the desired size. > > */ > > - if ((newblk = ffs_hashalloc(ip, dtog(fs, pref), pref, len, > > + if ((newblk = ffs_hashalloc(ip, dtog(fs, pref), pref, len, 0, > > ffs_clusteralloc)) == 0) > > goto fail; > > /* > > @@ -660,13 +671,13 @@ ffs2_reallocblks(void *v) > > /* > > * Find the preferred location for the cluster. > > */ > > - pref = ffs2_blkpref(ip, start_lbn, soff, sbap); > > + pref = ffs2_blkpref(ip, start_lbn, soff, 0, sbap); > > > > /* > > * Search the block map looking for an allocation of the desired size. > > */ > > if ((newblk = ffs_hashalloc(ip, dtog(fs, pref), pref, > > - len, ffs_clusteralloc)) == 0) > > + len, 0, ffs_clusteralloc)) == 0) > > goto fail; > > > > /* > > @@ -855,7 +866,7 @@ ffs_inode_alloc(struct inode *pip, mode_t mode, struct > > ucred *cred, > > if (fs->fs_contigdirs[cg] > 0) > > fs->fs_contigdirs[cg]--; > > } > > - ino = (ufsino_t)ffs_hashalloc(pip, cg, ipref, mode, ffs_nodealloccg); > > + ino = (ufsino_t)ffs_hashalloc(pip, cg, ipref, mode, 0, ffs_nodealloccg); > > if (ino == 0) > > goto noinodes; > > error = VFS_VGET(pvp->v_mount, ino, vpp); > > @@ -1060,7 +1071,7 @@ end: > > * allocated. > > */ > > int32_t > > -ffs1_blkpref(struct inode *ip, daddr_t lbn, int indx, int32_t *bap) > > +ffs1_blkpref(struct inode *ip, daddr_t lbn, int indx, int flags, int32_t > > *bap) > > { > > struct fs *fs; > > int cg, inocg, avgbfree, startcg; > > @@ -1068,6 +1079,28 @@ ffs1_blkpref(struct inode *ip, daddr_t lbn, int > > indx, int32_t *bap) > > > > KASSERT(indx <= 0 || bap != NULL); > > fs = ip->i_fs; > > + > > +#ifdef WAPBL > > + /* > > + * If allocating a contiguous file with B_CONTIG, use the hints > > + * in the inode extentions to return the desired block. > > + * > > + * For metadata (indirect blocks) return the address of where > > + * the first indirect block resides - we'll scan for the next > > + * available slot if we need to allocate more than one indirect > > + * block. For data, return the address of the actual block > > + * relative to the address of the first data block. > > + */ > > + if (flags & B_CONTIG) { > > + KASSERT(ip->i_ffs_first_data_blk != 0); > > + KASSERT(ip->i_ffs_first_indir_blk != 0); > > + if (flags & B_METAONLY) > > + return ip->i_ffs_first_indir_blk; > > + else > > + return ip->i_ffs_first_data_blk + blkstofrags(fs, lbn); > > + } > > +#endif /* WAPBL */ > > + > > /* > > * Allocation of indirect blocks is indicated by passing negative > > * values in indx: -1 for single indirect, -2 for double indirect, > > @@ -1160,7 +1193,7 @@ ffs1_blkpref(struct inode *ip, daddr_t lbn, int indx, > > int32_t *bap) > > */ > > #ifdef FFS2 > > int64_t > > -ffs2_blkpref(struct inode *ip, daddr_t lbn, int indx, int64_t *bap) > > +ffs2_blkpref(struct inode *ip, daddr_t lbn, int indx, int flags, int64_t > > *bap) > > { > > struct fs *fs; > > int cg, inocg, avgbfree, startcg; > > @@ -1168,6 +1201,28 @@ ffs2_blkpref(struct inode *ip, daddr_t lbn, int > > indx, int64_t *bap) > > > > KASSERT(indx <= 0 || bap != NULL); > > fs = ip->i_fs; > > + > > +#ifdef WAPBL > > + /* > > + * If allocating a contiguous file with B_CONTIG, use the hints > > + * in the inode extentions to return the desired block. > > + * > > + * For metadata (indirect blocks) return the address of where > > + * the first indirect block resides - we'll scan for the next > > + * available slot if we need to allocate more than one indirect > > + * block. For data, return the address of the actual block > > + * relative to the address of the first data block. > > + */ > > + if (flags & B_CONTIG) { > > + KASSERT(ip->i_ffs_first_data_blk != 0); > > + KASSERT(ip->i_ffs_first_indir_blk != 0); > > + if (flags & B_METAONLY) > > + return ip->i_ffs_first_indir_blk; > > + else > > + return ip->i_ffs_first_data_blk + blkstofrags(fs, lbn); > > + } > > +#endif /* WAPBL */ > > + > > /* > > * Allocation of indirect blocks is indicated by passing negative > > * values in indx: -1 for single indirect, -2 for double indirect, > > @@ -1267,8 +1322,8 @@ ffs2_blkpref(struct inode *ip, daddr_t lbn, int indx, > > int64_t *bap) > > * 3) brute force search for a free block. > > */ > > daddr_t > > -ffs_hashalloc(struct inode *ip, int cg, daddr_t pref, int size, > > - daddr_t (*allocator)(struct inode *, int, daddr_t, int)) > > +ffs_hashalloc(struct inode *ip, int cg, daddr_t pref, int size, int flags, > > + daddr_t (*allocator)(struct inode *, int, daddr_t, int, int)) > > { > > struct fs *fs; > > daddr_t result; > > @@ -1278,9 +1333,15 @@ ffs_hashalloc(struct inode *ip, int cg, daddr_t > > pref, int size, > > /* > > * 1: preferred cylinder group > > */ > > - result = (*allocator)(ip, cg, pref, size); > > + result = (*allocator)(ip, cg, pref, size, flags); > > if (result) > > return (result); > > + > > +#ifdef WAPBL > > + if (flags & B_CONTIG) > > + return (result); > > +#endif /* WAPBL */ > > + > > /* > > * 2: quadratic rehash > > */ > > @@ -1288,7 +1349,7 @@ ffs_hashalloc(struct inode *ip, int cg, daddr_t pref, > > int size, > > cg += i; > > if (cg >= fs->fs_ncg) > > cg -= fs->fs_ncg; > > - result = (*allocator)(ip, cg, 0, size); > > + result = (*allocator)(ip, cg, 0, size, flags); > > if (result) > > return (result); > > } > > @@ -1299,7 +1360,7 @@ ffs_hashalloc(struct inode *ip, int cg, daddr_t pref, > > int size, > > */ > > cg = (icg + 2) % fs->fs_ncg; > > for (i = 2; i < fs->fs_ncg; i++) { > > - result = (*allocator)(ip, cg, 0, size); > > + result = (*allocator)(ip, cg, 0, size, flags); > > if (result) > > return (result); > > cg++; > > @@ -1398,7 +1459,7 @@ ffs_fragextend(struct inode *ip, int cg, daddr_t > > bprev, int osize, int nsize) > > * and if it is, allocate it. > > */ > > daddr_t > > -ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size) > > +ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size, int flags) > > { > > struct fs *fs; > > struct cg *cgp; > > @@ -1423,7 +1484,7 @@ ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, > > int size) > > > > if (size == fs->fs_bsize) { > > /* allocate and return a complete data block */ > > - bno = ffs_alloccgblk(ip, bp, bpref); > > + bno = ffs_alloccgblk(ip, bp, bpref, flags); > > bdwrite(bp); > > return (bno); > > } > > @@ -1445,7 +1506,7 @@ ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, > > int size) > > brelse(bp); > > return (0); > > } > > - bno = ffs_alloccgblk(ip, bp, bpref); > > + bno = ffs_alloccgblk(ip, bp, bpref, flags); > > bpref = dtogd(fs, bno); > > for (i = frags; i < fs->fs_frag; i++) > > setbit(cg_blksfree(cgp), bpref + i); > > @@ -1487,7 +1548,7 @@ ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, > > int size) > > * blocks may be fragmented by the routine that allocates them. > > */ > > daddr_t > > -ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref) > > +ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref, int flags) > > { > > struct fs *fs; > > struct cg *cgp; > > @@ -1514,6 +1575,15 @@ ffs_alloccgblk(struct inode *ip, struct buf *bp, > > daddr_t bpref) > > bno = dtogd(fs, blknum(fs, bpref)); > > if (ffs_isblock(fs, blksfree, fragstoblks(fs, bno))) > > goto gotit; > > +#ifdef WAPBL > > + /* > > + * if the requested data block isn't available and we are trying to > > + * allocate a contiguous file, return an error. > > + */ > > + if ((flags & (B_CONTIG | B_METAONLY)) == B_CONTIG) > > + return (0); > > +#endif /* WAPBL */ > > + > > /* > > * Take the next available block in this cylinder group. > > */ > > @@ -1556,7 +1626,7 @@ gotit: > > * take the first one that we find following bpref. > > */ > > daddr_t > > -ffs_clusteralloc(struct inode *ip, int cg, daddr_t bpref, int len) > > +ffs_clusteralloc(struct inode *ip, int cg, daddr_t bpref, int len, int > > flags) > > { > > struct fs *fs; > > struct cg *cgp; > > @@ -1651,7 +1721,7 @@ ffs_clusteralloc(struct inode *ip, int cg, daddr_t > > bpref, int len) > > > > len = blkstofrags(fs, len); > > for (i = 0; i < len; i += fs->fs_frag) > > - if (ffs_alloccgblk(ip, bp, bno + i) != bno + i) > > + if (ffs_alloccgblk(ip, bp, bno + i, flags) != bno + i) > > panic("ffs_clusteralloc: lost block"); > > bdwrite(bp); > > return (bno); > > @@ -1663,7 +1733,7 @@ fail: > > > > /* inode allocation routine */ > > daddr_t > > -ffs_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode) > > +ffs_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode, int > > flags) > > { > > struct fs *fs; > > struct cg *cgp; > > diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c > > index ef9f6d4..34cffa6 100644 > > --- a/sys/ufs/ffs/ffs_balloc.c > > +++ b/sys/ufs/ffs/ffs_balloc.c > > @@ -103,8 +103,9 @@ ffs1_balloc(struct inode *ip, off_t startoffset, int > > size, struct ucred *cred, > > osize = blksize(fs, ip, nb); > > if (osize < fs->fs_bsize && osize > 0) { > > error = ffs_realloccg(ip, nb, > > - ffs1_blkpref(ip, nb, (int)nb, &ip->i_ffs1_db[0]), > > - osize, (int)fs->fs_bsize, cred, bpp, &newb); > > + ffs1_blkpref(ip, nb, (int)nb, flags, > > + &ip->i_ffs1_db[0]), osize, (int)fs->fs_bsize, > > + flags, cred, bpp, &newb); > > if (error) > > return (error); > > if (DOINGSOFTDEP(vp)) > > @@ -174,9 +175,9 @@ ffs1_balloc(struct inode *ip, off_t startoffset, int > > size, struct ucred *cred, > > * want, grow it. > > */ > > error = ffs_realloccg(ip, lbn, > > - ffs1_blkpref(ip, lbn, (int)lbn, > > + ffs1_blkpref(ip, lbn, (int)lbn, flags, > > &ip->i_ffs1_db[0]), > > - osize, nsize, cred, bpp, &newb); > > + osize, nsize, flags, cred, bpp, &newb); > > if (error) > > return (error); > > if (DOINGSOFTDEP(vp)) > > @@ -195,8 +196,8 @@ ffs1_balloc(struct inode *ip, off_t startoffset, int > > size, struct ucred *cred, > > else > > nsize = fs->fs_bsize; > > error = ffs_alloc(ip, lbn, > > - ffs1_blkpref(ip, lbn, (int)lbn, &ip->i_ffs1_db[0]), > > - nsize, cred, &newb); > > + ffs1_blkpref(ip, lbn, (int)lbn, flags, > > + &ip->i_ffs1_db[0]), nsize, flags, cred, &newb); > > if (error) > > return (error); > > if (bpp != NULL) { > > @@ -235,9 +236,10 @@ ffs1_balloc(struct inode *ip, off_t startoffset, int > > size, struct ucred *cred, > > allocib = NULL; > > allocblk = allociblk; > > if (nb == 0) { > > - pref = ffs1_blkpref(ip, lbn, -indirs[0].in_off - 1, NULL); > > + pref = ffs1_blkpref(ip, lbn, -indirs[0].in_off - 1, > > + flags | B_METAONLY, NULL); > > error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, > > - cred, &newb); > > + flags | B_METAONLY, cred, &newb); > > if (error) > > goto fail; > > nb = newb; > > @@ -283,9 +285,10 @@ ffs1_balloc(struct inode *ip, off_t startoffset, int > > size, struct ucred *cred, > > continue; > > } > > if (pref == 0) > > - pref = ffs1_blkpref(ip, lbn, i - num - 1, NULL); > > - error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, > > - &newb); > > + pref = ffs1_blkpref(ip, lbn, i - num - 1, > > + flags | B_METAONLY, NULL); > > + error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, > > + flags | B_METAONLY, cred, &newb); > > if (error) { > > brelse(bp); > > goto fail; > > @@ -323,13 +326,22 @@ ffs1_balloc(struct inode *ip, off_t startoffset, int > > size, struct ucred *cred, > > bdwrite(bp); > > } > > } > > + > > +#ifdef WAPBL > > + if (flags & B_METAONLY) { > > + KASSERT(bpp != NULL); > > + *bpp = bp; > > + return (0); > > + } > > +#endif /* WAPBL */ > > + > > /* > > * Get the data block, allocating if necessary. > > */ > > if (nb == 0) { > > - pref = ffs1_blkpref(ip, lbn, indirs[i].in_off, &bap[0]); > > - error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, > > - &newb); > > + pref = ffs1_blkpref(ip, lbn, indirs[i].in_off, flags, &bap[0]); > > + error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, flags, > > + cred, &newb); > > if (error) { > > brelse(bp); > > goto fail; > > @@ -468,8 +480,8 @@ ffs2_balloc(struct inode *ip, off_t off, int size, > > struct ucred *cred, > > osize = blksize(fs, ip, nb); > > if (osize < fs->fs_bsize && osize > 0) { > > error = ffs_realloccg(ip, nb, ffs2_blkpref(ip, > > - lastlbn, nb, &ip->i_ffs2_db[0]), osize, > > - (int) fs->fs_bsize, cred, bpp, &newb); > > + lastlbn, nb, flags, &ip->i_ffs2_db[0]), osize, > > + (int) fs->fs_bsize, flags, cred, bpp, &newb); > > if (error) > > return (error); > > > > @@ -545,9 +557,9 @@ ffs2_balloc(struct inode *ip, off_t off, int size, > > struct ucred *cred, > > * grow it. > > */ > > error = ffs_realloccg(ip, lbn, > > - ffs2_blkpref(ip, lbn, (int) lbn, > > - &ip->i_ffs2_db[0]), osize, nsize, cred, > > - bpp, &newb); > > + ffs2_blkpref(ip, lbn, (int) lbn, flags, > > + &ip->i_ffs2_db[0]), osize, nsize, flags, > > + cred, bpp, &newb); > > if (error) > > return (error); > > > > @@ -567,7 +579,8 @@ ffs2_balloc(struct inode *ip, off_t off, int size, > > struct ucred *cred, > > nsize = fs->fs_bsize; > > > > error = ffs_alloc(ip, lbn, ffs2_blkpref(ip, lbn, > > - (int) lbn, &ip->i_ffs2_db[0]), nsize, cred, &newb); > > + (int) lbn, flags, &ip->i_ffs2_db[0]), nsize, flags, > > + cred, &newb); > > if (error) > > return (error); > > > > @@ -614,9 +627,10 @@ ffs2_balloc(struct inode *ip, off_t off, int size, > > struct ucred *cred, > > allocblk = allociblk; > > > > if (nb == 0) { > > - pref = ffs2_blkpref(ip, lbn, -indirs[0].in_off - 1, NULL); > > - error = ffs_alloc(ip, lbn, pref, (int) fs->fs_bsize, cred, > > - &newb); > > + pref = ffs2_blkpref(ip, lbn, -indirs[0].in_off - 1, > > + flags | B_METAONLY, NULL); > > + error = ffs_alloc(ip, lbn, pref, (int) fs->fs_bsize, > > + flags | B_METAONLY, cred, &newb); > > if (error) > > goto fail; > > > > @@ -670,10 +684,11 @@ ffs2_balloc(struct inode *ip, off_t off, int size, > > struct ucred *cred, > > } > > > > if (pref == 0) > > - pref = ffs2_blkpref(ip, lbn, i - num - 1, NULL); > > + pref = ffs2_blkpref(ip, lbn, i - num - 1, > > + flags | B_METAONLY, NULL); > > > > - error = ffs_alloc(ip, lbn, pref, (int) fs->fs_bsize, cred, > > - &newb); > > + error = ffs_alloc(ip, lbn, pref, (int) fs->fs_bsize, > > + flags | B_METAONLY, cred, &newb); > > if (error) { > > brelse(bp); > > goto fail; > > @@ -716,14 +731,23 @@ ffs2_balloc(struct inode *ip, off_t off, int size, > > struct ucred *cred, > > bdwrite(bp); > > } > > > > +#ifdef WAPBL > > + if (flags & B_METAONLY) { > > + KASSERT(bpp != NULL); > > + *bpp = bp; > > + return (0); > > + } > > +#endif /* WAPBL */ > > + > > /* > > * Get the data block, allocating if necessary. > > */ > > if (nb == 0) { > > - pref = ffs2_blkpref(ip, lbn, indirs[num].in_off, &bap[0]); > > + pref = ffs2_blkpref(ip, lbn, indirs[num].in_off, flags, > > + &bap[0]); > > > > - error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, > > - &newb); > > + error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, flags, > > + cred, &newb); > > if (error) { > > brelse(bp); > > goto fail; > > diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h > > index 3e41bb3..502601b 100644 > > --- a/sys/ufs/ffs/ffs_extern.h > > +++ b/sys/ufs/ffs/ffs_extern.h > > @@ -99,19 +99,20 @@ extern struct vops ffs_specvops; > > extern struct vops ffs_fifovops; > > > > /* ffs_alloc.c */ > > -int ffs_alloc(struct inode *, daddr_t, daddr_t , int, struct ucred *, > > - daddr_t *); > > -int ffs_realloccg(struct inode *, daddr_t, daddr_t, int, int , > > - struct ucred *, struct buf **, daddr_t *); > > +int ffs_alloc(struct inode *, daddr_t, daddr_t , int, int, struct ucred *, > > + daddr_t *); > > +int ffs_realloccg(struct inode *, daddr_t, daddr_t, int, int, int, > > + struct ucred *, struct buf **, daddr_t *); > > int ffs_reallocblks(void *); > > int ffs_inode_alloc(struct inode *, mode_t, struct ucred *, struct vnode > > **); > > int ffs_inode_free(struct inode *, ufsino_t, mode_t); > > int ffs_freefile(struct inode *, ufsino_t, mode_t); > > > > -int32_t ffs1_blkpref(struct inode *, daddr_t, int, int32_t *); > > +int32_t ffs1_blkpref(struct inode *, daddr_t, int, int, int32_t *); > > #ifdef FFS2 > > -int64_t ffs2_blkpref(struct inode *, daddr_t, int, int64_t *); > > +int64_t ffs2_blkpref(struct inode *, daddr_t, int, int, int64_t *); > > #endif > > +int ffs_blkalloc_ump(struct ufsmount *, daddr_t, long); > > void ffs_blkfree(struct inode *, daddr_t, long); > > void ffs_clusteracct(struct fs *, struct cg *, daddr_t, int); > > > > diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h > > index a253b25..70301e5 100644 > > --- a/sys/ufs/ufs/inode.h > > +++ b/sys/ufs/ufs/inode.h > > @@ -48,6 +48,13 @@ > > /* > > * Per-filesystem inode extensions. > > */ > > +struct ffs_inode_ext { > > + daddr_t *ffs_snapblklist; /* Collect expunged snapshot blocks. */ > > + /* follow two fields are used by contiguous allocation code only. */ > > + daddr_t ffs_first_data_blk; /* first data block on disk. */ > > + daddr_t ffs_first_indir_blk; /* first indirect block on disk. */ > > +}; > > + > > struct ext2fs_inode_ext { > > u_int32_t ext2fs_last_lblk; /* last logical blk allocated */ > > u_int32_t ext2fs_last_blk; /* last blk allocated on disk */ > > @@ -102,10 +109,13 @@ struct inode { > > */ > > union { > > /* Other extensions could go here... */ > > + struct ffs_inode_ext ffs; > > struct ext2fs_inode_ext e2fs; > > struct dirhash *dirhash; > > } inode_ext; > > > > +#define i_ffs_first_data_blk inode_ext.ffs.ffs_first_data_blk > > +#define i_ffs_first_indir_blk inode_ext.ffs.ffs_first_indir_blk > > #define i_e2fs_last_lblk inode_ext.e2fs.ext2fs_last_lblk > > #define i_e2fs_last_blk inode_ext.e2fs.ext2fs_last_blk > > #define i_e2fs_uid inode_ext.e2fs.ext2fs_effective_uid > >