Add printf and fix error message.
[unix-history] / usr / src / libexec / lfs_cleanerd / library.c
CommitLineData
f97378c7
KB
1/*-
2 * Copyright (c) 1992 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8#ifndef lint
ec55debc 9static char sccsid[] = "@(#)library.c 5.4 (Berkeley) %G%";
f97378c7
KB
10#endif /* not lint */
11
8cfd96bf
KB
12#include <sys/param.h>
13#include <sys/time.h>
8cfd96bf
KB
14#include <sys/stat.h>
15#include <sys/mount.h>
16
17#include <ufs/ufs/dinode.h>
18#include <ufs/lfs/lfs.h>
8cfd96bf
KB
19
20#include <fcntl.h>
21#include <stdio.h>
22#include <unistd.h>
8d18badf
KB
23#include <stdlib.h>
24#include <string.h>
8cfd96bf
KB
25#include "clean.h"
26
8d18badf
KB
27void add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,
28 daddr_t, daddr_t));
875ef07c 29void add_inodes __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,
8d18badf
KB
30 daddr_t));
31int bi_compare __P((const void *, const void *));
32int bi_toss __P((const void *, const void *, const void *));
33void get_ifile __P((FS_INFO *));
34int get_superblock __P((FS_INFO *, struct lfs *));
8d18badf
KB
35int pseg_valid __P((FS_INFO *, SEGSUM *));
36
8cfd96bf 37/*
8d18badf 38 * This function will get information on all mounted file systems
8cfd96bf
KB
39 * of a given type.
40 */
41int
42fs_getmntinfo(buf, type)
43 struct statfs **buf;
44 int type;
45{
8d18badf
KB
46 struct statfs *tstatfsp;
47 struct statfs *sbp;
48 int count, i, tcount;
8cfd96bf 49
9dbe4842 50 tcount = getmntinfo(&tstatfsp, MNT_NOWAIT);
8cfd96bf
KB
51
52 if (tcount < 0) {
8d18badf
KB
53 err(0, "getmntinfo failed");
54 return (-1);
8cfd96bf
KB
55 }
56
8d18badf
KB
57 for (count = 0, i = 0; i < tcount ; ++i)
58 if (tstatfsp[i].f_type == type)
59 ++count;
60
61 if (count) {
62 if (!(*buf = (struct statfs *)
63 malloc(count * sizeof(struct statfs))))
64 err(1, "fs_getmntinfo: out of space");
65 for (i = 0, sbp = *buf; i < tcount ; ++i) {
66 if (tstatfsp[i].f_type == type) {
67 *sbp = tstatfsp[i];
68 ++sbp;
8cfd96bf
KB
69 }
70 }
8cfd96bf 71 }
8d18badf 72 return (count);
8cfd96bf
KB
73}
74
75/*
8d18badf
KB
76 * Get all the information available on an LFS file system.
77 * Returns an array of FS_INFO structures, NULL on error.
8cfd96bf 78 */
8d18badf
KB
79FS_INFO *
80get_fs_info (lstatfsp, count)
81 struct statfs *lstatfsp; /* IN: array of statfs structs */
82 int count; /* IN: number of file systems */
8cfd96bf 83{
8d18badf 84 FS_INFO *fp, *fsp;
8cfd96bf 85 int i;
8cfd96bf 86
8d18badf
KB
87 fsp = (FS_INFO *)malloc(count * sizeof(FS_INFO));
88
89 for (fp = fsp, i = 0; i < count; ++i, ++fp) {
90 fp->fi_statfsp = lstatfsp++;
91 if (get_superblock (fp, &fp->fi_lfs))
92 err(1, "get_fs_info: get_superblock failed");
93 fp->fi_daddr_shift =
94 fp->fi_lfs.lfs_bshift - fp->fi_lfs.lfs_fsbtodb;
95 get_ifile (fp);
8cfd96bf 96 }
8d18badf 97 return (fsp);
8cfd96bf
KB
98}
99
8d18badf
KB
100/*
101 * If we are reading the ifile then we need to refresh it. Even if
102 * we are mmapping it, it might have grown. Finally, we need to
103 * refresh the file system information (statfs) info.
104 */
8cfd96bf 105void
8d18badf
KB
106reread_fs_info(fsp, count)
107 FS_INFO *fsp; /* IN: array of fs_infos to free */
108 int count; /* IN: number of file systems */
8cfd96bf 109{
8d18badf 110 int i;
8cfd96bf 111
8d18badf
KB
112 for (i = 0; i < count; ++i, ++fsp) {
113 if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp))
114 err(0, "reread_fs_info: statfs failed");
115#ifdef MMAP_WORKS
116 if (munmap(fsp->fi_cip, fsp->fi_ifile_length) < 0)
117 err(0, "reread_fs_info: munmap failed");
8cfd96bf 118#else
8d18badf 119 free (fsp->fi_cip);
8cfd96bf 120#endif /* MMAP_WORKS */
8d18badf 121 get_ifile (fsp);
8cfd96bf 122 }
8cfd96bf
KB
123}
124
125/*
8d18badf 126 * Gets the superblock from disk (possibly in face of errors)
8cfd96bf
KB
127 */
128int
129get_superblock (fsp, sbp)
8d18badf
KB
130 FS_INFO *fsp; /* local file system info structure */
131 struct lfs *sbp;
8cfd96bf 132{
8d18badf
KB
133 char mntfromname[MNAMELEN+1];
134 int fid;
8cfd96bf
KB
135
136 strcpy(mntfromname, "/dev/r");
8d18badf 137 strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
8cfd96bf
KB
138
139 if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
8d18badf
KB
140 err(0, "get_superblock: bad open");
141 return (-1);
8cfd96bf
KB
142 }
143
8d18badf 144 get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs));
8cfd96bf
KB
145 close (fid);
146
8d18badf 147 return (0);
8cfd96bf
KB
148}
149
150/*
8d18badf
KB
151 * This function will map the ifile into memory. It causes a
152 * fatal error on failure.
8cfd96bf 153 */
8d18badf 154void
8cfd96bf
KB
155get_ifile (fsp)
156 FS_INFO *fsp;
157{
8d18badf
KB
158 struct stat file_stat;
159 caddr_t ifp;
160 char *ifile_name;
161 int count, fid;
8cfd96bf 162
8d18badf 163 ifp = NULL;
8d18badf
KB
164 ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) +
165 strlen(IFILE_NAME)+2);
166 strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"),
167 IFILE_NAME);
168
169 if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0)
170 err(1, "get_ifile: bad open");
171
172 if (fstat (fid, &file_stat))
173 err(1, "get_ifile: fstat failed");
174
175 fsp->fi_ifile_length = file_stat.st_size;
8cfd96bf
KB
176
177 /* get the ifile */
178#ifndef MMAP_WORKS
8d18badf
KB
179 if (!(ifp = malloc ((size_t)fsp->fi_ifile_length)))
180 err (1, "get_ifile: malloc failed");
181redo_read:
182 count = read (fid, ifp, (size_t) fsp->fi_ifile_length);
183
184 if (count < 0)
185 err(1, "get_ifile: bad ifile read");
186 else if (count < (int)fsp->fi_ifile_length) {
187 err(0, "get_ifile");
188 if (lseek(fid, 0, SEEK_SET) < 0)
189 err(1, "get_ifile: bad ifile lseek");
190 goto redo_read;
8cfd96bf
KB
191 }
192#else /* MMAP_WORKS */
8d18badf 193 ifp = mmap ((caddr_t)0, (size_t) fsp->fi_ifile_length, PROT_READ|PROT_WRITE,
8cfd96bf 194 MAP_FILE|MAP_SHARED, fid, (off_t)0);
8d18badf
KB
195 if (ifp < 0)
196 err(1, "get_ifile: mmap failed");
8cfd96bf
KB
197#endif /* MMAP_WORKS */
198
199 close (fid);
200
8d18badf
KB
201 fsp->fi_cip = (CLEANERINFO *)ifp;
202 fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp));
203 fsp->fi_ifilep = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp));
204
205 /*
206 * The number of ifile entries is equal to the number of blocks
207 * blocks in the ifile minus the ones allocated to cleaner info
208 * and segment usage table multiplied by the number of ifile
209 * entries per page.
210 */
211 fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift -
212 fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) *
213 fsp->fi_lfs.lfs_ifpb;
214
8cfd96bf 215 free (ifile_name);
8cfd96bf
KB
216}
217
8cfd96bf 218/*
8d18badf 219 * This function will scan a segment and return a list of
8cfd96bf 220 * <inode, blocknum> pairs which indicate which blocks were
8d18badf
KB
221 * contained as live data within the segment when the segment
222 * summary was read (it may have "died" since then). Any given
223 * pair will be listed at most once.
8cfd96bf
KB
224 */
225int
875ef07c 226lfs_segmapv(fsp, seg, seg_buf, blocks, bcount)
8d18badf
KB
227 FS_INFO *fsp; /* pointer to local file system information */
228 int seg; /* the segment number */
229 caddr_t seg_buf; /* the buffer containing the segment's data */
230 BLOCK_INFO **blocks; /* OUT: array of block_info for live blocks */
231 int *bcount; /* OUT: number of active blocks in segment */
8cfd96bf 232{
8d18badf 233 BLOCK_INFO *bip;
8d18badf
KB
234 SEGSUM *sp;
235 SEGUSE *sup;
236 struct lfs *lfsp;
237 caddr_t s, segend;
238 daddr_t pseg_addr, seg_addr;
875ef07c 239 int nelem, nblocks;
8d18badf
KB
240 time_t timestamp;
241
242 lfsp = &fsp->fi_lfs;
875ef07c
KB
243 nelem = 2 * lfsp->lfs_ssize;
244 if (!(bip = malloc(nelem * sizeof(BLOCK_INFO))))
8d18badf 245 goto err0;
8d18badf
KB
246
247 sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg);
248 s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0);
249 seg_addr = sntoda(lfsp, seg);
250 pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0);
251#ifdef VERBOSE
252 printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr);
253#endif /* VERBOSE */
254
8cfd96bf 255 *bcount = 0;
8d18badf
KB
256 for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) {
257 sp = (SEGSUM *)s;
8cfd96bf 258#ifdef VERBOSE
8d18badf
KB
259 printf("\tpartial at: 0x%x\n", pseg_addr);
260 print_SEGSUM(lfsp, sp);
8cfd96bf
KB
261 fflush(stdout);
262#endif /* VERBOSE */
263
8d18badf
KB
264 nblocks = pseg_valid(fsp, sp);
265 if (nblocks <= 0)
266 break;
8cfd96bf 267
8d18badf
KB
268 /* Check if we have hit old data */
269 if (timestamp > ((SEGSUM*)s)->ss_create)
270 break;
8cfd96bf
KB
271 timestamp = ((SEGSUM*)s)->ss_create;
272
875ef07c
KB
273 if (*bcount + nblocks + sp->ss_ninos > nelem) {
274 nelem = *bcount + nblocks + sp->ss_ninos;
275 bip = realloc (bip, nelem * sizeof(BLOCK_INFO));
276 if (!bip)
277 goto err0;
8d18badf 278 }
8d18badf 279 add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr);
875ef07c 280 add_inodes(fsp, bip, bcount, sp, seg_buf, seg_addr);
8d18badf
KB
281 pseg_addr += fsbtodb(lfsp, nblocks) +
282 bytetoda(fsp, LFS_SUMMARY_SIZE);
283 s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE;
8cfd96bf 284 }
8d18badf 285 qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare);
8d18badf
KB
286 toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL);
287#ifdef VERBOSE
288 {
289 BLOCK_INFO *_bip;
8d18badf
KB
290 int i;
291
292 printf("BLOCK INFOS\n");
293 for (_bip = bip, i=0; i < *bcount; ++_bip, ++i)
294 PRINT_BINFO(_bip);
8d18badf
KB
295 }
296#endif
297 *blocks = bip;
8d18badf
KB
298 return (0);
299
8d18badf 300err0: *bcount = 0;
8d18badf 301 return (-1);
8cfd96bf
KB
302
303}
304
305/*
8d18badf
KB
306 * This will parse a partial segment and fill in BLOCK_INFO structures
307 * for each block described in the segment summary. It will not include
308 * blocks or inodes from files with new version numbers.
8cfd96bf
KB
309 */
310void
8d18badf 311add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr)
8cfd96bf 312 FS_INFO *fsp; /* pointer to super block */
8d18badf
KB
313 BLOCK_INFO *bip; /* Block info array */
314 int *countp; /* IN/OUT: number of blocks in array */
315 SEGSUM *sp; /* segment summmary pointer */
316 caddr_t seg_buf; /* buffer containing segment */
317 daddr_t segaddr; /* address of this segment */
318 daddr_t psegaddr; /* address of this partial segment */
8cfd96bf 319{
8d18badf
KB
320 IFILE *ifp;
321 FINFO *fip;
322 caddr_t bp;
875ef07c 323 daddr_t *dp, *iaddrp;
8d18badf
KB
324 int db_per_block, i, j;
325 u_long page_size;
8cfd96bf
KB
326
327#ifdef VERBOSE
8d18badf 328 printf("FILE INFOS\n");
8cfd96bf 329#endif
8d18badf
KB
330 db_per_block = fsbtodb(&fsp->fi_lfs, 1);
331 page_size = fsp->fi_lfs.lfs_bsize;
332 bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE;
333 bip += *countp;
334 psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE);
335 iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
336 --iaddrp;
337 for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo;
338 ++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) {
339
340 ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino);
341 PRINT_FINFO(fip, ifp);
342 if (ifp->if_version > fip->fi_version)
8cfd96bf 343 continue;
8d18badf
KB
344 dp = &(fip->fi_blocks[0]);
345 for (j = 0; j < fip->fi_nblocks; j++, dp++) {
346 while (psegaddr == *iaddrp) {
347 psegaddr += db_per_block;
348 bp += page_size;
349 --iaddrp;
8cfd96bf 350 }
8d18badf
KB
351 bip->bi_inode = fip->fi_ino;
352 bip->bi_lbn = *dp;
353 bip->bi_daddr = psegaddr;
354 bip->bi_segcreate = (time_t)(sp->ss_create);
355 bip->bi_bp = bp;
356 psegaddr += db_per_block;
357 bp += page_size;
358 ++bip;
359 ++(*countp);
8cfd96bf
KB
360 }
361 }
8cfd96bf
KB
362}
363
8d18badf
KB
364/*
365 * For a particular segment summary, reads the inode blocks and adds
366 * INODE_INFO structures to the array. Returns the number of inodes
367 * actually added.
368 */
8cfd96bf 369void
875ef07c 370add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr)
8cfd96bf 371 FS_INFO *fsp; /* pointer to super block */
875ef07c 372 BLOCK_INFO *bip; /* block info array */
8d18badf
KB
373 int *countp; /* pointer to current number of inodes */
374 SEGSUM *sp; /* segsum pointer */
8cfd96bf 375 caddr_t seg_buf; /* the buffer containing the segment's data */
8d18badf 376 daddr_t seg_addr; /* disk address of seg_buf */
8cfd96bf 377{
8d18badf
KB
378 struct dinode *di;
379 struct lfs *lfsp;
380 IFILE *ifp;
875ef07c 381 BLOCK_INFO *bp;
8d18badf
KB
382 daddr_t *daddrp;
383 ino_t inum;
384 int i;
8cfd96bf 385
8d18badf
KB
386 if (sp->ss_ninos <= 0)
387 return;
8cfd96bf 388
875ef07c 389 bp = bip + *countp;
8d18badf 390 lfsp = &fsp->fi_lfs;
8cfd96bf 391#ifdef VERBOSE
875ef07c 392 (void) printf("INODES:\n");
8cfd96bf 393#endif
8d18badf
KB
394 daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
395 for (i = 0; i < sp->ss_ninos; ++i) {
8cfd96bf 396 if (i % INOPB(lfsp) == 0) {
8d18badf
KB
397 --daddrp;
398 di = (struct dinode *)(seg_buf +
399 ((*daddrp - seg_addr) << fsp->fi_daddr_shift));
8cfd96bf
KB
400 } else
401 ++di;
402
403 inum = di->di_inum;
875ef07c
KB
404 bp->bi_lbn = LFS_UNUSED_LBN;
405 bp->bi_inode = inum;
406 bp->bi_daddr = *daddrp;
407 bp->bi_bp = di;
408 bp->bi_segcreate = sp->ss_create;
8d18badf 409
ec55debc 410 if (inum == LFS_IFILE_INUM) {
875ef07c 411 bp++;
8d18badf 412 ++(*countp);
ec55debc
KB
413 PRINT_INODE(1, bp);
414 } else {
415 ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum);
416 PRINT_INODE(ifp->if_daddr == *daddrp, bp);
417 if (ifp->if_daddr == *daddrp) {
418 bp++;
419 ++(*countp);
420 }
421 }
8cfd96bf
KB
422 }
423}
424
8cfd96bf 425/*
8d18badf
KB
426 * Checks the summary checksum and the data checksum to determine if the
427 * segment is valid or not. Returns the size of the partial segment if it
428 * is valid, * and 0 otherwise. Use dump_summary to figure out size of the
429 * the partial as well as whether or not the checksum is valid.
8cfd96bf
KB
430 */
431int
432pseg_valid (fsp, ssp)
433 FS_INFO *fsp; /* pointer to file system info */
8d18badf 434 SEGSUM *ssp; /* pointer to segment summary block */
8cfd96bf 435{
8cfd96bf 436 caddr_t p;
8d18badf
KB
437 int i, nblocks;
438 u_long *datap;
8cfd96bf 439
8d18badf
KB
440 if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0)
441 return(0);
8cfd96bf 442
8d18badf
KB
443 /* check data/inode block(s) checksum too */
444 datap = (u_long *)malloc(nblocks * sizeof(u_long));
8cfd96bf 445 p = (caddr_t)ssp + LFS_SUMMARY_SIZE;
8d18badf 446 for (i = 0; i < nblocks; ++i) {
8cfd96bf 447 datap[i] = *((u_long *)p);
8d18badf 448 p += fsp->fi_lfs.lfs_bsize;
8cfd96bf 449 }
8d18badf
KB
450 if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum)
451 return (0);
8cfd96bf 452
8d18badf 453 return (nblocks);
8cfd96bf
KB
454}
455
8cfd96bf
KB
456
457/* #define MMAP_SEGMENT */
458/*
459 * read a segment into a memory buffer
460 */
461int
8d18badf
KB
462mmap_segment (fsp, segment, segbuf)
463 FS_INFO *fsp; /* file system information */
464 int segment; /* segment number */
465 caddr_t *segbuf; /* pointer to buffer area */
8cfd96bf 466{
8d18badf
KB
467 struct lfs *lfsp;
468 int fid; /* fildes for file system device */
469 daddr_t seg_daddr; /* base disk address of segment */
470 off_t seg_byte;
471 size_t ssize;
472 char mntfromname[MNAMELEN+2];
473
474 lfsp = &fsp->fi_lfs;
8cfd96bf
KB
475
476 /* get the disk address of the beginning of the segment */
477 seg_daddr = sntoda(lfsp, segment);
8d18badf
KB
478 seg_byte = datobyte(fsp, seg_daddr);
479 ssize = seg_size(lfsp);
8cfd96bf
KB
480
481 strcpy(mntfromname, "/dev/r");
8d18badf 482 strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
8cfd96bf
KB
483
484 if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
8d18badf
KB
485 err(0, "mmap_segment: bad open");
486 return (-1);
8cfd96bf
KB
487 }
488
489#ifdef MMAP_SEGMENT
8d18badf
KB
490 *segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ,
491 MAP_FILE, fid, seg_byte);
492 if (*(long *)segbuf < 0) {
493 err(0, "mmap_segment: mmap failed");
494 return (NULL);
8cfd96bf
KB
495 }
496#else /* MMAP_SEGMENT */
8d18badf
KB
497#ifdef VERBOSE
498 printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n",
499 seg_daddr, ssize, seg_byte);
500#endif
8cfd96bf 501 /* malloc the space for the buffer */
8d18badf
KB
502 *segbuf = malloc(ssize);
503 if (!*segbuf) {
504 err(0, "mmap_segment: malloc failed");
505 return(NULL);
506 }
8cfd96bf
KB
507
508 /* read the segment data into the buffer */
8d18badf
KB
509 if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) {
510 err (0, "mmap_segment: bad lseek");
511 free(*segbuf);
512 return (-1);
8cfd96bf
KB
513 }
514
8d18badf
KB
515 if (read (fid, *segbuf, ssize) != ssize) {
516 err (0, "mmap_segment: bad read");
517 free(*segbuf);
518 return (-1);
8cfd96bf
KB
519 }
520#endif /* MMAP_SEGMENT */
521 close (fid);
522
8d18badf 523 return (0);
8cfd96bf
KB
524}
525
526void
527munmap_segment (fsp, seg_buf)
8d18badf
KB
528 FS_INFO *fsp; /* file system information */
529 caddr_t seg_buf; /* pointer to buffer area */
8cfd96bf
KB
530{
531#ifdef MMAP_SEGMENT
8d18badf 532 munmap (seg_buf, seg_size(&fsp->fi_lfs));
8cfd96bf
KB
533#else /* MMAP_SEGMENT */
534 free (seg_buf);
535#endif /* MMAP_SEGMENT */
536}
537
538
539/*
540 * USEFUL DEBUGGING TOOLS:
541 */
8cfd96bf 542void
8d18badf
KB
543print_SEGSUM (lfsp, p)
544 struct lfs *lfsp;
545 SEGSUM *p;
8cfd96bf 546{
8d18badf
KB
547 if (p)
548 (void) dump_summary(lfsp, p, DUMP_ALL, NULL);
8cfd96bf
KB
549 else printf("0x0");
550 fflush(stdout);
551}
552
8d18badf
KB
553int
554bi_compare(a, b)
555 const void *a;
556 const void *b;
8cfd96bf 557{
8d18badf
KB
558 const BLOCK_INFO *ba, *bb;
559 int diff;
560
561 ba = a;
562 bb = b;
563
564 if (diff = (int)(ba->bi_inode - bb->bi_inode))
565 return (diff);
875ef07c
KB
566 if (diff = (int)(ba->bi_lbn - bb->bi_lbn)) {
567 if (ba->bi_lbn == LFS_UNUSED_LBN)
568 return(-1);
569 else if (bb->bi_lbn == LFS_UNUSED_LBN)
570 return(1);
571 else if (ba->bi_lbn < 0)
572 return(1);
573 else
574 return (diff);
575 }
8d18badf
KB
576 if (diff = (int)(ba->bi_segcreate - bb->bi_segcreate))
577 return (diff);
578 diff = (int)(ba->bi_daddr - bb->bi_daddr);
579 return (diff);
580}
8cfd96bf 581
8d18badf
KB
582int
583bi_toss(dummy, a, b)
584 const void *dummy;
585 const void *a;
586 const void *b;
8cfd96bf 587{
8d18badf 588 const BLOCK_INFO *ba, *bb;
8cfd96bf 589
8d18badf
KB
590 ba = a;
591 bb = b;
592
593 return(ba->bi_inode == bb->bi_inode && ba->bi_lbn == bb->bi_lbn);
8cfd96bf
KB
594}
595
8cfd96bf 596void
8d18badf
KB
597toss(p, nump, size, dotoss, client)
598 void *p;
599 int *nump;
600 size_t size;
601 int (*dotoss) __P((const void *, const void *, const void *));
602 void *client;
8cfd96bf 603{
8d18badf
KB
604 int i;
605 void *p1;
8cfd96bf 606
8d18badf
KB
607 if (*nump == 0)
608 return;
8cfd96bf 609
8d18badf
KB
610 for (i = *nump; --i > 0;) {
611 p1 = p + size;
612 if (dotoss(client, p, p1)) {
613 bcopy(p1, p, i * size);
614 --(*nump);
615 } else
616 p += size;
8cfd96bf 617 }
8cfd96bf 618}