Commit | Line | Data |
---|---|---|
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 | 9 | static 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 |
27 | void add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, |
28 | daddr_t, daddr_t)); | |
875ef07c | 29 | void add_inodes __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, |
8d18badf KB |
30 | daddr_t)); |
31 | int bi_compare __P((const void *, const void *)); | |
32 | int bi_toss __P((const void *, const void *, const void *)); | |
33 | void get_ifile __P((FS_INFO *)); | |
34 | int get_superblock __P((FS_INFO *, struct lfs *)); | |
8d18badf KB |
35 | int 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 | */ | |
41 | int | |
42 | fs_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 |
79 | FS_INFO * |
80 | get_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 | 105 | void |
8d18badf KB |
106 | reread_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 | */ |
128 | int | |
129 | get_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 | 154 | void |
8cfd96bf KB |
155 | get_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"); | |
181 | redo_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 | */ |
225 | int | |
875ef07c | 226 | lfs_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 | 300 | err0: *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 | */ |
310 | void | |
8d18badf | 311 | add_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 | 369 | void |
875ef07c | 370 | add_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 | */ |
431 | int | |
432 | pseg_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 | */ | |
461 | int | |
8d18badf KB |
462 | mmap_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 | ||
526 | void | |
527 | munmap_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 | 542 | void |
8d18badf KB |
543 | print_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 |
553 | int |
554 | bi_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 |
582 | int |
583 | bi_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 | 596 | void |
8d18badf KB |
597 | toss(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 | } |