xref: /openbsd-src/sbin/fsck_ffs/pass5.c (revision f6e4162f05818bbc182b2d0e7e8682ece0079a77)
1*f6e4162fSjsg /*	$OpenBSD: pass5.c,v 1.52 2024/09/15 07:14:58 jsg Exp $	*/
287304b87Stholo /*	$NetBSD: pass5.c,v 1.16 1996/09/27 22:45:18 christos Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*
5df930be7Sderaadt  * Copyright (c) 1980, 1986, 1993
6df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
9df930be7Sderaadt  * modification, are permitted provided that the following conditions
10df930be7Sderaadt  * are met:
11df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
12df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
13df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
14df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
15df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
161ef0d710Smillert  * 3. Neither the name of the University nor the names of its contributors
17df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
18df930be7Sderaadt  *    without specific prior written permission.
19df930be7Sderaadt  *
20df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30df930be7Sderaadt  * SUCH DAMAGE.
31df930be7Sderaadt  */
32df930be7Sderaadt 
3378eb0b7eSderaadt #include <sys/param.h>	/* MAXBSIZE roundup setbit */
34df930be7Sderaadt #include <sys/time.h>
35a4df0321Sderaadt #include <sys/lock.h>
36fb77a10bSderaadt #include <sys/ucred.h>
37df930be7Sderaadt #include <ufs/ffs/fs.h>
38a4df0321Sderaadt #include <ufs/ufs/quota.h>
39a4df0321Sderaadt #include <ufs/ufs/inode.h>
40a4df0321Sderaadt #include <ufs/ffs/ffs_extern.h>
41af9e537cSd #include <stdio.h>
42df930be7Sderaadt #include <string.h>
43b9fc9a72Sderaadt #include <limits.h>
4487304b87Stholo 
4587304b87Stholo #include "fsutil.h"
46df930be7Sderaadt #include "fsck.h"
47df930be7Sderaadt #include "extern.h"
48df930be7Sderaadt 
49b9fc9a72Sderaadt #define MINIMUM(a, b)	(((a) < (b)) ? (a) : (b))
50b9fc9a72Sderaadt 
51abbb3558Sotto static u_int info_cg;
52abbb3558Sotto static u_int info_maxcg;
53af9e537cSd 
54af9e537cSd static int
55379d1969Sderaadt pass5_info(char *buf, size_t buflen)
56af9e537cSd {
57abbb3558Sotto 	return (snprintf(buf, buflen, "phase 5, cg %u/%u",
58f3039facSmillert 	    info_cg, info_maxcg) > 0);
59af9e537cSd }
60af9e537cSd 
61df930be7Sderaadt void
6260d6b16fSgluk pass5(void)
63df930be7Sderaadt {
64abbb3558Sotto 	int blk, frags, basesize, sumsize, mapsize, savednrpos=0;
65abbb3558Sotto 	u_int c;
66767b3369Sart 	int inomapsize, blkmapsize;
67e073c79dSmpech 	struct fs *fs = &sblock;
681abdbfdeSderaadt 	daddr_t dbase, dmax;
691abdbfdeSderaadt 	daddr_t d;
70*f6e4162fSjsg 	long i, rewritecg = 0;
71abbb3558Sotto 	ino_t j;
72df930be7Sderaadt 	struct csum *cs;
732fffe0e0Smillert 	struct csum_total cstotal;
74df930be7Sderaadt 	struct inodesc idesc[3];
75df930be7Sderaadt 	char buf[MAXBSIZE];
76e073c79dSmpech 	struct cg *newcg = (struct cg *)buf;
77df930be7Sderaadt 	struct ocg *ocg = (struct ocg *)buf;
782062fcb1Sotto 	struct cg *cg;
792062fcb1Sotto 	struct bufarea *cgbp;
80df930be7Sderaadt 
81df930be7Sderaadt 	memset(newcg, 0, (size_t)fs->fs_cgsize);
82df930be7Sderaadt 	if (cvtlevel >= 3) {
83df930be7Sderaadt 		if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
84df930be7Sderaadt 			if (preen)
85df930be7Sderaadt 				pwarn("DELETING CLUSTERING MAPS\n");
86df930be7Sderaadt 			if (preen || reply("DELETE CLUSTERING MAPS")) {
87df930be7Sderaadt 				fs->fs_contigsumsize = 0;
88ef3a5fb0Sotto 				rewritecg = 1;
89df930be7Sderaadt 				sbdirty();
90df930be7Sderaadt 			}
91df930be7Sderaadt 		}
92df930be7Sderaadt 		if (fs->fs_maxcontig > 1) {
93df930be7Sderaadt 			char *doit = 0;
94df930be7Sderaadt 
95df930be7Sderaadt 			if (fs->fs_contigsumsize < 1) {
96df930be7Sderaadt 				doit = "CREAT";
97df930be7Sderaadt 			} else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
98df930be7Sderaadt 				   fs->fs_contigsumsize < FS_MAXCONTIG) {
99df930be7Sderaadt 				doit = "EXPAND";
100df930be7Sderaadt 			}
101df930be7Sderaadt 			if (doit) {
102df930be7Sderaadt 				i = fs->fs_contigsumsize;
103df930be7Sderaadt 				fs->fs_contigsumsize =
104b9fc9a72Sderaadt 				    MINIMUM(fs->fs_maxcontig, FS_MAXCONTIG);
105df930be7Sderaadt 				if (CGSIZE(fs) > fs->fs_bsize) {
106df930be7Sderaadt 					pwarn("CANNOT %s CLUSTER MAPS\n", doit);
107df930be7Sderaadt 					fs->fs_contigsumsize = i;
108df930be7Sderaadt 				} else if (preen ||
109df930be7Sderaadt 				    reply("CREATE CLUSTER MAPS")) {
110df930be7Sderaadt 					if (preen)
111df930be7Sderaadt 						pwarn("%sING CLUSTER MAPS\n",
112df930be7Sderaadt 						    doit);
113df930be7Sderaadt 					fs->fs_cgsize =
114df930be7Sderaadt 					    fragroundup(fs, CGSIZE(fs));
115ef3a5fb0Sotto 					rewritecg = 1;
116df930be7Sderaadt 					sbdirty();
117df930be7Sderaadt 				}
118df930be7Sderaadt 			}
119df930be7Sderaadt 		}
120df930be7Sderaadt 	}
121df930be7Sderaadt 	switch ((int)fs->fs_postblformat) {
122df930be7Sderaadt 
123df930be7Sderaadt 	case FS_42POSTBLFMT:
124df930be7Sderaadt 		basesize = (char *)(&ocg->cg_btot[0]) -
125df930be7Sderaadt 		    (char *)(&ocg->cg_firstfield);
126df930be7Sderaadt 		sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
127df930be7Sderaadt 		mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
128df930be7Sderaadt 			(u_char *)&ocg->cg_iused[0];
129767b3369Sart 		blkmapsize = howmany(fs->fs_fpg, NBBY);
13048475c7eScsapuntz 		inomapsize = sizeof(ocg->cg_iused);
131df930be7Sderaadt 		ocg->cg_magic = CG_MAGIC;
132df930be7Sderaadt 		savednrpos = fs->fs_nrpos;
133df930be7Sderaadt 		fs->fs_nrpos = 8;
134df930be7Sderaadt 		break;
135df930be7Sderaadt 
136df930be7Sderaadt 	case FS_DYNAMICPOSTBLFMT:
1372fffe0e0Smillert 		if (sblock.fs_magic == FS_UFS2_MAGIC) {
138a39d6216Spedro 			newcg->cg_iusedoff = sizeof(struct cg);
1392fffe0e0Smillert 		} else {
140a39d6216Spedro 			newcg->cg_btotoff = sizeof(struct cg);
1412fffe0e0Smillert 			newcg->cg_boff = newcg->cg_btotoff +
1422fffe0e0Smillert 			    fs->fs_cpg * sizeof(int32_t);
1432fffe0e0Smillert 			newcg->cg_iusedoff = newcg->cg_boff + fs->fs_cpg *
1442fffe0e0Smillert 			    fs->fs_nrpos * sizeof(int16_t);
1452fffe0e0Smillert 		}
146d9c15717Smillert 		inomapsize = howmany(fs->fs_ipg, CHAR_BIT);
147d9c15717Smillert 		newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize;
148d9c15717Smillert 		blkmapsize = howmany(fs->fs_fpg, CHAR_BIT);
149d9c15717Smillert 		newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize;
150767b3369Sart 		if (fs->fs_contigsumsize > 0) {
151767b3369Sart 			newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
152df930be7Sderaadt 			    sizeof(int32_t);
153df930be7Sderaadt 			newcg->cg_clustersumoff =
154df930be7Sderaadt 			    roundup(newcg->cg_clustersumoff, sizeof(int32_t));
155df930be7Sderaadt 			newcg->cg_clusteroff = newcg->cg_clustersumoff +
156df930be7Sderaadt 			    (fs->fs_contigsumsize + 1) * sizeof(int32_t);
157df930be7Sderaadt 			newcg->cg_nextfreeoff = newcg->cg_clusteroff +
158d9c15717Smillert 			    howmany(fragstoblks(fs, fs->fs_fpg), CHAR_BIT);
159df930be7Sderaadt 		}
160df930be7Sderaadt 		newcg->cg_magic = CG_MAGIC;
161a39d6216Spedro 		basesize = sizeof(struct cg);
162df930be7Sderaadt 		sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
163df930be7Sderaadt 		mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
164df930be7Sderaadt 		break;
165df930be7Sderaadt 
166df930be7Sderaadt 	default:
167767b3369Sart 		inomapsize = blkmapsize = sumsize = 0;
168df930be7Sderaadt 		errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d\n",
169df930be7Sderaadt 			fs->fs_postblformat);
170df930be7Sderaadt 	}
171df930be7Sderaadt 	memset(&idesc[0], 0, sizeof idesc);
172ef3a5fb0Sotto 	for (i = 0; i < 3; i++)
173df930be7Sderaadt 		idesc[i].id_type = ADDR;
174e9ae94acSotto 	memset(&cstotal, 0, sizeof(struct csum_total));
175d17d36e8Sotto 	dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1);
176d17d36e8Sotto 	for (d = fs->fs_size; d < dmax; d++)
177d17d36e8Sotto 		setbmap(d);
178af9e537cSd 	info_cg = 0;
179af9e537cSd 	info_maxcg = fs->fs_ncg;
180af9e537cSd 	info_fn = pass5_info;
181df930be7Sderaadt 	for (c = 0; c < fs->fs_ncg; c++) {
182af9e537cSd 		info_cg = c;
1832062fcb1Sotto 		cgbp = cglookup(c);
1842062fcb1Sotto 		cg = cgbp->b_un.b_cg;
185df930be7Sderaadt 		if (!cg_chkmagic(cg))
186abbb3558Sotto 			pfatal("CG %u: BAD MAGIC NUMBER\n", c);
187df930be7Sderaadt 		dbase = cgbase(fs, c);
188df930be7Sderaadt 		dmax = dbase + fs->fs_fpg;
1892fffe0e0Smillert 		if (dmax > fs->fs_size)
1902fffe0e0Smillert 			dmax = fs->fs_size;
191df930be7Sderaadt 		newcg->cg_time = cg->cg_time;
19230182ac8Spedro 		newcg->cg_ffs2_time = cg->cg_ffs2_time;
193df930be7Sderaadt 		newcg->cg_cgx = c;
194df930be7Sderaadt 		if (c == fs->fs_ncg - 1)
195df930be7Sderaadt 			newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
196df930be7Sderaadt 		else
197df930be7Sderaadt 			newcg->cg_ncyl = fs->fs_cpg;
198df930be7Sderaadt 		newcg->cg_ndblk = dmax - dbase;
199df930be7Sderaadt 		if (fs->fs_contigsumsize > 0)
200df930be7Sderaadt 			newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
201df930be7Sderaadt 		newcg->cg_cs.cs_ndir = 0;
202df930be7Sderaadt 		newcg->cg_cs.cs_nffree = 0;
203df930be7Sderaadt 		newcg->cg_cs.cs_nbfree = 0;
204df930be7Sderaadt 		newcg->cg_cs.cs_nifree = fs->fs_ipg;
205df930be7Sderaadt 		if (cg->cg_rotor < newcg->cg_ndblk)
206df930be7Sderaadt 			newcg->cg_rotor = cg->cg_rotor;
207df930be7Sderaadt 		else
208df930be7Sderaadt 			newcg->cg_rotor = 0;
209127a5070Spedro 		if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk)
210df930be7Sderaadt 			newcg->cg_frotor = cg->cg_frotor;
211df930be7Sderaadt 		else
212df930be7Sderaadt 			newcg->cg_frotor = 0;
213df930be7Sderaadt 		newcg->cg_irotor = 0;
2142fffe0e0Smillert 		if (fs->fs_magic == FS_UFS1_MAGIC) {
2152fffe0e0Smillert 			newcg->cg_initediblk = 0;
2162fffe0e0Smillert 			newcg->cg_niblk = cg->cg_niblk;
2172fffe0e0Smillert 			if (cg->cg_irotor >= 0 &&
2189456cfd1Sotto 			    cg->cg_irotor < fs->fs_ipg)
2192fffe0e0Smillert 				newcg->cg_irotor = cg->cg_irotor;
2202fffe0e0Smillert 		} else {
2212fffe0e0Smillert 			newcg->cg_ncyl = 0;
222abbb3558Sotto 			if (cg->cg_initediblk > fs->fs_ipg)
2232fffe0e0Smillert 				newcg->cg_initediblk = fs->fs_ipg;
2242fffe0e0Smillert 			else
2252fffe0e0Smillert 				newcg->cg_initediblk = cg->cg_initediblk;
2262fffe0e0Smillert 			newcg->cg_ffs2_niblk = fs->fs_ipg;
2272fffe0e0Smillert 			if (cg->cg_irotor >= 0 &&
2282fffe0e0Smillert 			    cg->cg_irotor < newcg->cg_ffs2_niblk)
2292fffe0e0Smillert 				newcg->cg_irotor = cg->cg_irotor;
2302fffe0e0Smillert 		}
231df930be7Sderaadt 		memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
2322fffe0e0Smillert 		memset(cg_inosused(newcg), 0, (size_t)(mapsize));
233df930be7Sderaadt 		if (fs->fs_postblformat == FS_42POSTBLFMT)
234df930be7Sderaadt 			ocg->cg_magic = CG_MAGIC;
235df930be7Sderaadt 		j = fs->fs_ipg * c;
2364d91232bSotto 		for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
2374aab0ea5Sotto 			switch (GET_ISTATE(j)) {
238df930be7Sderaadt 
239df930be7Sderaadt 			case USTATE:
240df930be7Sderaadt 				break;
241df930be7Sderaadt 
242df930be7Sderaadt 			case DSTATE:
243df930be7Sderaadt 			case DCLEAR:
244df930be7Sderaadt 			case DFOUND:
245df930be7Sderaadt 				newcg->cg_cs.cs_ndir++;
246898bdbabStedu 				/* FALLTHROUGH */
247df930be7Sderaadt 
248df930be7Sderaadt 			case FSTATE:
249df930be7Sderaadt 			case FCLEAR:
250df930be7Sderaadt 				newcg->cg_cs.cs_nifree--;
251df930be7Sderaadt 				setbit(cg_inosused(newcg), i);
252df930be7Sderaadt 				break;
253df930be7Sderaadt 
254df930be7Sderaadt 			default:
255df930be7Sderaadt 				if (j < ROOTINO)
256df930be7Sderaadt 					break;
2573b92bd08Sderaadt 				errexit("BAD STATE %d FOR INODE I=%llu\n",
2583b92bd08Sderaadt 				    GET_ISTATE(j), (unsigned long long)j);
259df930be7Sderaadt 			}
260df930be7Sderaadt 		}
261df930be7Sderaadt 		if (c == 0)
262df930be7Sderaadt 			for (i = 0; i < ROOTINO; i++) {
263df930be7Sderaadt 				setbit(cg_inosused(newcg), i);
264df930be7Sderaadt 				newcg->cg_cs.cs_nifree--;
265df930be7Sderaadt 			}
266df930be7Sderaadt 		for (i = 0, d = dbase;
267df930be7Sderaadt 		     d < dmax;
268df930be7Sderaadt 		     d += fs->fs_frag, i += fs->fs_frag) {
269df930be7Sderaadt 			frags = 0;
270df930be7Sderaadt 			for (j = 0; j < fs->fs_frag; j++) {
2718d1a1c43Sotto 				if (testbmap(d + j))
272df930be7Sderaadt 					continue;
273df930be7Sderaadt 				setbit(cg_blksfree(newcg), i + j);
274df930be7Sderaadt 				frags++;
275df930be7Sderaadt 			}
276df930be7Sderaadt 			if (frags == fs->fs_frag) {
277df930be7Sderaadt 				newcg->cg_cs.cs_nbfree++;
278df930be7Sderaadt 				if (fs->fs_contigsumsize > 0)
279df930be7Sderaadt 					setbit(cg_clustersfree(newcg),
280df930be7Sderaadt 					    i / fs->fs_frag);
281df930be7Sderaadt 			} else if (frags > 0) {
282df930be7Sderaadt 				newcg->cg_cs.cs_nffree += frags;
283df930be7Sderaadt 				blk = blkmap(fs, cg_blksfree(newcg), i);
284df930be7Sderaadt 				ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
285df930be7Sderaadt 			}
286df930be7Sderaadt 		}
287df930be7Sderaadt 		if (fs->fs_contigsumsize > 0) {
288df930be7Sderaadt 			int32_t *sump = cg_clustersum(newcg);
289df930be7Sderaadt 			u_char *mapp = cg_clustersfree(newcg);
290df930be7Sderaadt 			int map = *mapp++;
291df930be7Sderaadt 			int bit = 1;
292df930be7Sderaadt 			int run = 0;
293df930be7Sderaadt 
294df930be7Sderaadt 			for (i = 0; i < newcg->cg_nclusterblks; i++) {
295df930be7Sderaadt 				if ((map & bit) != 0) {
296df930be7Sderaadt 					run++;
297df930be7Sderaadt 				} else if (run != 0) {
298df930be7Sderaadt 					if (run > fs->fs_contigsumsize)
299df930be7Sderaadt 						run = fs->fs_contigsumsize;
300df930be7Sderaadt 					sump[run]++;
301df930be7Sderaadt 					run = 0;
302df930be7Sderaadt 				}
303df930be7Sderaadt 				if ((i & (NBBY - 1)) != (NBBY - 1)) {
304df930be7Sderaadt 					bit <<= 1;
305df930be7Sderaadt 				} else {
306df930be7Sderaadt 					map = *mapp++;
307df930be7Sderaadt 					bit = 1;
308df930be7Sderaadt 				}
309df930be7Sderaadt 			}
310df930be7Sderaadt 			if (run != 0) {
311df930be7Sderaadt 				if (run > fs->fs_contigsumsize)
312df930be7Sderaadt 					run = fs->fs_contigsumsize;
313df930be7Sderaadt 				sump[run]++;
314df930be7Sderaadt 			}
315df930be7Sderaadt 		}
316df930be7Sderaadt 		cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
317df930be7Sderaadt 		cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
318df930be7Sderaadt 		cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
319df930be7Sderaadt 		cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
320df930be7Sderaadt 		cs = &fs->fs_cs(fs, c);
321df930be7Sderaadt 		if (memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0 &&
322df930be7Sderaadt 		    dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
323df930be7Sderaadt 			memcpy(cs, &newcg->cg_cs, sizeof *cs);
324df930be7Sderaadt 			sbdirty();
325df930be7Sderaadt 		}
326ef3a5fb0Sotto 		if (rewritecg) {
327df930be7Sderaadt 			memcpy(cg, newcg, (size_t)fs->fs_cgsize);
3282062fcb1Sotto 			dirty(cgbp);
329df930be7Sderaadt 			continue;
330df930be7Sderaadt 		}
3312fffe0e0Smillert 		if (memcmp(newcg, cg, basesize) &&
332df930be7Sderaadt 		    dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
333df930be7Sderaadt 			memcpy(cg, newcg, (size_t)basesize);
3342062fcb1Sotto 			dirty(cgbp);
335df930be7Sderaadt 		}
336767b3369Sart 		if (memcmp(cg_inosused(newcg), cg_inosused(cg),
337767b3369Sart 			   mapsize) != 0 &&
338767b3369Sart 		    dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
339767b3369Sart 			memmove(cg_inosused(cg), cg_inosused(newcg),
340767b3369Sart 				(size_t)mapsize);
3412062fcb1Sotto 			dirty(cgbp);
342767b3369Sart 		}
343df930be7Sderaadt 	}
344af9e537cSd 	info_fn = NULL;
345df930be7Sderaadt 	if (fs->fs_postblformat == FS_42POSTBLFMT)
346df930be7Sderaadt 		fs->fs_nrpos = savednrpos;
347b8d36929Sotto 
348b8d36929Sotto 	sumsize = sizeof(cstotal) - sizeof(cstotal.cs_spare);
349b8d36929Sotto 	if (memcmp(&cstotal, &fs->fs_cstotal, sumsize) != 0
350df930be7Sderaadt 	    && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
351b8d36929Sotto 		memcpy(&fs->fs_cstotal, &cstotal, sumsize);
352df930be7Sderaadt 		fs->fs_ronly = 0;
353df930be7Sderaadt 		fs->fs_fmod = 0;
354df930be7Sderaadt 		sbdirty();
355df930be7Sderaadt 	}
356df930be7Sderaadt }
357