1 1.38 perseant /* $NetBSD: pass5.c,v 1.38 2025/09/14 19:14:30 perseant Exp $ */ 2 1.4 perseant 3 1.4 perseant /*- 4 1.12 perseant * Copyright (c) 2000, 2003 The NetBSD Foundation, Inc. 5 1.4 perseant * All rights reserved. 6 1.4 perseant * 7 1.4 perseant * This code is derived from software contributed to The NetBSD Foundation 8 1.4 perseant * by Konrad E. Schroder <perseant (at) hhhh.org>. 9 1.4 perseant * 10 1.4 perseant * Redistribution and use in source and binary forms, with or without 11 1.4 perseant * modification, are permitted provided that the following conditions 12 1.4 perseant * are met: 13 1.4 perseant * 1. Redistributions of source code must retain the above copyright 14 1.4 perseant * notice, this list of conditions and the following disclaimer. 15 1.4 perseant * 2. Redistributions in binary form must reproduce the above copyright 16 1.4 perseant * notice, this list of conditions and the following disclaimer in the 17 1.4 perseant * documentation and/or other materials provided with the distribution. 18 1.4 perseant * 19 1.4 perseant * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.4 perseant * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.4 perseant * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.4 perseant * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.4 perseant * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.4 perseant * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.4 perseant * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.4 perseant * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.4 perseant * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.4 perseant * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.4 perseant * POSSIBILITY OF SUCH DAMAGE. 30 1.4 perseant */ 31 1.1 perseant 32 1.12 perseant #include <sys/types.h> 33 1.1 perseant #include <sys/param.h> 34 1.1 perseant #include <sys/time.h> 35 1.12 perseant #include <sys/buf.h> 36 1.12 perseant #include <sys/mount.h> 37 1.12 perseant 38 1.26 dholland #define vnode uvnode 39 1.3 perseant #include <ufs/lfs/lfs.h> 40 1.32 dholland #include <ufs/lfs/lfs_accessors.h> 41 1.27 dholland #include <ufs/lfs/lfs_inode.h> 42 1.12 perseant #undef vnode 43 1.3 perseant 44 1.1 perseant #include <string.h> 45 1.12 perseant 46 1.12 perseant #include "bufcache.h" 47 1.17 christos #include "lfs_user.h" 48 1.12 perseant 49 1.1 perseant #include "fsck.h" 50 1.1 perseant #include "extern.h" 51 1.3 perseant #include "fsutil.h" 52 1.3 perseant 53 1.1 perseant void 54 1.14 xtraeme pass5(void) 55 1.1 perseant { 56 1.12 perseant SEGUSE *su; 57 1.13 yamt struct ubuf *bp; 58 1.38 perseant int i, nsb, curr, labelcorrect, mfs; 59 1.33 dholland daddr_t bb; /* total number of used blocks (lower bound) */ 60 1.33 dholland daddr_t ubb; /* upper bound number of used blocks */ 61 1.33 dholland daddr_t avail; /* blocks available for writing */ 62 1.12 perseant unsigned long dmeta; /* blocks in segsums and inodes */ 63 1.12 perseant int nclean; /* clean segments */ 64 1.12 perseant size_t labelskew; 65 1.12 perseant int diddirty; 66 1.3 perseant 67 1.3 perseant /* 68 1.3 perseant * Check segment holdings against actual holdings. Check for 69 1.16 perseant * "clean" segments that contain live data. If we are only 70 1.16 perseant * rolling forward, we can't check the segment holdings, but 71 1.16 perseant * we can still check the cleanerinfo data. 72 1.3 perseant */ 73 1.7 perseant nclean = 0; 74 1.6 perseant avail = 0; 75 1.6 perseant bb = ubb = 0; 76 1.8 perseant dmeta = 0; 77 1.38 perseant nsb = curr = labelcorrect = mfs = 0; 78 1.31 dholland for (i = 0; i < lfs_sb_getnseg(fs); i++) { 79 1.12 perseant diddirty = 0; 80 1.12 perseant LFS_SEGENTRY(su, fs, i, bp); 81 1.16 perseant if (!preen && !(su->su_flags & SEGUSE_DIRTY) && 82 1.4 perseant seg_table[i].su_nbytes > 0) { 83 1.21 perseant pwarn("CLEAN SEGMENT %d CONTAINS %d BYTES\n", 84 1.19 perseant i, seg_table[i].su_nbytes); 85 1.18 perseant if (reply("MARK SEGMENT DIRTY")) { 86 1.3 perseant su->su_flags |= SEGUSE_DIRTY; 87 1.12 perseant ++diddirty; 88 1.3 perseant } 89 1.3 perseant } 90 1.21 perseant if (!preen && su->su_nbytes != seg_table[i].su_nbytes) { 91 1.18 perseant pwarn("SEGMENT %d CLAIMS %d BYTES BUT HAS %d", 92 1.12 perseant i, su->su_nbytes, seg_table[i].su_nbytes); 93 1.12 perseant if ((int32_t)su->su_nbytes > 94 1.12 perseant (int32_t)seg_table[i].su_nbytes) 95 1.18 perseant pwarn(" (HIGH BY %d)\n", su->su_nbytes - 96 1.12 perseant seg_table[i].su_nbytes); 97 1.5 perseant else 98 1.18 perseant pwarn(" (LOW BY %d)\n", -su->su_nbytes + 99 1.12 perseant seg_table[i].su_nbytes); 100 1.18 perseant if (reply("FIX")) { 101 1.3 perseant su->su_nbytes = seg_table[i].su_nbytes; 102 1.12 perseant ++diddirty; 103 1.1 perseant } 104 1.1 perseant } 105 1.6 perseant if (su->su_flags & SEGUSE_DIRTY) { 106 1.28 christos bb += lfs_btofsb(fs, su->su_nbytes + 107 1.31 dholland su->su_nsums * lfs_sb_getsumsize(fs)); 108 1.28 christos ubb += lfs_btofsb(fs, su->su_nbytes + 109 1.31 dholland su->su_nsums * lfs_sb_getsumsize(fs) + 110 1.31 dholland su->su_ninos * lfs_sb_getibsize(fs)); 111 1.28 christos dmeta += lfs_btofsb(fs, 112 1.31 dholland lfs_sb_getsumsize(fs) * su->su_nsums); 113 1.28 christos dmeta += lfs_btofsb(fs, 114 1.31 dholland lfs_sb_getibsize(fs) * su->su_ninos); 115 1.6 perseant } else { 116 1.7 perseant nclean++; 117 1.28 christos avail += lfs_segtod(fs, 1); 118 1.6 perseant if (su->su_flags & SEGUSE_SUPERBLOCK) 119 1.38 perseant ++nsb; 120 1.34 dholland if (i == 0 && lfs_sb_getversion(fs) > 1 && 121 1.31 dholland lfs_sb_gets0addr(fs) < lfs_btofsb(fs, LFS_LABELPAD)) 122 1.38 perseant labelcorrect = lfs_btofsb(fs, LFS_LABELPAD) - 123 1.31 dholland lfs_sb_gets0addr(fs); 124 1.6 perseant } 125 1.12 perseant if (diddirty) 126 1.12 perseant VOP_BWRITE(bp); 127 1.12 perseant else 128 1.23 ad brelse(bp, 0); 129 1.6 perseant } 130 1.12 perseant 131 1.6 perseant /* Also may be available bytes in current seg */ 132 1.30 dholland i = lfs_dtosn(fs, lfs_sb_getoffset(fs)); 133 1.38 perseant curr = lfs_sntod(fs, i + 1) - lfs_sb_getoffset(fs); 134 1.6 perseant /* But do not count minfreesegs */ 135 1.38 perseant mfs = lfs_segtod(fs, (lfs_sb_getminfreeseg(fs) - 136 1.38 perseant (lfs_sb_getminfreeseg(fs) / 2))); 137 1.38 perseant 138 1.38 perseant avail = nclean * lfs_segtod(fs, 1); 139 1.38 perseant avail -= nsb * lfs_btofsb(fs, LFS_SBPAD); 140 1.38 perseant avail -= labelcorrect; 141 1.38 perseant avail += curr; 142 1.38 perseant avail -= mfs; 143 1.38 perseant 144 1.12 perseant /* Note we may have bytes to write yet */ 145 1.28 christos avail -= lfs_btofsb(fs, locked_queue_bytes); 146 1.12 perseant 147 1.38 perseant if (debug) 148 1.38 perseant pwarn("avail := clean %jd*%jd - sb %jd*%jd - lbl %jd" 149 1.38 perseant "+ curr %jd - mfs %jd - locked %jd = %jd\n", 150 1.38 perseant (intmax_t)nclean, 151 1.38 perseant (intmax_t)lfs_segtod(fs, 1), 152 1.38 perseant (intmax_t)nsb, 153 1.38 perseant (intmax_t)lfs_btofsb(fs, LFS_SBPAD), 154 1.38 perseant (intmax_t)labelcorrect, 155 1.38 perseant (intmax_t)curr, 156 1.38 perseant (intmax_t)mfs, 157 1.38 perseant (intmax_t)lfs_btofsb(fs, locked_queue_bytes), 158 1.38 perseant (intmax_t)avail); 159 1.38 perseant 160 1.15 perseant if (idaddr) 161 1.16 perseant pwarn("NOTE: when using -i, expect discrepancies in dmeta," 162 1.16 perseant " avail, nclean, bfree\n"); 163 1.31 dholland if (dmeta != lfs_sb_getdmeta(fs)) { 164 1.31 dholland pwarn("DMETA GIVEN AS %d, SHOULD BE %ld\n", 165 1.31 dholland lfs_sb_getdmeta(fs), dmeta); 166 1.18 perseant if (preen || reply("FIX")) { 167 1.31 dholland lfs_sb_setdmeta(fs, dmeta); 168 1.12 perseant sbdirty(); 169 1.12 perseant } 170 1.8 perseant } 171 1.38 perseant if (avail != lfs_sb_getavail(fs) && !aflag) { 172 1.35 dholland pwarn("AVAIL GIVEN AS %jd, SHOULD BE %jd\n", 173 1.35 dholland (intmax_t)lfs_sb_getavail(fs), (intmax_t)avail); 174 1.18 perseant if (preen || reply("FIX")) { 175 1.30 dholland lfs_sb_setavail(fs, avail); 176 1.7 perseant sbdirty(); 177 1.7 perseant } 178 1.7 perseant } 179 1.31 dholland if (nclean != lfs_sb_getnclean(fs)) { 180 1.31 dholland pwarn("NCLEAN GIVEN AS %d, SHOULD BE %d\n", lfs_sb_getnclean(fs), 181 1.12 perseant nclean); 182 1.18 perseant if (preen || reply("FIX")) { 183 1.31 dholland lfs_sb_setnclean(fs, nclean); 184 1.6 perseant sbdirty(); 185 1.6 perseant } 186 1.6 perseant } 187 1.12 perseant 188 1.11 perseant labelskew = 0; 189 1.34 dholland if (lfs_sb_getversion(fs) > 1 && 190 1.31 dholland lfs_sb_gets0addr(fs) < lfs_btofsb(fs, LFS_LABELPAD)) 191 1.28 christos labelskew = lfs_btofsb(fs, LFS_LABELPAD); 192 1.30 dholland if (lfs_sb_getbfree(fs) > lfs_sb_getdsize(fs) - bb - labelskew || 193 1.30 dholland lfs_sb_getbfree(fs) < lfs_sb_getdsize(fs) - ubb - labelskew) { 194 1.33 dholland pwarn("BFREE GIVEN AS %jd, SHOULD BE BETWEEN %jd AND %jd\n", 195 1.30 dholland (intmax_t)lfs_sb_getbfree(fs), 196 1.33 dholland (intmax_t)(lfs_sb_getdsize(fs) - ubb - labelskew), 197 1.33 dholland (intmax_t)(lfs_sb_getdsize(fs) - bb - labelskew)); 198 1.18 perseant if (preen || reply("FIX")) { 199 1.30 dholland lfs_sb_setbfree(fs, 200 1.30 dholland ((lfs_sb_getdsize(fs) - labelskew - ubb) + 201 1.30 dholland lfs_sb_getdsize(fs) - labelskew - bb) / 2); 202 1.6 perseant sbdirty(); 203 1.6 perseant } 204 1.1 perseant } 205 1.1 perseant } 206