/* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)icheck.c 5.1 (Berkeley) 5/28/85"; #endif not lint /* * icheck */ #define NB 500 #define MAXFN 500 #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) #ifndef STANDALONE #include #endif #ifndef SIMFS #include #include #include #else #include "../h/param.h" #include "../h/inode.h" #include "../h/fs.h" #endif union { struct fs sb; char pad[MAXBSIZE]; } sbun; #define sblock sbun.sb union { struct cg cg; char pad[MAXBSIZE]; } cgun; #define cgrp cgun.cg struct dinode itab[MAXIPG]; daddr_t blist[NB]; daddr_t fsblist[NB]; char *bmap; int mflg; int sflg; int dflg; int fi; ino_t ino; int cginit; ino_t nrfile; ino_t ndfile; ino_t nbfile; ino_t ncfile; ino_t nlfile; daddr_t nblock; daddr_t nfrag; daddr_t nindir; daddr_t niindir; daddr_t nffree; daddr_t nbfree; daddr_t ndup; int nerror; extern int inside[], around[]; extern unsigned char *fragtbl[]; long atol(); #ifndef STANDALONE char *malloc(); char *calloc(); #endif main(argc, argv) int argc; char *argv[]; { register i; long n; blist[0] = -1; #ifndef STANDALONE while (--argc) { argv++; if (**argv=='-') switch ((*argv)[1]) { case 'd': dflg++; continue; case 'm': mflg++; continue; case 's': sflg++; continue; case 'b': for(i=0; idi_mode & IFMT; if(i == 0) return; switch (i) { case IFCHR: ncfile++; return; case IFBLK: nbfile++; return; case IFDIR: ndfile++; break; case IFREG: nrfile++; break; case IFLNK: nlfile++; break; default: printf("bad mode %u\n", ino); return; } for (i = 0; i < NDADDR; i++) { db = ip->di_db[i]; if (db == 0) continue; siz = dblksize(&sblock, ip, i); sprintf(buf, "logical data block %d", i); chk(db, buf, siz); if (siz == sblock.fs_bsize) nblock++; else nfrag += howmany(siz, sblock.fs_fsize); } for(i = 0; i < NIADDR; i++) { ib = ip->di_ib[i]; if (ib == 0) continue; if (chk(ib, "1st indirect", sblock.fs_bsize)) continue; bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize); nindir++; for (j = 0; j < NINDIR(&sblock); j++) { ib = ind1[j]; if (ib == 0) continue; if (i == 0) { lbn = NDADDR + j; siz = dblksize(&sblock, ip, lbn); sprintf(buf, "logical data block %d", lbn); chk(ib, buf, siz); if (siz == sblock.fs_bsize) nblock++; else nfrag += howmany(siz, sblock.fs_fsize); continue; } if (chk(ib, "2nd indirect", sblock.fs_bsize)) continue; bread(fsbtodb(&sblock, ib), (char *)ind2, sblock.fs_bsize); niindir++; for (k = 0; k < NINDIR(&sblock); k++) { ib = ind2[k]; if (ib == 0) continue; lbn = NDADDR + NINDIR(&sblock) * (i + j) + k; siz = dblksize(&sblock, ip, lbn); sprintf(buf, "logical data block %d", lbn); chk(ib, buf, siz); if (siz == sblock.fs_bsize) nblock++; else nfrag += howmany(siz, sblock.fs_fsize); } } } } chk(bno, s, size) daddr_t bno; char *s; int size; { register n, cg; int frags; cg = dtog(&sblock, bno); if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) { printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); return(1); } frags = numfrags(&sblock, size); if (frags == sblock.fs_frag) { if (duped(bno, size)) { printf("%ld dup block; inode=%u, class=%s\n", bno, ino, s); ndup += sblock.fs_frag; } } else { for (n = 0; n < frags; n++) { if (duped(bno + n, sblock.fs_fsize)) { printf("%ld dup frag; inode=%u, class=%s\n", bno, ino, s); ndup++; } } } for (n=0; blist[n] != -1; n++) if (fsblist[n] >= bno && fsblist[n] < bno + frags) printf("%ld arg; frag %d of %d, inode=%u, class=%s\n", blist[n], fsblist[n] - bno, frags, ino, s); return(0); } duped(bno, size) daddr_t bno; int size; { if(dflg) return(0); if (size != sblock.fs_fsize && size != sblock.fs_bsize) printf("bad size %d to duped\n", size); if (size == sblock.fs_fsize) { if (isset(bmap, bno)) return(1); setbit(bmap, bno); return (0); } if (bno % sblock.fs_frag != 0) printf("bad bno %d to duped\n", bno); if (isblock(&sblock, bmap, bno/sblock.fs_frag)) return (1); setblock(&sblock, bmap, bno/sblock.fs_frag); return(0); } makecg() { int c, blk; daddr_t dbase, d, dlower, dupper, dmax; long i, j, s; register struct csum *cs; register struct dinode *dp; sblock.fs_cstotal.cs_nbfree = 0; sblock.fs_cstotal.cs_nffree = 0; sblock.fs_cstotal.cs_nifree = 0; sblock.fs_cstotal.cs_ndir = 0; for (c = 0; c < sblock.fs_ncg; c++) { dbase = cgbase(&sblock, c); dmax = dbase + sblock.fs_fpg; if (dmax > sblock.fs_size) { for ( ; dmax >= sblock.fs_size; dmax--) clrbit(cgrp.cg_free, dmax - dbase); dmax++; } dlower = cgsblock(&sblock, c) - dbase; dupper = cgdmin(&sblock, c) - dbase; cs = &sblock.fs_cs(&sblock, c); cgrp.cg_time = time(0); cgrp.cg_magic = CG_MAGIC; cgrp.cg_cgx = c; if (c == sblock.fs_ncg - 1) cgrp.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; else cgrp.cg_ncyl = sblock.fs_cpg; cgrp.cg_niblk = sblock.fs_ipg; cgrp.cg_ndblk = dmax - dbase; cgrp.cg_cs.cs_ndir = 0; cgrp.cg_cs.cs_nffree = 0; cgrp.cg_cs.cs_nbfree = 0; cgrp.cg_cs.cs_nifree = 0; cgrp.cg_rotor = 0; cgrp.cg_frotor = 0; cgrp.cg_irotor = 0; for (i = 0; i < sblock.fs_frag; i++) cgrp.cg_frsum[i] = 0; bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, sblock.fs_ipg * sizeof(struct dinode)); for (i = 0; i < sblock.fs_ipg; i++) { cgrp.cg_cs.cs_nifree++; clrbit(cgrp.cg_iused, i); dp = &itab[i]; if ((dp->di_mode & IFMT) != 0) { if ((dp->di_mode & IFMT) == IFDIR) cgrp.cg_cs.cs_ndir++; cgrp.cg_cs.cs_nifree--; setbit(cgrp.cg_iused, i); continue; } } while (i < MAXIPG) { clrbit(cgrp.cg_iused, i); i++; } if (c == 0) for (i = 0; i < ROOTINO; i++) { setbit(cgrp.cg_iused, i); cgrp.cg_cs.cs_nifree--; } for (s = 0; s < MAXCPG; s++) { cgrp.cg_btot[s] = 0; for (i = 0; i < NRPOS; i++) cgrp.cg_b[s][i] = 0; } if (c == 0) { dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); } for (d = dlower; d < dupper; d++) clrbit(cgrp.cg_free, d); for (d = 0; (d + sblock.fs_frag) <= dmax - dbase; d += sblock.fs_frag) { j = 0; for (i = 0; i < sblock.fs_frag; i++) { if (!isset(bmap, dbase + d + i)) { setbit(cgrp.cg_free, d + i); j++; } else clrbit(cgrp.cg_free, d+i); } if (j == sblock.fs_frag) { cgrp.cg_cs.cs_nbfree++; cgrp.cg_btot[cbtocylno(&sblock, d)]++; cgrp.cg_b[cbtocylno(&sblock, d)] [cbtorpos(&sblock, d)]++; } else if (j > 0) { cgrp.cg_cs.cs_nffree += j; blk = blkmap(&sblock, cgrp.cg_free, d); fragacct(&sblock, blk, cgrp.cg_frsum, 1); } } for (j = d; d < dmax - dbase; d++) { if (!isset(bmap, dbase + d)) { setbit(cgrp.cg_free, d); cgrp.cg_cs.cs_nffree++; } else clrbit(cgrp.cg_free, d); } for (; d % sblock.fs_frag != 0; d++) clrbit(cgrp.cg_free, d); if (j != d) { blk = blkmap(&sblock, cgrp.cg_free, j); fragacct(&sblock, blk, cgrp.cg_frsum, 1); } for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++) clrblock(&sblock, cgrp.cg_free, d); sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree; sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree; sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree; sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir; *cs = cgrp.cg_cs; bwrite(fsbtodb(&sblock, cgtod(&sblock, c)), &cgrp, sblock.fs_cgsize); } for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { bwrite(fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), (char *)sblock.fs_csp[j], sblock.fs_cssize - i < sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize); } sblock.fs_ronly = 0; sblock.fs_fmod = 0; bwrite(SBLOCK, (char *)&sblock, SBSIZE); } /* * update the frsum fields to reflect addition or deletion * of some frags */ fragacct(fs, fragmap, fraglist, cnt) struct fs *fs; int fragmap; long fraglist[]; int cnt; { int inblk; register int field, subfield; register int siz, pos; inblk = (int)(fragtbl[fs->fs_frag][fragmap] << 1); fragmap <<= 1; for (siz = 1; siz < fs->fs_frag; siz++) { if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) continue; field = around[siz]; subfield = inside[siz]; for (pos = siz; pos <= fs->fs_frag; pos++) { if ((fragmap & field) == subfield) { fraglist[siz] += cnt; pos += siz; field <<= siz; subfield <<= siz; } field <<= 1; subfield <<= 1; } } } getsb(fs, file) register struct fs *fs; char *file; { int i, j, size; if (bread(SBLOCK, fs, SBSIZE)) { printf("bad super block"); perror(file); nerror |= 04; return; } if (fs->fs_magic != FS_MAGIC) { printf("%s: bad magic number\n", file); nerror |= 04; return; } for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { size = sblock.fs_cssize - i < sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize; sblock.fs_csp[j] = (struct csum *)calloc(1, size); bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)), (char *)fs->fs_csp[j], size); } } bwrite(blk, buf, size) char *buf; daddr_t blk; register size; { if (lseek(fi, blk * DEV_BSIZE, 0) < 0) { perror("FS SEEK"); return(1); } if (write(fi, buf, size) != size) { perror("FS WRITE"); return(1); } return (0); } bread(bno, buf, cnt) daddr_t bno; char *buf; { register i; lseek(fi, bno * DEV_BSIZE, 0); if ((i = read(fi, buf, cnt)) != cnt) { if (sflg) { printf("No Update\n"); sflg = 0; } for(i=0; ifs_frag) { case 8: return (cp[h] == 0xff); case 4: mask = 0x0f << ((h & 0x1) << 2); return ((cp[h >> 1] & mask) == mask); case 2: mask = 0x03 << ((h & 0x3) << 1); return ((cp[h >> 2] & mask) == mask); case 1: mask = 0x01 << (h & 0x7); return ((cp[h >> 3] & mask) == mask); default: #ifdef STANDALONE printf("isblock bad fs_frag %d\n", fs->fs_frag); #else fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); #endif return; } } /* * take a block out of the map */ clrblock(fs, cp, h) struct fs *fs; unsigned char *cp; int h; { switch ((fs)->fs_frag) { case 8: cp[h] = 0; return; case 4: cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); return; case 2: cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); return; case 1: cp[h >> 3] &= ~(0x01 << (h & 0x7)); return; default: #ifdef STANDALONE printf("clrblock bad fs_frag %d\n", fs->fs_frag); #else fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); #endif return; } } /* * put a block into the map */ setblock(fs, cp, h) struct fs *fs; unsigned char *cp; int h; { switch (fs->fs_frag) { case 8: cp[h] = 0xff; return; case 4: cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); return; case 2: cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); return; case 1: cp[h >> 3] |= (0x01 << (h & 0x7)); return; default: #ifdef STANDALONE printf("setblock bad fs_frag %d\n", fs->fs_frag); #else fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); #endif return; } } /* tables.c 4.1 82/03/25 */ /* merged into kernel: tables.c 2.1 3/25/82 */ /* last monet version: partab.c 4.2 81/03/08 */ /* * bit patterns for identifying fragments in the block map * used as ((map & around) == inside) */ int around[9] = { 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff }; int inside[9] = { 0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe }; /* * given a block map bit pattern, the frag tables tell whether a * particular size fragment is available. * * used as: * if ((1 << (size - 1)) & fragtbl[fs->fs_frag][map] { * at least one fragment of the indicated size is available * } * * These tables are used by the scanc instruction on the VAX to * quickly find an appropriate fragment. */ unsigned char fragtbl124[256] = { 0x00, 0x16, 0x16, 0x2a, 0x16, 0x16, 0x26, 0x4e, 0x16, 0x16, 0x16, 0x3e, 0x2a, 0x3e, 0x4e, 0x8a, 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, 0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e, 0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa, 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, 0x26, 0x36, 0x36, 0x2e, 0x36, 0x36, 0x26, 0x6e, 0x36, 0x36, 0x36, 0x3e, 0x2e, 0x3e, 0x6e, 0xae, 0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e, 0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce, 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe, 0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e, 0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe, 0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e, 0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce, 0x8a, 0x9e, 0x9e, 0xaa, 0x9e, 0x9e, 0xae, 0xce, 0x9e, 0x9e, 0x9e, 0xbe, 0xaa, 0xbe, 0xce, 0x8a, }; unsigned char fragtbl8[256] = { 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a, 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x08, 0x09, 0x09, 0x0a, 0x10, 0x11, 0x20, 0x40, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0a, 0x12, 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0c, 0x08, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x0a, 0x0c, 0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80, }; /* * the actual fragtbl array */ unsigned char *fragtbl[MAXFRAG + 1] = { 0, fragtbl124, fragtbl124, 0, fragtbl124, 0, 0, 0, fragtbl8, };