Module Name:    src
Committed By:   dholland
Date:           Wed Aug 12 18:27:01 UTC 2015

Modified Files:
        src/libexec/lfs_cleanerd: lfs_cleanerd.c
        src/sbin/fsck_lfs: lfs.c lfs_user.h pass6.c segwrite.c segwrite.h
            setup.c
        src/sys/ufs/lfs: lfs.h lfs_accessors.h lfs_debug.c lfs_rfw.c
            lfs_segment.c lfs_vfsops.c
        src/usr.sbin/dumplfs: dumplfs.c

Log Message:
Provide 32-bit and 64-bit versions of FINFO.

This also entailed sorting out part of struct segment, as that
contains a pointer into the current FINFO data.


To generate a diff of this commit:
cvs rdiff -u -r1.48 -r1.49 src/libexec/lfs_cleanerd/lfs_cleanerd.c
cvs rdiff -u -r1.54 -r1.55 src/sbin/fsck_lfs/lfs.c
cvs rdiff -u -r1.8 -r1.9 src/sbin/fsck_lfs/lfs_user.h
cvs rdiff -u -r1.40 -r1.41 src/sbin/fsck_lfs/pass6.c
cvs rdiff -u -r1.39 -r1.40 src/sbin/fsck_lfs/segwrite.c
cvs rdiff -u -r1.5 -r1.6 src/sbin/fsck_lfs/segwrite.h
cvs rdiff -u -r1.53 -r1.54 src/sbin/fsck_lfs/setup.c
cvs rdiff -u -r1.177 -r1.178 src/sys/ufs/lfs/lfs.h
cvs rdiff -u -r1.11 -r1.12 src/sys/ufs/lfs/lfs_accessors.h
cvs rdiff -u -r1.50 -r1.51 src/sys/ufs/lfs/lfs_debug.c
cvs rdiff -u -r1.27 -r1.28 src/sys/ufs/lfs/lfs_rfw.c
cvs rdiff -u -r1.254 -r1.255 src/sys/ufs/lfs/lfs_segment.c
cvs rdiff -u -r1.338 -r1.339 src/sys/ufs/lfs/lfs_vfsops.c
cvs rdiff -u -r1.52 -r1.53 src/usr.sbin/dumplfs/dumplfs.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/libexec/lfs_cleanerd/lfs_cleanerd.c
diff -u src/libexec/lfs_cleanerd/lfs_cleanerd.c:1.48 src/libexec/lfs_cleanerd/lfs_cleanerd.c:1.49
--- src/libexec/lfs_cleanerd/lfs_cleanerd.c:1.48	Wed Aug 12 18:26:26 2015
+++ src/libexec/lfs_cleanerd/lfs_cleanerd.c	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_cleanerd.c,v 1.48 2015/08/12 18:26:26 dholland Exp $	 */
+/* $NetBSD: lfs_cleanerd.c,v 1.49 2015/08/12 18:27:01 dholland Exp $	 */
 
 /*-
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -546,7 +546,7 @@ parse_pseg(struct clfs *fs, daddr_t dadd
 		 * Kernels with this problem always wrote this zero-sized
 		 * finfo last, so just ignore it.
 		 */
