140939Sdes/*	$NetBSD: pass5.c,v 1.48 2008/02/23 21:41:48 christos Exp $	*/
240939Sdes
340939Sdes/*
440939Sdes * Copyright (c) 1980, 1986, 1993
540939Sdes *	The Regents of the University of California.  All rights reserved.
640939Sdes *
740939Sdes * Redistribution and use in source and binary forms, with or without
840939Sdes * modification, are permitted provided that the following conditions
940939Sdes * are met:
1040939Sdes * 1. Redistributions of source code must retain the above copyright
1140939Sdes *    notice, this list of conditions and the following disclaimer.
1240939Sdes * 2. Redistributions in binary form must reproduce the above copyright
1340939Sdes *    notice, this list of conditions and the following disclaimer in the
1440939Sdes *    documentation and/or other materials provided with the distribution.
1540939Sdes * 3. Neither the name of the University nor the names of its contributors
1640939Sdes *    may be used to endorse or promote products derived from this software
1740939Sdes *    without specific prior written permission.
1840939Sdes *
1940939Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2040939Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2140939Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2240939Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2340939Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2440939Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2540939Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2640939Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2740939Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2840939Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2984203Sdillon * SUCH DAMAGE.
3084203Sdillon */
3184203Sdillon
3241862Sdes#include <sys/cdefs.h>
3340939Sdes#ifndef lint
3455557Sdes#if 0
3562981Sdesstatic char sccsid[] = "@(#)pass5.c	8.9 (Berkeley) 4/28/95";
3640939Sdes#else
3740939Sdes__RCSID("$NetBSD: pass5.c,v 1.48 2008/02/23 21:41:48 christos Exp $");
3840939Sdes#endif
3940939Sdes#endif /* not lint */
4060924Sdes
4141862Sdes#include <sys/param.h>
4241862Sdes#include <sys/time.h>
4340939Sdes
4440939Sdes#include <ufs/ufs/dinode.h>
4540939Sdes#include <ufs/ffs/fs.h>
4640939Sdes#include <ufs/ffs/ffs_extern.h>
4740939Sdes#include <ufs/ufs/ufs_bswap.h>
4840939Sdes
4940975Sdes#include <err.h>
5040939Sdes#include <string.h>
5140939Sdes#include <malloc.h>
5240939Sdes
5340939Sdes#include "fsutil.h"
5440939Sdes#include "fsck.h"
5540939Sdes#include "extern.h"
5690267Sdes
5790267Sdesvoid print_bmap(u_char *,u_int32_t);
5890267Sdes
5990267Sdesvoid
6090267Sdespass5(void)
6140939Sdes{
6240939Sdes	int c, blk, frags, basesize, sumsize, mapsize, cssize;
6362981Sdes	int inomapsize, blkmapsize;
6475891Sarchie	struct fs *fs = sblock;
6540939Sdes	daddr_t dbase, dmax;
6662981Sdes	daddr_t d;
6740939Sdes	long i, j, k;
6840939Sdes	struct csum *cs;
6940939Sdes	struct csum_total cstotal;
7040939Sdes	struct inodesc idesc[4];
7140939Sdes	char buf[MAXBSIZE];
7260924Sdes	struct cg *newcg = (struct cg *)buf;
7340975Sdes	struct ocg *ocg = (struct ocg *)buf;
7440939Sdes	struct cg *cg = cgrp, *ncg;
7590267Sdes	struct inostat *info;
7690267Sdes	u_int32_t ncgsize;
7790267Sdes
7840939Sdes	inoinfo(WINO)->ino_state = USTATE;
7940939Sdes	memset(newcg, 0, (size_t)fs->fs_cgsize);
8040939Sdes	newcg->cg_niblk = fs->fs_ipg;
8140939Sdes	if (cvtlevel >= 3) {
8240939Sdes		if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
8340939Sdes			if (preen)
8440939Sdes				pwarn("DELETING CLUSTERING MAPS\n");
8540939Sdes			if (preen || reply("DELETE CLUSTERING MAPS")) {
8690267Sdes				fs->fs_contigsumsize = 0;
8790267Sdes				doinglevel1 = 1;
8890267Sdes				sbdirty();
8940939Sdes			}
9040939Sdes		}
9140939Sdes		if (fs->fs_maxcontig > 1) {
9240939Sdes			const char *doit = NULL;
9340939Sdes
9440939Sdes			if (fs->fs_contigsumsize < 1) {
9540939Sdes				doit = "CREAT";
9640939Sdes			} else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
9790267Sdes				   fs->fs_contigsumsize < FS_MAXCONTIG) {
9890267Sdes				doit = "EXPAND";
9990267Sdes			}
10090267Sdes			if (doit) {
10190267Sdes				i = fs->fs_contigsumsize;
10290267Sdes				fs->fs_contigsumsize =
10390267Sdes				    MIN(fs->fs_maxcontig, FS_MAXCONTIG);
10490267Sdes				if (CGSIZE(fs) > (uint32_t)fs->fs_bsize) {
10590267Sdes					pwarn("CANNOT %s CLUSTER MAPS\n", doit);
10690267Sdes					fs->fs_contigsumsize = i;
10790267Sdes				} else if (preen ||
10890267Sdes				    reply("CREATE CLUSTER MAPS")) {
10990267Sdes					if (preen)
11090267Sdes						pwarn("%sING CLUSTER MAPS\n",
11190267Sdes						    doit);
11290267Sdes					ncgsize = fragroundup(fs, CGSIZE(fs));
11390267Sdes					ncg = realloc(cgrp, ncgsize);
11490267Sdes					if (ncg == NULL)
11590267Sdes						errexit(
11690267Sdes						"cannot reallocate cg space");
11790267Sdes					cg = cgrp = ncg;
11890267Sdes					fs->fs_cgsize = ncgsize;
11990267Sdes					doinglevel1 = 1;
12090267Sdes					sbdirty();
12190267Sdes				}
12290267Sdes			}
12390267Sdes		}
12490267Sdes	}
12590267Sdes	basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
12690267Sdes	cssize = (u_char *)&cstotal.cs_spare[0] - (u_char *)&cstotal.cs_ndir;
12790267Sdes	sumsize = 0;
12890267Sdes	if (is_ufs2) {
12990267Sdes		newcg->cg_iusedoff = basesize;
13090267Sdes	} else {
13190267Sdes		/*
13290267Sdes		 * We reserve the space for the old rotation summary
13390267Sdes		 * tables for the benefit of old kernels, but do not
13490267Sdes		 * maintain them in modern kernels. In time, they can
13590267Sdes		 * go away.
13690267Sdes		 */
13790267Sdes		newcg->cg_old_btotoff = basesize;
13890267Sdes		newcg->cg_old_boff = newcg->cg_old_btotoff +
13990267Sdes		    fs->fs_old_cpg * sizeof(int32_t);
14090267Sdes		newcg->cg_iusedoff = newcg->cg_old_boff +
14190267Sdes		    fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t);
14290267Sdes		memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize);
14390267Sdes	}
14490267Sdes	inomapsize = howmany(fs->fs_ipg, CHAR_BIT);
14590267Sdes	newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize;
14690267Sdes	blkmapsize = howmany(fs->fs_fpg, CHAR_BIT);
14790267Sdes	newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize;
14840939Sdes	if (fs->fs_contigsumsize > 0) {
14940939Sdes		newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
15040939Sdes		    sizeof(u_int32_t);
15141862Sdes		if (isappleufs) {
15241862Sdes			/* Apple PR2216969 gives rationale for this change.
15341862Sdes			 * I believe they were mistaken, but we need to
15460924Sdes			 * duplicate it for compatibility.  -- dbj@NetBSD.org
15575891Sarchie			 */
15641862Sdes			newcg->cg_clustersumoff += sizeof(u_int32_t);
15790267Sdes		}
15890267Sdes		newcg->cg_clustersumoff =
15990267Sdes		    roundup(newcg->cg_clustersumoff, sizeof(u_int32_t));
16090267Sdes		newcg->cg_clusteroff = newcg->cg_clustersumoff +
16190267Sdes		    (fs->fs_contigsumsize + 1) * sizeof(u_int32_t);
16290267Sdes		newcg->cg_nextfreeoff = newcg->cg_clusteroff +
16341862Sdes		    howmany(fragstoblks(fs, fs->fs_fpg), CHAR_BIT);
16441862Sdes	}
16541862Sdes	newcg->cg_magic = CG_MAGIC;
16640939Sdes	mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
16740939Sdes	if (!is_ufs2 && ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0)) {
16840939Sdes		switch ((int)fs->fs_old_postblformat) {
16968551Sdes
17068551Sdes		case FS_42POSTBLFMT:
17168551Sdes			basesize = (char *)(&ocg->cg_btot[0]) -
17275891Sarchie			    (char *)(&ocg->cg_firstfield);
17368551Sdes			sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
17490267Sdes			mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
17568551Sdes			    (u_char *)&ocg->cg_iused[0];
17690267Sdes			blkmapsize = howmany(fs->fs_fpg, NBBY);
17790267Sdes			inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0];
17890267Sdes			ocg->cg_magic = CG_MAGIC;
17990267Sdes			newcg->cg_magic = 0;
18090267Sdes			break;
18190267Sdes
18290267Sdes		case FS_DYNAMICPOSTBLFMT:
18368551Sdes			sumsize = newcg->cg_iusedoff - newcg->cg_old_btotoff;
18468551Sdes			break;
18568551Sdes
18668551Sdes		default:
18768551Sdes			errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d",
18868551Sdes			    fs->fs_old_postblformat);
18975891Sarchie		}
19068551Sdes	}
19190267Sdes	memset(&idesc[0], 0, sizeof idesc);
19290267Sdes	for (i = 0; i < 4; i++) {
19390267Sdes		idesc[i].id_type = ADDR;
19490267Sdes		if (!is_ufs2 && doinglevel2)
19590267Sdes			idesc[i].id_fix = FIX;
19668551Sdes	}
19768551Sdes	memset(&cstotal, 0, sizeof(struct csum_total));
19898117Sdes	dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1);
19968551Sdes	for (d = fs->fs_size; d < dmax; d++)
20097866Sdes		setbmap(d);
20197866Sdes	for (c = 0; c < fs->fs_ncg; c++) {
20297866Sdes		if (got_siginfo) {
20397866Sdes			fprintf(stderr,
20497866Sdes			    "%s: phase 5: cyl group %d of %d (%d%%)\n",
20597866Sdes			    cdevname(), c, fs->fs_ncg,
20697866Sdes			    c * 100 / fs->fs_ncg);
20797866Sdes			got_siginfo = 0;
20897866Sdes		}
20997866Sdes#ifdef PROGRESS
21097866Sdes		progress_bar(cdevname(), preen ? NULL : "phase 5",
21198117Sdes			    c, fs->fs_ncg);
21297866Sdes#endif /* PROGRESS */
21397866Sdes		getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
21497866Sdes		memcpy(cg, cgblk.b_un.b_cg, fs->fs_cgsize);
21597866Sdes		if((doswap && !needswap) || (!doswap && needswap))
21697866Sdes			ffs_cg_swap(cgblk.b_un.b_cg, cg, sblock);
21798117Sdes		if (!doinglevel1 && !cg_chkmagic(cg, 0))
21898117Sdes			pfatal("CG %d: PASS5: BAD MAGIC NUMBER\n", c);
21998117Sdes		if(doswap)
22098117Sdes			cgdirty();
22198117Sdes		/*
22298117Sdes		 * While we have the disk head where we want it,
22398117Sdes		 * write back the superblock to the spare at this
22498117Sdes		 * cylinder group.
22598117Sdes		 */
22698117Sdes		if ((cvtlevel && sblk.b_dirty) || doswap) {
22798117Sdes			bwrite(fswritefd, sblk.b_un.b_buf,
22898117Sdes			    fsbtodb(sblock, cgsblock(sblock, c)),
22940939Sdes			    sblock->fs_sbsize);
23040939Sdes		} else {
23197856Sdes			/*
23275891Sarchie			 * Read in the current alternate superblock,
23340939Sdes			 * and compare it to the master.  If it's
23497856Sdes			 * wrong, fix it up.
23590267Sdes			 */
23690267Sdes			getblk(&asblk, cgsblock(sblock, c), sblock->fs_sbsize);
23790267Sdes			if (asblk.b_errs)
23840939Sdes				pfatal("CG %d: UNABLE TO READ ALTERNATE "
23990267Sdes				    "SUPERBLK\n", c);
24041862Sdes			else {
24190267Sdes				memmove(altsblock, asblk.b_un.b_fs,
24290267Sdes				    sblock->fs_sbsize);
24340939Sdes				if (needswap)
24490267Sdes					ffs_sb_swap(asblk.b_un.b_fs, altsblock);
24590267Sdes			}
24690267Sdes			sb_oldfscompat_write(sblock, sblocksave);
24790267Sdes			if ((asblk.b_errs || cmpsblks(sblock, altsblock)) &&
24890267Sdes			     dofix(&idesc[3],
24990267Sdes				   "ALTERNATE SUPERBLK(S) ARE INCORRECT")) {
25090267Sdes				bwrite(fswritefd, sblk.b_un.b_buf,
25190267Sdes				    fsbtodb(sblock, cgsblock(sblock, c)),
25297856Sdes				    sblock->fs_sbsize);
25390267Sdes			}
25490267Sdes			sb_oldfscompat_read(sblock, 0);
25590267Sdes		}
25690267Sdes		dbase = cgbase(fs, c);
25790267Sdes		dmax = dbase + fs->fs_fpg;
25890267Sdes		if (dmax > fs->fs_size)
25990267Sdes			dmax = fs->fs_size;
26090267Sdes		if (is_ufs2 || (fs->fs_old_flags & FS_FLAGS_UPDATED))
26162981Sdes			newcg->cg_time = cg->cg_time;
26290267Sdes		newcg->cg_old_time = cg->cg_old_time;
26390267Sdes		newcg->cg_cgx = c;
26490267Sdes		newcg->cg_ndblk = dmax - dbase;
26590267Sdes		if (!is_ufs2) {
26690267Sdes			if (c == fs->fs_ncg - 1) {
26790267Sdes				/* Avoid fighting old fsck for this value.  Its never used
26890267Sdes				 * outside of this check anyway.
26990267Sdes				 */
27090267Sdes				if ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0)
27197856Sdes					newcg->cg_old_ncyl = fs->fs_old_ncyl % fs->fs_old_cpg;
27290267Sdes				else
27340939Sdes					newcg->cg_old_ncyl = howmany(newcg->cg_ndblk,
27497866Sdes					    fs->fs_fpg / fs->fs_old_cpg);
27597856Sdes			} else
27697856Sdes				newcg->cg_old_ncyl = fs->fs_old_cpg;
27740939Sdes			newcg->cg_old_niblk = fs->fs_ipg;
27841989Sdes			newcg->cg_niblk = 0;
27941989Sdes		}
28055557Sdes		if (fs->fs_contigsumsize > 0)
28197868Sdes			newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
28297868Sdes		newcg->cg_cs.cs_ndir = 0;
28397868Sdes		newcg->cg_cs.cs_nffree = 0;
28497868Sdes		newcg->cg_cs.cs_nbfree = 0;
28597868Sdes		newcg->cg_cs.cs_nifree = fs->fs_ipg;
28697868Sdes		if (cg->cg_rotor >= 0 && cg->cg_rotor < newcg->cg_ndblk)
28797891Sdes			newcg->cg_rotor = cg->cg_rotor;
28897868Sdes		else
28997868Sdes			newcg->cg_rotor = 0;
29097868Sdes		if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk)
29197868Sdes			newcg->cg_frotor = cg->cg_frotor;
29297868Sdes		else
29397868Sdes			newcg->cg_frotor = 0;
29497868Sdes		if (cg->cg_irotor >= 0 && cg->cg_irotor < fs->fs_ipg)
29597868Sdes			newcg->cg_irotor = cg->cg_irotor;
29697868Sdes		else
29797868Sdes			newcg->cg_irotor = 0;
29897868Sdes		if (!is_ufs2) {
29997868Sdes			newcg->cg_initediblk = 0;
30097868Sdes		} else {
30197868Sdes			if ((unsigned)cg->cg_initediblk > (unsigned)fs->fs_ipg)
30297868Sdes				newcg->cg_initediblk = fs->fs_ipg;
30397868Sdes			else
30497868Sdes				newcg->cg_initediblk = cg->cg_initediblk;
30597868Sdes		}
30697868Sdes		memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
30797868Sdes		memset(&old_cg_blktot(newcg, 0)[0], 0, (size_t)(sumsize));
30897868Sdes		memset(cg_inosused(newcg, 0), 0, (size_t)(mapsize));
30997868Sdes		if (!is_ufs2 && ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) &&
31097868Sdes		    fs->fs_old_postblformat == FS_42POSTBLFMT)
31197868Sdes			ocg->cg_magic = CG_MAGIC;
31297868Sdes		j = fs->fs_ipg * c;
31397868Sdes		for (i = 0; i < fs->fs_ipg; j++, i++) {
31497868Sdes			info = inoinfo(j);
31597868Sdes			switch (info->ino_state) {
31697868Sdes
31797868Sdes			case USTATE:
31897868Sdes				break;
31997868Sdes
32097868Sdes			case DSTATE:
32197868Sdes			case DCLEAR:
32297868Sdes			case DFOUND:
32397868Sdes				newcg->cg_cs.cs_ndir++;
32497868Sdes				/* fall through */
32597868Sdes
32697868Sdes			case FSTATE:
32797868Sdes			case FCLEAR:
32897891Sdes				newcg->cg_cs.cs_nifree--;
32997891Sdes				setbit(cg_inosused(newcg, 0), i);
33097891Sdes				break;
33197891Sdes
33297891Sdes			default:
33397891Sdes				if ((ino_t)j < ROOTINO)
33497868Sdes					break;
33597868Sdes				errexit("BAD STATE %d FOR INODE I=%ld",
33698117Sdes				    info->ino_state, (long)j);
33797868Sdes			}
33897866Sdes		}
33955557Sdes		if (c == 0)
34097866Sdes			for (i = 0; i < (long)ROOTINO; i++) {
34197866Sdes				setbit(cg_inosused(newcg, 0), i);
34255557Sdes				newcg->cg_cs.cs_nifree--;
34390267Sdes			}
34490267Sdes		for (i = 0, d = dbase;
34597866Sdes		     d < dmax;
34690267Sdes		     d += fs->fs_frag, i += fs->fs_frag) {
34790267Sdes			frags = 0;
34855557Sdes			for (j = 0; j < fs->fs_frag; j++) {
34997866Sdes				if (testbmap(d + j))
35090267Sdes					continue;
35190267Sdes				setbit(cg_blksfree(newcg, 0), i + j);
35255557Sdes				frags++;
35390267Sdes			}
35497866Sdes			if (frags == fs->fs_frag) {
35597866Sdes				newcg->cg_cs.cs_nbfree++;
35697866Sdes				if (sumsize) {
35797856Sdes					j = old_cbtocylno(fs, i);
35890267Sdes					old_cg_blktot(newcg, 0)[j]++;
35990267Sdes					old_cg_blks(fs, newcg, j, 0)[old_cbtorpos(fs, i)]++;
36090267Sdes				}
36190267Sdes				if (fs->fs_contigsumsize > 0)
36290267Sdes					setbit(cg_clustersfree(newcg, 0),
36390267Sdes					    fragstoblks(fs, i));
36490267Sdes			} else if (frags > 0) {
36597866Sdes				newcg->cg_cs.cs_nffree += frags;
36697866Sdes				blk = blkmap(fs, cg_blksfree(newcg, 0), i);
36797866Sdes				ffs_fragacct(fs, blk, newcg->cg_frsum, 1, 0);
36897856Sdes			}
36990267Sdes		}
37090267Sdes		if (fs->fs_contigsumsize > 0) {
37190267Sdes			int32_t *sump = cg_clustersum(newcg, 0);
37290267Sdes			u_char *mapp = cg_clustersfree(newcg, 0);
37390267Sdes			int map = *mapp++;
37490267Sdes			int bit = 1;
37597891Sdes			int run = 0;
37697866Sdes
37797866Sdes			for (i = 0; i < newcg->cg_nclusterblks; i++) {
37897866Sdes				if ((map & bit) != 0) {
37997891Sdes					run++;
38097866Sdes				} else if (run != 0) {
38197866Sdes					if (run > fs->fs_contigsumsize)
38290267Sdes						run = fs->fs_contigsumsize;
38397866Sdes					sump[run]++;
38490267Sdes					run = 0;
38590267Sdes				}
38690267Sdes				if ((i & (NBBY - 1)) != (NBBY - 1)) {
38790267Sdes					bit <<= 1;
38897866Sdes				} else {
38997866Sdes					map = *mapp++;
39097866Sdes					bit = 1;
39197866Sdes				}
39297866Sdes			}
39397866Sdes			if (run != 0) {
39497866Sdes				if (run > fs->fs_contigsumsize)
39598117Sdes					run = fs->fs_contigsumsize;
39697866Sdes				sump[run]++;
39797866Sdes			}
39897866Sdes		}
39997866Sdes		cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
40097866Sdes		cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
40197866Sdes		cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
40297866Sdes		cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
40397866Sdes		cs = &fs->fs_cs(fs, c);
40497866Sdes		if (memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0) {
40597866Sdes			if (debug) {
40697866Sdes				printf("cg %d: nffree: %d/%d nbfree %d/%d"
40797866Sdes					" nifree %d/%d ndir %d/%d\n",
40897866Sdes					c, cs->cs_nffree,newcg->cg_cs.cs_nffree,
40997866Sdes					cs->cs_nbfree,newcg->cg_cs.cs_nbfree,
41097866Sdes					cs->cs_nifree,newcg->cg_cs.cs_nifree,
41197866Sdes					cs->cs_ndir,newcg->cg_cs.cs_ndir);
41297866Sdes			}
41397866Sdes			if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
41497866Sdes				memmove(cs, &newcg->cg_cs, sizeof *cs);
41597866Sdes				sbdirty();
41697866Sdes			} else
41797866Sdes				markclean = 0;
41897866Sdes		}
41997866Sdes		if (doinglevel1) {
42097866Sdes			memmove(cg, newcg, (size_t)fs->fs_cgsize);
42197866Sdes			cgdirty();
42297856Sdes			continue;
42397856Sdes		}
42497856Sdes		if ((memcmp(newcg, cg, basesize) != 0) ||
42597856Sdes		    (memcmp(&old_cg_blktot(newcg, 0)[0],
42697856Sdes		        &old_cg_blktot(cg, 0)[0], sumsize) != 0)) {
42790267Sdes		 	if (dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
42890267Sdes				memmove(cg, newcg, (size_t)basesize);
42990267Sdes				memmove(&old_cg_blktot(cg, 0)[0],
43097856Sdes			       &old_cg_blktot(newcg, 0)[0], (size_t)sumsize);
43197856Sdes				cgdirty();
43290267Sdes			} else
43390267Sdes				markclean = 0;
43490267Sdes		}
43597856Sdes		if (usedsoftdep) {
43697856Sdes			for (i = 0; i < inomapsize; i++) {
43790267Sdes				j = cg_inosused(newcg, 0)[i];
43855557Sdes				if ((cg_inosused(cg, 0)[i] & j) == j)
43955557Sdes					continue;
44055557Sdes				for (k = 0; k < NBBY; k++) {
44162981Sdes					if ((j & (1 << k)) == 0)
44297866Sdes						continue;
44362981Sdes					if (cg_inosused(cg, 0)[i] & (1 << k))
44497866Sdes						continue;
44597866Sdes					pwarn("ALLOCATED INODE %ld "
44697866Sdes					    "MARKED FREE\n",
44797866Sdes					    c * fs->fs_ipg + i * 8 + k);
44897866Sdes				}
44997866Sdes			}
45097866Sdes			for (i = 0; i < blkmapsize; i++) {
45197866Sdes				j = cg_blksfree(cg, 0)[i];
45297866Sdes				if ((cg_blksfree(newcg, 0)[i] & j) == j)
45397866Sdes					continue;
45497866Sdes				for (k = 0; k < NBBY; k++) {
45597866Sdes					if ((j & (1 << k)) == 0)
45697866Sdes						continue;
45797866Sdes					if (cg_inosused(cg, 0)[i] & (1 << k))
45897866Sdes						continue;
45997866Sdes					pwarn("ALLOCATED FRAG %ld "
46097866Sdes					    "MARKED FREE\n",
46197866Sdes					    c * fs->fs_fpg + i * 8 + k);
46297866Sdes				}
46397866Sdes			}
46497866Sdes		}
46597866Sdes		if (memcmp(cg_inosused(newcg, 0), cg_inosused(cg, 0), mapsize)
46697866Sdes		    != 0 && dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
46797866Sdes			memmove(cg_inosused(cg, 0), cg_inosused(newcg, 0),
46897866Sdes			    (size_t)mapsize);
46997866Sdes                        cgdirty();
47097866Sdes                }
47197866Sdes	}
47297866Sdes	if (memcmp(&cstotal, &fs->fs_cstotal, cssize) != 0) {
47397866Sdes		if (debug) {
47497866Sdes			printf("total: nffree: %lld/%lld nbfree %lld/%lld"
47597866Sdes				" nifree %lld/%lld ndir %lld/%lld\n",
47697866Sdes				(long long int)fs->fs_cstotal.cs_nffree,
47797866Sdes				(long long int)cstotal.cs_nffree,
47897866Sdes				(long long int)fs->fs_cstotal.cs_nbfree,
47997866Sdes				(long long int)cstotal.cs_nbfree,
48097866Sdes				(long long int)fs->fs_cstotal.cs_nifree,
48197891Sdes				(long long int)cstotal.cs_nifree,
48297866Sdes				(long long int)fs->fs_cstotal.cs_ndir,
48397866Sdes				(long long int)cstotal.cs_ndir);
48497866Sdes		}
48597891Sdes		if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
48697866Sdes			memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal);
48797866Sdes			fs->fs_ronly = 0;
48897866Sdes			fs->fs_fmod = 0;
48997866Sdes			sbdirty();
49097866Sdes		} else
49197866Sdes			markclean = 0;
49297866Sdes	}
49397866Sdes#ifdef PROGRESS
49497866Sdes	if (!preen)
49597866Sdes		progress_done();
49697866Sdes#endif /* PROGRESS */
49797866Sdes}
49897866Sdes
49997866Sdesvoid
50097866Sdesprint_bmap(u_char *map, uint32_t size)
50197866Sdes{
50298117Sdes	uint32_t i, j;
50397866Sdes
50497866Sdes	i = 0;
50597866Sdes	while (i < size) {
50662981Sdes		printf("%u: ",i);
50797856Sdes		for (j = 0; j < 16; j++, i++)
50862981Sdes			printf("%2x ", (u_int)map[i] & 0xff);
50997866Sdes		printf("\n");
51097866Sdes	}
51190267Sdes}
51290267Sdes