1 /* $NetBSD: lfs_rfw.c,v 1.45 2026/09/09 22:15:02 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.45 2026/09/09 22:15:02 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 KASSERT(ino > LFS_IFILE_INUM); 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 KASSERT(lbn >= 0); /* no indirect blocks */ 247 KASSERT(ino > LFS_IFILE_INUM); 248 249 DLOG((DLOG_RF, "update_meta: ino %d lbn %d size %d at 0x%jx\n", 250 (int)ino, (int)lbn, (int)size, (uintmax_t)ndaddr)); 251 252 if ((error = lfs_rf_valloc(fs, ino, vers, l, &vp, NULL)) != 0) 253 return error; 254 ip = VTOI(vp); 255 256 /* 257 * If block already exists, note its new location 258 * but do not account it as new. 259 */ 260 ulfs_bmaparray(vp, lbn, &odaddr, &a[0], &num, NULL, NULL); 261 if (odaddr == UNASSIGNED) { 262 if ((error = lfs_balloc(vp, (lbn << lfs_sb_getbshift(fs)), 263 size, NOCRED, 0, &bp)) != 0) { 264 vput(vp); 265 return (error); 266 } 267 /* No need to write, the block is already on disk */ 268 if (bp->b_oflags & BO_DELWRI) { 269 LFS_UNLOCK_BUF(bp); 270 /* Account recovery of the previous version */ 271 lfs_sb_addavail(fs, lfs_btofsb(fs, bp->b_bcount)); 272 } 273 brelse(bp, BC_INVAL); 274 DLOG((DLOG_RF, "balloc ip->i_lfs_effnblks = %d," 275 " lfs_dino_getblocks(fs, ip->i_din) = %d\n", 276 (int)ip->i_lfs_effnblks, 277 (int)lfs_dino_getblocks(fs, ip->i_din))); 278 } else { 279 /* XXX fragextend? */ 280 DLOG((DLOG_RF, "block exists, no balloc\n")); 281 } 282 283 /* 284 * Extend the file, if it is not large enough already. 285 * XXX This is not exactly right, we don't know how much of the 286 * XXX last block is actually used. 287 * 288 * XXX We should be able to encode the actual data length of the 289 * XXX last block in fi_lastlength, since we can infer the 290 * XXX necessary block length from that using a variant of 291 * XXX lfs_blksize(). 292 */ 293 loff = lfs_lblktosize(fs, lbn); 294 if (loff >= (ULFS_NDADDR << lfs_sb_getbshift(fs))) { 295 /* No fragments */ 296 newsize = loff + 1; 297 } else { 298 /* Subtract only a fragment to account for block size */ 299 newsize = loff + size - lfs_fsbtob(fs, 1) + 1; 300 } 301 302 if (ip->i_size < newsize) { 303 DLOG((DLOG_RF, "ino %d size %d -> %d\n", 304 (int)ino, (int)ip->i_size, (int)newsize)); 305 lfs_dino_setsize(fs, ip->i_din, newsize); 306 ip->i_size = newsize; 307 /* 308 * tell vm our new size for the case the inode won't 309 * appear later. 310 */ 311 uvm_vnp_setsize(vp, newsize); 312 } 313 314 lfs_update_single(fs, NULL, vp, lbn, ndaddr, size); 315 316 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, ndaddr), bp); 317 DLOG((DLOG_SU, "seg %jd += %jd for ino %jd" 318 " lbn %jd db 0x%jd (rfw)\n", 319 (intmax_t)lfs_dtosn(fs, ndaddr), 320 (intmax_t)size, 321 (intmax_t)ip->i_number, 322 (intmax_t)lbn, 323 (intmax_t)ndaddr)); 324 sup->su_nbytes += size; 325 LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, ndaddr), bp); 326 327 /* differences here should be due to UNWRITTEN indirect blocks. */ 328 if (vp->v_type != VLNK) { 329 if (!(ip->i_lfs_effnblks >= lfs_dino_getblocks(fs, ip->i_din)) 330 #if 0 331 || !(lfs_lblkno(fs, ip->i_size) > ULFS_NDADDR || 332 ip->i_lfs_effnblks == lfs_dino_getblocks(fs, ip->i_din)) 333 #endif /* 0 */ 334 ) { 335 vprint("vnode", vp); 336 printf("effnblks=%jd dino_getblocks=%jd\n", 337 (intmax_t)ip->i_lfs_effnblks, 338 (intmax_t)lfs_dino_getblocks(fs, ip->i_din)); 339 } 340 KASSERT(ip->i_lfs_effnblks >= lfs_dino_getblocks(fs, ip->i_din)); 341 #if 0 342 KASSERT(lfs_lblkno(fs, ip->i_size) > ULFS_NDADDR || 343 ip->i_lfs_effnblks == lfs_dino_getblocks(fs, ip->i_din)); 344 #endif /* 0 */ 345 } 346 347 #ifdef DEBUG 348 /* Now look again to make sure it worked */ 349 ulfs_bmaparray(vp, lbn, &odaddr, &a[0], &num, NULL, NULL); 350 if (LFS_DBTOFSB(fs, odaddr) != ndaddr) 351 DLOG((DLOG_RF, "update_meta: failed setting ino %jd lbn %jd" 352 " to %jd\n", (intmax_t)ino, (intmax_t)lbn, (intmax_t)ndaddr)); 353 #endif /* DEBUG */ 354 vput(vp); 355 return 0; 356 } 357 358 /* 359 * Copy some the fields of the dinode as needed by update_inoblk(). 360 */ 361 static void 362 update_inoblk_copy_dinode(struct lfs *fs, 363 union lfs_dinode *dstu, const union lfs_dinode *srcu) 364 { 365 if (fs->lfs_is64) { 366 struct lfs64_dinode *dst = &dstu->u_64; 367 const struct lfs64_dinode *src = &srcu->u_64; 368 unsigned i; 369 370 /* 371 * Copy everything but the block pointers and di_blocks. 372 * XXX what about di_extb? 373 */ 374 dst->di_mode = src->di_mode; 375 dst->di_nlink = src->di_nlink; 376 dst->di_uid = src->di_uid; 377 dst->di_gid = src->di_gid; 378 dst->di_blksize = src->di_blksize; 379 dst->di_size = src->di_size; 380 dst->di_atime = src->di_atime; 381 dst->di_mtime = src->di_mtime; 382 dst->di_ctime = src->di_ctime; 383 dst->di_birthtime = src->di_birthtime; 384 dst->di_mtimensec = src->di_mtimensec; 385 dst->di_atimensec = src->di_atimensec; 386 dst->di_ctimensec = src->di_ctimensec; 387 dst->di_birthnsec = src->di_birthnsec; 388 dst->di_gen = src->di_gen; 389 dst->di_kernflags = src->di_kernflags; 390 dst->di_flags = src->di_flags; 391 dst->di_extsize = src->di_extsize; 392 dst->di_modrev = src->di_modrev; 393 dst->di_inumber = src->di_inumber; 394 for (i = 0; i < __arraycount(src->di_spare); i++) { 395 dst->di_spare[i] = src->di_spare[i]; 396 } 397 /* Short symlinks store their data in di_db. */ 398 if ((src->di_mode & LFS_IFMT) == LFS_IFLNK 399 && src->di_size < lfs_sb_getmaxsymlinklen(fs)) { 400 memcpy(dst->di_db, src->di_db, src->di_size); 401 } 402 } else { 403 struct lfs32_dinode *dst = &dstu->u_32; 404 const struct lfs32_dinode *src = &srcu->u_32; 405 406 /* Get mode, link count, size, and times */ 407 memcpy(dst, src, offsetof(struct lfs32_dinode, di_db[0])); 408 409 /* Then the rest, except di_blocks */ 410 dst->di_flags = src->di_flags; 411 dst->di_gen = src->di_gen; 412 dst->di_uid = src->di_uid; 413 dst->di_gid = src->di_gid; 414 dst->di_modrev = src->di_modrev; 415 416 /* Short symlinks store their data in di_db. */ 417 if ((src->di_mode & LFS_IFMT) == LFS_IFLNK 418 && src->di_size < lfs_sb_getmaxsymlinklen(fs)) { 419 memcpy(dst->di_db, src->di_db, src->di_size); 420 } 421 } 422 } 423 424 static int 425 update_inoblk(struct lfs_inofuncarg *lifa) 426 { 427 struct lfs *fs; 428 daddr_t offset; 429 struct lwp *l; 430 struct vnode *devvp, *vp; 431 struct inode *ip; 432 union lfs_dinode *dip; 433 struct buf *dbp, *ibp; 434 int error; 435 IFILE *ifp; 436 unsigned i, num; 437 uint32_t gen; 438 char *buf; 439 ino_t ino; 440 441 fs = lifa->fs; 442 offset = lifa->offset; 443 l = lifa->l; 444 devvp = VTOI(fs->lfs_ivnode)->i_devvp; 445 446 /* 447 * Get the inode, update times and perms. 448 * DO NOT update disk blocks, we do that separately. 449 */ 450 error = bread(devvp, LFS_FSBTODB(fs, offset), lfs_sb_getibsize(fs), 451 0, &dbp); 452 if (error) { 453 DLOG((DLOG_RF, "update_inoblk: bread returned %d\n", error)); 454 return error; 455 } 456 buf = malloc(dbp->b_bcount, M_SEGMENT, M_WAITOK); 457 memcpy(buf, dbp->b_data, dbp->b_bcount); 458 brelse(dbp, BC_AGE); 459 num = LFS_INOPB(fs); 460 for (i = num; i-- > 0; ) { 461 dip = DINO_IN_BLOCK(fs, buf, i); 462 ino = lfs_dino_getinumber(fs, dip); 463 if (ino <= LFS_IFILE_INUM) 464 continue; 465 466 if ((error = raise_maxino(fs, ino)) != 0) 467 continue; 468 469 /* Check generation number */ 470 LFS_IENTRY(ifp, fs, lfs_dino_getinumber(fs, dip), ibp); 471 gen = lfs_if_getversion(fs, ifp); 472 brelse(ibp, 0); 473 if (lfs_dino_getgen(fs, dip) < gen) { 474 continue; 475 } 476 477 /* 478 * This inode is the newest generation. Load it. 479 */ 480 error = lfs_rf_valloc(fs, ino, lfs_dino_getgen(fs, dip), 481 l, &vp, dip); 482 if (error) { 483 DLOG((DLOG_RF, "update_inoblk: lfs_rf_valloc" 484 " returned %d\n", error)); 485 continue; 486 } 487 ip = VTOI(vp); 488 if (lfs_dino_getsize(fs, dip) != ip->i_size 489 && vp->v_type != VLNK) { 490 /* XXX What should we do with symlinks? */ 491 DLOG((DLOG_RF, " ino %jd size %jd -> %jd\n", 492 (intmax_t)ino, 493 (intmax_t)ip->i_size, 494 (intmax_t)lfs_dino_getsize(fs, dip))); 495 lfs_truncate(vp, lfs_dino_getsize(fs, dip), 0, 496 NOCRED); 497 } 498 update_inoblk_copy_dinode(fs, ip->i_din, dip); 499 500 ip->i_flags = lfs_dino_getflags(fs, dip); 501 ip->i_gen = lfs_dino_getgen(fs, dip); 502 ip->i_uid = lfs_dino_getuid(fs, dip); 503 ip->i_gid = lfs_dino_getgid(fs, dip); 504 505 ip->i_mode = lfs_dino_getmode(fs, dip); 506 ip->i_nlink = lfs_dino_getnlink(fs, dip); 507 ip->i_size = lfs_dino_getsize(fs, dip); 508 509 LFS_SET_UINO(ip, IN_CHANGE | IN_UPDATE); 510 511 /* Re-initialize to get type right */ 512 ulfs_vinit(vp->v_mount, lfs_specop_p, lfs_fifoop_p, 513 &vp); 514 515 /* Record change in location and do segment accounting */ 516 lfs_update_iaddr(fs, ip, offset); 517 518 vput(vp); 519 } 520 free(buf, M_SEGMENT); 521 522 return 0; 523 } 524 525 /* 526 * Note the highest generation number of each inode in the Ifile. 527 * This allows us to skip processing data for intermediate versions. 528 */ 529 static int 530 update_inogen(struct lfs_inofuncarg *lifa) 531 { 532 struct lfs *fs; 533 daddr_t offset; 534 struct vnode *devvp; 535 union lfs_dinode *dip; 536 struct buf *dbp, *ibp; 537 int error; 538 IFILE *ifp; 539 unsigned i, num; 540 541 fs = lifa->fs; 542 offset = lifa->offset; 543 devvp = VTOI(fs->lfs_ivnode)->i_devvp; 544 545 /* Read inode block */ 546 error = bread(devvp, LFS_FSBTODB(fs, offset), lfs_sb_getibsize(fs), 547 0, &dbp); 548 if (error) { 549 DLOG((DLOG_RF, "update_inoblk: bread returned %d\n", error)); 550 return error; 551 } 552 553 /* Check each inode against ifile entry */ 554 num = LFS_INOPB(fs); 555 for (i = num; i-- > 0; ) { 556 dip = DINO_IN_BLOCK(fs, dbp->b_data, i); 557 if (lfs_dino_getinumber(fs, dip) == LFS_IFILE_INUM) 558 continue; 559 560 /* Update generation number */ 561 LFS_IENTRY(ifp, fs, lfs_dino_getinumber(fs, dip), ibp); 562 if (lfs_if_getversion(fs, ifp) < lfs_dino_getgen(fs, dip)) 563 lfs_if_setversion(fs, ifp, lfs_dino_getgen(fs, dip)); 564 LFS_WRITEIENTRY(ifp, fs, lfs_dino_getinumber(fs, dip), ibp); 565 if (error) 566 break; 567 } 568 brelse(dbp, 0); 569 570 return error; 571 } 572 573 static int 574 finfo_func_rfw(struct lfs_finfofuncarg *lffa) 575 { 576 struct lfs *fs; 577 FINFO *fip; 578 daddr_t *offsetp; 579 struct lwp *l; 580 int j; 581 size_t size; 582 ino_t ino; 583 584 fs = lffa->fs; 585 fip = lffa->finfop; 586 offsetp = lffa->offsetp; 587 l = lffa->l; 588 size = lfs_sb_getbsize(fs); 589 ino = lfs_fi_getino(fs, fip); 590 LFS_ASSERT_MAXINO(fs, ino); 591 for (j = 0; j < lfs_fi_getnblocks(fs, fip); ++j) { 592 if (j == lfs_fi_getnblocks(fs, fip) - 1) 593 size = lfs_fi_getlastlength(fs, fip); 594 595 /* Account for and update any direct blocks */ 596 if (ino > LFS_IFILE_INUM && 597 lfs_fi_getblock(fs, fip, j) >= 0) { 598 update_meta(fs, ino, 599 lfs_fi_getversion(fs, fip), 600 lfs_fi_getblock(fs, fip, j), 601 *offsetp, size, l); 602 ++rblkcnt; 603 } 604 *offsetp += lfs_btofsb(fs, size); 605 } 606 607 return 0; 608 } 609 610 int 611 lfs_skip_superblock(struct lfs *fs, daddr_t *offsetp) 612 { 613 daddr_t offset; 614 int i; 615 616 /* 617 * If this is segment 0, skip the label. 618 * If the segment has a superblock and we're at the top 619 * of the segment, skip the superblock. 620 */ 621 offset = *offsetp; 622 if (offset == lfs_sb_gets0addr(fs)) { 623 offset += lfs_btofsb(fs, LFS_LABELPAD); 624 } 625 for (i = 0; i < LFS_MAXNUMSB; i++) { 626 if (offset == lfs_sb_getsboff(fs, i)) { 627 offset += lfs_btofsb(fs, LFS_SBPAD); 628 break; 629 } 630 } 631 *offsetp = offset; 632 return 0; 633 } 634 635 /* 636 * Read the partial segment at offset. 637 * 638 * If finfo_func and ino_func are both NULL, check the summary 639 * and data checksums. During roll forward, this must be done in its 640 * entirety before processing any blocks. 641 * 642 * If finfo_func is given, use that to process every file block 643 * in the segment summary. If ino_func is given, use that to process 644 * every inode block. 645 */ 646 int 647 lfs_parse_pseg(struct lfs *fs, daddr_t *offsetp, u_int64_t nextserial, 648 kauth_cred_t cred, int *pseg_flags, struct lwp *l, 649 int (*ino_func)(struct lfs_inofuncarg *), 650 int (*finfo_func)(struct lfs_finfofuncarg *), 651 int flags, void *arg) 652 { 653 struct vnode *devvp; 654 struct buf *bp, *dbp; 655 int error, ninos, i, j; 656 SEGSUM *ssp; 657 daddr_t offset, prevoffset; 658 IINFO *iip; 659 FINFO *fip; 660 size_t size; 661 uint32_t datasum, foundsum; 662 char *buf; 663 struct lfs_inofuncarg lifa; 664 struct lfs_finfofuncarg lffa; 665 666 KASSERT(fs != NULL); 667 KASSERT(offsetp != NULL); 668 669 devvp = VTOI(fs->lfs_ivnode)->i_devvp; 670 671 /* Set up callback arguments */ 672 lifa.fs = fs; 673 /* lifa.offset = offset; */ 674 lifa.cred = cred; 675 lifa.l = l; 676 lifa.buf = malloc(lfs_sb_getbsize(fs), M_SEGMENT, M_WAITOK); 677 678 lifa.arg = arg; 679 680 lffa.fs = fs; 681 /* lffa.offsetp = offsetp; */ 682 /* lffa.finfop = finfop; */ 683 lffa.cred = cred; 684 lffa.l = l; 685 lffa.arg = arg; 686 687 prevoffset = *offsetp; 688 lfs_skip_superblock(fs, offsetp); 689 offset = *offsetp; 690 691 /* Read in the segment summary */ 692 buf = malloc(lfs_sb_getsumsize(fs), M_SEGMENT, M_WAITOK); 693 error = bread(devvp, LFS_FSBTODB(fs, offset), lfs_sb_getsumsize(fs), 694 0, &bp); 695 if (error) 696 goto err; 697 memcpy(buf, bp->b_data, bp->b_bcount); 698 brelse(bp, BC_AGE); 699 700 ssp = (SEGSUM *)buf; 701 702 if (lfs_ss_getmagic(fs, ssp) != SS_MAGIC) { 703 DLOG((DLOG_RF, "Bad magic at 0x%" PRIx64 "\n", 704 offset)); 705 offset = -1; 706 goto err; 707 } 708 709 if (flags & CKSEG_CKSUM) { 710 size_t sumstart; 711 712 sumstart = lfs_ss_getsumstart(fs); 713 if (lfs_ss_getsumsum(fs, ssp) != 714 cksum((char *)ssp + sumstart, 715 lfs_sb_getsumsize(fs) - sumstart)) { 716 DLOG((DLOG_RF, "Sumsum error at 0x%" PRIx64 "\n", 717 offset)); 718 offset = -1; 719 goto err; 720 } 721 } 722 723 #if 0 724 /* 725 * Under normal conditions, we should never be producing 726 * a partial segment with neither inode blocks nor data blocks. 727 * However, these do sometimes appear and they need not 728 * prevent us from continuing. 729 */ 730 if (lfs_ss_getnfinfo(fs, ssp) == 0 && 731 lfs_ss_getninos(fs, ssp) == 0) { 732 DLOG((DLOG_RF, "Empty pseg at 0x%" PRIx64 "\n", 733 offset)); 734 offset = -1; 735 goto err; 736 } 737 #endif /* 0 */ 738 739 if (lfs_sb_getversion(fs) == 1) { 740 if (lfs_ss_getcreate(fs, ssp) < lfs_sb_gettstamp(fs)) { 741 DLOG((DLOG_RF, "Old data at 0x%" PRIx64 "\n", offset)); 742 offset = -1; 743 goto err; 744 } 745 } else { 746 if (nextserial > 0 747 && lfs_ss_getserial(fs, ssp) != nextserial) { 748 DLOG((DLOG_RF, "Serial number at 0x%jx given as 0x%jx," 749 " expected 0x%jx\n", (intmax_t)offset, 750 (intmax_t)lfs_ss_getserial(fs, ssp), 751 (intmax_t)nextserial)); 752 offset = -1; 753 goto err; 754 } 755 if (lfs_ss_getident(fs, ssp) != lfs_sb_getident(fs)) { 756 DLOG((DLOG_RF, "Incorrect fsid (0x%x vs 0x%x) at 0x%" 757 PRIx64 "\n", lfs_ss_getident(fs, ssp), 758 lfs_sb_getident(fs), offset)); 759 offset = -1; 760 goto err; 761 } 762 } 763 764 #ifdef DIAGNOSTIC 765 if (lfs_ss_getnfinfo(fs, ssp) > lfs_sb_getssize(fs) / lfs_sb_getfsize(fs)) { 766 printf("At offset 0x%jx, nfinfo %jd > max frags %jd\n", 767 (intmax_t)offset, 768 (intmax_t)lfs_ss_getnfinfo(fs, ssp), 769 (intmax_t)lfs_sb_getssize(fs) / lfs_sb_getfsize(fs)); 770 } 771 #endif 772 KASSERT(lfs_ss_getnfinfo(fs, ssp) <= lfs_sb_getssize(fs) / lfs_sb_getfsize(fs)); 773 #ifdef DIAGNOSTIC 774 if (lfs_ss_getnfinfo(fs, ssp) > lfs_sb_getfsize(fs) / sizeof(FINFO32)) { 775 printf("At offset 0x%jx, nfinfo %jd > max entries %jd\n", 776 (intmax_t)offset, 777 (intmax_t)lfs_ss_getnfinfo(fs, ssp), 778 (intmax_t)lfs_sb_getssize(fs) / lfs_sb_getfsize(fs)); 779 } 780 #endif 781 KASSERT(lfs_ss_getnfinfo(fs, ssp) <= lfs_sb_getfsize(fs) / sizeof(FINFO32)); 782 783 if (pseg_flags) 784 *pseg_flags = lfs_ss_getflags(fs, ssp); 785 ninos = howmany(lfs_ss_getninos(fs, ssp), LFS_INOPB(fs)); 786 iip = SEGSUM_IINFOSTART(fs, buf); 787 fip = SEGSUM_FINFOBASE(fs, (SEGSUM *)buf); 788 789 /* Handle individual blocks */ 790 foundsum = 0; 791 offset += lfs_btofsb(fs, lfs_sb_getsumsize(fs)); 792 for (i = 0; i < lfs_ss_getnfinfo(fs, ssp) || ninos; ++i) { 793 /* Inode block? */ 794 if (ninos && lfs_ii_getblock(fs, iip) == offset) { 795 if (flags & CKSEG_CKSUM) { 796 /* Read in the head and add to the buffer */ 797 error = bread(devvp, LFS_FSBTODB(fs, offset), 798 lfs_sb_getbsize(fs), 0, &dbp); 799 if (error) { 800 offset = -1; 801 goto err; 802 } 803 foundsum = lfs_cksum_part(dbp->b_data, 804 sizeof(uint32_t), foundsum); 805 brelse(dbp, BC_AGE); 806 } else if (ino_func != NULL) { 807 lifa.offset = offset; 808 error = (*ino_func)(&lifa); 809 if (error != 0) { 810 offset = -1; 811 goto err; 812 } 813 } 814 815 offset += lfs_btofsb(fs, lfs_sb_getibsize(fs)); 816 iip = NEXTLOWER_IINFO(fs, iip); 817 --ninos; 818 --i; /* compensate for ++i in loop header */ 819 continue; 820 } 821 822 /* File block */ 823 size = lfs_sb_getbsize(fs); 824 if (flags & CKSEG_CKSUM) { 825 for (j = 0; j < lfs_fi_getnblocks(fs, fip); ++j) { 826 if (j == lfs_fi_getnblocks(fs, fip) - 1) 827 size = lfs_fi_getlastlength(fs, fip); 828 error = bread(devvp, LFS_FSBTODB(fs, offset), 829 size, 0, &dbp); 830 if (error) { 831 offset = -1; 832 goto err; 833 } 834 foundsum = lfs_cksum_part(dbp->b_data, 835 sizeof(uint32_t), foundsum); 836 brelse(dbp, BC_AGE); 837 offset += lfs_btofsb(fs, size); 838 } 839 } else if (finfo_func != NULL) { 840 lffa.offsetp = &offset; 841 lffa.finfop = fip; 842 (*finfo_func)(&lffa); 843 } else { 844 int n = lfs_fi_getnblocks(fs, fip); 845 size = lfs_fi_getlastlength(fs, fip); 846 offset += lfs_btofsb(fs, lfs_sb_getbsize(fs) * (n - 1) 847 + size); 848 } 849 fip = NEXT_FINFO(fs, fip); 850 } 851 852 /* Checksum the array, compare */ 853 if (flags & CKSEG_CKSUM) { 854 datasum = lfs_ss_getdatasum(fs, ssp); 855 foundsum = lfs_cksum_fold(foundsum); 856 if (datasum != foundsum) { 857 DLOG((DLOG_RF, "Datasum error at 0x%" PRIx64 858 " (wanted %x got %x)\n", 859 offset, datasum, foundsum)); 860 offset = -1; 861 goto err; 862 } 863 } else { 864 /* Don't clog the buffer queue */ 865 mutex_enter(&lfs_lock); 866 if (locked_queue_count > LFS_MAX_BUFS || 867 locked_queue_bytes > LFS_MAX_BYTES) { 868 lfs_flush(fs, SEGM_CKP, 0); 869 } 870 mutex_exit(&lfs_lock); 871 } 872 873 /* 874 * If we're at the end of the segment, move to the next. 875 * A partial segment needs space for a segment header (1 fsb) 876 * and a full block ("frag" fsb). Thus, adding "frag" fsb should 877 * still be within the current segment (whereas frag + 1 might 878 * be at the start of the next segment). 879 * 880 * This needs to match the definition of LFS_PARTIAL_FITS 881 * in lfs_segment.c. 882 */ 883 if (lfs_dtosn(fs, offset + lfs_sb_getfrag(fs)) 884 != lfs_dtosn(fs, offset)) { 885 if (lfs_dtosn(fs, offset) == lfs_dtosn(fs, lfs_ss_getnext(fs, 886 ssp))) { 887 offset = -1; 888 goto err; 889 } 890 offset = lfs_ss_getnext(fs, ssp); 891 DLOG((DLOG_RF, "LFS roll forward: moving to offset 0x%" PRIx64 892 " -> segment %d\n", offset, lfs_dtosn(fs,offset))); 893 } 894 if (flags & CKSEG_AVAIL) 895 lfs_sb_subavail(fs, offset - prevoffset); 896 897 err: 898 free(lifa.buf, M_SEGMENT); 899 free(buf, M_SEGMENT); 900 901 *offsetp = offset; 902 return 0; 903 } 904 905 /* 906 * Roll forward. 907 */ 908 void 909 lfs_roll_forward(struct lfs *fs, struct mount *mp, struct lwp *l) 910 { 911 int flags, dirty; 912 daddr_t startoffset, offset, nextoffset, endpseg; 913 u_int64_t nextserial, startserial, endserial; 914 int sn, curseg; 915 struct proc *p; 916 kauth_cred_t cred; 917 SEGUSE *sup; 918 struct buf *bp; 919 920 p = l ? l->l_proc : NULL; 921 cred = p ? p->p_cred : NOCRED; 922 923 /* 924 * We don't roll forward for v1 filesystems, because 925 * of the danger that the clock was turned back between the last 926 * checkpoint and crash. This would roll forward garbage. 927 * 928 * v2 filesystems don't have this problem because they use a 929 * monotonically increasing serial number instead of a timestamp. 930 */ 931 rblkcnt = 0; 932 if ((lfs_sb_getpflags(fs) & LFS_PF_CLEAN) || !lfs_do_rfw 933 || lfs_sb_getversion(fs) <= 1 || p == NULL) 934 return; 935 936 DLOG((DLOG_RF, "%s: begin roll forward at serial 0x%jx\n", 937 lfs_sb_getfsmnt(fs), (intmax_t)lfs_sb_getserial(fs))); 938 DEBUG_CHECK_FREELIST(fs); 939 940 /* 941 * Phase I: Find the address of the last good partial 942 * segment that was written after the checkpoint. Mark 943 * the segments in question dirty, so they won't be 944 * reallocated. 945 */ 946 endpseg = startoffset = offset = lfs_sb_getoffset(fs); 947 flags = 0x0; 948 DLOG((DLOG_RF, "LFS roll forward phase 1: start at offset 0x%" 949 PRIx64 "\n", offset)); 950 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, offset), bp); 951 if (!(sup->su_flags & SEGUSE_DIRTY)) 952 lfs_sb_subnclean(fs, 1); 953 sup->su_flags |= SEGUSE_DIRTY; 954 LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, offset), bp); 955 956 startserial = lfs_sb_getserial(fs); 957 endserial = nextserial = startserial + 1; 958 nextoffset = offset; 959 while (1) { 960 nextoffset = offset; 961 lfs_parse_pseg(fs, &nextoffset, nextserial, 962 cred, &flags, l, NULL, NULL, CKSEG_CKSUM, NULL); 963 if (nextoffset == -1) 964 break; 965 if (lfs_sntod(fs, offset) != lfs_sntod(fs, nextoffset)) { 966 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, offset), 967 bp); 968 if (!(sup->su_flags & SEGUSE_DIRTY)) 969 lfs_sb_subnclean(fs, 1); 970 sup->su_flags |= SEGUSE_DIRTY; 971 LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, offset), bp); 972 } 973 974 DLOG((DLOG_RF, "LFS roll forward phase 1: offset=0x%jx" 975 " serial=0x%jx\n", (intmax_t)nextoffset, 976 (intmax_t)nextserial)); 977 if (flags & SS_DIROP) { 978 DLOG((DLOG_RF, "lfs_mountfs: dirops at 0x%" 979 PRIx64 "\n", offset)); 980 if (!(flags & SS_CONT)) { 981 DLOG((DLOG_RF, "lfs_mountfs: dirops end " 982 "at 0x%" PRIx64 "\n", offset)); 983 } 984 } 985 offset = nextoffset; 986 ++nextserial; 987 988 if (!(flags & SS_CONT)) { 989 endpseg = nextoffset; 990 endserial = nextserial; 991 } 992 if (lfs_rfw_max_psegs > 0 993 && nextserial > startserial + lfs_rfw_max_psegs) 994 break; 995 } 996 if (flags & SS_CONT) { 997 DLOG((DLOG_RF, "LFS roll forward: warning: incomplete " 998 "dirops discarded (0x%jx < 0x%jx)\n", 999 endpseg, nextoffset)); 1000 } 1001 if (lfs_sb_getversion(fs) > 1) 1002 lfs_sb_setserial(fs, endserial); 1003 DLOG((DLOG_RF, "LFS roll forward phase 1: completed: " 1004 "endpseg=0x%" PRIx64 "\n", endpseg)); 1005 offset = startoffset; 1006 if (offset != endpseg) { 1007 /* Don't overwrite what we're trying to preserve */ 1008 lfs_sb_setoffset(fs, endpseg); 1009 lfs_sb_setcurseg(fs, lfs_sntod(fs, lfs_dtosn(fs, endpseg))); 1010 for (sn = curseg = lfs_dtosn(fs, lfs_sb_getcurseg(fs));;) { 1011 sn = (sn + 1) % lfs_sb_getnseg(fs); 1012 /* XXX could we just fail to roll forward? */ 1013 if (sn == curseg) 1014 panic("lfs_mountfs: no clean segments"); 1015 LFS_SEGENTRY(sup, fs, sn, bp); 1016 dirty = (sup->su_flags & SEGUSE_DIRTY); 1017 brelse(bp, 0); 1018 if (!dirty) 1019 break; 1020 } 1021 lfs_sb_setnextseg(fs, lfs_sntod(fs, sn)); 1022 /* Explicitly set this segment dirty */ 1023 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, endpseg), bp); 1024 sup->su_flags |= SEGUSE_DIRTY | SEGUSE_ACTIVE; 1025 LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, endpseg), bp); 1026 1027 /* 1028 * Phase II: Identify the highest generation of each 1029 * inode. We will ignore inodes and data blocks 1030 * belonging to old versions. 1031 */ 1032 offset = startoffset; 1033 nextserial = startserial + 1; 1034 DLOG((DLOG_RF, "LFS roll forward phase 2 beginning\n")); 1035 while (offset > 0 && offset != endpseg) { 1036 lfs_parse_pseg(fs, &offset, nextserial++, cred, 1037 NULL, l, update_inogen, NULL, 1038 CKSEG_NONE, NULL); 1039 DEBUG_CHECK_FREELIST(fs); 1040 } 1041 1042 /* 1043 * Phase III: Update inodes. 1044 */ 1045 offset = startoffset; 1046 nextserial = startserial + 1; 1047 DLOG((DLOG_RF, "LFS roll forward phase 3 beginning\n")); 1048 while (offset > 0 && offset != endpseg) { 1049 lfs_parse_pseg(fs, &offset, nextserial++, cred, 1050 NULL, l, update_inoblk, NULL, 1051 CKSEG_NONE, NULL); 1052 DEBUG_CHECK_FREELIST(fs); 1053 } 1054 1055 /* 1056 * Phase IV: Roll forward, updating data blocks. 1057 */ 1058 offset = startoffset; 1059 nextserial = startserial + 1; 1060 DLOG((DLOG_RF, "LFS roll forward phase 4 beginning\n")); 1061 while (offset > 0 && offset != endpseg) { 1062 lfs_parse_pseg(fs, &offset, nextserial++, cred, 1063 NULL, l, NULL, finfo_func_rfw, 1064 CKSEG_AVAIL, NULL); 1065 DEBUG_CHECK_FREELIST(fs); 1066 } 1067 1068 /* 1069 * Finish: flush our changes to disk. 1070 */ 1071 lfs_sb_setserial(fs, endserial); 1072 1073 lfs_segwrite(mp, SEGM_CKP | SEGM_SYNC); 1074 DLOG((DLOG_RF, "lfs_mountfs: roll forward " 1075 "examined %jd blocks\n", 1076 (intmax_t)(endpseg - startoffset))); 1077 } 1078 1079 /* Get rid of our vnodes, except the ifile */ 1080 drop_vnode_pages(mp, l); 1081 DLOG((DLOG_RF, "LFS roll forward complete\n")); 1082 printf("%s: roll forward recovered %d data blocks\n", 1083 lfs_sb_getfsmnt(fs), rblkcnt); 1084 1085 /* 1086 * At this point we have no more changes to write to disk. 1087 * Reset the "avail" count to match the segments as they 1088 * appear on disk, and the clean segment count. 1089 */ 1090 lfs_reset_avail(fs); 1091 } 1092 1093 static bool 1094 all_selector(void *cl, struct vnode *vp) 1095 { 1096 return true; 1097 } 1098 1099 /* 1100 * Dump any pages from vnodes that may have been put on 1101 * during truncation. 1102 */ 1103 static void 1104 drop_vnode_pages(struct mount *mp, struct lwp *l) 1105 { 1106 struct vnode_iterator *marker; 1107 struct lfs *fs; 1108 struct vnode *vp; 1109 1110 fs = VFSTOULFS(mp)->um_lfs; 1111 vfs_vnode_iterator_init(mp, &marker); 1112 while ((vp = vfs_vnode_iterator_next(marker, 1113 all_selector, NULL)) != NULL) { 1114 if (vp == fs->lfs_ivnode) 1115 continue; 1116 VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY); 1117 uvm_vnp_setsize(vp, 0); 1118 uvm_vnp_setsize(vp, VTOI(vp)->i_size); 1119 VOP_UNLOCK(vp); 1120 vrele(vp); 1121 } 1122 vfs_vnode_iterator_destroy(marker); 1123 } 1124