155491Sbostic #include <sys/param.h>
255491Sbostic #include <sys/time.h>
355491Sbostic #include <sys/stat.h>
455491Sbostic #include <sys/mount.h>
555491Sbostic 
655491Sbostic #include <ufs/ufs/dinode.h>
755491Sbostic #include <ufs/lfs/lfs.h>
855491Sbostic 
955491Sbostic #include <fcntl.h>
1055491Sbostic #include <stdio.h>
1155491Sbostic #include <unistd.h>
12*55856Sbostic #include <stdlib.h>
13*55856Sbostic #include <string.h>
1455491Sbostic #include "clean.h"
1555491Sbostic 
16*55856Sbostic void	 add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,
17*55856Sbostic 	     daddr_t, daddr_t));
18*55856Sbostic void	 add_inodes __P((FS_INFO *, INODE_INFO *, int *, SEGSUM *, caddr_t,
19*55856Sbostic 	     daddr_t));
20*55856Sbostic int	 bi_compare __P((const void *, const void *));
21*55856Sbostic int	 bi_toss __P((const void *, const void *, const void *));
22*55856Sbostic void	 get_ifile __P((FS_INFO *));
23*55856Sbostic int	 get_superblock __P((FS_INFO *, struct lfs *));
24*55856Sbostic int	 ii_compare __P((const void *, const void *));
25*55856Sbostic int	 ii_toss __P((const void *, const void *, const void *));
26*55856Sbostic int	 pseg_valid __P((FS_INFO *, SEGSUM *));
27*55856Sbostic 
2855491Sbostic /*
29*55856Sbostic  * This function will get information on all mounted file systems
3055491Sbostic  * of a given type.
3155491Sbostic  */
3255491Sbostic int
3355491Sbostic fs_getmntinfo(buf, type)
3455491Sbostic 	struct	statfs	**buf;
3555491Sbostic 	int	type;
3655491Sbostic {
37*55856Sbostic 	struct statfs *tstatfsp;
38*55856Sbostic 	struct statfs *sbp;
39*55856Sbostic 	int count, i, tcount;
4055491Sbostic 
4155491Sbostic 	tcount = getmntinfo(&tstatfsp, 0);
4255491Sbostic 
4355491Sbostic 	if (tcount < 0) {
44*55856Sbostic 		err(0, "getmntinfo failed");
45*55856Sbostic 		return (-1);
4655491Sbostic 	}
4755491Sbostic 
48*55856Sbostic 	for (count = 0, i = 0; i < tcount ; ++i)
49*55856Sbostic 		if (tstatfsp[i].f_type == type)
50*55856Sbostic 			++count;
5155491Sbostic 
52*55856Sbostic 	if (count) {
53*55856Sbostic 		if (!(*buf = (struct statfs *)
54*55856Sbostic 			malloc(count * sizeof(struct statfs))))
55*55856Sbostic 			err(1, "fs_getmntinfo: out of space");
56*55856Sbostic 		for (i = 0, sbp = *buf; i < tcount ; ++i) {
57*55856Sbostic 			if (tstatfsp[i].f_type == type) {
58*55856Sbostic 				*sbp = tstatfsp[i];
59*55856Sbostic 				++sbp;
6055491Sbostic 			}
6155491Sbostic 		}
6255491Sbostic 	}
63*55856Sbostic 	return (count);
6455491Sbostic }
6555491Sbostic 
6655491Sbostic /*
67*55856Sbostic  * Get all the information available on an LFS file system.
68*55856Sbostic  * Returns an array of FS_INFO structures, NULL on error.
6955491Sbostic  */
70*55856Sbostic FS_INFO *
71*55856Sbostic get_fs_info (lstatfsp, count)
72*55856Sbostic 	struct statfs *lstatfsp;	/* IN: array of statfs structs */
73*55856Sbostic 	int count;			/* IN: number of file systems */
7455491Sbostic {
75*55856Sbostic 	FS_INFO	*fp, *fsp;
7655491Sbostic 	int	i;
7755491Sbostic 
78*55856Sbostic 	fsp = (FS_INFO *)malloc(count * sizeof(FS_INFO));
7955491Sbostic 
80*55856Sbostic 	for (fp = fsp, i = 0; i < count; ++i, ++fp) {
81*55856Sbostic 		fp->fi_statfsp = lstatfsp++;
82*55856Sbostic 		if (get_superblock (fp, &fp->fi_lfs))
83*55856Sbostic 			err(1, "get_fs_info: get_superblock failed");
84*55856Sbostic 		fp->fi_daddr_shift =
85*55856Sbostic 		     fp->fi_lfs.lfs_bshift - fp->fi_lfs.lfs_fsbtodb;
86*55856Sbostic 		get_ifile (fp);
8755491Sbostic 	}
88*55856Sbostic 	return (fsp);
8955491Sbostic }
9055491Sbostic 
91*55856Sbostic /*
92*55856Sbostic  * If we are reading the ifile then we need to refresh it.  Even if
93*55856Sbostic  * we are mmapping it, it might have grown.  Finally, we need to
94*55856Sbostic  * refresh the file system information (statfs) info.
95*55856Sbostic  */
9655491Sbostic void
97*55856Sbostic reread_fs_info(fsp, count)
98*55856Sbostic 	FS_INFO *fsp;	/* IN: array of fs_infos to free */
99*55856Sbostic 	int count;	/* IN: number of file systems */
10055491Sbostic {
101*55856Sbostic 	int i;
10255491Sbostic 
103*55856Sbostic 	for (i = 0; i < count; ++i, ++fsp) {
104*55856Sbostic 		if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp))
105*55856Sbostic 			err(0, "reread_fs_info: statfs failed");
106*55856Sbostic #ifdef MMAP_WORKS
107*55856Sbostic 		if (munmap(fsp->fi_cip, fsp->fi_ifile_length) < 0)
108*55856Sbostic 			err(0, "reread_fs_info: munmap failed");
10955491Sbostic #else
110*55856Sbostic 		free (fsp->fi_cip);
11155491Sbostic #endif /* MMAP_WORKS */
112*55856Sbostic 		get_ifile (fsp);
11355491Sbostic 	}
11455491Sbostic }
11555491Sbostic 
11655491Sbostic /*
117*55856Sbostic  * Gets the superblock from disk (possibly in face of errors)
11855491Sbostic  */
11955491Sbostic int
12055491Sbostic get_superblock (fsp, sbp)
121*55856Sbostic 	FS_INFO *fsp;		/* local file system info structure */
122*55856Sbostic 	struct lfs *sbp;
12355491Sbostic {
124*55856Sbostic 	char mntfromname[MNAMELEN+1];
125*55856Sbostic         int fid;
12655491Sbostic 
12755491Sbostic 	strcpy(mntfromname, "/dev/r");
128*55856Sbostic 	strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
12955491Sbostic 
13055491Sbostic 	if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
131*55856Sbostic 		err(0, "get_superblock: bad open");
132*55856Sbostic 		return (-1);
13355491Sbostic 	}
13455491Sbostic 
135*55856Sbostic 	get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs));
13655491Sbostic 	close (fid);
13755491Sbostic 
138*55856Sbostic 	return (0);
13955491Sbostic }
14055491Sbostic 
14155491Sbostic /*
142*55856Sbostic  * This function will map the ifile into memory.  It causes a
143*55856Sbostic  * fatal error on failure.
14455491Sbostic  */
145*55856Sbostic void
14655491Sbostic get_ifile (fsp)
14755491Sbostic 	FS_INFO	*fsp;
14855491Sbostic {
149*55856Sbostic 	struct stat file_stat;
150*55856Sbostic 	caddr_t ifp;
151*55856Sbostic 	char *ifile_name;
152*55856Sbostic 	int count, fid;
15355491Sbostic 
154*55856Sbostic 	ifp = NULL;
155*55856Sbostic 	sync();
156*55856Sbostic 	ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) +
157*55856Sbostic 	    strlen(IFILE_NAME)+2);
158*55856Sbostic 	strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"),
159*55856Sbostic 	    IFILE_NAME);
16055491Sbostic 
161*55856Sbostic 	if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0)
162*55856Sbostic 		err(1, "get_ifile: bad open");
16355491Sbostic 
164*55856Sbostic 	if (fstat (fid, &file_stat))
165*55856Sbostic 		err(1, "get_ifile: fstat failed");
16655491Sbostic 
167*55856Sbostic 	fsp->fi_ifile_length = file_stat.st_size;
168*55856Sbostic 
16955491Sbostic 	/* get the ifile */
17055491Sbostic #ifndef MMAP_WORKS
171*55856Sbostic 	if (!(ifp = malloc ((size_t)fsp->fi_ifile_length)))
172*55856Sbostic 		err (1, "get_ifile: malloc failed");
173*55856Sbostic redo_read:
174*55856Sbostic 	count = read (fid, ifp, (size_t) fsp->fi_ifile_length);
17555491Sbostic 
176*55856Sbostic 	if (count < 0)
177*55856Sbostic 		err(1, "get_ifile: bad ifile read");
178*55856Sbostic 	else if (count < (int)fsp->fi_ifile_length) {
179*55856Sbostic 		err(0, "get_ifile");
180*55856Sbostic 		if (lseek(fid, 0, SEEK_SET) < 0)
181*55856Sbostic 			err(1, "get_ifile: bad ifile lseek");
182*55856Sbostic 		goto redo_read;
18355491Sbostic 	}
18455491Sbostic #else	/* MMAP_WORKS */
185*55856Sbostic 	ifp = mmap ((caddr_t)0, (size_t) fsp->fi_ifile_length, PROT_READ|PROT_WRITE,
18655491Sbostic 		MAP_FILE|MAP_SHARED, fid, (off_t)0);
187*55856Sbostic 	if (ifp < 0)
188*55856Sbostic 		err(1, "get_ifile: mmap failed");
18955491Sbostic #endif	/* MMAP_WORKS */
19055491Sbostic 
19155491Sbostic 	close (fid);
19255491Sbostic 
193*55856Sbostic 	fsp->fi_cip = (CLEANERINFO *)ifp;
194*55856Sbostic 	fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp));
195*55856Sbostic 	fsp->fi_ifilep  = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp));
196*55856Sbostic 
197*55856Sbostic 	/*
198*55856Sbostic 	 * The number of ifile entries is equal to the number of blocks
199*55856Sbostic 	 * blocks in the ifile minus the ones allocated to cleaner info
200*55856Sbostic 	 * and segment usage table multiplied by the number of ifile
201*55856Sbostic 	 * entries per page.
202*55856Sbostic 	 */
203*55856Sbostic 	fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift -
204*55856Sbostic 	    fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) *
205*55856Sbostic 	    fsp->fi_lfs.lfs_ifpb;
206*55856Sbostic 
20755491Sbostic 	free (ifile_name);
20855491Sbostic }
20955491Sbostic 
21055491Sbostic /*
211*55856Sbostic  * This function will scan a segment and return a list of
21255491Sbostic  * <inode, blocknum> pairs which indicate which blocks were
213*55856Sbostic  * contained as live data within the segment when the segment
214*55856Sbostic  * summary was read (it may have "died" since then).  Any given
215*55856Sbostic  * pair will be listed at most once.
21655491Sbostic  */
21755491Sbostic int
21855491Sbostic lfs_segmapv(fsp, seg, seg_buf, blocks, bcount, inodes, icount)
219*55856Sbostic 	FS_INFO *fsp;		/* pointer to local file system information */
220*55856Sbostic 	int seg;		/* the segment number */
221*55856Sbostic 	caddr_t seg_buf;	/* the buffer containing the segment's data */
222*55856Sbostic 	BLOCK_INFO **blocks;	/* OUT: array of block_info for live blocks */
223*55856Sbostic 	int *bcount;		/* OUT: number of active blocks in segment */
224*55856Sbostic 	INODE_INFO **inodes;	/* OUT: array of inode_info for live inodes */
225*55856Sbostic 	int *icount; 		/* OUT: number of active inodes in segment */
22655491Sbostic {
227*55856Sbostic 	BLOCK_INFO *bip;
228*55856Sbostic 	INODE_INFO *iip;
229*55856Sbostic 	SEGSUM *sp;
230*55856Sbostic 	SEGUSE *sup;
231*55856Sbostic 	struct lfs *lfsp;
232*55856Sbostic 	caddr_t s, segend;
233*55856Sbostic 	daddr_t pseg_addr, seg_addr;
234*55856Sbostic 	int nblocks, num_iblocks;
235*55856Sbostic 	time_t timestamp;
23655491Sbostic 
237*55856Sbostic 	lfsp = &fsp->fi_lfs;
238*55856Sbostic 	num_iblocks = lfsp->lfs_ssize;
239*55856Sbostic 	if (!(bip = malloc(lfsp->lfs_ssize * sizeof(BLOCK_INFO))))
240*55856Sbostic 		goto err0;
241*55856Sbostic 	if (!(iip = malloc(lfsp->lfs_ssize * sizeof(INODE_INFO))))
242*55856Sbostic 		goto err1;
24355491Sbostic 
244*55856Sbostic 	sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg);
245*55856Sbostic 	s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0);
246*55856Sbostic 	seg_addr = sntoda(lfsp, seg);
247*55856Sbostic 	pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0);
248*55856Sbostic #ifdef VERBOSE
249*55856Sbostic 		printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr);
250*55856Sbostic #endif /* VERBOSE */
25155491Sbostic 
252*55856Sbostic 	*bcount = 0;
253*55856Sbostic 	*icount = 0;
254*55856Sbostic 	for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) {
255*55856Sbostic 		sp = (SEGSUM *)s;
25655491Sbostic #ifdef VERBOSE
257*55856Sbostic 		printf("\tpartial at: 0x%x\n", pseg_addr);
258*55856Sbostic 		print_SEGSUM(lfsp, sp);
25955491Sbostic 		fflush(stdout);
26055491Sbostic #endif /* VERBOSE */
26155491Sbostic 
262*55856Sbostic 		nblocks = pseg_valid(fsp, sp);
263*55856Sbostic 		if (nblocks <= 0)
264*55856Sbostic 			break;
26555491Sbostic 
266*55856Sbostic 		/* Check if we have hit old data */
267*55856Sbostic 		if (timestamp > ((SEGSUM*)s)->ss_create)
268*55856Sbostic 			break;
26955491Sbostic 		timestamp = ((SEGSUM*)s)->ss_create;
27055491Sbostic 
271*55856Sbostic 		/*
272*55856Sbostic 		 * Right now we die if we run out of room, we could probably
273*55856Sbostic 		 * recover if we were smart.
274*55856Sbostic 		 */
275*55856Sbostic 		if (*icount + sp->ss_ninos > num_iblocks) {
276*55856Sbostic 			num_iblocks = *icount + sp->ss_ninos;
277*55856Sbostic 			iip = realloc (iip, num_iblocks * sizeof(INODE_INFO));
278*55856Sbostic 			if (!iip)
279*55856Sbostic 				goto err1;
280*55856Sbostic 		}
281*55856Sbostic 		add_inodes(fsp, iip, icount, sp, seg_buf, seg_addr);
282*55856Sbostic 		add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr);
283*55856Sbostic 		pseg_addr += fsbtodb(lfsp, nblocks) +
284*55856Sbostic 		    bytetoda(fsp, LFS_SUMMARY_SIZE);
285*55856Sbostic 		s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE;
286*55856Sbostic 	}
287*55856Sbostic 	qsort(iip, *icount, sizeof(INODE_INFO), ii_compare);
288*55856Sbostic 	qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare);
289*55856Sbostic 	toss(iip, icount, sizeof(INODE_INFO), ii_toss, NULL);
290*55856Sbostic 	toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL);
291*55856Sbostic #ifdef VERBOSE
292*55856Sbostic 	{
293*55856Sbostic 		BLOCK_INFO *_bip;
294*55856Sbostic 		INODE_INFO *_iip;
295*55856Sbostic 		int i;
29655491Sbostic 
297*55856Sbostic 		printf("BLOCK INFOS\n");
298*55856Sbostic 		for (_bip = bip, i=0; i < *bcount; ++_bip, ++i)
299*55856Sbostic 			PRINT_BINFO(_bip);
300*55856Sbostic 		printf("INODE INFOS\n");
301*55856Sbostic 		for (_iip = iip, i=0; i < *icount; ++_iip, ++i)
302*55856Sbostic 			PRINT_IINFO(1, _iip);
30355491Sbostic 	}
304*55856Sbostic #endif
305*55856Sbostic 	*blocks = bip;
306*55856Sbostic 	*inodes = iip;
307*55856Sbostic 	return (0);
308*55856Sbostic 
309*55856Sbostic err1:	free(bip);
310*55856Sbostic err0:	*bcount = 0;
311*55856Sbostic 	*icount = 0;
312*55856Sbostic 	return (-1);
31355491Sbostic 
31455491Sbostic }
31555491Sbostic 
31655491Sbostic /*
317*55856Sbostic  * This will parse a partial segment and fill in BLOCK_INFO structures
318*55856Sbostic  * for each block described in the segment summary.  It will not include
319*55856Sbostic  * blocks or inodes from files with new version numbers.
32055491Sbostic  */
32155491Sbostic void
322*55856Sbostic add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr)
32355491Sbostic 	FS_INFO *fsp;		/* pointer to super block */
324*55856Sbostic 	BLOCK_INFO *bip;	/* Block info array */
325*55856Sbostic 	int *countp;		/* IN/OUT: number of blocks in array */
326*55856Sbostic 	SEGSUM	*sp;		/* segment summmary pointer */
327*55856Sbostic 	caddr_t seg_buf;	/* buffer containing segment */
328*55856Sbostic 	daddr_t segaddr;	/* address of this segment */
329*55856Sbostic 	daddr_t psegaddr;	/* address of this partial segment */
33055491Sbostic {
331*55856Sbostic 	IFILE	*ifp;
332*55856Sbostic 	FINFO	*fip;
333*55856Sbostic 	caddr_t	bp;
334*55856Sbostic 	daddr_t	*dp;
335*55856Sbostic 	daddr_t *iaddrp;	/* pointer to current inode block */
336*55856Sbostic 	int db_per_block, i, j;
337*55856Sbostic 	u_long page_size;
33855491Sbostic 
33955491Sbostic #ifdef VERBOSE
340*55856Sbostic 	printf("FILE INFOS\n");
34155491Sbostic #endif
342*55856Sbostic 	db_per_block = fsbtodb(&fsp->fi_lfs, 1);
343*55856Sbostic 	page_size = fsp->fi_lfs.lfs_bsize;
344*55856Sbostic 	bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE;
345*55856Sbostic 	bip += *countp;
346*55856Sbostic 	psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE);
347*55856Sbostic 	iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
348*55856Sbostic 	--iaddrp;
349*55856Sbostic 	for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo;
350*55856Sbostic 	    ++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) {
35155491Sbostic 
352*55856Sbostic 		ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino);
353*55856Sbostic 		PRINT_FINFO(fip, ifp);
354*55856Sbostic 		if (ifp->if_version > fip->fi_version)
35555491Sbostic 			continue;
356*55856Sbostic 		dp = &(fip->fi_blocks[0]);
357*55856Sbostic 		for (j = 0; j < fip->fi_nblocks; j++, dp++) {
358*55856Sbostic 			while (psegaddr == *iaddrp) {
359*55856Sbostic 				psegaddr += db_per_block;
360*55856Sbostic 				bp += page_size;
361*55856Sbostic 				--iaddrp;
36255491Sbostic 			}
363*55856Sbostic 			bip->bi_inode = fip->fi_ino;
364*55856Sbostic 			bip->bi_lbn = *dp;
365*55856Sbostic 			bip->bi_daddr = psegaddr;
366*55856Sbostic 			bip->bi_segcreate = (time_t)(sp->ss_create);
367*55856Sbostic 			bip->bi_bp = bp;
368*55856Sbostic 			psegaddr += db_per_block;
369*55856Sbostic 			bp += page_size;
370*55856Sbostic 			++bip;
371*55856Sbostic 			++(*countp);
37255491Sbostic 		}
37355491Sbostic 	}
37455491Sbostic }
37555491Sbostic 
376*55856Sbostic /*
377*55856Sbostic  * For a particular segment summary, reads the inode blocks and adds
378*55856Sbostic  * INODE_INFO structures to the array.  Returns the number of inodes
379*55856Sbostic  * actually added.
380*55856Sbostic  */
38155491Sbostic void
382*55856Sbostic add_inodes (fsp, iip, countp, sp, seg_buf, seg_addr)
38355491Sbostic 	FS_INFO *fsp;		/* pointer to super block */
384*55856Sbostic 	INODE_INFO *iip;
385*55856Sbostic 	int *countp;		/* pointer to current number of inodes */
386*55856Sbostic 	SEGSUM *sp;		/* segsum pointer */
38755491Sbostic 	caddr_t	seg_buf;	/* the buffer containing the segment's data */
388*55856Sbostic 	daddr_t	seg_addr;	/* disk address of seg_buf */
38955491Sbostic {
390*55856Sbostic 	struct dinode *di;
391*55856Sbostic 	struct lfs *lfsp;
392*55856Sbostic 	IFILE *ifp;
393*55856Sbostic 	INODE_INFO *ip;
394*55856Sbostic 	daddr_t	*daddrp;
395*55856Sbostic 	ino_t inum;
396*55856Sbostic 	int i;
39755491Sbostic 
398*55856Sbostic 	if (sp->ss_ninos <= 0)
399*55856Sbostic 		return;
40055491Sbostic 
401*55856Sbostic 	ip = iip + *countp;
402*55856Sbostic 	lfsp = &fsp->fi_lfs;
40355491Sbostic #ifdef VERBOSE
404*55856Sbostic 	(void) printf("INODE_INFOS:\n");
40555491Sbostic #endif
406*55856Sbostic 	daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
407*55856Sbostic 	for (i = 0; i < sp->ss_ninos; ++i) {
40855491Sbostic 		if (i % INOPB(lfsp) == 0) {
409*55856Sbostic 			--daddrp;
410*55856Sbostic 			di = (struct dinode *)(seg_buf +
411*55856Sbostic 			    ((*daddrp - seg_addr) << fsp->fi_daddr_shift));
41255491Sbostic 		} else
41355491Sbostic 			++di;
41455491Sbostic 
41555491Sbostic 		inum = di->di_inum;
416*55856Sbostic 		ip->ii_daddr = *daddrp;
417*55856Sbostic 		ip->ii_inode = inum;
418*55856Sbostic 		ip->ii_dinode = di;
419*55856Sbostic 		ip->ii_segcreate = sp->ss_create;
42055491Sbostic 
421*55856Sbostic 		ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum);
422*55856Sbostic 		PRINT_IINFO(ifp->if_daddr == *daddrp, ip);
423*55856Sbostic 		if (ifp->if_daddr == *daddrp) {
424*55856Sbostic 			ip++;
425*55856Sbostic 			++(*countp);
42655491Sbostic 		}
42755491Sbostic 	}
42855491Sbostic }
42955491Sbostic 
43055491Sbostic /*
431*55856Sbostic  * Checks the summary checksum and the data checksum to determine if the
432*55856Sbostic  * segment is valid or not.  Returns the size of the partial segment if it
433*55856Sbostic  * is valid, * and 0 otherwise.  Use dump_summary to figure out size of the
434*55856Sbostic  * the partial as well as whether or not the checksum is valid.
43555491Sbostic  */
43655491Sbostic int
43755491Sbostic pseg_valid (fsp, ssp)
43855491Sbostic 	FS_INFO *fsp;   /* pointer to file system info */
439*55856Sbostic 	SEGSUM *ssp;	/* pointer to segment summary block */
44055491Sbostic {
44155491Sbostic 	caddr_t	p;
442*55856Sbostic 	int i, nblocks;
443*55856Sbostic 	u_long *datap;
44455491Sbostic 
445*55856Sbostic 	if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0)
446*55856Sbostic 		return(0);
44755491Sbostic 
448*55856Sbostic 	/* check data/inode block(s) checksum too */
449*55856Sbostic 	datap = (u_long *)malloc(nblocks * sizeof(u_long));
45055491Sbostic 	p = (caddr_t)ssp + LFS_SUMMARY_SIZE;
451*55856Sbostic 	for (i = 0; i < nblocks; ++i) {
45255491Sbostic 		datap[i] = *((u_long *)p);
453*55856Sbostic 		p += fsp->fi_lfs.lfs_bsize;
45455491Sbostic 	}
455*55856Sbostic 	if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum)
456*55856Sbostic 		return (0);
45755491Sbostic 
458*55856Sbostic 	return (nblocks);
45955491Sbostic }
46055491Sbostic 
46155491Sbostic 
46255491Sbostic /* #define MMAP_SEGMENT */
46355491Sbostic /*
46455491Sbostic  * read a segment into a memory buffer
46555491Sbostic  */
46655491Sbostic int
467*55856Sbostic mmap_segment (fsp, segment, segbuf)
468*55856Sbostic 	FS_INFO *fsp;		/* file system information */
469*55856Sbostic 	int segment;		/* segment number */
470*55856Sbostic 	caddr_t *segbuf;	/* pointer to buffer area */
47155491Sbostic {
472*55856Sbostic 	struct lfs *lfsp;
473*55856Sbostic 	int fid;		/* fildes for file system device */
474*55856Sbostic 	daddr_t seg_daddr;	/* base disk address of segment */
475*55856Sbostic 	off_t seg_byte;
476*55856Sbostic 	size_t ssize;
477*55856Sbostic 	char mntfromname[MNAMELEN+2];
47855491Sbostic 
479*55856Sbostic 	lfsp = &fsp->fi_lfs;
480*55856Sbostic 
48155491Sbostic 	/* get the disk address of the beginning of the segment */
48255491Sbostic 	seg_daddr = sntoda(lfsp, segment);
483*55856Sbostic 	seg_byte = datobyte(fsp, seg_daddr);
484*55856Sbostic 	ssize = seg_size(lfsp);
48555491Sbostic 
48655491Sbostic 	strcpy(mntfromname, "/dev/r");
487*55856Sbostic 	strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
48855491Sbostic 
48955491Sbostic 	if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
490*55856Sbostic 		err(0, "mmap_segment: bad open");
491*55856Sbostic 		return (-1);
49255491Sbostic 	}
49355491Sbostic 
49455491Sbostic #ifdef MMAP_SEGMENT
495*55856Sbostic 	*segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ,
496*55856Sbostic 	    MAP_FILE, fid, seg_byte);
497*55856Sbostic 	if (*(long *)segbuf < 0) {
498*55856Sbostic 		err(0, "mmap_segment: mmap failed");
499*55856Sbostic 		return (NULL);
50055491Sbostic 	}
50155491Sbostic #else /* MMAP_SEGMENT */
502*55856Sbostic #ifdef VERBOSE
503*55856Sbostic 	printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n",
504*55856Sbostic 	    seg_daddr, ssize, seg_byte);
505*55856Sbostic #endif
50655491Sbostic 	/* malloc the space for the buffer */
507*55856Sbostic 	*segbuf = malloc(ssize);
508*55856Sbostic 	if (!*segbuf) {
509*55856Sbostic 		err(0, "mmap_segment: malloc failed");
510*55856Sbostic 		return(NULL);
511*55856Sbostic 	}
51255491Sbostic 
51355491Sbostic 	/* read the segment data into the buffer */
514*55856Sbostic 	if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) {
515*55856Sbostic 		err (0, "mmap_segment: bad lseek");
516*55856Sbostic 		free(*segbuf);
517*55856Sbostic 		return (-1);
51855491Sbostic 	}
51955491Sbostic 
520*55856Sbostic 	if (read (fid, *segbuf, ssize) != ssize) {
521*55856Sbostic 		err (0, "mmap_segment: bad read");
522*55856Sbostic 		free(*segbuf);
523*55856Sbostic 		return (-1);
52455491Sbostic 	}
52555491Sbostic #endif /* MMAP_SEGMENT */
52655491Sbostic 	close (fid);
52755491Sbostic 
528*55856Sbostic 	return (0);
52955491Sbostic }
53055491Sbostic 
53155491Sbostic void
53255491Sbostic munmap_segment (fsp, seg_buf)
533*55856Sbostic 	FS_INFO *fsp;		/* file system information */
534*55856Sbostic 	caddr_t seg_buf;	/* pointer to buffer area */
53555491Sbostic {
53655491Sbostic #ifdef MMAP_SEGMENT
537*55856Sbostic 	munmap (seg_buf, seg_size(&fsp->fi_lfs));
53855491Sbostic #else /* MMAP_SEGMENT */
53955491Sbostic 	free (seg_buf);
54055491Sbostic #endif /* MMAP_SEGMENT */
54155491Sbostic }
54255491Sbostic 
54355491Sbostic 
54455491Sbostic /*
54555491Sbostic  * USEFUL DEBUGGING TOOLS:
54655491Sbostic  */
54755491Sbostic void
548*55856Sbostic print_SEGSUM (lfsp, p)
549*55856Sbostic 	struct lfs *lfsp;
550*55856Sbostic 	SEGSUM	*p;
55155491Sbostic {
552*55856Sbostic 	if (p)
553*55856Sbostic 		(void) dump_summary(lfsp, p, DUMP_ALL, NULL);
55455491Sbostic 	else printf("0x0");
55555491Sbostic 	fflush(stdout);
55655491Sbostic }
55755491Sbostic 
558*55856Sbostic int
559*55856Sbostic bi_compare(a, b)
560*55856Sbostic 	const void *a;
561*55856Sbostic 	const void *b;
56255491Sbostic {
563*55856Sbostic 	const BLOCK_INFO *ba, *bb;
564*55856Sbostic 	int diff;
56555491Sbostic 
566*55856Sbostic 	ba = a;
567*55856Sbostic 	bb = b;
56855491Sbostic 
569*55856Sbostic 	if (diff = (int)(ba->bi_inode - bb->bi_inode))
570*55856Sbostic 		return (diff);
571*55856Sbostic 	if (diff = (int)(ba->bi_lbn - bb->bi_lbn))
572*55856Sbostic 		return (diff);
573*55856Sbostic 	if (diff = (int)(ba->bi_segcreate - bb->bi_segcreate))
574*55856Sbostic 		return (diff);
575*55856Sbostic 	diff = (int)(ba->bi_daddr - bb->bi_daddr);
576*55856Sbostic 	return (diff);
577*55856Sbostic }
57855491Sbostic 
579*55856Sbostic int
580*55856Sbostic bi_toss(dummy, a, b)
581*55856Sbostic 	const void *dummy;
582*55856Sbostic 	const void *a;
583*55856Sbostic 	const void *b;
58455491Sbostic {
585*55856Sbostic 	const BLOCK_INFO *ba, *bb;
58655491Sbostic 
587*55856Sbostic 	ba = a;
588*55856Sbostic 	bb = b;
589*55856Sbostic 
590*55856Sbostic 	return(ba->bi_inode == bb->bi_inode && ba->bi_lbn == bb->bi_lbn);
59155491Sbostic }
59255491Sbostic 
593*55856Sbostic /*
594*55856Sbostic  * Right now, we never look at the actually data being
595*55856Sbostic  * passed to the kernel in iip->ii_dinode.  Therefore,
596*55856Sbostic  * if the same inode appears twice in the same block
597*55856Sbostic  * (i.e.  has the same disk address), it doesn't matter
598*55856Sbostic  * which entry we pass.  However, if we get the kernel
599*55856Sbostic  * to start looking at the dinode, then we will care
600*55856Sbostic  * and we'll need some way to distinguish which inode
601*55856Sbostic  * is the more recent one.
602*55856Sbostic  */
603*55856Sbostic int
604*55856Sbostic ii_compare(a, b)
605*55856Sbostic 	const void *a;
606*55856Sbostic 	const void *b;
60755491Sbostic {
608*55856Sbostic 	const INODE_INFO *ia, *ib;
609*55856Sbostic 	int diff;
61055491Sbostic 
611*55856Sbostic 	ia = a;
612*55856Sbostic 	ib = b;
613*55856Sbostic 
614*55856Sbostic 	if (diff = (int)(ia->ii_inode - ib->ii_inode))
615*55856Sbostic 		return (diff);
616*55856Sbostic 	if (diff = (int)(ia->ii_segcreate - ib->ii_segcreate))
617*55856Sbostic 		return (diff);
618*55856Sbostic 	diff = (int)(ia->ii_daddr - ib->ii_daddr);
619*55856Sbostic 	return (diff);
62055491Sbostic }
62155491Sbostic 
622*55856Sbostic int
623*55856Sbostic ii_toss(dummy, a, b)
624*55856Sbostic 	const void *dummy;
625*55856Sbostic 	const void *a;
626*55856Sbostic 	const void *b;
62755491Sbostic {
628*55856Sbostic 	const INODE_INFO *ia, *ib;
62955491Sbostic 
630*55856Sbostic 	ia = a;
631*55856Sbostic 	ib = b;
632*55856Sbostic 
633*55856Sbostic 	return(ia->ii_inode == ib->ii_inode);
63455491Sbostic }
63555491Sbostic 
63655491Sbostic void
637*55856Sbostic toss(p, nump, size, dotoss, client)
638*55856Sbostic 	void *p;
639*55856Sbostic 	int *nump;
640*55856Sbostic 	size_t size;
641*55856Sbostic 	int (*dotoss) __P((const void *, const void *, const void *));
642*55856Sbostic 	void *client;
64355491Sbostic {
644*55856Sbostic 	int i;
645*55856Sbostic 	void *p1;
64655491Sbostic 
647*55856Sbostic 	if (*nump == 0)
648*55856Sbostic 		return;
64955491Sbostic 
650*55856Sbostic 	for (i = *nump; --i > 0;) {
651*55856Sbostic 		p1 = p + size;
652*55856Sbostic 		if (dotoss(client, p, p1)) {
653*55856Sbostic 			bcopy(p1, p, i * size);
654*55856Sbostic 			--(*nump);
655*55856Sbostic 		} else
656*55856Sbostic 			p += size;
65755491Sbostic 	}
65855491Sbostic }
659