-		if (fip->fi_nblocks == 0) {
+		if (lfs_fi_getnblocks(fs, fip) == 0) {
 #ifdef REPAIR_ZERO_FINFO
 			struct ubuf *nbp;
 			SEGSUM *nssp;
@@ -572,27 +572,27 @@ parse_pseg(struct clfs *fs, daddr_t dadd
 #ifdef REPAIR_ZERO_FINFO
 		vers = -1;
 #else
-		lfs_ientry(&ifp, fs, fip->fi_ino, &ifbp);
+		lfs_ientry(&ifp, fs, lfs_fi_getino(fs, fip), &ifbp);
 		vers = lfs_if_getversion(fs, ifp);
 		brelse(ifbp, 0);
 #endif
-		if (vers != fip->fi_version) {
+		if (vers != lfs_fi_getversion(fs, fip)) {
 			size_t size;
 
 			/* Read all the blocks from the data summary */
-			for (i = 0; i < fip->fi_nblocks; i++) {
-				size = (i == fip->fi_nblocks - 1) ?
-					fip->fi_lastlength : lfs_sb_getbsize(fs);
+			for (i = 0; i < lfs_fi_getnblocks(fs, fip); i++) {
+				size = (i == lfs_fi_getnblocks(fs, fip) - 1) ?
+					lfs_fi_getlastlength(fs, fip) : lfs_sb_getbsize(fs);
 				cp = fd_ptrget(fs->clfs_devvp, daddr);
 				ck = lfs_cksum_part(cp, sizeof(u_int32_t), ck);
 				daddr += lfs_btofsb(fs, size);
 			}
-			fip = (FINFO *)(fip->fi_blocks + fip->fi_nblocks);
+			fip = NEXT_FINFO(fs, fip);
 			continue;
 		}
 
 		/* Add all the blocks from the finfos (current or not) */
-		nbip = (BLOCK_INFO *)realloc(bip, (*bic + fip->fi_nblocks) *
+		nbip = (BLOCK_INFO *)realloc(bip, (*bic + lfs_fi_getnblocks(fs, fip)) *
 					     sizeof(*bip));
 		if (nbip)
 			bip = nbip;
@@ -601,14 +601,14 @@ parse_pseg(struct clfs *fs, daddr_t dadd
 			return 0x0;
 		}
 
-		for (i = 0; i < fip->fi_nblocks; i++) {
-			bip[*bic + i].bi_inode = fip->fi_ino;
-			bip[*bic + i].bi_lbn = fip->fi_blocks[i];
+		for (i = 0; i < lfs_fi_getnblocks(fs, fip); i++) {
+			bip[*bic + i].bi_inode = lfs_fi_getino(fs, fip);
+			bip[*bic + i].bi_lbn = lfs_fi_getblock(fs, fip, i);
 			bip[*bic + i].bi_daddr = daddr;
 			bip[*bic + i].bi_segcreate = lfs_ss_getcreate(fs, ssp);
-			bip[*bic + i].bi_version = fip->fi_version;
-			bip[*bic + i].bi_size = (i == fip->fi_nblocks - 1) ?
-				fip->fi_lastlength : lfs_sb_getbsize(fs);
+			bip[*bic + i].bi_version = lfs_fi_getversion(fs, fip);
+			bip[*bic + i].bi_size = (i == lfs_fi_getnblocks(fs, fip) - 1) ?
+				lfs_fi_getlastlength(fs, fip) : lfs_sb_getbsize(fs);
 			cp = fd_ptrget(fs->clfs_devvp, daddr);
 			ck = lfs_cksum_part(cp, sizeof(u_int32_t), ck);
 			bip[*bic + i].bi_bp = cp;
@@ -618,7 +618,7 @@ parse_pseg(struct clfs *fs, daddr_t dadd
 			check_test_pattern(bip + *bic + i); /* XXXDEBUG */
 #endif
 		}
-		*bic += fip->fi_nblocks;
+		*bic += lfs_fi_getnblocks(fs, fip);
 		fip = NEXT_FINFO(fs, fip);
 	}
 

Index: src/sbin/fsck_lfs/lfs.c
diff -u src/sbin/fsck_lfs/lfs.c:1.54 src/sbin/fsck_lfs/lfs.c:1.55
--- src/sbin/fsck_lfs/lfs.c:1.54	Wed Aug 12 18:26:26 2015
+++ src/sbin/fsck_lfs/lfs.c	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs.c,v 1.54 2015/08/12 18:26:26 dholland Exp $ */
+/* $NetBSD: lfs.c,v 1.55 2015/08/12 18:27:01 dholland Exp $ */
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -768,8 +768,8 @@ check_summary(struct lfs *fs, SEGSUM *sp
 
 	fp = SEGSUM_FINFOBASE(fs, sp);
 	for (i = 0; i < lfs_ss_getnfinfo(fs, sp); i++) {
-		nblocks += fp->fi_nblocks;
-		bc += fp->fi_lastlength + ((fp->fi_nblocks - 1)
+		nblocks += lfs_fi_getnblocks(fs, fp);
+		bc += lfs_fi_getlastlength(fs, fp) + ((lfs_fi_getnblocks(fs, fp) - 1)
 					   << lfs_sb_getbshift(fs));
 		assert(bc >= 0);
 		fp = NEXT_FINFO(fs, fp);
@@ -811,9 +811,9 @@ check_summary(struct lfs *fs, SEGSUM *sp
 		if (i < lfs_ss_getnfinfo(fs, sp)) {
 			if (func)
 				func(daddr, fp);
-			for (k = 0; k < fp->fi_nblocks; k++) {
-				len = (k == fp->fi_nblocks - 1 ?
-				       fp->fi_lastlength
+			for (k = 0; k < lfs_fi_getnblocks(fs, fp); k++) {
+				len = (k == lfs_fi_getnblocks(fs, fp) - 1 ?
+				       lfs_fi_getlastlength(fs, fp)
 				       : lfs_sb_getbsize(fs));
 				bread(devvp, LFS_FSBTODB(fs, daddr), len,
 				    0, &bp);

Index: src/sbin/fsck_lfs/lfs_user.h
diff -u src/sbin/fsck_lfs/lfs_user.h:1.8 src/sbin/fsck_lfs/lfs_user.h:1.9
--- src/sbin/fsck_lfs/lfs_user.h:1.8	Wed Aug 12 18:26:26 2015
+++ src/sbin/fsck_lfs/lfs_user.h	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_user.h,v 1.8 2015/08/12 18:26:26 dholland Exp $ */
+/* $NetBSD: lfs_user.h,v 1.9 2015/08/12 18:27:01 dholland Exp $ */
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -33,7 +33,7 @@
 struct lfs;
 /* XXX do these really need to be here? */
 union segsum;
-struct finfo;
+union finfo;
 
 /*
  * In the fsck code we don't need lfs_unlockvp, but we don't have a mount
@@ -86,7 +86,7 @@ int lfs_vop_bmap(struct uvnode *, daddr_
 struct uvnode *lfs_raw_vget(struct lfs *, ino_t, int, ulfs_daddr_t);
 struct lfs *lfs_init(int, daddr_t, daddr_t, int, int);
 struct lfs *lfs_verify(struct lfs *, struct lfs *, struct uvnode *, int);
-int check_summary(struct lfs *, union segsum *, ulfs_daddr_t, int, struct uvnode *, void (*)(ulfs_daddr_t, struct finfo *));
+int check_summary(struct lfs *, union segsum *, ulfs_daddr_t, int, struct uvnode *, void (*)(ulfs_daddr_t, union finfo *));
 ulfs_daddr_t try_verify(struct lfs *, struct uvnode *, ulfs_daddr_t, int);
 struct ulfs1_dinode *lfs_ifind(struct lfs *, ino_t, struct ubuf *);
 void call_panic(const char *, ...);

Index: src/sbin/fsck_lfs/pass6.c
diff -u src/sbin/fsck_lfs/pass6.c:1.40 src/sbin/fsck_lfs/pass6.c:1.41
--- src/sbin/fsck_lfs/pass6.c:1.40	Wed Aug 12 18:26:26 2015
+++ src/sbin/fsck_lfs/pass6.c	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: pass6.c,v 1.40 2015/08/12 18:26:26 dholland Exp $	 */
+/* $NetBSD: pass6.c,v 1.41 2015/08/12 18:27:01 dholland Exp $	 */
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -262,18 +262,18 @@ pass6harvest(ulfs_daddr_t daddr, FINFO *
 	int i;
 	size_t size;
 
-	vp = vget(fs, fip->fi_ino);
+	vp = vget(fs, lfs_fi_getino(fs, fip));
 	if (vp && vp != fs->lfs_ivnode &&
-	    VTOI(vp)->i_ffs1_gen == fip->fi_version) {
-		for (i = 0; i < fip->fi_nblocks; i++) {
-			size = (i == fip->fi_nblocks - 1 ?
-				fip->fi_lastlength : lfs_sb_getbsize(fs));
+	    VTOI(vp)->i_ffs1_gen == lfs_fi_getversion(fs, fip)) {
+		for (i = 0; i < lfs_fi_getnblocks(fs, fip); i++) {
+			size = (i == lfs_fi_getnblocks(fs, fip) - 1 ?
+				lfs_fi_getlastlength(fs, fip) : lfs_sb_getbsize(fs));
 			if (debug)
-				pwarn("ino %lld lbn %lld -> 0x%lx\n",
-					(long long)fip->fi_ino,
-					(long long)fip->fi_blocks[i],
-					(long)daddr);
-			rfw_update_single(vp, fip->fi_blocks[i], daddr, size);
+				pwarn("ino %ju lbn %jd -> 0x%jx\n",
+					(uintmax_t)lfs_fi_getino(fs, fip),
+					(intmax_t)lfs_fi_getblock(fs, fip, i),
+					(intmax_t)daddr);
+			rfw_update_single(vp, lfs_fi_getblock(fs, fip, i), daddr, size);
 			daddr += lfs_btofsb(fs, size);
 		}
 	}

Index: src/sbin/fsck_lfs/segwrite.c
diff -u src/sbin/fsck_lfs/segwrite.c:1.39 src/sbin/fsck_lfs/segwrite.c:1.40
--- src/sbin/fsck_lfs/segwrite.c:1.39	Wed Aug 12 18:26:27 2015
+++ src/sbin/fsck_lfs/segwrite.c	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: segwrite.c,v 1.39 2015/08/12 18:26:27 dholland Exp $ */
+/* $NetBSD: segwrite.c,v 1.40 2015/08/12 18:27:01 dholland Exp $ */
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -106,6 +106,9 @@ extern u_int32_t cksum(void *, size_t);
 extern u_int32_t lfs_sb_cksum(struct lfs *);
 extern int preen;
 
+static void lfs_shellsort(struct lfs *,
+			  struct ubuf **, union lfs_blocks *, int, int);
+
 /*
  * Logical block number match routines used when traversing the dirty block
  * chain.
@@ -198,7 +201,7 @@ void
 lfs_writefile(struct lfs * fs, struct segment * sp, struct uvnode * vp)
 {
 	struct ubuf *bp;
-	struct finfo *fip;
+	FINFO *fip;
 	struct inode *ip;
 	IFILE *ifp;
 	SEGSUM *ssp;
@@ -206,10 +209,10 @@ lfs_writefile(struct lfs * fs, struct se
 	ip = VTOI(vp);
 
 	if (sp->seg_bytes_left < lfs_sb_getbsize(fs) ||
-	    sp->sum_bytes_left < sizeof(struct finfo))
+	    sp->sum_bytes_left < FINFOSIZE(fs) + LFS_BLKPTRSIZE(fs))
 		(void) lfs_writeseg(fs, sp);
 
-	sp->sum_bytes_left -= FINFOSIZE;
+	sp->sum_bytes_left -= FINFOSIZE(fs);
 	ssp = (SEGSUM *)sp->segsum;
 	lfs_ss_setnfinfo(fs, ssp, lfs_ss_getnfinfo(fs, ssp) + 1);
 
@@ -219,10 +222,10 @@ lfs_writefile(struct lfs * fs, struct se
 	}
 
 	fip = sp->fip;
-	fip->fi_nblocks = 0;
-	fip->fi_ino = ip->i_number;
-	LFS_IENTRY(ifp, fs, fip->fi_ino, bp);
-	fip->fi_version = lfs_if_getversion(fs, ifp);
+	lfs_fi_setnblocks(fs, fip, 0);
+	lfs_fi_setino(fs, fip, ip->i_number);
+	LFS_IENTRY(ifp, fs, lfs_fi_getino(fs, fip), bp);
+	lfs_fi_setversion(fs, fip, lfs_if_getversion(fs, ifp));
 	brelse(bp, 0);
 
 	lfs_gather(fs, sp, vp, lfs_match_data);
@@ -231,11 +234,12 @@ lfs_writefile(struct lfs * fs, struct se
 	lfs_gather(fs, sp, vp, lfs_match_tindir);
 
 	fip = sp->fip;
-	if (fip->fi_nblocks != 0) {
+	if (lfs_fi_getnblocks(fs, fip) != 0) {
 		sp->fip = NEXT_FINFO(fs, fip);
-		sp->start_lbp = &sp->fip->fi_blocks[0];
+		lfs_blocks_fromfinfo(fs, &sp->start_lbp, sp->fip);
 	} else {
-		sp->sum_bytes_left += FINFOSIZE;
+		/* XXX shouldn't this update sp->fip? */
+		sp->sum_bytes_left += FINFOSIZE(fs);
 		lfs_ss_setnfinfo(fs, ssp, lfs_ss_getnfinfo(fs, ssp) - 1);
 	}
 }
@@ -380,15 +384,15 @@ lfs_gatherblock(struct segment * sp, str
 	    sp->seg_bytes_left < bp->b_bcount) {
 		lfs_updatemeta(sp);
 
-		version = sp->fip->fi_version;
+		version = lfs_fi_getversion(fs, sp->fip);
 		(void) lfs_writeseg(fs, sp);
 
-		sp->fip->fi_version = version;
-		sp->fip->fi_ino = VTOI(sp->vp)->i_number;
+		lfs_fi_setversion(fs, sp->fip, version);
+		lfs_fi_setino(fs, sp->fip, VTOI(sp->vp)->i_number);
 		/* Add the current file to the segment summary. */
 		ssp = (SEGSUM *)sp->segsum;
 		lfs_ss_setnfinfo(fs, ssp, lfs_ss_getnfinfo(fs, ssp) + 1);
-		sp->sum_bytes_left -= FINFOSIZE;
+		sp->sum_bytes_left -= FINFOSIZE(fs);
 
 		return 1;
 	}
@@ -397,8 +401,13 @@ lfs_gatherblock(struct segment * sp, str
 	/* bp->b_flags &= ~B_DONE; */
 
 	*sp->cbpp++ = bp;
-	for (j = 0; j < blksinblk; j++)
-		sp->fip->fi_blocks[sp->fip->fi_nblocks++] = bp->b_lblkno + j;
+	for (j = 0; j < blksinblk; j++) {
+		unsigned bn;
+
+		bn = lfs_fi_getnblocks(fs, sp->fip);
+		lfs_fi_setnblocks(fs, sp->fip, bn + 1);
+		lfs_fi_setblock(fs, sp->fip, bn, bp->b_lblkno + j);;
+	}
 
 	sp->sum_bytes_left -= sizeof(ulfs_daddr_t) * blksinblk;
 	sp->seg_bytes_left -= bp->b_bcount;
@@ -533,9 +542,22 @@ lfs_updatemeta(struct segment * sp)
 	int i, nblocks, num;
 	int frags;
 	int bytesleft, size;
+	union lfs_blocks tmpptr;
 
+	fs = sp->fs;
 	vp = sp->vp;
+
+	/*
+	 * This code was cutpasted from the kernel. See the
+	 * corresponding comment in lfs_segment.c.
+	 */
+#if 0
 	nblocks = &sp->fip->fi_blocks[sp->fip->fi_nblocks] - sp->start_lbp;
+#else
+	lfs_blocks_fromvoid(fs, &tmpptr, (void *)NEXT_FINFO(fs, sp->fip));
+	nblocks = lfs_blocks_sub(fs, &tmpptr, &sp->start_lbp);
+	//nblocks_orig = nblocks;
+#endif	
 
 	if (vp == NULL || nblocks == 0)
 		return;
@@ -544,7 +566,6 @@ lfs_updatemeta(struct segment * sp)
 	 * This count may be high due to oversize blocks from lfs_gop_write.
 	 * Correct for this. (XXX we should be able to keep track of these.)
 	 */
-	fs = sp->fs;
 	for (i = 0; i < nblocks; i++) {
 		if (sp->start_bpp[i] == NULL) {
 			printf("nblocks = %d, not %d\n", i, nblocks);
@@ -558,7 +579,7 @@ lfs_updatemeta(struct segment * sp)
 	/*
 	 * Sort the blocks.
 	 */
-	lfs_shellsort(sp->start_bpp, sp->start_lbp, nblocks, lfs_sb_getbsize(fs));
+	lfs_shellsort(fs, sp->start_bpp, &sp->start_lbp, nblocks, lfs_sb_getbsize(fs));
 
 	/*
 	 * Record the length of the last block in case it's a fragment.
@@ -566,8 +587,8 @@ lfs_updatemeta(struct segment * sp)
 	 * indirect block will be lfs_bsize and its presence indicates
 	 * that you cannot have fragments.
 	 */
-	sp->fip->fi_lastlength = ((sp->start_bpp[nblocks - 1]->b_bcount - 1) &
-	    lfs_sb_getbmask(fs)) + 1;
+	lfs_fi_setlastlength(fs, sp->fip, ((sp->start_bpp[nblocks - 1]->b_bcount - 1) &
+	    lfs_sb_getbmask(fs)) + 1);
 
 	/*
 	 * Assign disk addresses, and update references to the logical
@@ -575,7 +596,7 @@ lfs_updatemeta(struct segment * sp)
 	 */
 	for (i = nblocks; i--; ++sp->start_bpp) {
 		sbp = *sp->start_bpp;
-		lbn = *sp->start_lbp;
+		lbn = lfs_blocks_get(fs, &sp->start_lbp, 0);
 
 		sbp->b_blkno = LFS_FSBTODB(fs, lfs_sb_getoffset(fs));
 
@@ -597,7 +618,8 @@ lfs_updatemeta(struct segment * sp)
 		    bytesleft -= lfs_sb_getbsize(fs)) {
 			size = MIN(bytesleft, lfs_sb_getbsize(fs));
 			frags = lfs_numfrags(fs, size);
-			lbn = *sp->start_lbp++;
+			lbn = lfs_blocks_get(fs, &sp->start_lbp, 0);
+			lfs_blocks_inc(fs, &sp->start_lbp);
 			lfs_update_single(fs, sp, lbn, lfs_sb_getoffset(fs), size);
 			lfs_sb_addoffset(fs, frags);
 		}
@@ -680,9 +702,9 @@ lfs_initseg(struct lfs * fs)
 
 	/* Set pointer to first FINFO, initialize it. */
 	sp->fip = SEGSUM_FINFOBASE(fs, ssp);
-	sp->fip->fi_nblocks = 0;
-	sp->start_lbp = &sp->fip->fi_blocks[0];
-	sp->fip->fi_lastlength = 0;
+	lfs_fi_setnblocks(fs, sp->fip, 0);
+	lfs_blocks_fromfinfo(fs, &sp->start_lbp, sp->fip);
+	lfs_fi_setlastlength(fs, sp->fip, 0);
 
 	sp->seg_bytes_left -= lfs_sb_getsumsize(fs);
 	sp->sum_bytes_left = lfs_sb_getsumsize(fs) - SEGSUM_SIZE(fs);
@@ -869,8 +891,9 @@ lfs_writeseg(struct lfs * fs, struct seg
 /*
  * Our own copy of shellsort.  XXX use qsort or heapsort.
  */
-void
-lfs_shellsort(struct ubuf ** bp_array, ulfs_daddr_t * lb_array, int nmemb, int size)
+static void
+lfs_shellsort(struct lfs *fs,
+	      struct ubuf ** bp_array, union lfs_blocks *lb_array, int nmemb, int size)
 {
 	static int __rsshell_increments[] = {4, 1, 0};
 	int incr, *incrp, t1, t2;
@@ -892,7 +915,8 @@ lfs_shellsort(struct ubuf ** bp_array, u
 	incr = 0;
 	for (t1 = 0; t1 < nmemb; t1++) {
 		for (t2 = 0; t2 * size < bp_array[t1]->b_bcount; t2++) {
-			lb_array[incr++] = bp_array[t1]->b_lblkno + t2;
+			lfs_blocks_set(fs, lb_array, incr++,
+				       bp_array[t1]->b_lblkno + t2);
 		}
 	}
 }

Index: src/sbin/fsck_lfs/segwrite.h
diff -u src/sbin/fsck_lfs/segwrite.h:1.5 src/sbin/fsck_lfs/segwrite.h:1.6
--- src/sbin/fsck_lfs/segwrite.h:1.5	Fri Jul 24 06:56:41 2015
+++ src/sbin/fsck_lfs/segwrite.h	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: segwrite.h,v 1.5 2015/07/24 06:56:41 dholland Exp $ */
+/* $NetBSD: segwrite.h,v 1.6 2015/08/12 18:27:01 dholland Exp $ */
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -57,8 +57,6 @@ int lfs_match_indir(struct lfs *, struct
 int lfs_match_dindir(struct lfs *, struct ubuf *);
 int lfs_match_tindir(struct lfs *, struct ubuf *);
 
-void lfs_shellsort(struct ubuf **, int32_t *, int, int);
-
 int ulfs_getlbns(struct lfs *, struct uvnode *, daddr_t, struct indir *, int *);
 int ulfs_bmaparray(struct lfs *, struct uvnode *, daddr_t, daddr_t *, struct indir *, int *);
 

Index: src/sbin/fsck_lfs/setup.c
diff -u src/sbin/fsck_lfs/setup.c:1.53 src/sbin/fsck_lfs/setup.c:1.54
--- src/sbin/fsck_lfs/setup.c:1.53	Wed Aug 12 18:26:27 2015
+++ src/sbin/fsck_lfs/setup.c	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: setup.c,v 1.53 2015/08/12 18:26:27 dholland Exp $ */
+/* $NetBSD: setup.c,v 1.54 2015/08/12 18:27:01 dholland Exp $ */
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -277,7 +277,7 @@ setup(const char *dev)
 				(lfs_sb_getversion(fs) > 1 ? lfs_sb_getffshift(fs) :
 						       lfs_sb_getbshift(fs));
 			for (i = 0; i < lfs_ss_getnfinfo(fs, sp); i++) {
-				bc += fp->fi_lastlength + ((fp->fi_nblocks - 1)
+				bc += lfs_fi_getlastlength(fs, fp) + ((lfs_fi_getnblocks(fs, fp) - 1)
 					<< lfs_sb_getbshift(fs));
 				fp = NEXT_FINFO(fs, fp);
 			}

Index: src/sys/ufs/lfs/lfs.h
diff -u src/sys/ufs/lfs/lfs.h:1.177 src/sys/ufs/lfs/lfs.h:1.178
--- src/sys/ufs/lfs/lfs.h:1.177	Wed Aug 12 18:26:27 2015
+++ src/sys/ufs/lfs/lfs.h	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs.h,v 1.177 2015/08/12 18:26:27 dholland Exp $	*/
+/*	$NetBSD: lfs.h,v 1.178 2015/08/12 18:27:01 dholland Exp $	*/
 
 /*  from NetBSD: dinode.h,v 1.22 2013/01/22 09:39:18 dholland Exp  */
 /*  from NetBSD: dir.h,v 1.21 2009/07/22 04:49:19 dholland Exp  */
@@ -475,17 +475,33 @@ struct segusage_v1 {
 
 /*
  * On-disk file information.  One per file with data blocks in the segment.
+ *
+ * The FINFO structure is a header; it is followed by fi_nblocks block
+ * pointers, which are logical block numbers of the file. (These are the
+ * blocks of the file present in this segment.)
  */
-typedef struct finfo FINFO;
-struct finfo {
+
+typedef struct finfo64 FINFO64;
+struct finfo64 {
+	u_int32_t fi_nblocks;		/* number of blocks */
+	u_int32_t fi_version;		/* version number */
+	u_int64_t fi_ino;		/* inode number */
+	u_int32_t fi_lastlength;	/* length of last block in array */
+	u_int32_t fi_pad;		/* unused */
+};
+
+typedef struct finfo32 FINFO32;
+struct finfo32 {
 	u_int32_t fi_nblocks;		/* number of blocks */
 	u_int32_t fi_version;		/* version number */
 	u_int32_t fi_ino;		/* inode number */
 	u_int32_t fi_lastlength;	/* length of last block in array */
-	int32_t	  fi_blocks[1];		/* array of logical block numbers */
 };
-/* sizeof FINFO except fi_blocks */
-#define	FINFOSIZE	(sizeof(FINFO) - sizeof(int32_t))
+
+typedef union finfo {
+	struct finfo64 u_64;
+	struct finfo32 u_32;
+} FINFO;
 
 /*
  * Index file inode entries.
@@ -974,6 +990,16 @@ typedef struct block_info_15 {
 	int	bi_size;		/* size of the block (if fragment) */
 } BLOCK_INFO_15;
 
+/*
+ * 32/64-bit-clean pointer to block pointers. This points into
+ * already-existing storage; it is mostly used to access the block
+ * pointers following a FINFO.
+ */
+union lfs_blocks {
+	int64_t *b64;
+	int32_t *b32;
+};
+
 /* In-memory description of a segment about to be written. */
 struct segment {
 	struct lfs	 *fs;		/* file system pointer */
@@ -982,14 +1008,14 @@ struct segment {
 	struct buf	**start_bpp;	/* pointer to first bp in this set */
 	struct buf	 *ibp;		/* buffer pointer to inode page */
 	struct ulfs1_dinode    *idp;          /* pointer to ifile dinode */
-	struct finfo	 *fip;		/* current fileinfo pointer */
+	FINFO *fip;			/* current fileinfo pointer */
 	struct vnode	 *vp;		/* vnode being gathered */
 	void	 *segsum;		/* segment summary info */
 	u_int32_t ninodes;		/* number of inodes in this segment */
 	int32_t seg_bytes_left;		/* bytes left in segment */
 	int32_t sum_bytes_left;		/* bytes left in summary block */
 	u_int32_t seg_number;		/* number of this segment */
-	int32_t *start_lbp;		/* beginning lbn for this set */
+	union lfs_blocks start_lbp;	/* beginning lbn for this set */
 
 #define SEGM_CKP	0x0001		/* doing a checkpoint */
 #define SEGM_CLEAN	0x0002		/* cleaner call; don't sort */

Index: src/sys/ufs/lfs/lfs_accessors.h
diff -u src/sys/ufs/lfs/lfs_accessors.h:1.11 src/sys/ufs/lfs/lfs_accessors.h:1.12
--- src/sys/ufs/lfs/lfs_accessors.h:1.11	Wed Aug 12 18:26:27 2015
+++ src/sys/ufs/lfs/lfs_accessors.h	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_accessors.h,v 1.11 2015/08/12 18:26:27 dholland Exp $	*/
+/*	$NetBSD: lfs_accessors.h,v 1.12 2015/08/12 18:27:01 dholland Exp $	*/
 
 /*  from NetBSD: lfs.h,v 1.165 2015/07/24 06:59:32 dholland Exp  */
 /*  from NetBSD: dinode.h,v 1.22 2013/01/22 09:39:18 dholland Exp  */
@@ -285,13 +285,77 @@
 /* XXX: move to a more suitable location in this file */
 #define LFS_BLKPTRSIZE(fs) ((fs)->lfs_is64 ? sizeof(int64_t) : sizeof(int32_t))
 
+/* Size of an on-disk inode number. */
+/* XXX: move to a more suitable location in this file */
+#define LFS_INUMSIZE(fs) ((fs)->lfs_is64 ? sizeof(int64_t) : sizeof(int32_t))
+
+/* size of a FINFO, without the block pointers */
+#define	FINFOSIZE(fs)	((fs)->lfs_is64 ? sizeof(FINFO64) : sizeof(FINFO32))
+
 /* Full size of the provided FINFO record, including its block pointers. */
 #define FINFO_FULLSIZE(fs, fip) \
-	(FINFOSIZE + (fip)->fi_nblocks * LFS_BLKPTRSIZE(fs))
+	(FINFOSIZE(fs) + lfs_fi_getnblocks(fs, fip) * LFS_BLKPTRSIZE(fs))
 
 #define NEXT_FINFO(fs, fip) \
 	((FINFO *)((char *)(fip) + FINFO_FULLSIZE(fs, fip)))
 
+#define LFS_DEF_FI_ACCESSOR(type, type32, field) \
+	static __unused inline type				\
+	lfs_fi_get##field(STRUCT_LFS *fs, FINFO *fip)		\
+	{							\
+		if (fs->lfs_is64) {				\
+			return fip->u_64.fi_##field; 		\
+		} else {					\
+			return fip->u_32.fi_##field; 		\
+		}						\
+	}							\
+	static __unused inline void				\
+	lfs_fi_set##field(STRUCT_LFS *fs, FINFO *fip, type val) \
+	{							\
+		if (fs->lfs_is64) {				\
+			type *p = &fip->u_64.fi_##field;	\
+			(void)p;				\
+			fip->u_64.fi_##field = val;		\
+		} else {					\
+			type32 *p = &fip->u_32.fi_##field;	\
+			(void)p;				\
+			fip->u_32.fi_##field = val;		\
+		}						\
+	}							\
+
+LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, nblocks);
+LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, version);
+LFS_DEF_FI_ACCESSOR(uint64_t, uint32_t, ino);
+LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, lastlength);
+
+static __unused inline daddr_t
+lfs_fi_getblock(STRUCT_LFS *fs, FINFO *fip, unsigned index)
+{
+	void *firstblock;
+
+	firstblock = (char *)fip + FINFOSIZE(fs);
+	KASSERT(index < lfs_fi_getnblocks(fs, fip));
+	if (fs->lfs_is64) {
+		return ((int64_t *)firstblock)[index];
+	} else {
+		return ((int32_t *)firstblock)[index];
+	}
+}
+
+static __unused inline void
+lfs_fi_setblock(STRUCT_LFS *fs, FINFO *fip, unsigned index, daddr_t blk)
+{
+	void *firstblock;
+
+	firstblock = (char *)fip + FINFOSIZE(fs);
+	KASSERT(index < lfs_fi_getnblocks(fs, fip));
+	if (fs->lfs_is64) {
+		((int64_t *)firstblock)[index] = blk;
+	} else {
+		((int32_t *)firstblock)[index] = blk;
+	}
+}
+
 /*
  * Index file inode entries.
  */
@@ -498,11 +562,11 @@ lfs_ci_shiftdirtytoclean(STRUCT_LFS *fs,
 static __unused inline FINFO *
 segsum_finfobase(STRUCT_LFS *fs, SEGSUM *ssp)
 {
-	return (FINFO *)((char *)ssp) + SEGSUM_SIZE(fs);
+	return (FINFO *)((char *)ssp + SEGSUM_SIZE(fs));
 }
 #else
 #define SEGSUM_FINFOBASE(fs, ssp) \
-	((FINFO *)((char *)(ssp)) + SEGSUM_SIZE(fs));
+	((FINFO *)((char *)(ssp) + SEGSUM_SIZE(fs)));
 #endif
 
 #define LFS_DEF_SS_ACCESSOR(type, type32, field) \
@@ -858,6 +922,88 @@ lfs_blksize(STRUCT_LFS *fs, struct inode
 }
 #endif
 
+/*
+ * union lfs_blocks
+ */
+
+static __unused inline void
+lfs_blocks_fromvoid(STRUCT_LFS *fs, union lfs_blocks *bp, void *p)
+{
+	if (fs->lfs_is64) {
+		bp->b64 = p;
+	} else {
+		bp->b32 = p;
+	}
+}
+
+static __unused inline void
+lfs_blocks_fromfinfo(STRUCT_LFS *fs, union lfs_blocks *bp, FINFO *fip)
+{
+	void *firstblock;
+
+	firstblock = (char *)fip + FINFOSIZE(fs);
+	if (fs->lfs_is64) {
+		bp->b64 = (int64_t *)firstblock;
+	}  else {
+		bp->b32 = (int32_t *)firstblock;
+	}
+}
+
+static __unused inline daddr_t
+lfs_blocks_get(STRUCT_LFS *fs, union lfs_blocks *bp, unsigned index)
+{
+	if (fs->lfs_is64) {
+		return bp->b64[index];
+	} else {
+		return bp->b32[index];
+	}
+}
+
+static __unused inline void
+lfs_blocks_set(STRUCT_LFS *fs, union lfs_blocks *bp, unsigned index, daddr_t val)
+{
+	if (fs->lfs_is64) {
+		bp->b64[index] = val;
+	} else {
+		bp->b32[index] = val;
+	}
+}
+
+static __unused inline void
+lfs_blocks_inc(STRUCT_LFS *fs, union lfs_blocks *bp)
+{
+	if (fs->lfs_is64) {
+		bp->b64++;
+	} else {
+		bp->b32++;
+	}
+}
+
+static __unused inline int
+lfs_blocks_eq(STRUCT_LFS *fs, union lfs_blocks *bp1, union lfs_blocks *bp2)
+{
+	if (fs->lfs_is64) {
+		return bp1->b64 == bp2->b64;
+	} else {
+		return bp1->b32 == bp2->b32;
+	}
+}
+
+static __unused inline int
+lfs_blocks_sub(STRUCT_LFS *fs, union lfs_blocks *bp1, union lfs_blocks *bp2)
+{
+	/* (remember that the pointers are typed) */
+	if (fs->lfs_is64) {
+		return bp1->b64 - bp2->b64;
+	} else {
+		return bp1->b32 - bp2->b32;
+	}
+}
+
+/*
+ * struct segment
+ */
+
 
 /*
  * Macros for determining free space on the disk, with the variable metadata

Index: src/sys/ufs/lfs/lfs_debug.c
diff -u src/sys/ufs/lfs/lfs_debug.c:1.50 src/sys/ufs/lfs/lfs_debug.c:1.51
--- src/sys/ufs/lfs/lfs_debug.c:1.50	Sun Aug  2 18:18:10 2015
+++ src/sys/ufs/lfs/lfs_debug.c	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_debug.c,v 1.50 2015/08/02 18:18:10 dholland Exp $	*/
+/*	$NetBSD: lfs_debug.c,v 1.51 2015/08/12 18:27:01 dholland Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_debug.c,v 1.50 2015/08/02 18:18:10 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_debug.c,v 1.51 2015/08/12 18:27:01 dholland Exp $");
 
 #ifdef DEBUG
 
@@ -225,9 +225,10 @@ lfs_check_segsum(struct lfs *fs, struct 
 	if ((actual = 1) == 1)
 		return; /* XXXX not checking this anymore, really */
 
-	if (sp->sum_bytes_left >= FINFOSIZE
-	   && sp->fip->fi_nblocks > 512) {
-		printf("%s:%d: fi_nblocks = %d\n",file,line,sp->fip->fi_nblocks);
+	if (sp->sum_bytes_left >= FINFOSIZE(fs)
+	   && lfs_fi_getnblocks(fs, sp->fip) > 512) {
+		printf("%s:%d: fi_nblocks = %d\n", file, line,
+		       lfs_fi_getnblocks(fs, sp->fip));
 #ifdef DDB
 		Debugger();
 #endif
@@ -241,9 +242,10 @@ lfs_check_segsum(struct lfs *fs, struct 
 
 	actual = lfs_sb_getsumsize(fs)
 		/* amount taken up by FINFOs */
-		- ((char *)&(sp->fip->fi_blocks[sp->fip->fi_nblocks]) - (char *)(sp->segsum))
+		- ((char *)NEXT_FINFO(fs, sp->fip) - (char *)(sp->segsum))
 			/* amount taken up by inode blocks */
-			- sizeof(int32_t)*((sp->ninodes+LFS_INOPB(fs)-1) / LFS_INOPB(fs));
+			/* XXX should this be INUMSIZE or BLKPTRSIZE? */
+			- LFS_INUMSIZE(fs)*((sp->ninodes+LFS_INOPB(fs)-1) / LFS_INOPB(fs));
 #if 0
 	if (actual - sp->sum_bytes_left < offset)
 	{

Index: src/sys/ufs/lfs/lfs_rfw.c
diff -u src/sys/ufs/lfs/lfs_rfw.c:1.27 src/sys/ufs/lfs/lfs_rfw.c:1.28
--- src/sys/ufs/lfs/lfs_rfw.c:1.27	Wed Aug 12 18:26:27 2015
+++ src/sys/ufs/lfs/lfs_rfw.c	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_rfw.c,v 1.27 2015/08/12 18:26:27 dholland Exp $	*/
+/*	$NetBSD: lfs_rfw.c,v 1.28 2015/08/12 18:27:01 dholland Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_rfw.c,v 1.27 2015/08/12 18:26:27 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_rfw.c,v 1.28 2015/08/12 18:27:01 dholland Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_quota.h"
@@ -428,8 +428,8 @@ check_segsum(struct lfs *fs, daddr_t off
 		nblocks = 0;
 		fip = SEGSUM_FINFOBASE(fs, (SEGSUM *)bp->b_data);
 		for (i = 0; i < lfs_ss_getnfinfo(fs, ssp); ++i) {
-			nblocks += fip->fi_nblocks;
-			if (fip->fi_nblocks <= 0)
+			nblocks += lfs_fi_getnblocks(fs, fip);
+			if (lfs_fi_getnblocks(fs, fip) <= 0)
 				break;
 			fip = NEXT_FINFO(fs, fip);
 		}
@@ -452,6 +452,7 @@ check_segsum(struct lfs *fs, daddr_t off
 					offset = -1;
 					goto err2;
 				}
+				/* XXX this can't be right, on-disk u_long? */
 				(*dp++) = ((u_long *)(dbp->b_data))[0];
 				brelse(dbp, BC_AGE);
 			}
@@ -469,9 +470,9 @@ check_segsum(struct lfs *fs, daddr_t off
 			continue;
 		}
 		size = lfs_sb_getbsize(fs);
-		for (j = 0; j < fip->fi_nblocks; ++j) {
-			if (j == fip->fi_nblocks - 1)
-				size = fip->fi_lastlength;
+		for (j = 0; j < lfs_fi_getnblocks(fs, fip); ++j) {
+			if (j == lfs_fi_getnblocks(fs, fip) - 1)
+				size = lfs_fi_getlastlength(fs, fip);
 			if (flags & CHECK_CKSUM) {
 				error = bread(devvp, LFS_FSBTODB(fs, offset), size,
 				    0, &dbp);
@@ -484,10 +485,12 @@ check_segsum(struct lfs *fs, daddr_t off
 			}
 			/* Account for and update any direct blocks */
 			if ((flags & CHECK_UPDATE) &&
-			   fip->fi_ino > LFS_IFILE_INUM &&
-			   fip->fi_blocks[j] >= 0) {
-				update_meta(fs, fip->fi_ino, fip->fi_version,
-					    fip->fi_blocks[j], offset, size, l);
+			   lfs_fi_getino(fs, fip) > LFS_IFILE_INUM &&
+			   lfs_fi_getblock(fs, fip, j) >= 0) {
+				update_meta(fs, lfs_fi_getino(fs, fip),
+					    lfs_fi_getversion(fs, fip),
+					    lfs_fi_getblock(fs, fip, j),
+					    offset, size, l);
 			}
 			offset += lfs_btofsb(fs, size);
 		}

Index: src/sys/ufs/lfs/lfs_segment.c
diff -u src/sys/ufs/lfs/lfs_segment.c:1.254 src/sys/ufs/lfs/lfs_segment.c:1.255
--- src/sys/ufs/lfs/lfs_segment.c:1.254	Wed Aug 12 18:26:27 2015
+++ src/sys/ufs/lfs/lfs_segment.c	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_segment.c,v 1.254 2015/08/12 18:26:27 dholland Exp $	*/
+/*	$NetBSD: lfs_segment.c,v 1.255 2015/08/12 18:27:01 dholland Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.254 2015/08/12 18:26:27 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.255 2015/08/12 18:27:01 dholland Exp $");
 
 #define _VFS_VNODE_PRIVATE	/* XXX: check for VI_MARKER, this has to go */
 
@@ -138,14 +138,15 @@ static void lfs_cluster_callback(struct 
 
 int	 lfs_match_fake(struct lfs *, struct buf *);
 void	 lfs_newseg(struct lfs *);
-/* XXX ondisk32 */
-void	 lfs_shellsort(struct buf **, int32_t *, int, int);
 void	 lfs_supercallback(struct buf *);
 void	 lfs_updatemeta(struct segment *);
 void	 lfs_writesuper(struct lfs *, daddr_t);
 int	 lfs_writevnodes(struct lfs *fs, struct mount *mp,
 	    struct segment *sp, int dirops);
 
+static void lfs_shellsort(struct lfs *, struct buf **, union lfs_blocks *,
+			  int, int);
+
 int	lfs_allclean_wakeup;		/* Cleaner wakeup address. */
 int	lfs_writeindir = 1;		/* whether to flush indir on non-ckp */
 int	lfs_clean_vnhead = 0;		/* Allow freeing to head of vn list */
@@ -1332,7 +1333,7 @@ lfs_gatherblock(struct segment *sp, stru
 			mutex_exit(mptr);
 		lfs_updatemeta(sp);
 
-		vers = sp->fip->fi_version;
+		vers = lfs_fi_getversion(fs, sp->fip);
 		(void) lfs_writeseg(fs, sp);
 
 		/* Add the current file to the segment summary. */
@@ -1344,9 +1345,9 @@ lfs_gatherblock(struct segment *sp, stru
 	}
 
 	if (bp->b_flags & B_GATHERED) {
-		DLOG((DLOG_SEG, "lfs_gatherblock: already gathered! Ino %d,"
+		DLOG((DLOG_SEG, "lfs_gatherblock: already gathered! Ino %ju,"
 		      " lbn %" PRId64 "\n",
-		      sp->fip->fi_ino, bp->b_lblkno));
+		      (uintmax_t)lfs_fi_getino(fs, sp->fip), bp->b_lblkno));
 		return (0);
 	}
 
@@ -1355,7 +1356,11 @@ lfs_gatherblock(struct segment *sp, stru
 
 	*sp->cbpp++ = bp;
 	for (j = 0; j < blksinblk; j++) {
-		sp->fip->fi_blocks[sp->fip->fi_nblocks++] = bp->b_lblkno + j;
+		unsigned bn;
+
+		bn = lfs_fi_getnblocks(fs, sp->fip);
+		lfs_fi_setnblocks(fs, sp->fip, bn+1);
+		lfs_fi_setblock(fs, sp->fip, bn, bp->b_lblkno + j);
 		/* This block's accounting moves from lfs_favail to lfs_avail */
 		lfs_deregister_block(sp->vp, bp->b_lblkno + j);
 	}
@@ -1611,13 +1616,44 @@ lfs_updatemeta(struct segment *sp)
 	struct lfs *fs;
 	struct vnode *vp;
 	daddr_t lbn;
-	int i, nblocks, num;
+	int i, nblocks, nblocks_orig, num;
 	int bb;
 	int bytesleft, size;
+	unsigned lastlength;
+	union lfs_blocks tmpptr;
 
-	ASSERT_SEGLOCK(sp->fs);
+	fs = sp->fs;
 	vp = sp->vp;
-	nblocks = &sp->fip->fi_blocks[sp->fip->fi_nblocks] - sp->start_lbp;
+	ASSERT_SEGLOCK(fs);
+
+	/*
+	 * This used to be:
+	 *
+	 *  nblocks = &sp->fip->fi_blocks[sp->fip->fi_nblocks] - sp->start_lbp;
+	 *
+	 * that is, it allowed for the possibility that start_lbp did
+	 * not point to the beginning of the finfo block pointer area.
+	 * This particular formulation is six kinds of painful in the
+	 * lfs64 world where we have two sizes of block pointer, so
+	 * unless/until everything can be cleaned up to not move
+	 * start_lbp around but instead use an offset, we do the
+	 * following:
+	 *    1. Get NEXT_FINFO(sp->fip). This is the same pointer as
+	 * &sp->fip->fi_blocks[sp->fip->fi_nblocks], just the wrong
+	 * type. (Ugh.)
+	 *    2. Cast it to void *, then assign it to a temporary
+	 * union lfs_blocks.
+	 *    3. Subtract start_lbp from that.
+	 *    4. Save the value of nblocks in blocks_orig so we can
+	 * assert below that it hasn't changed without repeating this
+	 * rubbish.
+	 *
+	 * XXX.
+	 */
+	lfs_blocks_fromvoid(fs, &tmpptr, (void *)NEXT_FINFO(fs, sp->fip));
+	nblocks = lfs_blocks_sub(fs, &tmpptr, &sp->start_lbp);
+	nblocks_orig = nblocks;
+
 	KASSERT(nblocks >= 0);
 	KASSERT(vp != NULL);
 	if (nblocks == 0)
@@ -1627,7 +1663,6 @@ lfs_updatemeta(struct segment *sp)
 	 * This count may be high due to oversize blocks from lfs_gop_write.
 	 * Correct for this. (XXX we should be able to keep track of these.)
 	 */
-	fs = sp->fs;
 	for (i = 0; i < nblocks; i++) {
 		if (sp->start_bpp[i] == NULL) {
 			DLOG((DLOG_SEG, "lfs_updatemeta: nblocks = %d, not %d\n", i, nblocks));
@@ -1639,8 +1674,13 @@ lfs_updatemeta(struct segment *sp)
 		nblocks -= num - 1;
 	}
 
+#if 0
+	/* pre-lfs64 assertion */
 	KASSERT(vp->v_type == VREG ||
 	   nblocks == &sp->fip->fi_blocks[sp->fip->fi_nblocks] - sp->start_lbp);
+#else
+	KASSERT(vp->v_type == VREG || nblocks == nblocks_orig);
+#endif
 	KASSERT(nblocks == sp->cbpp - sp->start_bpp);
 
 	/*
@@ -1651,7 +1691,7 @@ lfs_updatemeta(struct segment *sp)
 	 * same inode...and if we don't sort, and there are fragments
 	 * present, blocks may be written in the wrong place.
 	 */
-	lfs_shellsort(sp->start_bpp, sp->start_lbp, nblocks, lfs_sb_getbsize(fs));
+	lfs_shellsort(fs, sp->start_bpp, &sp->start_lbp, nblocks, lfs_sb_getbsize(fs));
 
 	/*
 	 * Record the length of the last block in case it's a fragment.
@@ -1664,8 +1704,9 @@ lfs_updatemeta(struct segment *sp)
 	 * XXX true until lfs_markv is fixed to do everything with
 	 * XXX fake blocks (including fake inodes and fake indirect blocks).
 	 */
-	sp->fip->fi_lastlength = ((sp->start_bpp[nblocks - 1]->b_bcount - 1) &
+	lastlength = ((sp->start_bpp[nblocks - 1]->b_bcount - 1) &
 		lfs_sb_getbmask(fs)) + 1;
+	lfs_fi_setlastlength(fs, sp->fip, lastlength);
 
 	/*
 	 * Assign disk addresses, and update references to the logical
@@ -1673,7 +1714,7 @@ lfs_updatemeta(struct segment *sp)
 	 */
 	for (i = nblocks; i--; ++sp->start_bpp) {
 		sbp = *sp->start_bpp;
-		lbn = *sp->start_lbp;
+		lbn = lfs_blocks_get(fs, &sp->start_lbp, 0);
 		KASSERT(sbp->b_lblkno == lbn);
 
 		sbp->b_blkno = LFS_FSBTODB(fs, lfs_sb_getoffset(fs));
@@ -1698,7 +1739,8 @@ lfs_updatemeta(struct segment *sp)
 		     bytesleft -= lfs_sb_getbsize(fs)) {
 			size = MIN(bytesleft, lfs_sb_getbsize(fs));
 			bb = lfs_numfrags(fs, size);
-			lbn = *sp->start_lbp++;
+			lbn = lfs_blocks_get(fs, &sp->start_lbp, 0);
+			lfs_blocks_inc(fs, &sp->start_lbp);
 			lfs_update_single(fs, sp, sp->vp, lbn, lfs_sb_getoffset(fs),
 			    size);
 			lfs_sb_addoffset(fs, bb);
@@ -1850,9 +1892,9 @@ lfs_initseg(struct lfs *fs)
 
 	/* Set pointer to first FINFO, initialize it. */
 	sp->fip = SEGSUM_FINFOBASE(fs, sp->segsum);
-	sp->fip->fi_nblocks = 0;
-	sp->start_lbp = &sp->fip->fi_blocks[0];
-	sp->fip->fi_lastlength = 0;
+	lfs_fi_setnblocks(fs, sp->fip, 0);
+	lfs_fi_setlastlength(fs, sp->fip, 0);
+	lfs_blocks_fromfinfo(fs, &sp->start_lbp, sp->fip);
 
 	sp->seg_bytes_left -= lfs_sb_getsumsize(fs);
 	sp->sum_bytes_left = lfs_sb_getsumsize(fs) - SEGSUM_SIZE(fs);
@@ -2061,8 +2103,8 @@ lfs_writeseg(struct lfs *fs, struct segm
 	/* Check for zero-length and zero-version FINFO entries. */
 	fip = SEGSUM_FINFOBASE(fs, ssp);
 	for (findex = 0; findex < lfs_ss_getnfinfo(fs, ssp); findex++) {
-		KDASSERT(fip->fi_nblocks > 0);
-		KDASSERT(fip->fi_version > 0);
+		KDASSERT(lfs_fi_getnblocks(fs, fip) > 0);
+		KDASSERT(lfs_fi_getversion(fs, fip) > 0);
 		fip = NEXT_FINFO(fs, fip);
 	}
 #endif /* DEBUG */
@@ -2716,8 +2758,10 @@ lfs_callback(struct buf *bp)
  * negative block numbers (meta data blocks) sort AFTER the data blocks.
  */
 
-void
-lfs_shellsort(struct buf **bp_array, int32_t *lb_array, int nmemb, int size)
+static void
+lfs_shellsort(struct lfs *fs,
+	      struct buf **bp_array, union lfs_blocks *lb_array,
+	      int nmemb, int size)
 {
 	static int __rsshell_increments[] = { 4, 1, 0 };
 	int incr, *incrp, t1, t2;
@@ -2727,7 +2771,7 @@ lfs_shellsort(struct buf **bp_array, int
 	incr = 0;
 	for (t1 = 0; t1 < nmemb; t1++) {
 		for (t2 = 0; t2 * size < bp_array[t1]->b_bcount; t2++) {
-			if (lb_array[incr++] != bp_array[t1]->b_lblkno + t2) {
+			if (lfs_blocks_get(fs, lb_array, incr++) != bp_array[t1]->b_lblkno + t2) {
 				/* dump before panic */
 				printf("lfs_shellsort: nmemb=%d, size=%d\n",
 				    nmemb, size);
@@ -2742,8 +2786,8 @@ lfs_shellsort(struct buf **bp_array, int
 					printf("lbns:");
 					for (t2 = 0; t2 * size < bp->b_bcount;
 					    t2++) {
-						printf(" %" PRId32,
-						    lb_array[incr++]);
+						printf(" %jd",
+						    (intmax_t)lfs_blocks_get(fs, lb_array, incr++));
 					}
 					printf("\n");
 				}
@@ -2756,8 +2800,8 @@ lfs_shellsort(struct buf **bp_array, int
 	for (incrp = __rsshell_increments; (incr = *incrp++) != 0;)
 		for (t1 = incr; t1 < nmemb; ++t1)
 			for (t2 = t1 - incr; t2 >= 0;)
-				if ((u_int32_t)bp_array[t2]->b_lblkno >
-				    (u_int32_t)bp_array[t2 + incr]->b_lblkno) {
+				if ((u_int64_t)bp_array[t2]->b_lblkno >
+				    (u_int64_t)bp_array[t2 + incr]->b_lblkno) {
 					bp_temp = bp_array[t2];
 					bp_array[t2] = bp_array[t2 + incr];
 					bp_array[t2 + incr] = bp_temp;
@@ -2769,7 +2813,8 @@ lfs_shellsort(struct buf **bp_array, int
 	incr = 0;
 	for (t1 = 0; t1 < nmemb; t1++) {
 		for (t2 = 0; t2 * size < bp_array[t1]->b_bcount; t2++) {
-			lb_array[incr++] = bp_array[t1]->b_lblkno + t2;
+			lfs_blocks_set(fs, lb_array, incr++, 
+				       bp_array[t1]->b_lblkno + t2);
 		}
 	}
 }
@@ -2787,15 +2832,15 @@ lfs_acquire_finfo(struct lfs *fs, ino_t 
 	KASSERT(vers > 0);
 
 	if (sp->seg_bytes_left < lfs_sb_getbsize(fs) ||
-	    sp->sum_bytes_left < sizeof(struct finfo))
+	    sp->sum_bytes_left < FINFOSIZE(fs) + LFS_BLKPTRSIZE(fs))
 		(void) lfs_writeseg(fs, fs->lfs_sp);
 	
-	sp->sum_bytes_left -= FINFOSIZE;
+	sp->sum_bytes_left -= FINFOSIZE(fs);
 	ssp = (SEGSUM *)sp->segsum;
 	lfs_ss_setnfinfo(fs, ssp, lfs_ss_getnfinfo(fs, ssp) + 1);
-	sp->fip->fi_nblocks = 0;
-	sp->fip->fi_ino = ino;
-	sp->fip->fi_version = vers;
+	lfs_fi_setnblocks(fs, sp->fip, 0);
+	lfs_fi_setino(fs, sp->fip, ino);
+	lfs_fi_setversion(fs, sp->fip, vers);
 }
 
 /*
@@ -2808,11 +2853,12 @@ lfs_release_finfo(struct lfs *fs)
 	struct segment *sp = fs->lfs_sp;
 	SEGSUM *ssp;
 
-	if (sp->fip->fi_nblocks != 0) {
+	if (lfs_fi_getnblocks(fs, sp->fip) != 0) {
 		sp->fip = NEXT_FINFO(fs, sp->fip);
-		sp->start_lbp = &sp->fip->fi_blocks[0];
+		lfs_blocks_fromfinfo(fs, &sp->start_lbp, sp->fip);
 	} else {
-		sp->sum_bytes_left += FINFOSIZE;
+		/* XXX shouldn't this update sp->fip? */
+		sp->sum_bytes_left += FINFOSIZE(fs);
 		ssp = (SEGSUM *)sp->segsum;
 		lfs_ss_setnfinfo(fs, ssp, lfs_ss_getnfinfo(fs, ssp) - 1);
 	}

Index: src/sys/ufs/lfs/lfs_vfsops.c
diff -u src/sys/ufs/lfs/lfs_vfsops.c:1.338 src/sys/ufs/lfs/lfs_vfsops.c:1.339
--- src/sys/ufs/lfs/lfs_vfsops.c:1.338	Wed Aug 12 18:26:27 2015
+++ src/sys/ufs/lfs/lfs_vfsops.c	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_vfsops.c,v 1.338 2015/08/12 18:26:27 dholland Exp $	*/
+/*	$NetBSD: lfs_vfsops.c,v 1.339 2015/08/12 18:27:01 dholland Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.338 2015/08/12 18:26:27 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.339 2015/08/12 18:27:01 dholland Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_lfs.h"
@@ -2057,7 +2057,7 @@ lfs_gop_write(struct vnode *vp, struct v
 			int vers;
 
 			lfs_updatemeta(sp);
-			vers = sp->fip->fi_version;
+			vers = lfs_fi_getversion(fs, sp->fip);
 			lfs_release_finfo(fs);
 			(void) lfs_writeseg(fs, sp);
 

Index: src/usr.sbin/dumplfs/dumplfs.c
diff -u src/usr.sbin/dumplfs/dumplfs.c:1.52 src/usr.sbin/dumplfs/dumplfs.c:1.53
--- src/usr.sbin/dumplfs/dumplfs.c:1.52	Wed Aug 12 18:26:27 2015
+++ src/usr.sbin/dumplfs/dumplfs.c	Wed Aug 12 18:27:01 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: dumplfs.c,v 1.52 2015/08/12 18:26:27 dholland Exp $	*/
+/*	$NetBSD: dumplfs.c,v 1.53 2015/08/12 18:27:01 dholland Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -40,7 +40,7 @@ __COPYRIGHT("@(#) Copyright (c) 1991, 19
 #if 0
 static char sccsid[] = "@(#)dumplfs.c	8.5 (Berkeley) 5/24/95";
 #else
-__RCSID("$NetBSD: dumplfs.c,v 1.52 2015/08/12 18:26:27 dholland Exp $");
+__RCSID("$NetBSD: dumplfs.c,v 1.53 2015/08/12 18:27:01 dholland Exp $");
 #endif
 #endif /* not lint */
 
@@ -498,6 +498,7 @@ dump_sum(int fd, struct lfs *lfsp, SEGSU
 {
 	FINFO *fp;
 	int32_t *dp, *idp;
+	union lfs_blocks fipblocks;
 	int i, j, acc;
 	int ck;
 	int numbytes, numblocks;
@@ -580,23 +581,26 @@ dump_sum(int fd, struct lfs *lfsp, SEGSU
 
 	fp = SEGSUM_FINFOBASE(lfsp, sp);
 	for (i = 0; i < lfs_ss_getnfinfo(lfsp, sp); i++) {
-		(void)printf("    FINFO for inode: %d version %d nblocks %d lastlength %d\n",
-		    fp->fi_ino, fp->fi_version, fp->fi_nblocks,
-		    fp->fi_lastlength);
-		dp = &(fp->fi_blocks[0]);
-		numblocks += fp->fi_nblocks;
-		for (j = 0; j < fp->fi_nblocks; j++, dp++) {
-			(void)printf("\t%d", *dp);
+		(void)printf("    FINFO for inode: %ju version %u nblocks %u lastlength %u\n",
+		    (uintmax_t)lfs_fi_getino(lfsp, fp),
+		    lfs_fi_getversion(lfsp, fp),
+		    lfs_fi_getnblocks(lfsp, fp),
+		    lfs_fi_getlastlength(lfsp, fp));
+		lfs_blocks_fromfinfo(lfsp, &fipblocks, fp);
+		numblocks += lfs_fi_getnblocks(lfsp, fp);
+		for (j = 0; j < lfs_fi_getnblocks(lfsp, fp); j++) {
+			(void)printf("\t%jd",
+			    (intmax_t)lfs_blocks_get(lfsp, &fipblocks, j));
 			if ((j % 8) == 7)
 				(void)printf("\n");
-			if (j == fp->fi_nblocks - 1)
-				numbytes += fp->fi_lastlength;
+			if (j == lfs_fi_getnblocks(lfsp, fp) - 1)
+				numbytes += lfs_fi_getlastlength(lfsp, fp);
 			else
 				numbytes += lfs_sb_getbsize(lfsp);
 		}
 		if ((j % 8) != 0)
 			(void)printf("\n");
-		fp = (FINFO *)dp;
+		fp = NEXT_FINFO(lfsp, fp);
 	}
 
 	if (datasum_check == 0)
@@ -630,16 +634,16 @@ dump_sum(int fd, struct lfs *lfsp, SEGSU
 			--idp;
 			++acc;
 		}
-		for (j = 0; j < fp->fi_nblocks; j++) {
+		for (j = 0; j < lfs_fi_getnblocks(lfsp, fp); j++) {
 			get(fd, fsbtobyte(lfsp, addr), buf, lfs_sb_getfsize(lfsp));
 			memcpy(datap + acc * el_size, buf, el_size);
-			if (j == fp->fi_nblocks - 1)
-				addr += lfs_btofsb(lfsp, fp->fi_lastlength);
+			if (j == lfs_fi_getnblocks(lfsp, fp) - 1)
+				addr += lfs_btofsb(lfsp, lfs_fi_getlastlength(lfsp, fp));
 			else
 				addr += lfs_btofsb(lfsp, lfs_sb_getbsize(lfsp));
 			++acc;
 		}
-		fp = (FINFO *)&(fp->fi_blocks[fp->fi_nblocks]);
+		fp = NEXT_FINFO(lfsp, fp);
 	}
 	while (addr == *idp) {
 		get(fd, fsbtobyte(lfsp, addr), buf, lfs_sb_getibsize(lfsp));

Reply via email to