1*55860Sbostic /*-
2*55860Sbostic  * Copyright (c) 1992 The Regents of the University of California.
3*55860Sbostic  * All rights reserved.
4*55860Sbostic  *
5*55860Sbostic  * %sccs.include.redist.c%
6*55860Sbostic  */
7*55860Sbostic 
8*55860Sbostic #ifndef lint
9*55860Sbostic static char sccsid[] = "@(#)library.c	5.1 (Berkeley) 08/06/92";
10*55860Sbostic #endif /* not lint */
11*55860Sbostic 
1255491Sbostic #include <sys/param.h>
1355491Sbostic #include <sys/time.h>
1455491Sbostic #include <sys/stat.h>
1555491Sbostic #include <sys/mount.h>
1655491Sbostic 
1755491Sbostic #include <ufs/ufs/dinode.h>
1855491Sbostic #include <ufs/lfs/lfs.h>
1955491Sbostic 
2055491Sbostic #include <fcntl.h>
2155491Sbostic #include <stdio.h>
2255491Sbostic #include <unistd.h>
2355856Sbostic #include <stdlib.h>
2455856Sbostic #include <string.h>
2555491Sbostic #include "clean.h"
2655491Sbostic 
2755856Sbostic void	 add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,
2855856Sbostic 	     daddr_t, daddr_t));
2955856Sbostic void	 add_inodes __P((FS_INFO *, INODE_INFO *, int *, SEGSUM *, caddr_t,
3055856Sbostic 	     daddr_t));
3155856Sbostic int	 bi_compare __P((const void *, const void *));
3255856Sbostic int	 bi_toss __P((const void *, const void *, const void *));
3355856Sbostic void	 get_ifile __P((FS_INFO *));
3455856Sbostic int	 get_superblock __P((FS_INFO *, struct lfs *));
3555856Sbostic int	 ii_compare __P((const void *, const void *));
3655856Sbostic int	 ii_toss __P((const void *, const void *, const void *));
3755856Sbostic int	 pseg_valid __P((FS_INFO *, SEGSUM *));
3855856Sbostic 
3955491Sbostic /*
4055856Sbostic  * This function will get information on all mounted file systems
4155491Sbostic  * of a given type.
4255491Sbostic  */
4355491Sbostic int
4455491Sbostic fs_getmntinfo(buf, type)
4555491Sbostic 	struct	statfs	**buf;
4655491Sbostic 	int	type;
4755491Sbostic {
4855856Sbostic 	struct statfs *tstatfsp;
4955856Sbostic 	struct statfs *sbp;
5055856Sbostic 	int count, i, tcount;
5155491Sbostic 
5255491Sbostic 	tcount = getmntinfo(&tstatfsp, 0);
5355491Sbostic 
5455491Sbostic 	if (tcount < 0) {
5555856Sbostic 		err(0, "getmntinfo failed");
5655856Sbostic 		return (-1);
5755491Sbostic 	}
5855491Sbostic 
5955856Sbostic 	for (count = 0, i = 0; i < tcount ; ++i)
6055856Sbostic 		if (tstatfsp[i].f_type == type)
6155856Sbostic 			++count;
6255491Sbostic 
6355856Sbostic 	if (count) {
6455856Sbostic 		if (!(*buf = (struct statfs *)
6555856Sbostic 			malloc(count * sizeof(struct statfs))))
6655856Sbostic 			err(1, "fs_getmntinfo: out of space");
6755856Sbostic 		for (i = 0, sbp = *buf; i < tcount ; ++i) {
6855856Sbostic 			if (tstatfsp[i].f_type == type) {
6955856Sbostic 				*sbp = tstatfsp[i];
7055856Sbostic 				++sbp;
7155491Sbostic 			}
7255491Sbostic 		}
7355491Sbostic 	}
7455856Sbostic 	return (count);
7555491Sbostic }
7655491Sbostic 
7755491Sbostic /*
7855856Sbostic  * Get all the information available on an LFS file system.
7955856Sbostic  * Returns an array of FS_INFO structures, NULL on error.
8055491Sbostic  */
8155856Sbostic FS_INFO *
8255856Sbostic get_fs_info (lstatfsp, count)
8355856Sbostic 	struct statfs *lstatfsp;	/* IN: array of statfs structs */
8455856Sbostic 	int count;			/* IN: number of file systems */
8555491Sbostic {
8655856Sbostic 	FS_INFO	*fp, *fsp;
8755491Sbostic 	int	i;
8855491Sbostic 
8955856Sbostic 	fsp = (FS_INFO *)malloc(count * sizeof(FS_INFO));
9055491Sbostic 
9155856Sbostic 	for (fp = fsp, i = 0; i < count; ++i, ++fp) {
9255856Sbostic 		fp->fi_statfsp = lstatfsp++;
9355856Sbostic 		if (get_superblock (fp, &fp->fi_lfs))
9455856Sbostic 			err(1, "get_fs_info: get_superblock failed");
9555856Sbostic 		fp->fi_daddr_shift =
9655856Sbostic 		     fp->fi_lfs.lfs_bshift - fp->fi_lfs.lfs_fsbtodb;
9755856Sbostic 		get_ifile (fp);
9855491Sbostic 	}
9955856Sbostic 	return (fsp);
10055491Sbostic }
10155491Sbostic 
10255856Sbostic /*
10355856Sbostic  * If we are reading the ifile then we need to refresh it.  Even if
10455856Sbostic  * we are mmapping it, it might have grown.  Finally, we need to
10555856Sbostic  * refresh the file system information (statfs) info.
10655856Sbostic  */
10755491Sbostic void
10855856Sbostic reread_fs_info(fsp, count)
10955856Sbostic 	FS_INFO *fsp;	/* IN: array of fs_infos to free */
11055856Sbostic 	int count;	/* IN: number of file systems */
11155491Sbostic {
11255856Sbostic 	int i;
11355491Sbostic 
11455856Sbostic 	for (i = 0; i < count; ++i, ++fsp) {
11555856Sbostic 		if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp))
11655856Sbostic 			err(0, "reread_fs_info: statfs failed");
11755856Sbostic #ifdef MMAP_WORKS
11855856Sbostic 		if (munmap(fsp->fi_cip, fsp->fi_ifile_length) < 0)
11955856Sbostic 			err(0, "reread_fs_info: munmap failed");
12055491Sbostic #else
12155856Sbostic 		free (fsp->fi_cip);
12255491Sbostic #endif /* MMAP_WORKS */
12355856Sbostic 		get_ifile (fsp);
12455491Sbostic 	}
12555491Sbostic }
12655491Sbostic 
12755491Sbostic /*
12855856Sbostic  * Gets the superblock from disk (possibly in face of errors)
12955491Sbostic  */
13055491Sbostic int
13155491Sbostic get_superblock (fsp, sbp)
13255856Sbostic 	FS_INFO *fsp;		/* local file system info structure */
13355856Sbostic 	struct lfs *sbp;
13455491Sbostic {
13555856Sbostic 	char mntfromname[MNAMELEN+1];
13655856Sbostic         int fid;
13755491Sbostic 
13855491Sbostic 	strcpy(mntfromname, "/dev/r");
13955856Sbostic 	strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
14055491Sbostic 
14155491Sbostic 	if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
14255856Sbostic 		err(0, "get_superblock: bad open");
14355856Sbostic 		return (-1);
14455491Sbostic 	}
14555491Sbostic 
14655856Sbostic 	get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs));
14755491Sbostic 	close (fid);
14855491Sbostic 
14955856Sbostic 	return (0);
15055491Sbostic }
15155491Sbostic 
15255491Sbostic /*
15355856Sbostic  * This function will map the ifile into memory.  It causes a
15455856Sbostic  * fatal error on failure.
15555491Sbostic  */
15655856Sbostic void
15755491Sbostic get_ifile (fsp)
15855491Sbostic 	FS_INFO	*fsp;
15955491Sbostic {
16055856Sbostic 	struct stat file_stat;
16155856Sbostic 	caddr_t ifp;
16255856Sbostic 	char *ifile_name;
16355856Sbostic 	int count, fid;
16455491Sbostic 
16555856Sbostic 	ifp = NULL;
16655856Sbostic 	sync();
16755856Sbostic 	ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) +
16855856Sbostic 	    strlen(IFILE_NAME)+2);
16955856Sbostic 	strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"),
17055856Sbostic 	    IFILE_NAME);
17155491Sbostic 
17255856Sbostic 	if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0)
17355856Sbostic 		err(1, "get_ifile: bad open");
17455491Sbostic 
17555856Sbostic 	if (fstat (fid, &file_stat))
17655856Sbostic 		err(1, "get_ifile: fstat failed");
17755491Sbostic 
17855856Sbostic 	fsp->fi_ifile_length = file_stat.st_size;
17955856Sbostic 
18055491Sbostic 	/* get the ifile */
18155491Sbostic #ifndef MMAP_WORKS
18255856Sbostic 	if (!(ifp = malloc ((size_t)fsp->fi_ifile_length)))
18355856Sbostic 		err (1, "get_ifile: malloc failed");
18455856Sbostic redo_read:
18555856Sbostic 	count = read (fid, ifp, (size_t) fsp->fi_ifile_length);
18655491Sbostic 
18755856Sbostic 	if (count < 0)
18855856Sbostic 		err(1, "get_ifile: bad ifile read");
18955856Sbostic 	else if (count < (int)fsp->fi_ifile_length) {
19055856Sbostic 		err(0, "get_ifile");
19155856Sbostic 		if (lseek(fid, 0, SEEK_SET) < 0)
19255856Sbostic 			err(1, "get_ifile: bad ifile lseek");
19355856Sbostic 		goto redo_read;
19455491Sbostic 	}
19555491Sbostic #else	/* MMAP_WORKS */
19655856Sbostic 	ifp = mmap ((caddr_t)0, (size_t) fsp->fi_ifile_length, PROT_READ|PROT_WRITE,
19755491Sbostic 		MAP_FILE|MAP_SHARED, fid, (off_t)0);
19855856Sbostic 	if (ifp < 0)
19955856Sbostic 		err(1, "get_ifile: mmap failed");
20055491Sbostic #endif	/* MMAP_WORKS */
20155491Sbostic 
20255491Sbostic 	close (fid);
20355491Sbostic 
20455856Sbostic 	fsp->fi_cip = (CLEANERINFO *)ifp;
20555856Sbostic 	fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp));
20655856Sbostic 	fsp->fi_ifilep  = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp));
20755856Sbostic 
20855856Sbostic 	/*
20955856Sbostic 	 * The number of ifile entries is equal to the number of blocks
21055856Sbostic 	 * blocks in the ifile minus the ones allocated to cleaner info
21155856Sbostic 	 * and segment usage table multiplied by the number of ifile
21255856Sbostic 	 * entries per page.
21355856Sbostic 	 */
21455856Sbostic 	fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift -
21555856Sbostic 	    fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) *
21655856Sbostic 	    fsp->fi_lfs.lfs_ifpb;
21755856Sbostic 
21855491Sbostic 	free (ifile_name);
21955491Sbostic }
22055491Sbostic 
22155491Sbostic /*
22255856Sbostic  * This function will scan a segment and return a list of
22355491Sbostic  * <inode, blocknum> pairs which indicate which blocks were
22455856Sbostic  * contained as live data within the segment when the segment
22555856Sbostic  * summary was read (it may have "died" since then).  Any given
22655856Sbostic  * pair will be listed at most once.
22755491Sbostic  */
22855491Sbostic int
22955491Sbostic lfs_segmapv(fsp, seg, seg_buf, blocks, bcount, inodes, icount)
23055856Sbostic 	FS_INFO *fsp;		/* pointer to local file system information */
23155856Sbostic 	int seg;		/* the segment number */
23255856Sbostic 	caddr_t seg_buf;	/* the buffer containing the segment's data */
23355856Sbostic 	BLOCK_INFO **blocks;	/* OUT: array of block_info for live blocks */
23455856Sbostic 	int *bcount;		/* OUT: number of active blocks in segment */
23555856Sbostic 	INODE_INFO **inodes;	/* OUT: array of inode_info for live inodes */
23655856Sbostic 	int *icount; 		/* OUT: number of active inodes in segment */
23755491Sbostic {
23855856Sbostic 	BLOCK_INFO *bip;
23955856Sbostic 	INODE_INFO *iip;
24055856Sbostic 	SEGSUM *sp;
24155856Sbostic 	SEGUSE *sup;
24255856Sbostic 	struct lfs *lfsp;
24355856Sbostic 	caddr_t s, segend;
24455856Sbostic 	daddr_t pseg_addr, seg_addr;
24555856Sbostic 	int nblocks, num_iblocks;
24655856Sbostic 	time_t timestamp;
24755491Sbostic 
24855856Sbostic 	lfsp = &fsp->fi_lfs;
24955856Sbostic 	num_iblocks = lfsp->lfs_ssize;
25055856Sbostic 	if (!(bip = malloc(lfsp->lfs_ssize * sizeof(BLOCK_INFO))))
25155856Sbostic 		goto err0;
25255856Sbostic 	if (!(iip = malloc(lfsp->lfs_ssize * sizeof(INODE_INFO))))
25355856Sbostic 		goto err1;
25455491Sbostic 
25555856Sbostic 	sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg);
25655856Sbostic 	s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0);
25755856Sbostic 	seg_addr = sntoda(lfsp, seg);
25855856Sbostic 	pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0);
25955856Sbostic #ifdef VERBOSE
26055856Sbostic 		printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr);
26155856Sbostic #endif /* VERBOSE */
26255491Sbostic 
26355856Sbostic 	*bcount = 0;
26455856Sbostic 	*icount = 0;
26555856Sbostic 	for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) {
26655856Sbostic 		sp = (SEGSUM *)s;
26755491Sbostic #ifdef VERBOSE
26855856Sbostic 		printf("\tpartial at: 0x%x\n", pseg_addr);
26955856Sbostic 		print_SEGSUM(lfsp, sp);
27055491Sbostic 		fflush(stdout);
27155491Sbostic #endif /* VERBOSE */
27255491Sbostic 
27355856Sbostic 		nblocks = pseg_valid(fsp, sp);
27455856Sbostic 		if (nblocks <= 0)
27555856Sbostic 			break;
27655491Sbostic 
27755856Sbostic 		/* Check if we have hit old data */
27855856Sbostic 		if (timestamp > ((SEGSUM*)s)->ss_create)
27955856Sbostic 			break;
28055491Sbostic 		timestamp = ((SEGSUM*)s)->ss_create;
28155491Sbostic 
28255856Sbostic 		/*
28355856Sbostic 		 * Right now we die if we run out of room, we could probably
28455856Sbostic 		 * recover if we were smart.
28555856Sbostic 		 */
28655856Sbostic 		if (*icount + sp->ss_ninos > num_iblocks) {
28755856Sbostic 			num_iblocks = *icount + sp->ss_ninos;
28855856Sbostic 			iip = realloc (iip, num_iblocks * sizeof(INODE_INFO));
28955856Sbostic 			if (!iip)
29055856Sbostic 				goto err1;
29155856Sbostic 		}
29255856Sbostic 		add_inodes(fsp, iip, icount, sp, seg_buf, seg_addr);
29355856Sbostic 		add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr);
29455856Sbostic 		pseg_addr += fsbtodb(lfsp, nblocks) +
29555856Sbostic 		    bytetoda(fsp, LFS_SUMMARY_SIZE);
29655856Sbostic 		s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE;
29755856Sbostic 	}
29855856Sbostic 	qsort(iip, *icount, sizeof(INODE_INFO), ii_compare);
29955856Sbostic 	qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare);
30055856Sbostic 	toss(iip, icount, sizeof(INODE_INFO), ii_toss, NULL);
30155856Sbostic 	toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL);
30255856Sbostic #ifdef VERBOSE
30355856Sbostic 	{
30455856Sbostic 		BLOCK_INFO *_bip;
30555856Sbostic 		INODE_INFO *_iip;
30655856Sbostic 		int i;
30755491Sbostic 
30855856Sbostic 		printf("BLOCK INFOS\n");
30955856Sbostic 		for (_bip = bip, i=0; i < *bcount; ++_bip, ++i)
31055856Sbostic 			PRINT_BINFO(_bip);
31155856Sbostic 		printf("INODE INFOS\n");
31255856Sbostic 		for (_iip = iip, i=0; i < *icount; ++_iip, ++i)
31355856Sbostic 			PRINT_IINFO(1, _iip);
31455491Sbostic 	}
31555856Sbostic #endif
31655856Sbostic 	*blocks = bip;
31755856Sbostic 	*inodes = iip;
31855856Sbostic 	return (0);
31955856Sbostic 
32055856Sbostic err1:	free(bip);
32155856Sbostic err0:	*bcount = 0;
32255856Sbostic 	*icount = 0;
32355856Sbostic 	return (-1);
32455491Sbostic 
32555491Sbostic }
32655491Sbostic 
32755491Sbostic /*
32855856Sbostic  * This will parse a partial segment and fill in BLOCK_INFO structures
32955856Sbostic  * for each block described in the segment summary.  It will not include
33055856Sbostic  * blocks or inodes from files with new version numbers.
33155491Sbostic  */
33255491Sbostic void
33355856Sbostic add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr)
33455491Sbostic 	FS_INFO *fsp;		/* pointer to super block */
33555856Sbostic 	BLOCK_INFO *bip;	/* Block info array */
33655856Sbostic 	int *countp;		/* IN/OUT: number of blocks in array */
33755856Sbostic 	SEGSUM	*sp;		/* segment summmary pointer */
33855856Sbostic 	caddr_t seg_buf;	/* buffer containing segment */
33955856Sbostic 	daddr_t segaddr;	/* address of this segment */
34055856Sbostic 	daddr_t psegaddr;	/* address of this partial segment */
34155491Sbostic {
34255856Sbostic 	IFILE	*ifp;
34355856Sbostic 	FINFO	*fip;
34455856Sbostic 	caddr_t	bp;
34555856Sbostic 	daddr_t	*dp;
34655856Sbostic 	daddr_t *iaddrp;	/* pointer to current inode block */
34755856Sbostic 	int db_per_block, i, j;
34855856Sbostic 	u_long page_size;
34955491Sbostic 
35055491Sbostic #ifdef VERBOSE
35155856Sbostic 	printf("FILE INFOS\n");
35255491Sbostic #endif
35355856Sbostic 	db_per_block = fsbtodb(&fsp->fi_lfs, 1);
35455856Sbostic 	page_size = fsp->fi_lfs.lfs_bsize;
35555856Sbostic 	bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE;
35655856Sbostic 	bip += *countp;
35755856Sbostic 	psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE);
35855856Sbostic 	iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
35955856Sbostic 	--iaddrp;
36055856Sbostic 	for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo;
36155856Sbostic 	    ++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) {
36255491Sbostic 
36355856Sbostic 		ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino);
36455856Sbostic 		PRINT_FINFO(fip, ifp);
36555856Sbostic 		if (ifp->if_version > fip->fi_version)
36655491Sbostic 			continue;
36755856Sbostic 		dp = &(fip->fi_blocks[0]);
36855856Sbostic 		for (j = 0; j < fip->fi_nblocks; j++, dp++) {
36955856Sbostic 			while (psegaddr == *iaddrp) {
37055856Sbostic 				psegaddr += db_per_block;
37155856Sbostic 				bp += page_size;
37255856Sbostic 				--iaddrp;
37355491Sbostic 			}
37455856Sbostic 			bip->bi_inode = fip->fi_ino;
37555856Sbostic 			bip->bi_lbn = *dp;
37655856Sbostic 			bip->bi_daddr = psegaddr;
37755856Sbostic 			bip->bi_segcreate = (time_t)(sp->ss_create);
37855856Sbostic 			bip->bi_bp = bp;
37955856Sbostic 			psegaddr += db_per_block;
38055856Sbostic 			bp += page_size;
38155856Sbostic 			++bip;
38255856Sbostic 			++(*countp);
38355491Sbostic 		}
38455491Sbostic 	}
38555491Sbostic }
38655491Sbostic 
38755856Sbostic /*
38855856Sbostic  * For a particular segment summary, reads the inode blocks and adds
38955856Sbostic  * INODE_INFO structures to the array.  Returns the number of inodes
39055856Sbostic  * actually added.
39155856Sbostic  */
39255491Sbostic void
39355856Sbostic add_inodes (fsp, iip, countp, sp, seg_buf, seg_addr)
39455491Sbostic 	FS_INFO *fsp;		/* pointer to super block */
39555856Sbostic 	INODE_INFO *iip;
39655856Sbostic 	int *countp;		/* pointer to current number of inodes */
39755856Sbostic 	SEGSUM *sp;		/* segsum pointer */
39855491Sbostic 	caddr_t	seg_buf;	/* the buffer containing the segment's data */
39955856Sbostic 	daddr_t	seg_addr;	/* disk address of seg_buf */
40055491Sbostic {
40155856Sbostic 	struct dinode *di;
40255856Sbostic 	struct lfs *lfsp;
40355856Sbostic 	IFILE *ifp;
40455856Sbostic 	INODE_INFO *ip;
40555856Sbostic 	daddr_t	*daddrp;
40655856Sbostic 	ino_t inum;
40755856Sbostic 	int i;
40855491Sbostic 
40955856Sbostic 	if (sp->ss_ninos <= 0)
41055856Sbostic 		return;
41155491Sbostic 
41255856Sbostic 	ip = iip + *countp;
41355856Sbostic 	lfsp = &fsp->fi_lfs;
41455491Sbostic #ifdef VERBOSE
41555856Sbostic 	(void) printf("INODE_INFOS:\n");
41655491Sbostic #endif
41755856Sbostic 	daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
41855856Sbostic 	for (i = 0; i < sp->ss_ninos; ++i) {
41955491Sbostic 		if (i % INOPB(lfsp) == 0) {
42055856Sbostic 			--daddrp;
42155856Sbostic 			di = (struct dinode *)(seg_buf +
42255856Sbostic 			    ((*daddrp - seg_addr) << fsp->fi_daddr_shift));
42355491Sbostic 		} else
42455491Sbostic 			++di;
42555491Sbostic 
42655491Sbostic 		inum = di->di_inum;
42755856Sbostic 		ip->ii_daddr = *daddrp;
42855856Sbostic 		ip->ii_inode = inum;
42955856Sbostic 		ip->ii_dinode = di;
43055856Sbostic 		ip->ii_segcreate = sp->ss_create;
43155491Sbostic 
43255856Sbostic 		ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum);
43355856Sbostic 		PRINT_IINFO(ifp->if_daddr == *daddrp, ip);
43455856Sbostic 		if (ifp->if_daddr == *daddrp) {
43555856Sbostic 			ip++;
43655856Sbostic 			++(*countp);
43755491Sbostic 		}
43855491Sbostic 	}
43955491Sbostic }
44055491Sbostic 
44155491Sbostic /*
44255856Sbostic  * Checks the summary checksum and the data checksum to determine if the
44355856Sbostic  * segment is valid or not.  Returns the size of the partial segment if it
44455856Sbostic  * is valid, * and 0 otherwise.  Use dump_summary to figure out size of the
44555856Sbostic  * the partial as well as whether or not the checksum is valid.
44655491Sbostic  */
44755491Sbostic int
44855491Sbostic pseg_valid (fsp, ssp)
44955491Sbostic 	FS_INFO *fsp;   /* pointer to file system info */
45055856Sbostic 	SEGSUM *ssp;	/* pointer to segment summary block */
45155491Sbostic {
45255491Sbostic 	caddr_t	p;
45355856Sbostic 	int i, nblocks;
45455856Sbostic 	u_long *datap;
45555491Sbostic 
45655856Sbostic 	if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0)
45755856Sbostic 		return(0);
45855491Sbostic 
45955856Sbostic 	/* check data/inode block(s) checksum too */
46055856Sbostic 	datap = (u_long *)malloc(nblocks * sizeof(u_long));
46155491Sbostic 	p = (caddr_t)ssp + LFS_SUMMARY_SIZE;
46255856Sbostic 	for (i = 0; i < nblocks; ++i) {
46355491Sbostic 		datap[i] = *((u_long *)p);
46455856Sbostic 		p += fsp->fi_lfs.lfs_bsize;
46555491Sbostic 	}
46655856Sbostic 	if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum)
46755856Sbostic 		return (0);
46855491Sbostic 
46955856Sbostic 	return (nblocks);
47055491Sbostic }
47155491Sbostic 
47255491Sbostic 
47355491Sbostic /* #define MMAP_SEGMENT */
47455491Sbostic /*
47555491Sbostic  * read a segment into a memory buffer
47655491Sbostic  */
47755491Sbostic int
47855856Sbostic mmap_segment (fsp, segment, segbuf)
47955856Sbostic 	FS_INFO *fsp;		/* file system information */
48055856Sbostic 	int segment;		/* segment number */
48155856Sbostic 	caddr_t *segbuf;	/* pointer to buffer area */
48255491Sbostic {
48355856Sbostic 	struct lfs *lfsp;
48455856Sbostic 	int fid;		/* fildes for file system device */
48555856Sbostic 	daddr_t seg_daddr;	/* base disk address of segment */
48655856Sbostic 	off_t seg_byte;
48755856Sbostic 	size_t ssize;
48855856Sbostic 	char mntfromname[MNAMELEN+2];
48955491Sbostic 
49055856Sbostic 	lfsp = &fsp->fi_lfs;
49155856Sbostic 
49255491Sbostic 	/* get the disk address of the beginning of the segment */
49355491Sbostic 	seg_daddr = sntoda(lfsp, segment);
49455856Sbostic 	seg_byte = datobyte(fsp, seg_daddr);
49555856Sbostic 	ssize = seg_size(lfsp);
49655491Sbostic 
49755491Sbostic 	strcpy(mntfromname, "/dev/r");
49855856Sbostic 	strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
49955491Sbostic 
50055491Sbostic 	if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
50155856Sbostic 		err(0, "mmap_segment: bad open");
50255856Sbostic 		return (-1);
50355491Sbostic 	}
50455491Sbostic 
50555491Sbostic #ifdef MMAP_SEGMENT
50655856Sbostic 	*segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ,
50755856Sbostic 	    MAP_FILE, fid, seg_byte);
50855856Sbostic 	if (*(long *)segbuf < 0) {
50955856Sbostic 		err(0, "mmap_segment: mmap failed");
51055856Sbostic 		return (NULL);
51155491Sbostic 	}
51255491Sbostic #else /* MMAP_SEGMENT */
51355856Sbostic #ifdef VERBOSE
51455856Sbostic 	printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n",
51555856Sbostic 	    seg_daddr, ssize, seg_byte);
51655856Sbostic #endif
51755491Sbostic 	/* malloc the space for the buffer */
51855856Sbostic 	*segbuf = malloc(ssize);
51955856Sbostic 	if (!*segbuf) {
52055856Sbostic 		err(0, "mmap_segment: malloc failed");
52155856Sbostic 		return(NULL);
52255856Sbostic 	}
52355491Sbostic 
52455491Sbostic 	/* read the segment data into the buffer */
52555856Sbostic 	if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) {
52655856Sbostic 		err (0, "mmap_segment: bad lseek");
52755856Sbostic 		free(*segbuf);
52855856Sbostic 		return (-1);
52955491Sbostic 	}
53055491Sbostic 
53155856Sbostic 	if (read (fid, *segbuf, ssize) != ssize) {
53255856Sbostic 		err (0, "mmap_segment: bad read");
53355856Sbostic 		free(*segbuf);
53455856Sbostic 		return (-1);
53555491Sbostic 	}
53655491Sbostic #endif /* MMAP_SEGMENT */
53755491Sbostic 	close (fid);
53855491Sbostic 
53955856Sbostic 	return (0);
54055491Sbostic }
54155491Sbostic 
54255491Sbostic void
54355491Sbostic munmap_segment (fsp, seg_buf)
54455856Sbostic 	FS_INFO *fsp;		/* file system information */
54555856Sbostic 	caddr_t seg_buf;	/* pointer to buffer area */
54655491Sbostic {
54755491Sbostic #ifdef MMAP_SEGMENT
54855856Sbostic 	munmap (seg_buf, seg_size(&fsp->fi_lfs));
54955491Sbostic #else /* MMAP_SEGMENT */
55055491Sbostic 	free (seg_buf);
55155491Sbostic #endif /* MMAP_SEGMENT */
55255491Sbostic }
55355491Sbostic 
55455491Sbostic 
55555491Sbostic /*
55655491Sbostic  * USEFUL DEBUGGING TOOLS:
55755491Sbostic  */
55855491Sbostic void
55955856Sbostic print_SEGSUM (lfsp, p)
56055856Sbostic 	struct lfs *lfsp;
56155856Sbostic 	SEGSUM	*p;
56255491Sbostic {
56355856Sbostic 	if (p)
56455856Sbostic 		(void) dump_summary(lfsp, p, DUMP_ALL, NULL);
56555491Sbostic 	else printf("0x0");
56655491Sbostic 	fflush(stdout);
56755491Sbostic }
56855491Sbostic 
56955856Sbostic int
57055856Sbostic bi_compare(a, b)
57155856Sbostic 	const void *a;
57255856Sbostic 	const void *b;
57355491Sbostic {
57455856Sbostic 	const BLOCK_INFO *ba, *bb;
57555856Sbostic 	int diff;
57655491Sbostic 
57755856Sbostic 	ba = a;
57855856Sbostic 	bb = b;
57955491Sbostic 
58055856Sbostic 	if (diff = (int)(ba->bi_inode - bb->bi_inode))
58155856Sbostic 		return (diff);
58255856Sbostic 	if (diff = (int)(ba->bi_lbn - bb->bi_lbn))
58355856Sbostic 		return (diff);
58455856Sbostic 	if (diff = (int)(ba->bi_segcreate - bb->bi_segcreate))
58555856Sbostic 		return (diff);
58655856Sbostic 	diff = (int)(ba->bi_daddr - bb->bi_daddr);
58755856Sbostic 	return (diff);
58855856Sbostic }
58955491Sbostic 
59055856Sbostic int
59155856Sbostic bi_toss(dummy, a, b)
59255856Sbostic 	const void *dummy;
59355856Sbostic 	const void *a;
59455856Sbostic 	const void *b;
59555491Sbostic {
59655856Sbostic 	const BLOCK_INFO *ba, *bb;
59755491Sbostic 
59855856Sbostic 	ba = a;
59955856Sbostic 	bb = b;
60055856Sbostic 
60155856Sbostic 	return(ba->bi_inode == bb->bi_inode && ba->bi_lbn == bb->bi_lbn);
60255491Sbostic }
60355491Sbostic 
60455856Sbostic /*
60555856Sbostic  * Right now, we never look at the actually data being
60655856Sbostic  * passed to the kernel in iip->ii_dinode.  Therefore,
60755856Sbostic  * if the same inode appears twice in the same block
60855856Sbostic  * (i.e.  has the same disk address), it doesn't matter
60955856Sbostic  * which entry we pass.  However, if we get the kernel
61055856Sbostic  * to start looking at the dinode, then we will care
61155856Sbostic  * and we'll need some way to distinguish which inode
61255856Sbostic  * is the more recent one.
61355856Sbostic  */
61455856Sbostic int
61555856Sbostic ii_compare(a, b)
61655856Sbostic 	const void *a;
61755856Sbostic 	const void *b;
61855491Sbostic {
61955856Sbostic 	const INODE_INFO *ia, *ib;
62055856Sbostic 	int diff;
62155491Sbostic 
62255856Sbostic 	ia = a;
62355856Sbostic 	ib = b;
62455856Sbostic 
62555856Sbostic 	if (diff = (int)(ia->ii_inode - ib->ii_inode))
62655856Sbostic 		return (diff);
62755856Sbostic 	if (diff = (int)(ia->ii_segcreate - ib->ii_segcreate))
62855856Sbostic 		return (diff);
62955856Sbostic 	diff = (int)(ia->ii_daddr - ib->ii_daddr);
63055856Sbostic 	return (diff);
63155491Sbostic }
63255491Sbostic 
63355856Sbostic int
63455856Sbostic ii_toss(dummy, a, b)
63555856Sbostic 	const void *dummy;
63655856Sbostic 	const void *a;
63755856Sbostic 	const void *b;
63855491Sbostic {
63955856Sbostic 	const INODE_INFO *ia, *ib;
64055491Sbostic 
64155856Sbostic 	ia = a;
64255856Sbostic 	ib = b;
64355856Sbostic 
64455856Sbostic 	return(ia->ii_inode == ib->ii_inode);
64555491Sbostic }
64655491Sbostic 
64755491Sbostic void
64855856Sbostic toss(p, nump, size, dotoss, client)
64955856Sbostic 	void *p;
65055856Sbostic 	int *nump;
65155856Sbostic 	size_t size;
65255856Sbostic 	int (*dotoss) __P((const void *, const void *, const void *));
65355856Sbostic 	void *client;
65455491Sbostic {
65555856Sbostic 	int i;
65655856Sbostic 	void *p1;
65755491Sbostic 
65855856Sbostic 	if (*nump == 0)
65955856Sbostic 		return;
66055491Sbostic 
66155856Sbostic 	for (i = *nump; --i > 0;) {
66255856Sbostic 		p1 = p + size;
66355856Sbostic 		if (dotoss(client, p, p1)) {
66455856Sbostic 			bcopy(p1, p, i * size);
66555856Sbostic 			--(*nump);
66655856Sbostic 		} else
66755856Sbostic 			p += size;
66855491Sbostic 	}
66955491Sbostic }
670