Home | History | Annotate | Line # | Download | only in lfs
      1 /*	$NetBSD: lfs_rfw.c,v 1.48 2026/09/23 17:47:52 perseant Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2025 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Konrad E. Schroder <perseant (at) hhhh.org>.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: lfs_rfw.c,v 1.48 2026/09/23 17:47:52 perseant Exp $");
     34 
     35 #if defined(_KERNEL_OPT)
     36 #include "opt_quota.h"
     37 #endif
     38 
     39 #include <sys/param.h>
     40 #include <sys/systm.h>
     41 #include <sys/namei.h>
     42 #include <sys/proc.h>
     43 #include <sys/kernel.h>
     44 #include <sys/vnode.h>
     45 #include <sys/mount.h>
     46 #include <sys/kthread.h>
     47 #include <sys/buf.h>
     48 #include <sys/device.h>
     49 #include <sys/file.h>
     50 #include <sys/disklabel.h>
     51 #include <sys/ioctl.h>
     52 #include <sys/errno.h>
     53 #include <sys/malloc.h>
     54 #include <sys/pool.h>
     55 #include <sys/socket.h>
     56 #include <sys/stat.h>
     57 #include <sys/syslog.h>
     58 #include <sys/sysctl.h>
     59 #include <sys/conf.h>
     60 #include <sys/kauth.h>
     61 
     62 #include <miscfs/specfs/specdev.h>
     63 
     64 #include <ufs/lfs/ulfs_quotacommon.h>
     65 #include <ufs/lfs/ulfs_inode.h>
     66 #include <ufs/lfs/ulfsmount.h>
     67 #include <ufs/lfs/ulfs_extern.h>
     68 
     69 #include <uvm/uvm_extern.h>
     70 
     71 #include <ufs/lfs/lfs.h>
     72 #include <ufs/lfs/lfs_accessors.h>
     73 #include <ufs/lfs/lfs_kernel.h>
     74 #include <ufs/lfs/lfs_extern.h>
     75 
     76 #include <miscfs/genfs/genfs.h>
     77 #include <miscfs/genfs/genfs_node.h>
     78 
     79 /*
     80  * Roll-forward code.
     81  */
     82 static bool all_selector(void *, struct vnode *);
     83 static void drop_vnode_pages(struct mount *, struct lwp *);
     84 static void update_inoblk_copy_dinode(struct lfs *, union lfs_dinode *,
     85 				      const union lfs_dinode *);
     86 static int update_inogen(struct lfs_inofuncarg *);
     87 static int update_inoblk(struct lfs_inofuncarg *);
     88 static int finfo_func_rfw(struct lfs_finfofuncarg *);
     89 static int raise_maxino(struct lfs *, ino_t);
     90 
     91 static int update_meta(struct lfs *, ino_t, int, daddr_t, daddr_t, size_t,
     92 		       struct lwp *l);
     93 #if 0
     94 static bool lfs_isseq(const struct lfs *fs, long int lbn1, long int lbn2);
     95 #endif
     96 
     97 extern int lfs_do_rfw;
     98 int rblkcnt;
     99 int lfs_rfw_max_psegs = 0;
    100 
    101 static int
    102 raise_maxino(struct lfs *fs, ino_t ino)
    103 {
    104 	int error = 0;
    105 
    106 	while (ino >= LFS_MAXINO(fs)) {
    107 		error = lfs_extend_ifile(fs, NOCRED);
    108 		if (error)
    109 			break;
    110 	}
    111 	return error;
    112 }
    113 
    114 /*
    115  * Allocate a particular inode with a particular version number, freeing
    116  * any previous versions of this inode that may have gone before.
    117  * Used by the roll-forward code.
    118  *
    119  * XXX this function does not have appropriate locking to be used on a live fs;
    120  * XXX but something similar could probably be used for an "undelete" call.
    121  *
    122  * Called with the Ifile inode locked.
    123  */
    124 int
    125 lfs_rf_valloc(struct lfs *fs, ino_t ino, int vers, struct lwp *l,
    126 	      struct vnode **vpp, union lfs_dinode *dip)
    127 {
    128 	struct vattr va;
    129 	struct vnode *vp;
    130 	struct inode *ip;
    131 	int error;
    132 
    133 	ASSERT_SEGLOCK(fs); /* XXX it doesn't, really */
    134 
    135 	KASSERTMSG(ino > LFS_IFILE_INUM, "ino=%lld", (long long)ino);
    136 	if ((error = raise_maxino(fs, ino)) != 0)
    137 		return error;
    138 
    139 	/*
    140 	 * First, just try a vget. If the version number is the one we want,
    141 	 * we don't have to do anything else.  If the version number is wrong,
    142 	 * take appropriate action.
    143 	 */
    144 	error = VFS_VGET(fs->lfs_ivnode->v_mount, ino, LK_EXCLUSIVE, &vp);
    145 	if (error == 0) {
    146 		DLOG((DLOG_RF, "lfs_rf_valloc[1]: ino %d vp %p\n",
    147 			(int)ino, vp));
    148 
    149 		*vpp = vp;
    150 		ip = VTOI(vp);
    151 		DLOG((DLOG_RF, "  ip->i_gen=%jd dip nlink %jd seeking"
    152 			" version %jd\n", (intmax_t)ip->i_gen,
    153 			(intmax_t)(dip == NULL ? -1
    154 				: lfs_dino_getnlink(fs, dip)), (intmax_t)vers));
    155 		if (ip->i_gen == vers) {
    156 			/*
    157 			 * We have what we wanted already.
    158 			 */
    159 			DLOG((DLOG_RF, "  pre-existing\n"));
    160 			return 0;
    161 		} else if (ip->i_gen < vers && dip != NULL
    162 			&& lfs_dino_getnlink(fs, dip) > 0) {
    163 			/*
    164 			 * We have found a newer version.  Truncate
    165 			 * the old vnode to zero and re-initialize
    166 			 * from the given dinode.
    167 			 */
    168 			DLOG((DLOG_RF, "  replace old version %jd\n",
    169 				(intmax_t)ip->i_gen));
    170 			lfs_truncate(vp, (off_t)0, 0, NOCRED);
    171 			ip->i_gen = vers;
    172 			vp->v_type = IFTOVT(lfs_dino_getmode(fs, dip));
    173 			update_inoblk_copy_dinode(fs, ip->i_din, dip);
    174 			LFS_SET_UINO(ip, IN_CHANGE | IN_UPDATE);
    175 			return 0;
    176 		} else {
    177 			/*
    178 			 * Not the right version and nothing to
    179 			 * initialize from.  Don't recover this data.
    180 			 */
    181 			DLOG((DLOG_RF, "ino %d: sought version %d, got %d\n",
    182 				(int)ino, (int)vers,
    183 				(int)lfs_dino_getgen(fs, ip->i_din)));
    184 			vput(vp);
    185 			*vpp = NULLVP;
    186 			return EEXIST;
    187 		}
    188 	}
    189 
    190 	/*
    191 	 * No version of this inode was found in the cache.
    192 	 * Make a new one from the dinode.  We will add data blocks
    193 	 * as they come in, so scrub any block addresses off of the
    194 	 * inode and reset block counts to zero.
    195 	 */
    196 	if (dip == NULL)
    197 		return ENOENT;
    198 
    199 	vattr_null(&va);
    200 	va.va_type = IFTOVT(lfs_dino_getmode(fs, dip));
    201 	va.va_mode = lfs_dino_getmode(fs, dip) & ALLPERMS;
    202 	va.va_fileid = ino;
    203 	va.va_gen = vers;
    204 	error = vcache_new(fs->lfs_ivnode->v_mount, NULL, &va, NOCRED, NULL,
    205 	    &vp);
    206 	if (error)
    207 		return error;
    208 	error = vn_lock(vp, LK_EXCLUSIVE);
    209 	if (error)
    210 		goto err;
    211 
    212 	ip = VTOI(vp);
    213 	update_inoblk_copy_dinode(fs, ip->i_din, dip);
    214 
    215 	DLOG((DLOG_RF, "lfs_valloc[2] ino %d vp %p size=%lld effnblks=%d,"
    216 		" blocks=%d\n", (int)ino, vp, (long long)ip->i_size,
    217 		(int)ip->i_lfs_effnblks,
    218 		(int)lfs_dino_getblocks(fs, ip->i_din)));
    219 	*vpp = vp;
    220 	return 0;
    221 
    222 err:
    223 	vrele(vp);
    224 	*vpp = NULLVP;
    225 	return error;
    226 }
    227 
    228 /*
    229  * Load the appropriate indirect block, and change the appropriate pointer.
    230  * Mark the block dirty.  Do segment and avail accounting.
    231  */
    232 static int
    233 update_meta(struct lfs *fs, ino_t ino, int vers, daddr_t lbn,
    234 	    daddr_t ndaddr, size_t size, struct lwp *l)
    235 {
    236 	int error;
    237 	struct vnode *vp;
    238 	struct inode *ip;
    239 	daddr_t odaddr;
    240 	struct indir a[ULFS_NIADDR];
    241 	int num;
    242 	struct buf *bp;
    243 	SEGUSE *sup;
    244 	u_int64_t newsize, loff;
    245 
    246 	KASSERTMSG(lbn >= 0, "lbn=%lld",	/* no indirect blocks */
    247 	    (long long)lbn);
    248 	KASSERTMSG(ino > LFS_IFILE_INUM, "ino=%lld", (long long)ino);
    249 
    250 	DLOG((DLOG_RF, "update_meta: ino %d lbn %d size %d at 0x%jx\n",
    251 	      (int)ino, (int)lbn, (int)size, (uintmax_t)ndaddr));
    252 
    253 	if ((error = lfs_rf_valloc(fs, ino, vers, l, &vp, NULL)) != 0)
    254 		return error;
    255 	ip = VTOI(vp);
    256 
    257 	/*
    258 	 * If block already exists, note its new location
    259 	 * but do not account it as new.
    260 	 */
    261 	ulfs_bmaparray(vp, lbn, &odaddr, &a[0], &num, NULL, NULL);
    262 	if (odaddr == UNASSIGNED) {
    263 		if ((error = lfs_balloc(vp, (lbn << lfs_sb_getbshift(fs)),
    264 					size, NOCRED, 0, &bp)) != 0) {
    265 			vput(vp);
    266 			return (error);
    267 		}
    268 		/* No need to write, the block is already on disk */
    269 		if (bp->b_oflags & BO_DELWRI) {
    270 			LFS_UNLOCK_BUF(bp);
    271 			/* Account recovery of the previous version */
    272 			lfs_sb_addavail(fs, lfs_btofsb(fs, bp->b_bcount));
    273 		}
    274 		brelse(bp, BC_INVAL);
    275 		DLOG((DLOG_RF, "balloc ip->i_lfs_effnblks = %d,"
    276 			" lfs_dino_getblocks(fs, ip->i_din) = %d\n",
    277 			(int)ip->i_lfs_effnblks,
    278 			(int)lfs_dino_getblocks(fs, ip->i_din)));
    279 	} else {
    280 		/* XXX fragextend? */
    281 		DLOG((DLOG_RF, "block exists, no balloc\n"));
    282 	}
    283 
    284 	/*
    285 	 * Extend the file, if it is not large enough already.
    286 	 * XXX This is not exactly right, we don't know how much of the
    287 	 * XXX last block is actually used.
    288 	 *
    289 	 * XXX We should be able to encode the actual data length of the
    290 	 * XXX last block in fi_lastlength, since we can infer the
    291 	 * XXX necessary block length from that using a variant of
    292 	 * XXX lfs_blksize().
    293 	 */
    294 	loff = lfs_lblktosize(fs, lbn);
    295 	if (loff >= (ULFS_NDADDR << lfs_sb_getbshift(fs))) {
    296 		/* No fragments */
    297 		newsize = loff + 1;
    298 	} else {
    299 		/* Subtract only a fragment to account for block size */
    300 		newsize = loff + size - lfs_fsbtob(fs, 1) + 1;
    301 	}
    302 
    303 	if (ip->i_size < newsize) {
    304 		DLOG((DLOG_RF, "ino %d size %d -> %d\n",
    305 		      (int)ino, (int)ip->i_size, (int)newsize));
    306 		lfs_dino_setsize(fs, ip->i_din, newsize);
    307 		ip->i_size = newsize;
    308 		/*
    309 		 * tell vm our new size for the case the inode won't
    310 		 * appear later.
    311 		 */
    312 		uvm_vnp_setsize(vp, newsize);
    313 	}
    314 
    315 	lfs_update_single(fs, NULL, vp, lbn, ndaddr, size);
    316 
    317 	LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, ndaddr), bp);
    318 	DLOG((DLOG_SU, "seg %jd += %jd for ino %jd"
    319 		" lbn %jd db 0x%jd (rfw)\n",
    320 		(intmax_t)lfs_dtosn(fs, ndaddr),
    321 		(intmax_t)size,
    322 		(intmax_t)ip->i_number,
    323 		(intmax_t)lbn,
    324 		(intmax_t)ndaddr));
    325 	sup->su_nbytes += size;
    326 	LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, ndaddr), bp);
    327 
    328 	/* differences here should be due to UNWRITTEN indirect blocks. */
    329 	if (vp->v_type != VLNK) {
    330 		if (!(ip->i_lfs_effnblks >= lfs_dino_getblocks(fs, ip->i_din))
    331 #if 0
    332 		    || !(lfs_lblkno(fs, ip->i_size) > ULFS_NDADDR ||
    333 			 ip->i_lfs_effnblks == lfs_dino_getblocks(fs, ip->i_din))
    334 #endif /* 0 */
    335 			) {
    336 			vprint("vnode", vp);
    337 			printf("effnblks=%jd dino_getblocks=%jd\n",
    338 			       (intmax_t)ip->i_lfs_effnblks,
    339 			       (intmax_t)lfs_dino_getblocks(fs, ip->i_din));
    340 		}
    341 		KASSERT(ip->i_lfs_effnblks >= lfs_dino_getblocks(fs, ip->i_din));
    342 #if 0
    343 		KASSERT(lfs_lblkno(fs, ip->i_size) > ULFS_NDADDR ||
    344 			ip->i_lfs_effnblks == lfs_dino_getblocks(fs, ip->i_din));
    345 #endif /* 0 */
    346 	}
    347 
    348 #ifdef DEBUG
    349 	/* Now look again to make sure it worked */
    350 	ulfs_bmaparray(vp, lbn, &odaddr, &a[0], &num, NULL, NULL);
    351 	if (LFS_DBTOFSB(fs, odaddr) != ndaddr)
    352 		DLOG((DLOG_RF, "update_meta: failed setting ino %jd lbn %jd"
    353 		      " to %jd\n", (intmax_t)ino, (intmax_t)lbn, (intmax_t)ndaddr));
    354 #endif /* DEBUG */
    355 	vput(vp);
    356 	return 0;
    357 }
    358 
    359 /*
    360  * Copy some the fields of the dinode as needed by update_inoblk().
    361  */
    362 static void
    363 update_inoblk_copy_dinode(struct lfs *fs,
    364     union lfs_dinode *dstu, const union lfs_dinode *srcu)
    365 {
    366 	if (fs->lfs_is64) {
    367 		struct lfs64_dinode *dst = &dstu->u_64;
    368 		const struct lfs64_dinode *src = &srcu->u_64;
    369 		unsigned i;
    370 
    371 		/*
    372 		 * Copy everything but the block pointers and di_blocks.
    373 		 * XXX what about di_extb?
    374 		 */
    375 		dst->di_mode = src->di_mode;
    376 		dst->di_nlink = src->di_nlink;
    377 		dst->di_uid = src->di_uid;
    378 		dst->di_gid = src->di_gid;
    379 		dst->di_blksize = src->di_blksize;
    380 		dst->di_size = src->di_size;
    381 		dst->di_atime = src->di_atime;
    382 		dst->di_mtime = src->di_mtime;
    383 		dst->di_ctime = src->di_ctime;
    384 		dst->di_birthtime = src->di_birthtime;
    385 		dst->di_mtimensec = src->di_mtimensec;
    386 		dst->di_atimensec = src->di_atimensec;
    387 		dst->di_ctimensec = src->di_ctimensec;
    388 		dst->di_birthnsec = src->di_birthnsec;
    389 		dst->di_gen = src->di_gen;
    390 		dst->di_kernflags = src->di_kernflags;
    391 		dst->di_flags = src->di_flags;
    392 		dst->di_extsize = src->di_extsize;
    393 		dst->di_modrev = src->di_modrev;
    394 		dst->di_inumber = src->di_inumber;
    395 		for (i = 0; i < __arraycount(src->di_spare); i++) {
    396 			dst->di_spare[i] = src->di_spare[i];
    397 		}
    398 		/* Short symlinks store their data in di_db. */
    399 		if ((src->di_mode & LFS_IFMT) == LFS_IFLNK
    400 		    && src->di_size < lfs_sb_getmaxsymlinklen(fs)) {
    401 			memcpy(dst->di_db, src->di_db, src->di_size);
    402 		}
    403 	} else {
    404 		struct lfs32_dinode *dst = &dstu->u_32;
    405 		const struct lfs32_dinode *src = &srcu->u_32;
    406 
    407 		/* Get mode, link count, size, and times */
    408 		memcpy(dst, src, offsetof(struct lfs32_dinode, di_db[0]));
    409 
    410 		/* Then the rest, except di_blocks */
    411 		dst->di_flags = src->di_flags;
    412 		dst->di_gen = src->di_gen;
    413 		dst->di_uid = src->di_uid;
    414 		dst->di_gid = src->di_gid;
    415 		dst->di_modrev = src->di_modrev;
    416 
    417 		/* Short symlinks store their data in di_db. */
    418 		if ((src->di_mode & LFS_IFMT) == LFS_IFLNK
    419 		    && src->di_size < lfs_sb_getmaxsymlinklen(fs)) {
    420 			memcpy(dst->di_db, src->di_db, src->di_size);
    421 		}
    422 	}
    423 }
    424 
    425 static int
    426 update_inoblk(struct lfs_inofuncarg *lifa)
    427 {
    428 	struct lfs *fs;
    429 	daddr_t offset;
    430 	struct lwp *l;
    431 	struct vnode *devvp, *vp;
    432 	struct inode *ip;
    433 	union lfs_dinode *dip;
    434 	struct buf *dbp, *ibp;
    435 	int error;
    436 	IFILE *ifp;
    437 	unsigned i, num;
    438 	uint32_t gen;
    439 	char *buf;
    440 	ino_t ino;
    441 
    442 	fs = lifa->fs;
    443 	offset = lifa->offset;
    444 	l = lifa->l;
    445 	devvp = VTOI(fs->lfs_ivnode)->i_devvp;
    446 
    447 	/*
    448 	 * Get the inode, update times and perms.
    449 	 * DO NOT update disk blocks, we do that separately.
    450 	 */
    451 	error = bread(devvp, LFS_FSBTODB(fs, offset), lfs_sb_getibsize(fs),
    452 	    0, &dbp);
    453 	if (error) {
    454 		DLOG((DLOG_RF, "update_inoblk: bread returned %d\n", error));
    455 		return error;
    456 	}
    457 	buf = malloc(dbp->b_bcount, M_SEGMENT, M_WAITOK);
    458 	memcpy(buf, dbp->b_data, dbp->b_bcount);
    459 	brelse(dbp, BC_AGE);
    460 	num = LFS_INOPB(fs);
    461 	for (i = num; i-- > 0; ) {
    462 		dip = DINO_IN_BLOCK(fs, buf, i);
    463 		ino = lfs_dino_getinumber(fs, dip);
    464 		if (ino <= LFS_IFILE_INUM)
    465 			continue;
    466 
    467 		if ((error = raise_maxino(fs, ino)) != 0)
    468 			continue;
    469 
    470 		/* Check generation number */
    471 		LFS_IENTRY(ifp, fs, lfs_dino_getinumber(fs, dip), ibp);
    472 		gen = lfs_if_getversion(fs, ifp);
    473 		LFS_RELEASEIENTRY(ifp, fs, lfs_dino_getinumber(fs, dip), ibp);
    474 		if (lfs_dino_getgen(fs, dip) < gen) {
    475 			continue;
    476 		}
    477 
    478 		/*
    479 		 * This inode is the newest generation.  Load it.
    480 		 */
    481 		error = lfs_rf_valloc(fs, ino, lfs_dino_getgen(fs, dip),
    482 				      l, &vp, dip);
    483 		if (error) {
    484 			DLOG((DLOG_RF, "update_inoblk: lfs_rf_valloc"
    485 			      " returned %d\n", error));
    486 			continue;
    487 		}
    488 		ip = VTOI(vp);
    489 		if (lfs_dino_getsize(fs, dip) != ip->i_size
    490 		    && vp->v_type != VLNK) {
    491 			/* XXX What should we do with symlinks? */
    492 			DLOG((DLOG_RF, "  ino %jd size %jd -> %jd\n",
    493 				(intmax_t)ino,
    494 				(intmax_t)ip->i_size,
    495 				(intmax_t)lfs_dino_getsize(fs, dip)));
    496 			lfs_truncate(vp, lfs_dino_getsize(fs, dip), 0,
    497 				     NOCRED);
    498 		}
    499 		update_inoblk_copy_dinode(fs, ip->i_din, dip);
    500 
    501 		ip->i_flags = lfs_dino_getflags(fs, dip);
    502 		ip->i_gen = lfs_dino_getgen(fs, dip);
    503 		ip->i_uid = lfs_dino_getuid(fs, dip);
    504 		ip->i_gid = lfs_dino_getgid(fs, dip);
    505 
    506 		ip->i_mode = lfs_dino_getmode(fs, dip);
    507 		ip->i_nlink = lfs_dino_getnlink(fs, dip);
    508 		ip->i_size = lfs_dino_getsize(fs, dip);
    509 
    510 		LFS_SET_UINO(ip, IN_CHANGE | IN_UPDATE);
    511 
    512 		/* Re-initialize to get type right */
    513 		ulfs_vinit(vp->v_mount, lfs_specop_p, lfs_fifoop_p,
    514 			  &vp);
    515 
    516 		/* Record change in location and do segment accounting */
    517 		lfs_update_iaddr(fs, ip, offset);
    518 
    519 		vput(vp);
    520 	}
    521 	free(buf, M_SEGMENT);
    522 
    523 	return 0;
    524 }
    525 
    526 /*
    527  * Note the highest generation number of each inode in the Ifile.
    528  * This allows us to skip processing data for intermediate versions.
    529  */
    530 static int
    531 update_inogen(struct lfs_inofuncarg *lifa)
    532 {
    533 	struct lfs *fs;
    534 	daddr_t offset;
    535 	struct vnode *devvp;
    536 	union lfs_dinode *dip;
    537 	struct buf *dbp, *ibp;
    538 	int error;
    539 	IFILE *ifp;
    540 	unsigned i, num;
    541 
    542 	fs = lifa->fs;
    543 	offset = lifa->offset;
    544 	devvp = VTOI(fs->lfs_ivnode)->i_devvp;
    545 
    546 	/* Read inode block */
    547 	error = bread(devvp, LFS_FSBTODB(fs, offset), lfs_sb_getibsize(fs),
    548 	    0, &dbp);
    549 	if (error) {
    550 		DLOG((DLOG_RF, "update_inoblk: bread returned %d\n", error));
    551 		return error;
    552 	}
    553 
    554 	/* Check each inode against ifile entry */
    555 	num = LFS_INOPB(fs);
    556 	for (i = num; i-- > 0; ) {
    557 		dip = DINO_IN_BLOCK(fs, dbp->b_data, i);
    558 		if (lfs_dino_getinumber(fs, dip) == LFS_IFILE_INUM)
    559 			continue;
    560 
    561 		/* Update generation number */
    562 		LFS_IENTRY(ifp, fs, lfs_dino_getinumber(fs, dip), ibp);
    563 		if (lfs_if_getversion(fs, ifp) < lfs_dino_getgen(fs, dip))
    564 			lfs_if_setversion(fs, ifp, lfs_dino_getgen(fs, dip));
    565 		LFS_WRITEIENTRY(ifp, fs, lfs_dino_getinumber(fs, dip), ibp);
    566 		if (error)
    567 			break;
    568 	}
    569 	brelse(dbp, 0);
    570 
    571 	return error;
    572 }
    573 
    574 static int
    575 finfo_func_rfw(struct lfs_finfofuncarg *lffa)
    576 {
    577 	struct lfs *fs;
    578 	FINFO *fip;
    579 	daddr_t *offsetp;
    580 	struct lwp *l;
    581 	int j;
    582 	size_t size;
    583 	ino_t ino;
    584 
    585 	fs = lffa->fs;
    586 	fip = lffa->finfop;
    587 	offsetp = lffa->offsetp;
    588 	l = lffa->l;
    589 	size = lfs_sb_getbsize(fs);
    590 	ino = lfs_fi_getino(fs, fip);
    591 	LFS_ASSERT_MAXINO(fs, ino);
    592 	for (j = 0; j < lfs_fi_getnblocks(fs, fip); ++j) {
    593 		if (j == lfs_fi_getnblocks(fs, fip) - 1)
    594 			size = lfs_fi_getlastlength(fs, fip);
    595 
    596 		/* Account for and update any direct blocks */
    597 		if (ino > LFS_IFILE_INUM &&
    598 		    lfs_fi_getblock(fs, fip, j) >= 0) {
    599 			update_meta(fs, ino,
    600 				    lfs_fi_getversion(fs, fip),
    601 				    lfs_fi_getblock(fs, fip, j),
    602 				    *offsetp, size, l);
    603 			++rblkcnt;
    604 		}
    605 		*offsetp += lfs_btofsb(fs, size);
    606 	}
    607 
    608 	return 0;
    609 }
    610 
    611 int
    612 lfs_skip_superblock(struct lfs *fs, daddr_t *offsetp)
    613 {
    614 	daddr_t offset;
    615 	int i;
    616 
    617 	/*
    618 	 * If this is segment 0, skip the label.
    619 	 * If the segment has a superblock and we're at the top
    620 	 * of the segment, skip the superblock.
    621 	 */
    622 	offset = *offsetp;
    623 	if (offset == lfs_sb_gets0addr(fs)) {
    624 		offset += lfs_btofsb(fs, LFS_LABELPAD);
    625 	}
    626 	for (i = 0; i < LFS_MAXNUMSB; i++) {
    627 		if (offset == lfs_sb_getsboff(fs, i)) {
    628 			offset += lfs_btofsb(fs, LFS_SBPAD);
    629 			break;
    630 		}
    631 	}
    632 	*offsetp = offset;
    633 	return 0;
    634 }
    635 
    636 /*
    637  * Read the partial segment at offset.
    638  *
    639  * If finfo_func and ino_func are both NULL, check the summary
    640  * and data checksums.  During roll forward, this must be done in its
    641  * entirety before processing any blocks.
    642  *
    643  * If finfo_func is given, use that to process every file block
    644  * in the segment summary.  If ino_func is given, use that to process
    645  * every inode block.
    646  */
    647 int
    648 lfs_parse_pseg(struct lfs *fs, daddr_t *offsetp, u_int64_t nextserial,
    649 	       kauth_cred_t cred, int *pseg_flags, struct lwp *l,
    650 	       int (*ino_func)(struct lfs_inofuncarg *),
    651 	       int (*finfo_func)(struct lfs_finfofuncarg *),
    652 	       int flags, void *arg)
    653 {
    654 	struct vnode *devvp;
    655 	struct buf *bp, *dbp;
    656 	int error, ninos, i, j;
    657 	SEGSUM *ssp;
    658 	daddr_t offset, prevoffset;
    659 	IINFO *iip;
    660 	FINFO *fip;
    661 	size_t size;
    662 	uint32_t datasum, foundsum;
    663 	char *buf;
    664 	struct lfs_inofuncarg lifa;
    665 	struct lfs_finfofuncarg lffa;
    666 
    667 	KASSERT(fs != NULL);
    668 	KASSERT(offsetp != NULL);
    669 
    670 	devvp = VTOI(fs->lfs_ivnode)->i_devvp;
    671 
    672 	/* Set up callback arguments */
    673 	lifa.fs = fs;
    674 	/* lifa.offset = offset; */
    675 	lifa.cred = cred;
    676 	lifa.l = l;
    677 	lifa.buf = malloc(lfs_sb_getbsize(fs), M_SEGMENT, M_WAITOK);
    678 
    679 	lifa.arg = arg;
    680 
    681 	lffa.fs = fs;
    682 	/* lffa.offsetp = offsetp; */
    683 	/* lffa.finfop = finfop; */
    684 	lffa.cred = cred;
    685 	lffa.l = l;
    686 	lffa.arg = arg;
    687 
    688 	prevoffset = *offsetp;
    689 	lfs_skip_superblock(fs, offsetp);
    690 	offset = *offsetp;
    691 
    692 	/* Read in the segment summary */
    693 	buf = malloc(lfs_sb_getsumsize(fs), M_SEGMENT, M_WAITOK);
    694 	error = bread(devvp, LFS_FSBTODB(fs, offset), lfs_sb_getsumsize(fs),
    695 	    0, &bp);
    696 	if (error)
    697 		goto err;
    698 	memcpy(buf, bp->b_data, bp->b_bcount);
    699 	brelse(bp, BC_AGE);
    700 
    701 	ssp = (SEGSUM *)buf;
    702 
    703 	if (lfs_ss_getmagic(fs, ssp) != SS_MAGIC) {
    704 		DLOG((DLOG_RF, "Bad magic at 0x%" PRIx64 "\n",
    705 		      offset));
    706 		offset = -1;
    707 		goto err;
    708 	}
    709 
    710 	if (flags & CKSEG_CKSUM) {
    711 		size_t sumstart;
    712 
    713 		sumstart = lfs_ss_getsumstart(fs);
    714 		if (lfs_ss_getsumsum(fs, ssp) !=
    715 		    cksum((char *)ssp + sumstart,
    716 			  lfs_sb_getsumsize(fs) - sumstart)) {
    717 			DLOG((DLOG_RF, "Sumsum error at 0x%" PRIx64 "\n",
    718 				offset));
    719 			offset = -1;
    720 			goto err;
    721 		}
    722 	}
    723 
    724 #if 0
    725 	/*
    726 	 * Under normal conditions, we should never be producing
    727 	 * a partial segment with neither inode blocks nor data blocks.
    728 	 * However, these do sometimes appear and they need not
    729 	 * prevent us from continuing.
    730 	 */
    731 	if (lfs_ss_getnfinfo(fs, ssp) == 0 &&
    732 	    lfs_ss_getninos(fs, ssp) == 0) {
    733 		DLOG((DLOG_RF, "Empty pseg at 0x%" PRIx64 "\n",
    734 		      offset));
    735 		offset = -1;
    736 		goto err;
    737 	}
    738 #endif /* 0 */
    739 
    740 	if (lfs_sb_getversion(fs) == 1) {
    741 		if (lfs_ss_getcreate(fs, ssp) < lfs_sb_gettstamp(fs)) {
    742 			DLOG((DLOG_RF, "Old data at 0x%" PRIx64 "\n", offset));
    743 			offset = -1;
    744 			goto err;
    745 		}
    746 	} else {
    747 		if (nextserial > 0
    748 		    && lfs_ss_getserial(fs, ssp) != nextserial) {
    749 			DLOG((DLOG_RF, "Serial number at 0x%jx given as 0x%jx,"
    750 			      " expected 0x%jx\n", (intmax_t)offset,
    751 			      (intmax_t)lfs_ss_getserial(fs, ssp),
    752 			      (intmax_t)nextserial));
    753 			offset = -1;
    754 			goto err;
    755 		}
    756 		if (lfs_ss_getident(fs, ssp) != lfs_sb_getident(fs)) {
    757 			DLOG((DLOG_RF, "Incorrect fsid (0x%x vs 0x%x) at 0x%"
    758 			      PRIx64 "\n", lfs_ss_getident(fs, ssp),
    759 			      lfs_sb_getident(fs), offset));
    760 			offset = -1;
    761 			goto err;
    762 		}
    763 	}
    764 
    765 #ifdef DIAGNOSTIC
    766 	if (lfs_ss_getnfinfo(fs, ssp) > lfs_sb_getssize(fs) / lfs_sb_getfsize(fs)) {
    767 		printf("At offset 0x%jx, nfinfo %jd > max frags %jd\n",
    768 		       (intmax_t)offset,
    769 		       (intmax_t)lfs_ss_getnfinfo(fs, ssp),
    770 		       (intmax_t)lfs_sb_getssize(fs) / lfs_sb_getfsize(fs));
    771 	}
    772 #endif
    773 	KASSERT(lfs_ss_getnfinfo(fs, ssp) <= lfs_sb_getssize(fs) / lfs_sb_getfsize(fs));
    774 #ifdef DIAGNOSTIC
    775 	if (lfs_ss_getnfinfo(fs, ssp) > lfs_sb_getfsize(fs) / sizeof(FINFO32)) {
    776 		printf("At offset 0x%jx, nfinfo %jd > max entries %jd\n",
    777 		       (intmax_t)offset,
    778 		       (intmax_t)lfs_ss_getnfinfo(fs, ssp),
    779 		       (intmax_t)lfs_sb_getssize(fs) / lfs_sb_getfsize(fs));
    780 	}
    781 #endif
    782 	KASSERT(lfs_ss_getnfinfo(fs, ssp) <= lfs_sb_getfsize(fs) / sizeof(FINFO32));
    783 
    784 	if (pseg_flags)
    785 		*pseg_flags = lfs_ss_getflags(fs, ssp);
    786 	ninos = howmany(lfs_ss_getninos(fs, ssp), LFS_INOPB(fs));
    787 	iip = SEGSUM_IINFOSTART(fs, buf);
    788 	fip = SEGSUM_FINFOBASE(fs, (SEGSUM *)buf);
    789 
    790 	/* Handle individual blocks */
    791 	foundsum = 0;
    792 	offset += lfs_btofsb(fs, lfs_sb_getsumsize(fs));
    793 	for (i = 0; i < lfs_ss_getnfinfo(fs, ssp) || ninos; ++i) {
    794 		/* Inode block? */
    795 		if (ninos && lfs_ii_getblock(fs, iip) == offset) {
    796 			if (flags & CKSEG_CKSUM) {
    797 				/* Read in the head and add to the buffer */
    798 				error = bread(devvp, LFS_FSBTODB(fs, offset),
    799 					lfs_sb_getbsize(fs), 0, &dbp);
    800 				if (error) {
    801 					offset = -1;
    802 					goto err;
    803 				}
    804 				foundsum = lfs_cksum_part(dbp->b_data,
    805 					sizeof(uint32_t), foundsum);
    806 				brelse(dbp, BC_AGE);
    807 			} else if (ino_func != NULL) {
    808 				lifa.offset = offset;
    809 				error = (*ino_func)(&lifa);
    810 				if (error != 0) {
    811 					offset = -1;
    812 					goto err;
    813 				}
    814 			}
    815 
    816 			offset += lfs_btofsb(fs, lfs_sb_getibsize(fs));
    817 			iip = NEXTLOWER_IINFO(fs, iip);
    818 			--ninos;
    819 			--i; /* compensate for ++i in loop header */
    820 			continue;
    821 		}
    822 
    823 		/* File block */
    824 		size = lfs_sb_getbsize(fs);
    825 		if (flags & CKSEG_CKSUM) {
    826 			for (j = 0; j < lfs_fi_getnblocks(fs, fip); ++j) {
    827 				if (j == lfs_fi_getnblocks(fs, fip) - 1)
    828 					size = lfs_fi_getlastlength(fs, fip);
    829 				error = bread(devvp, LFS_FSBTODB(fs, offset),
    830 					      size, 0, &dbp);
    831 				if (error) {
    832 					offset = -1;
    833 					goto err;
    834 				}
    835 				foundsum = lfs_cksum_part(dbp->b_data,
    836 							  sizeof(uint32_t), foundsum);
    837 				brelse(dbp, BC_AGE);
    838 				offset += lfs_btofsb(fs, size);
    839 			}
    840 		} else if (finfo_func != NULL) {
    841 			lffa.offsetp = &offset;
    842 			lffa.finfop = fip;
    843 			error = (*finfo_func)(&lffa);
    844 			if (error == ESTALE)
    845 				error = 0;
    846 			if (error)
    847 				goto err;
    848 		} else {
    849 			int n = lfs_fi_getnblocks(fs, fip);
    850 			size = lfs_fi_getlastlength(fs, fip);
    851 			offset += lfs_btofsb(fs, lfs_sb_getbsize(fs) * (n - 1)
    852 					     + size);
    853 		}
    854 		fip = NEXT_FINFO(fs, fip);
    855 	}
    856 
    857 	/* Checksum the array, compare */
    858 	if (flags & CKSEG_CKSUM) {
    859 		datasum = lfs_ss_getdatasum(fs, ssp);
    860 		foundsum = lfs_cksum_fold(foundsum);
    861 		if (datasum != foundsum) {
    862 			DLOG((DLOG_RF, "Datasum error at 0x%" PRIx64
    863 			      " (wanted %x got %x)\n",
    864 			      offset, datasum, foundsum));
    865 			offset = -1;
    866 			goto err;
    867 		}
    868 	} else {
    869 		/* Don't clog the buffer queue */
    870 		mutex_enter(&lfs_lock);
    871 		if (locked_queue_count > LFS_MAX_BUFS ||
    872 		    locked_queue_bytes > LFS_MAX_BYTES) {
    873 			lfs_flush(fs, SEGM_CKP, 0);
    874 		}
    875 		mutex_exit(&lfs_lock);
    876 	}
    877 
    878 	/*
    879 	 * If we're at the end of the segment, move to the next.
    880 	 * A partial segment needs space for a segment header (1 fsb)
    881 	 * and a full block ("frag" fsb).  Thus, adding "frag" fsb should
    882 	 * still be within the current segment (whereas frag + 1 might
    883 	 * be at the start of the next segment).
    884 	 *
    885 	 * This needs to match the definition of LFS_PARTIAL_FITS
    886 	 * in lfs_segment.c.
    887 	 */
    888 	if (lfs_dtosn(fs, offset + lfs_sb_getfrag(fs))
    889 	    != lfs_dtosn(fs, offset)) {
    890 		if (lfs_dtosn(fs, offset) == lfs_dtosn(fs, lfs_ss_getnext(fs,
    891 									ssp))) {
    892 			offset = -1;
    893 			goto err;
    894 		}
    895 		offset = lfs_ss_getnext(fs, ssp);
    896 		DLOG((DLOG_RF, "LFS roll forward: moving to offset 0x%" PRIx64
    897 		       " -> segment %d\n", offset, lfs_dtosn(fs,offset)));
    898 	}
    899 	if (flags & CKSEG_AVAIL)
    900 		lfs_sb_subavail(fs, offset - prevoffset);
    901 
    902     err:
    903 	free(lifa.buf, M_SEGMENT);
    904 	free(buf, M_SEGMENT);
    905 
    906 	*offsetp = offset;
    907 	return error;
    908 }
    909 
    910 /*
    911  * Roll forward.
    912  */
    913 void
    914 lfs_roll_forward(struct lfs *fs, struct mount *mp, struct lwp *l)
    915 {
    916 	int flags, dirty;
    917 	daddr_t startoffset, offset, nextoffset, endpseg;
    918 	u_int64_t nextserial, startserial, endserial;
    919 	int sn, curseg;
    920 	struct proc *p;
    921 	kauth_cred_t cred;
    922 	SEGUSE *sup;
    923 	struct buf *bp;
    924 
    925 	p = l ? l->l_proc : NULL;
    926 	cred = p ? p->p_cred : NOCRED;
    927 
    928 	/*
    929 	 * We don't roll forward for v1 filesystems, because
    930 	 * of the danger that the clock was turned back between the last
    931 	 * checkpoint and crash.  This would roll forward garbage.
    932 	 *
    933 	 * v2 filesystems don't have this problem because they use a
    934 	 * monotonically increasing serial number instead of a timestamp.
    935 	 */
    936 	rblkcnt = 0;
    937 	if ((lfs_sb_getpflags(fs) & LFS_PF_CLEAN) || !lfs_do_rfw
    938 	    || lfs_sb_getversion(fs) <= 1 || p == NULL)
    939 		return;
    940 
    941 	DLOG((DLOG_RF, "%s: begin roll forward at serial 0x%jx\n",
    942 		lfs_sb_getfsmnt(fs), (intmax_t)lfs_sb_getserial(fs)));
    943 	DEBUG_CHECK_FREELIST(fs);
    944 
    945 	/*
    946 	 * Phase I: Find the address of the last good partial
    947 	 * segment that was written after the checkpoint.  Mark
    948 	 * the segments in question dirty, so they won't be
    949 	 * reallocated.
    950 	 */
    951 	endpseg = startoffset = offset = lfs_sb_getoffset(fs);
    952 	flags = 0x0;
    953 	DLOG((DLOG_RF, "LFS roll forward phase 1: start at offset 0x%"
    954 	      PRIx64 "\n", offset));
    955 	LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, offset), bp);
    956 	if (!(sup->su_flags & SEGUSE_DIRTY))
    957 		lfs_sb_subnclean(fs, 1);
    958 	sup->su_flags |= SEGUSE_DIRTY;
    959 	LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, offset), bp);
    960 
    961 	startserial = lfs_sb_getserial(fs);
    962 	endserial = nextserial = startserial + 1;
    963 	nextoffset = offset;
    964 	while (1) {
    965 		nextoffset = offset;
    966 		lfs_parse_pseg(fs, &nextoffset, nextserial,
    967 			     cred, &flags, l, NULL, NULL, CKSEG_CKSUM, NULL);
    968 		if (nextoffset == -1)
    969 			break;
    970 		if (lfs_sntod(fs, offset) != lfs_sntod(fs, nextoffset)) {
    971 			LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, offset),
    972 				     bp);
    973 			if (!(sup->su_flags & SEGUSE_DIRTY))
    974 				lfs_sb_subnclean(fs, 1);
    975 			sup->su_flags |= SEGUSE_DIRTY;
    976 			LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, offset), bp);
    977 		}
    978 
    979 		DLOG((DLOG_RF, "LFS roll forward phase 1: offset=0x%jx"
    980 			" serial=0x%jx\n", (intmax_t)nextoffset,
    981 			(intmax_t)nextserial));
    982 		if (flags & SS_DIROP) {
    983 			DLOG((DLOG_RF, "lfs_mountfs: dirops at 0x%"
    984 			      PRIx64 "\n", offset));
    985 			if (!(flags & SS_CONT)) {
    986 			     DLOG((DLOG_RF, "lfs_mountfs: dirops end "
    987 				   "at 0x%" PRIx64 "\n", offset));
    988 			}
    989 		}
    990 		offset = nextoffset;
    991 		++nextserial;
    992 
    993 		if (!(flags & SS_CONT)) {
    994 			endpseg = nextoffset;
    995 			endserial = nextserial;
    996 		}
    997 		if (lfs_rfw_max_psegs > 0
    998 		    && nextserial > startserial + lfs_rfw_max_psegs)
    999 			break;
   1000 	}
   1001 	if (flags & SS_CONT) {
   1002 		DLOG((DLOG_RF, "LFS roll forward: warning: incomplete "
   1003 			"dirops discarded (0x%jx < 0x%jx)\n",
   1004 			endpseg, nextoffset));
   1005 	}
   1006 	if (lfs_sb_getversion(fs) > 1)
   1007 		lfs_sb_setserial(fs, endserial);
   1008 	DLOG((DLOG_RF, "LFS roll forward phase 1: completed: "
   1009 	      "endpseg=0x%" PRIx64 "\n", endpseg));
   1010 	offset = startoffset;
   1011 	if (offset != endpseg) {
   1012 		/* Don't overwrite what we're trying to preserve */
   1013 		lfs_sb_setoffset(fs, endpseg);
   1014 		lfs_sb_setcurseg(fs, lfs_sntod(fs, lfs_dtosn(fs, endpseg)));
   1015 		for (sn = curseg = lfs_dtosn(fs, lfs_sb_getcurseg(fs));;) {
   1016 			sn = (sn + 1) % lfs_sb_getnseg(fs);
   1017 			/* XXX could we just fail to roll forward? */
   1018 			if (sn == curseg)
   1019 				panic("lfs_mountfs: no clean segments");
   1020 			LFS_SEGENTRY(sup, fs, sn, bp);
   1021 			dirty = (sup->su_flags & SEGUSE_DIRTY);
   1022 			LFS_RELEASESEGENTRY(sup, fs, sn, bp);
   1023 			if (!dirty)
   1024 				break;
   1025 		}
   1026 		lfs_sb_setnextseg(fs, lfs_sntod(fs, sn));
   1027 		/* Explicitly set this segment dirty */
   1028 		LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, endpseg), bp);
   1029 		sup->su_flags |= SEGUSE_DIRTY | SEGUSE_ACTIVE;
   1030 		LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, endpseg), bp);
   1031 
   1032 		/*
   1033 		 * Phase II: Identify the highest generation of each
   1034 		 * inode.  We will ignore inodes and data blocks
   1035 		 * belonging to old versions.
   1036 		 */
   1037 		offset = startoffset;
   1038 		nextserial = startserial + 1;
   1039 		DLOG((DLOG_RF, "LFS roll forward phase 2 beginning\n"));
   1040 		while (offset > 0 && offset != endpseg) {
   1041 			lfs_parse_pseg(fs, &offset, nextserial++, cred,
   1042 				     NULL, l, update_inogen, NULL,
   1043 				     CKSEG_NONE, NULL);
   1044 			DEBUG_CHECK_FREELIST(fs);
   1045 		}
   1046 
   1047 		/*
   1048 		 * Phase III: Update inodes.
   1049 		 */
   1050 		offset = startoffset;
   1051 		nextserial = startserial + 1;
   1052 		DLOG((DLOG_RF, "LFS roll forward phase 3 beginning\n"));
   1053 		while (offset > 0 && offset != endpseg) {
   1054 			lfs_parse_pseg(fs, &offset, nextserial++, cred,
   1055 				     NULL, l, update_inoblk, NULL,
   1056 				     CKSEG_NONE, NULL);
   1057 			DEBUG_CHECK_FREELIST(fs);
   1058 		}
   1059 
   1060 		/*
   1061 		 * Phase IV: Roll forward, updating data blocks.
   1062 		 */
   1063 		offset = startoffset;
   1064 		nextserial = startserial + 1;
   1065 		DLOG((DLOG_RF, "LFS roll forward phase 4 beginning\n"));
   1066 		while (offset > 0 && offset != endpseg) {
   1067 			lfs_parse_pseg(fs, &offset, nextserial++, cred,
   1068 				     NULL, l, NULL, finfo_func_rfw,
   1069 				     CKSEG_AVAIL, NULL);
   1070 			DEBUG_CHECK_FREELIST(fs);
   1071 		}
   1072 
   1073 		/*
   1074 		 * Finish: flush our changes to disk.
   1075 		 */
   1076 		lfs_sb_setserial(fs, endserial);
   1077 
   1078 		lfs_segwrite(mp, SEGM_CKP | SEGM_SYNC);
   1079 		DLOG((DLOG_RF, "lfs_mountfs: roll forward "
   1080 		      "examined %jd blocks\n",
   1081 		      (intmax_t)(endpseg - startoffset)));
   1082 	}
   1083 
   1084 	/* Get rid of our vnodes, except the ifile */
   1085 	drop_vnode_pages(mp, l);
   1086 	DLOG((DLOG_RF, "LFS roll forward complete\n"));
   1087 	printf("%s: roll forward recovered %d data blocks\n",
   1088 		lfs_sb_getfsmnt(fs), rblkcnt);
   1089 
   1090 	/*
   1091 	 * At this point we have no more changes to write to disk.
   1092 	 * Reset the "avail" count to match the segments as they
   1093 	 * appear on disk, and the clean segment count.
   1094 	 */
   1095 	lfs_reset_avail(fs);
   1096 }
   1097 
   1098 static bool
   1099 all_selector(void *cl, struct vnode *vp)
   1100 {
   1101 	return true;
   1102 }
   1103 
   1104 /*
   1105  * Dump any pages from vnodes that may have been put on
   1106  * during truncation.
   1107  */
   1108 static void
   1109 drop_vnode_pages(struct mount *mp, struct lwp *l)
   1110 {
   1111        struct vnode_iterator *marker;
   1112        struct lfs *fs;
   1113        struct vnode *vp;
   1114 
   1115        fs = VFSTOULFS(mp)->um_lfs;
   1116        vfs_vnode_iterator_init(mp, &marker);
   1117        while ((vp = vfs_vnode_iterator_next(marker,
   1118                all_selector, NULL)) != NULL) {
   1119                if (vp == fs->lfs_ivnode)
   1120                        continue;
   1121                VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY);
   1122                uvm_vnp_setsize(vp, 0);
   1123                uvm_vnp_setsize(vp, VTOI(vp)->i_size);
   1124                VOP_UNLOCK(vp);
   1125                vrele(vp);
   1126        }
   1127        vfs_vnode_iterator_destroy(marker);
   1128 }
   1129