[net.sources] Find lost blocks in V6 filesystem

campbell@maynard.UUCP (Larry Campbell) (03/22/86)

V6 and V7 apparently have filesystem bug(s) that can result in a file
claiming to be n bytes long but actually owning many more than (n+511)/512
blocks.  fsck doesn't help;  everything seems consistent, but when you
add everything up you find that you're short several thousand blocks.

This program, originally written for V7 by Fred Toth, is a lifesaver.
It will find all the files that incorrectly own big chunks of the disk;
you can then copy the files (cp only copies up to the EOF pointer) and
delete the original to free up the space.  I have modified it for V6
filesystems to run on my VENIX 2.0 system (V7 kernel with V6 filesystem).

Share and enjoy.
------------------------------cut here------------------------------
/*
 * This posting is for those interested in the 'disappearing disk space'
 * discussion in net.unix-wizards.
 *
 * Fred Toth
 * Washburn Graphics, Inc.
 * Charlotte, NC
 * decvax!mcnc!unccvax!wgivax!fpt
 *
 * scani.c
 *
 * This program scans a v7 file system, looking for inodes
 * that have more blocks allocated to them then they need
 * based on the size field.
 *
 * It reads it's standard input and reports inode numbers.
 * Ncheck can then be used to find the files.
 * Copying them and deleting the original will free the blocks.
 *
 ***********************************************************************
 *
 * Modified for V6 (VENIX, actually, V7 kernel with V6 filesystem)
 * by Larry Campbell (maynard!campbell)
 *
 */
#include <stdio.h>
#include <sys/param.h>
#include <sys/filsys.h>
#include <sys/ino.h>

struct filsys sb;

struct inode mynod;

#define NADDR 8		/* number of disk address in inode */
#define SINODE 32	/* size of an inode in bytes */
#define BLKSIZ 512	/* size of a disk block */
#define NBLKADR (BLKSIZ / (sizeof daddr_t))	/* disk addresses per block */

long ci, cii, ciii;

main()
{
	int i;
	unsigned toti, in;
	long has, need, countb(), extra, totex, totb, size;
	int files;

	files = 0;
	totb = totex = 0L;
	lseek(0, (long) BLKSIZ, 0);
	read(0, &sb, sizeof(struct filsys));
	toti = (sb.s_isize - 2) * (BLKSIZ / SINODE);
	printf("%u inodes\n", toti);
	lseek(0, (long) BLKSIZ*2, 0);
	in = 0;
	while (toti--) {
		in++;
		lseek(0, (((long) in - 1L) * 32L) + (long) BLKSIZ*2, 0);
		if (read(0, &mynod, sizeof(struct inode)) == NULL)
			break;
		if (mynod.i_mode) {
			if (mynod.i_mode & IFCHR)
				continue;
			files++;
			size = (((long) mynod.i_size0) << 16) + mynod.i_size1;
			need = (size + (BLKSIZ-1)) / BLKSIZ;
			if ((has = countb()) > need) {
				extra = has - need;
				totex += extra;
				printf("i %u, needs %D, has %D, %D extra\n", in, need, has, extra);
			}
			totb += has;
		}
	}
	printf("Did %u inodes, %d files\n", in, files);
	printf("%D extra allocated blocks\n", totex);
	printf("%D data, %D i, %D, ii, %D iii\n", totb, ci, cii, ciii);
}
long
countb()
{
	int i;
	long count, cindir(), cdoub(), ctrip();

	count = 0;
	if (mynod.i_mode & ILARG)
	    {
	    for (i = 0; i < 6; i++)
		if (mynod.i_addr[i])
		    count += cindir(mynod.i_addr[i]);
	    if (mynod.i_addr[7])
	        count += cdoub(mynod.i_addr[7]);
	    }
	else
	    for (i = 0; i < 7; i++)
		if (mynod.i_addr[i])
		    count++;
	return(count);
}
long
cindir(blk)
daddr_t blk;
{
	long count;
	daddr_t ib[256];
	int i;

	count = 0;
	getblk(ib, blk);
	ci++;
	for (i = 0; i < 256; i++)
		if (ib[i])
			count++;
	return(count);
}
getblk(p, no)
char *p;
daddr_t no;
{
	lseek(0, ((long) no) * BLKSIZ, 0);
	if (read(0, p, BLKSIZ) <= 0)
		printf("bad read, b %D\n", no);
}
long
cdoub(blk)
daddr_t blk;
{
	daddr_t dib[256];
	long count;
	int i;

	count = 0;
	getblk(dib, blk);
	cii++;
	for (i = 0; i < 256; i++)
		if (dib[i])
			count += cindir(dib[i]);
	return(count);
}
long
ctrip(blk)
daddr_t blk;
{
	daddr_t tib[256];
	long count;
	int i;

	count = 0;
	getblk(tib, blk);
	ciii++;
	for (i = 0; i < 256; i++)
		if (tib[i])
			count += cdoub(tib[i]);
	return(count);
}

-- 
Larry Campbell                                 The Boston Software Works, Inc.
ARPA: maynard.UUCP:campbell@harvard.ARPA       120 Fulton Street
UUCP: {harvard,cbosgd}!wjh12!maynard!campbell  Boston MA 02109