xref: /netbsd-src/sbin/fsck_ext2fs/pass5.c (revision 2d1cf01ec89d19779c89084e5924876f77380288)
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