1*2d1cf01eSdholland /* $NetBSD: pass5.c,v 1.20 2012/08/26 09:33:18 dholland Exp $ */
2bf07c871Sagc
3bf07c871Sagc /*
4bf07c871Sagc * Copyright (c) 1980, 1986, 1993
5bf07c871Sagc * The Regents of the University of California. All rights reserved.
6bf07c871Sagc *
7bf07c871Sagc * Redistribution and use in source and binary forms, with or without
8bf07c871Sagc * modification, are permitted provided that the following conditions
9bf07c871Sagc * are met:
10bf07c871Sagc * 1. Redistributions of source code must retain the above copyright
11bf07c871Sagc * notice, this list of conditions and the following disclaimer.
12bf07c871Sagc * 2. Redistributions in binary form must reproduce the above copyright
13bf07c871Sagc * notice, this list of conditions and the following disclaimer in the
14bf07c871Sagc * documentation and/or other materials provided with the distribution.
15bf07c871Sagc * 3. Neither the name of the University nor the names of its contributors
16bf07c871Sagc * may be used to endorse or promote products derived from this software
17bf07c871Sagc * without specific prior written permission.
18bf07c871Sagc *
19bf07c871Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20bf07c871Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21bf07c871Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22bf07c871Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23bf07c871Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24bf07c871Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25bf07c871Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26bf07c871Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27bf07c871Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28bf07c871Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29bf07c871Sagc * SUCH DAMAGE.
30bf07c871Sagc */
318f7c2b37Sbouyer
328f7c2b37Sbouyer /*
338f7c2b37Sbouyer * Copyright (c) 1997 Manuel Bouyer.
348f7c2b37Sbouyer *
358f7c2b37Sbouyer * Redistribution and use in source and binary forms, with or without
368f7c2b37Sbouyer * modification, are permitted provided that the following conditions
378f7c2b37Sbouyer * are met:
388f7c2b37Sbouyer * 1. Redistributions of source code must retain the above copyright
398f7c2b37Sbouyer * notice, this list of conditions and the following disclaimer.
408f7c2b37Sbouyer * 2. Redistributions in binary form must reproduce the above copyright
418f7c2b37Sbouyer * notice, this list of conditions and the following disclaimer in the
428f7c2b37Sbouyer * documentation and/or other materials provided with the distribution.
438f7c2b37Sbouyer *
442f853da9Sbouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
452f853da9Sbouyer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
462f853da9Sbouyer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
472f853da9Sbouyer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
482f853da9Sbouyer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
492f853da9Sbouyer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
502f853da9Sbouyer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
512f853da9Sbouyer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
522f853da9Sbouyer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
532f853da9Sbouyer * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
548f7c2b37Sbouyer */
558f7c2b37Sbouyer
564b836889Slukem #include <sys/cdefs.h>
578f7c2b37Sbouyer #ifndef lint
588f7c2b37Sbouyer #if 0
598f7c2b37Sbouyer static char sccsid[] = "@(#)pass5.c 8.6 (Berkeley) 11/30/94";
608f7c2b37Sbouyer #else
61*2d1cf01eSdholland __RCSID("$NetBSD: pass5.c,v 1.20 2012/08/26 09:33:18 dholland Exp $");
628f7c2b37Sbouyer #endif
638f7c2b37Sbouyer #endif /* not lint */
648f7c2b37Sbouyer
658f7c2b37Sbouyer #include <sys/param.h>
668f7c2b37Sbouyer #include <sys/time.h>
67e5bc90f4Sfvdl #include <ufs/ufs/dinode.h>
688f7c2b37Sbouyer #include <ufs/ext2fs/ext2fs_dinode.h>
698f7c2b37Sbouyer #include <ufs/ext2fs/ext2fs.h>
705bd52bbaSlukem #include <inttypes.h>
718f7c2b37Sbouyer #include <string.h>
72*2d1cf01eSdholland #include <stdlib.h>
738f7c2b37Sbouyer #include <stdio.h>
748f7c2b37Sbouyer
758f7c2b37Sbouyer #include "fsutil.h"
768f7c2b37Sbouyer #include "fsck.h"
778f7c2b37Sbouyer #include "extern.h"
788f7c2b37Sbouyer
798f7c2b37Sbouyer
8036f9677dSdholland static void print_bmap(char *, uint32_t);
818f7c2b37Sbouyer
828f7c2b37Sbouyer void
pass5(void)83ccde05f0Sxtraeme pass5(void)
848f7c2b37Sbouyer {
854b836889Slukem int c;
864b836889Slukem struct m_ext2fs *fs = &sblock;
878f7c2b37Sbouyer daddr_t dbase, dmax;
884b836889Slukem daddr_t d;
895bd52bbaSlukem uint32_t i, j;
908f7c2b37Sbouyer struct inodesc idesc[3];
918f7c2b37Sbouyer struct bufarea *ino_bitmap = NULL, *blk_bitmap = NULL;
928f7c2b37Sbouyer char *ibmap, *bbmap;
938f7c2b37Sbouyer u_int32_t cs_ndir, cs_nbfree, cs_nifree;
948f7c2b37Sbouyer char msg[255];
958f7c2b37Sbouyer
968f7c2b37Sbouyer cs_ndir = 0;
978f7c2b37Sbouyer cs_nbfree = 0;
988f7c2b37Sbouyer cs_nifree = 0;
998f7c2b37Sbouyer
1008f7c2b37Sbouyer ibmap = malloc(fs->e2fs_bsize);
1018f7c2b37Sbouyer bbmap = malloc(fs->e2fs_bsize);
1028f7c2b37Sbouyer if (ibmap == NULL || bbmap == NULL) {
103481ad7b0Slukem errexit("out of memory");
1048f7c2b37Sbouyer }
1058f7c2b37Sbouyer
1068f7c2b37Sbouyer for (c = 0; c < fs->e2fs_ncg; c++) {
1078f7c2b37Sbouyer u_int32_t nbfree = 0;
1088f7c2b37Sbouyer u_int32_t nifree = 0;
1098f7c2b37Sbouyer u_int32_t ndirs = 0;
1108f7c2b37Sbouyer
1118f7c2b37Sbouyer nbfree = 0;
1128f7c2b37Sbouyer nifree = fs->e2fs.e2fs_ipg;
1138f7c2b37Sbouyer ndirs = 0;
1148f7c2b37Sbouyer
1158f7c2b37Sbouyer if (blk_bitmap == NULL) {
1167052d78bSbouyer blk_bitmap = getdatablk(fs2h32(fs->e2fs_gd[c].ext2bgd_b_bitmap),
1178f7c2b37Sbouyer fs->e2fs_bsize);
1188f7c2b37Sbouyer } else {
1197052d78bSbouyer getblk(blk_bitmap, fs2h32(fs->e2fs_gd[c].ext2bgd_b_bitmap),
1208f7c2b37Sbouyer fs->e2fs_bsize);
1218f7c2b37Sbouyer }
1228f7c2b37Sbouyer if (ino_bitmap == NULL) {
1237052d78bSbouyer ino_bitmap = getdatablk(fs2h32(fs->e2fs_gd[c].ext2bgd_i_bitmap),
1248f7c2b37Sbouyer fs->e2fs_bsize);
1258f7c2b37Sbouyer } else {
1267052d78bSbouyer getblk(ino_bitmap, fs2h32(fs->e2fs_gd[c].ext2bgd_i_bitmap),
1278f7c2b37Sbouyer fs->e2fs_bsize);
1288f7c2b37Sbouyer }
1298f7c2b37Sbouyer memset(bbmap, 0, fs->e2fs_bsize);
1308f7c2b37Sbouyer memset(ibmap, 0, fs->e2fs_bsize);
1318f7c2b37Sbouyer memset(&idesc[0], 0, sizeof idesc);
1328f7c2b37Sbouyer for (i = 0; i < 3; i++) {
1338f7c2b37Sbouyer idesc[i].id_type = ADDR;
1348f7c2b37Sbouyer }
1358f7c2b37Sbouyer
1368f7c2b37Sbouyer j = fs->e2fs.e2fs_ipg * c + 1;
1378f7c2b37Sbouyer
1388f7c2b37Sbouyer for (i = 0; i < fs->e2fs.e2fs_ipg; j++, i++) {
1398f7c2b37Sbouyer if ((j < EXT2_FIRSTINO) && (j != EXT2_ROOTINO)) {
1408f7c2b37Sbouyer setbit(ibmap, i);
1418f7c2b37Sbouyer nifree--;
1428f7c2b37Sbouyer continue;
1438f7c2b37Sbouyer }
1448f7c2b37Sbouyer if (j > fs->e2fs.e2fs_icount) {
1458f7c2b37Sbouyer setbit(ibmap, i);
1468f7c2b37Sbouyer continue;
1478f7c2b37Sbouyer }
1488f7c2b37Sbouyer switch (statemap[j]) {
1498f7c2b37Sbouyer
1508f7c2b37Sbouyer case USTATE:
1518f7c2b37Sbouyer break;
1528f7c2b37Sbouyer
1538f7c2b37Sbouyer case DSTATE:
1548f7c2b37Sbouyer case DCLEAR:
1558f7c2b37Sbouyer case DFOUND:
1568f7c2b37Sbouyer ndirs++;
1578f7c2b37Sbouyer /* fall through */
1588f7c2b37Sbouyer
1598f7c2b37Sbouyer case FSTATE:
1608f7c2b37Sbouyer case FCLEAR:
1618f7c2b37Sbouyer nifree--;
1628f7c2b37Sbouyer setbit(ibmap, i);
1638f7c2b37Sbouyer break;
1648f7c2b37Sbouyer
1658f7c2b37Sbouyer default:
1665bd52bbaSlukem errexit("BAD STATE %d FOR INODE I=%"PRIu32,
1678f7c2b37Sbouyer statemap[j], j);
1688f7c2b37Sbouyer }
1698f7c2b37Sbouyer }
1708f7c2b37Sbouyer
1718f7c2b37Sbouyer /* fill in unused par of the inode map */
1725bd52bbaSlukem for (i = fs->e2fs.e2fs_ipg / NBBY; i < (uint32_t)fs->e2fs_bsize; i++)
1738f7c2b37Sbouyer ibmap[i] = 0xff;
1748f7c2b37Sbouyer
17509d4663fSbouyer dbase = c * sblock.e2fs.e2fs_bpg +
17609d4663fSbouyer sblock.e2fs.e2fs_first_dblock;
17709d4663fSbouyer dmax = (c+1) * sblock.e2fs.e2fs_bpg +
17809d4663fSbouyer sblock.e2fs.e2fs_first_dblock;
1798f7c2b37Sbouyer
18009d4663fSbouyer for (i = 0, d = dbase;
1818f7c2b37Sbouyer d < dmax;
1828f7c2b37Sbouyer d ++, i ++) {
1838f7c2b37Sbouyer if (testbmap(d) || d >= sblock.e2fs.e2fs_bcount) {
1848f7c2b37Sbouyer setbit(bbmap, i);
1858f7c2b37Sbouyer continue;
1868f7c2b37Sbouyer } else {
1878f7c2b37Sbouyer nbfree++;
1888f7c2b37Sbouyer }
1898f7c2b37Sbouyer
1908f7c2b37Sbouyer }
1918f7c2b37Sbouyer cs_nbfree += nbfree;
1928f7c2b37Sbouyer cs_nifree += nifree;
1938f7c2b37Sbouyer cs_ndir += ndirs;
1948f7c2b37Sbouyer
1957052d78bSbouyer if (debug && (fs2h16(fs->e2fs_gd[c].ext2bgd_nbfree) != nbfree ||
1967052d78bSbouyer fs2h16(fs->e2fs_gd[c].ext2bgd_nifree) != nifree ||
1977052d78bSbouyer fs2h16(fs->e2fs_gd[c].ext2bgd_ndirs) != ndirs)) {
1988f7c2b37Sbouyer printf("summary info for cg %d is %d, %d, %d,"
1998f7c2b37Sbouyer "should be %d, %d, %d\n", c,
2007052d78bSbouyer fs2h16(fs->e2fs_gd[c].ext2bgd_nbfree),
2017052d78bSbouyer fs2h16(fs->e2fs_gd[c].ext2bgd_nifree),
2027052d78bSbouyer fs2h16(fs->e2fs_gd[c].ext2bgd_ndirs),
2038f7c2b37Sbouyer nbfree,
2048f7c2b37Sbouyer nifree,
2058f7c2b37Sbouyer ndirs);
2068f7c2b37Sbouyer }
207519d8585Smycroft (void)snprintf(msg, sizeof(msg),
208519d8585Smycroft "SUMMARY INFORMATIONS WRONG FOR CG #%d", c);
2097052d78bSbouyer if ((fs2h16(fs->e2fs_gd[c].ext2bgd_nbfree) != nbfree ||
2107052d78bSbouyer fs2h16(fs->e2fs_gd[c].ext2bgd_nifree) != nifree ||
2117052d78bSbouyer fs2h16(fs->e2fs_gd[c].ext2bgd_ndirs) != ndirs) &&
2128f7c2b37Sbouyer dofix(&idesc[0], msg)) {
2137052d78bSbouyer fs->e2fs_gd[c].ext2bgd_nbfree = h2fs16(nbfree);
2147052d78bSbouyer fs->e2fs_gd[c].ext2bgd_nifree = h2fs16(nifree);
2157052d78bSbouyer fs->e2fs_gd[c].ext2bgd_ndirs = h2fs16(ndirs);
2168f7c2b37Sbouyer sbdirty();
2178f7c2b37Sbouyer }
2188f7c2b37Sbouyer
2198f7c2b37Sbouyer if (debug && memcmp(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize)) {
2208f7c2b37Sbouyer printf("blk_bitmap:\n");
2218f7c2b37Sbouyer print_bmap(blk_bitmap->b_un.b_buf, fs->e2fs_bsize);
2228f7c2b37Sbouyer printf("bbmap:\n");
2238f7c2b37Sbouyer print_bmap(bbmap, fs->e2fs_bsize);
2248f7c2b37Sbouyer }
2258f7c2b37Sbouyer
226519d8585Smycroft (void)snprintf(msg, sizeof(msg),
227519d8585Smycroft "BLK(S) MISSING IN BIT MAPS #%d", c);
2288f7c2b37Sbouyer if (memcmp(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize) &&
2298f7c2b37Sbouyer dofix(&idesc[1], msg)) {
2308f7c2b37Sbouyer memcpy(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize);
2318f7c2b37Sbouyer dirty(blk_bitmap);
2328f7c2b37Sbouyer }
2338f7c2b37Sbouyer if (debug && memcmp(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize)) {
2348f7c2b37Sbouyer printf("ino_bitmap:\n");
2358f7c2b37Sbouyer print_bmap(ino_bitmap->b_un.b_buf, fs->e2fs_bsize);
2368f7c2b37Sbouyer printf("ibmap:\n");
2378f7c2b37Sbouyer print_bmap(ibmap, fs->e2fs_bsize);
2388f7c2b37Sbouyer }
239519d8585Smycroft (void)snprintf(msg, sizeof(msg),
240519d8585Smycroft "INODE(S) MISSING IN BIT MAPS #%d", c);
2418f7c2b37Sbouyer if (memcmp(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize) &&
2428f7c2b37Sbouyer dofix(&idesc[1], msg)) {
2438f7c2b37Sbouyer memcpy(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize);
2448f7c2b37Sbouyer dirty(ino_bitmap);
2458f7c2b37Sbouyer }
2468f7c2b37Sbouyer
2478f7c2b37Sbouyer }
2488f7c2b37Sbouyer if (debug && (fs->e2fs.e2fs_fbcount != cs_nbfree ||
2498f7c2b37Sbouyer fs->e2fs.e2fs_ficount != cs_nifree)) {
2508f7c2b37Sbouyer printf("summary info bad in superblock: %d, %d should be %d, %d\n",
2518f7c2b37Sbouyer fs->e2fs.e2fs_fbcount, fs->e2fs.e2fs_ficount,
2528f7c2b37Sbouyer cs_nbfree, cs_nifree);
2538f7c2b37Sbouyer }
2548f7c2b37Sbouyer if ((fs->e2fs.e2fs_fbcount != cs_nbfree ||
2558f7c2b37Sbouyer fs->e2fs.e2fs_ficount != cs_nifree)
2568f7c2b37Sbouyer && dofix(&idesc[0], "SUPERBLK SUMMARY INFORMATION BAD")) {
2578f7c2b37Sbouyer fs->e2fs.e2fs_fbcount = cs_nbfree;
2588f7c2b37Sbouyer fs->e2fs.e2fs_ficount = cs_nifree;
2598f7c2b37Sbouyer sbdirty();
2608f7c2b37Sbouyer }
261ef75a584Schristos free(ibmap);
262ef75a584Schristos free(bbmap);
2638f7c2b37Sbouyer }
2648f7c2b37Sbouyer
2652fb6ddeeSdholland static void
print_bmap(char * map,uint32_t size)26636f9677dSdholland print_bmap(char *map, uint32_t size)
2678f7c2b37Sbouyer {
2685bd52bbaSlukem uint32_t i, j;
2698f7c2b37Sbouyer
2708f7c2b37Sbouyer i = 0;
2718f7c2b37Sbouyer while (i < size) {
27298bd33ecStsutsui printf("%04x: ",i);
2738f7c2b37Sbouyer for (j = 0; j < 16; j++, i++)
27436f9677dSdholland printf("%02x ", (unsigned char)map[i] & 0xff);
2758f7c2b37Sbouyer printf("\n");
2768f7c2b37Sbouyer }
2778f7c2b37Sbouyer }
278