122053Sdist /*
261492Sbostic * Copyright (c) 1980, 1986, 1993
361492Sbostic * The Regents of the University of California. All rights reserved.
439976Smckusick *
542702Sbostic * %sccs.include.redist.c%
622053Sdist */
722053Sdist
816267Smckusick #ifndef lint
9*68992Sbostic static char sccsid[] = "@(#)pass5.c 8.9 (Berkeley) 04/28/95";
1039976Smckusick #endif /* not lint */
1116267Smckusick
1216267Smckusick #include <sys/param.h>
1353703Smckusick #include <sys/time.h>
1468908Smckusick
1551532Sbostic #include <ufs/ufs/dinode.h>
1651532Sbostic #include <ufs/ffs/fs.h>
1768908Smckusick
1868908Smckusick #include <err.h>
1944934Smckusick #include <string.h>
2068908Smckusick
2116267Smckusick #include "fsck.h"
2216267Smckusick
2368908Smckusick void
pass5()2416267Smckusick pass5()
2516267Smckusick {
2634141Smckusick int c, blk, frags, basesize, sumsize, mapsize, savednrpos;
2768548Smckusick struct fs *fs = &sblock;
2868548Smckusick struct cg *cg = &cgrp;
2968548Smckusick ufs_daddr_t dbase, dmax;
3068548Smckusick ufs_daddr_t d;
3168548Smckusick long i, j;
3217937Smckusick struct csum *cs;
3317937Smckusick struct csum cstotal;
3437099Smckusick struct inodesc idesc[3];
3517937Smckusick char buf[MAXBSIZE];
3617937Smckusick register struct cg *newcg = (struct cg *)buf;
3734141Smckusick struct ocg *ocg = (struct ocg *)buf;
3816267Smckusick
3967879Smckusick statemap[WINO] = USTATE;
40*68992Sbostic memset(newcg, 0, (size_t)fs->fs_cgsize);
4134223Smckusick newcg->cg_niblk = fs->fs_ipg;
4268007Smckusick if (cvtlevel >= 3) {
4365969Smckusick if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
4465969Smckusick if (preen)
4565969Smckusick pwarn("DELETING CLUSTERING MAPS\n");
4665969Smckusick if (preen || reply("DELETE CLUSTERING MAPS")) {
4765969Smckusick fs->fs_contigsumsize = 0;
4865969Smckusick doinglevel1 = 1;
4965969Smckusick sbdirty();
5065969Smckusick }
5165969Smckusick }
5265969Smckusick if (fs->fs_maxcontig > 1) {
5365969Smckusick char *doit = 0;
5465969Smckusick
5565969Smckusick if (fs->fs_contigsumsize < 1) {
5665969Smckusick doit = "CREAT";
5765969Smckusick } else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
5865969Smckusick fs->fs_contigsumsize < FS_MAXCONTIG) {
5965969Smckusick doit = "EXPAND";
6065969Smckusick }
6165969Smckusick if (doit) {
6265969Smckusick i = fs->fs_contigsumsize;
6365969Smckusick fs->fs_contigsumsize =
6465969Smckusick MIN(fs->fs_maxcontig, FS_MAXCONTIG);
6565969Smckusick if (CGSIZE(fs) > fs->fs_bsize) {
6665969Smckusick pwarn("CANNOT %s CLUSTER MAPS\n", doit);
6765969Smckusick fs->fs_contigsumsize = i;
6865969Smckusick } else if (preen ||
6965969Smckusick reply("CREATE CLUSTER MAPS")) {
7065969Smckusick if (preen)
7165969Smckusick pwarn("%sING CLUSTER MAPS\n",
7265969Smckusick doit);
7365969Smckusick fs->fs_cgsize =
7465969Smckusick fragroundup(fs, CGSIZE(fs));
7565969Smckusick doinglevel1 = 1;
7665969Smckusick sbdirty();
7765969Smckusick }
7865969Smckusick }
7965969Smckusick }
8065969Smckusick }
8139973Smckusick switch ((int)fs->fs_postblformat) {
8234141Smckusick
8334141Smckusick case FS_42POSTBLFMT:
8467669Smckusick basesize = (char *)(&ocg->cg_btot[0]) -
8567669Smckusick (char *)(&ocg->cg_firstfield);
8667669Smckusick sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
8734223Smckusick mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
8834141Smckusick (u_char *)&ocg->cg_iused[0];
8934141Smckusick ocg->cg_magic = CG_MAGIC;
9034223Smckusick savednrpos = fs->fs_nrpos;
9134223Smckusick fs->fs_nrpos = 8;
9234141Smckusick break;
9334141Smckusick
9434141Smckusick case FS_DYNAMICPOSTBLFMT:
9534141Smckusick newcg->cg_btotoff =
9667669Smckusick &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
9734141Smckusick newcg->cg_boff =
9865969Smckusick newcg->cg_btotoff + fs->fs_cpg * sizeof(long);
9934141Smckusick newcg->cg_iusedoff = newcg->cg_boff +
10065969Smckusick fs->fs_cpg * fs->fs_nrpos * sizeof(short);
10134141Smckusick newcg->cg_freeoff =
10265969Smckusick newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
10365969Smckusick if (fs->fs_contigsumsize <= 0) {
10465969Smckusick newcg->cg_nextfreeoff = newcg->cg_freeoff +
10565969Smckusick howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
10665969Smckusick } else {
10765969Smckusick newcg->cg_clustersumoff = newcg->cg_freeoff +
10865969Smckusick howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY) -
10965969Smckusick sizeof(long);
11065969Smckusick newcg->cg_clustersumoff =
11165969Smckusick roundup(newcg->cg_clustersumoff, sizeof(long));
11265969Smckusick newcg->cg_clusteroff = newcg->cg_clustersumoff +
11365969Smckusick (fs->fs_contigsumsize + 1) * sizeof(long);
11465969Smckusick newcg->cg_nextfreeoff = newcg->cg_clusteroff +
11565969Smckusick howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY);
11665969Smckusick }
11734141Smckusick newcg->cg_magic = CG_MAGIC;
11867669Smckusick basesize = &newcg->cg_space[0] -
11967669Smckusick (u_char *)(&newcg->cg_firstfield);
12034141Smckusick sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
12134141Smckusick mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
12234141Smckusick break;
12334141Smckusick
12434141Smckusick default:
12568908Smckusick sumsize = 0; /* keep lint happy */
12668908Smckusick errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d",
12734223Smckusick fs->fs_postblformat);
12834141Smckusick }
129*68992Sbostic memset(&idesc[0], 0, sizeof idesc);
13054601Smckusick for (i = 0; i < 3; i++) {
13137099Smckusick idesc[i].id_type = ADDR;
13254601Smckusick if (doinglevel2)
13354601Smckusick idesc[i].id_fix = FIX;
13454601Smckusick }
135*68992Sbostic memset(&cstotal, 0, sizeof(struct csum));
13640018Smckusick j = blknum(fs, fs->fs_size + fs->fs_frag - 1);
13740018Smckusick for (i = fs->fs_size; i < j; i++)
13834141Smckusick setbmap(i);
13934223Smckusick for (c = 0; c < fs->fs_ncg; c++) {
14034223Smckusick getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
14134223Smckusick if (!cg_chkmagic(cg))
14216267Smckusick pfatal("CG %d: BAD MAGIC NUMBER\n", c);
14334223Smckusick dbase = cgbase(fs, c);
14434223Smckusick dmax = dbase + fs->fs_fpg;
14534223Smckusick if (dmax > fs->fs_size)
14634223Smckusick dmax = fs->fs_size;
14756353Smckusick newcg->cg_time = cg->cg_time;
14817937Smckusick newcg->cg_cgx = c;
14934223Smckusick if (c == fs->fs_ncg - 1)
15034223Smckusick newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
15117937Smckusick else
15234223Smckusick newcg->cg_ncyl = fs->fs_cpg;
15317937Smckusick newcg->cg_ndblk = dmax - dbase;
15465969Smckusick if (fs->fs_contigsumsize > 0)
15565969Smckusick newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
15617937Smckusick newcg->cg_cs.cs_ndir = 0;
15717937Smckusick newcg->cg_cs.cs_nffree = 0;
15817937Smckusick newcg->cg_cs.cs_nbfree = 0;
15934223Smckusick newcg->cg_cs.cs_nifree = fs->fs_ipg;
16034223Smckusick if (cg->cg_rotor < newcg->cg_ndblk)
16134223Smckusick newcg->cg_rotor = cg->cg_rotor;
16217937Smckusick else
16317937Smckusick newcg->cg_rotor = 0;
16434223Smckusick if (cg->cg_frotor < newcg->cg_ndblk)
16534223Smckusick newcg->cg_frotor = cg->cg_frotor;
16617937Smckusick else
16717937Smckusick newcg->cg_frotor = 0;
16834223Smckusick if (cg->cg_irotor < newcg->cg_niblk)
16934223Smckusick newcg->cg_irotor = cg->cg_irotor;
17017937Smckusick else
17117937Smckusick newcg->cg_irotor = 0;
172*68992Sbostic memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
173*68992Sbostic memset(&cg_blktot(newcg)[0], 0,
17444934Smckusick (size_t)(sumsize + mapsize));
17534223Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT)
17634141Smckusick ocg->cg_magic = CG_MAGIC;
17734223Smckusick j = fs->fs_ipg * c;
17834223Smckusick for (i = 0; i < fs->fs_ipg; j++, i++) {
17917937Smckusick switch (statemap[j]) {
18017937Smckusick
18117937Smckusick case USTATE:
18217937Smckusick break;
18317937Smckusick
18417937Smckusick case DSTATE:
18517937Smckusick case DCLEAR:
18617937Smckusick case DFOUND:
18717937Smckusick newcg->cg_cs.cs_ndir++;
18817937Smckusick /* fall through */
18917937Smckusick
19017937Smckusick case FSTATE:
19117937Smckusick case FCLEAR:
19217937Smckusick newcg->cg_cs.cs_nifree--;
19334141Smckusick setbit(cg_inosused(newcg), i);
19417937Smckusick break;
19526480Smckusick
19626480Smckusick default:
19726480Smckusick if (j < ROOTINO)
19826480Smckusick break;
19968908Smckusick errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
20026480Smckusick statemap[j], j);
20117937Smckusick }
20216267Smckusick }
20317937Smckusick if (c == 0)
20417937Smckusick for (i = 0; i < ROOTINO; i++) {
20534141Smckusick setbit(cg_inosused(newcg), i);
20617937Smckusick newcg->cg_cs.cs_nifree--;
20716267Smckusick }
20817937Smckusick for (i = 0, d = dbase;
20934141Smckusick d < dmax;
21034223Smckusick d += fs->fs_frag, i += fs->fs_frag) {
21117937Smckusick frags = 0;
21234223Smckusick for (j = 0; j < fs->fs_frag; j++) {
21339973Smckusick if (testbmap(d + j))
21417937Smckusick continue;
21534141Smckusick setbit(cg_blksfree(newcg), i + j);
21617937Smckusick frags++;
21717937Smckusick }
21834223Smckusick if (frags == fs->fs_frag) {
21917937Smckusick newcg->cg_cs.cs_nbfree++;
22034223Smckusick j = cbtocylno(fs, i);
22134141Smckusick cg_blktot(newcg)[j]++;
22234223Smckusick cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++;
22365969Smckusick if (fs->fs_contigsumsize > 0)
22465969Smckusick setbit(cg_clustersfree(newcg),
22565969Smckusick i / fs->fs_frag);
22617937Smckusick } else if (frags > 0) {
22717937Smckusick newcg->cg_cs.cs_nffree += frags;
22834223Smckusick blk = blkmap(fs, cg_blksfree(newcg), i);
22951637Sbostic ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
23017937Smckusick }
23116267Smckusick }
23265969Smckusick if (fs->fs_contigsumsize > 0) {
23368014Smckusick int32_t *sump = cg_clustersum(newcg);
23465969Smckusick u_char *mapp = cg_clustersfree(newcg);
23565969Smckusick int map = *mapp++;
23665969Smckusick int bit = 1;
23765969Smckusick int run = 0;
23865969Smckusick
23965969Smckusick for (i = 0; i < newcg->cg_nclusterblks; i++) {
24065969Smckusick if ((map & bit) != 0) {
24165969Smckusick run++;
24265969Smckusick } else if (run != 0) {
24365969Smckusick if (run > fs->fs_contigsumsize)
24465969Smckusick run = fs->fs_contigsumsize;
24565969Smckusick sump[run]++;
24665969Smckusick run = 0;
24765969Smckusick }
24865969Smckusick if ((i & (NBBY - 1)) != (NBBY - 1)) {
24965969Smckusick bit <<= 1;
25065969Smckusick } else {
25165969Smckusick map = *mapp++;
25265969Smckusick bit = 1;
25365969Smckusick }
25465969Smckusick }
25565969Smckusick if (run != 0) {
25665969Smckusick if (run > fs->fs_contigsumsize)
25765969Smckusick run = fs->fs_contigsumsize;
25865969Smckusick sump[run]++;
25965969Smckusick }
26065969Smckusick }
26117937Smckusick cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
26217937Smckusick cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
26317937Smckusick cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
26417937Smckusick cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
26534223Smckusick cs = &fs->fs_cs(fs, c);
266*68992Sbostic if (memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0 &&
26737099Smckusick dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
268*68992Sbostic memmove(cs, &newcg->cg_cs, sizeof *cs);
26934141Smckusick sbdirty();
27034141Smckusick }
27154601Smckusick if (doinglevel1) {
272*68992Sbostic memmove(cg, newcg, (size_t)fs->fs_cgsize);
27334141Smckusick cgdirty();
27434141Smckusick continue;
27534141Smckusick }
276*68992Sbostic if (memcmp(cg_inosused(newcg),
27734223Smckusick cg_inosused(cg), mapsize) != 0 &&
27837099Smckusick dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
279*68992Sbostic memmove(cg_inosused(cg), cg_inosused(newcg),
28044934Smckusick (size_t)mapsize);
28117937Smckusick cgdirty();
28216267Smckusick }
283*68992Sbostic if ((memcmp(newcg, cg, basesize) != 0 ||
284*68992Sbostic memcmp(&cg_blktot(newcg)[0],
285*68992Sbostic &cg_blktot(cg)[0], sumsize) != 0) &&
28637099Smckusick dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
287*68992Sbostic memmove(cg, newcg, (size_t)basesize);
288*68992Sbostic memmove(&cg_blktot(cg)[0],
289*68992Sbostic &cg_blktot(newcg)[0], (size_t)sumsize);
29017937Smckusick cgdirty();
29116267Smckusick }
29216267Smckusick }
29334223Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT)
29434223Smckusick fs->fs_nrpos = savednrpos;
295*68992Sbostic if (memcmp(&cstotal, &fs->fs_cstotal, sizeof *cs) != 0
29637099Smckusick && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
297*68992Sbostic memmove(&fs->fs_cstotal, &cstotal, sizeof *cs);
29834223Smckusick fs->fs_ronly = 0;
29934223Smckusick fs->fs_fmod = 0;
30017937Smckusick sbdirty();
30116267Smckusick }
30216267Smckusick }
303