Annotation of src/sbin/fsck_lfs/setup.c, Revision 1.39
1.39 ! dholland 1: /* $NetBSD: setup.c,v 1.38 2011/08/29 18:43:20 bouyer Exp $ */
1.1 perseant 2:
1.13 perseant 3: /*-
4: * Copyright (c) 2003 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Konrad E. Schroder <perseant@hhhh.org>.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29: * POSSIBILITY OF SUCH DAMAGE.
30: */
1.1 perseant 31: /*
32: * Copyright (c) 1980, 1986, 1993
33: * The Regents of the University of California. All rights reserved.
34: *
35: * Redistribution and use in source and binary forms, with or without
36: * modification, are permitted provided that the following conditions
37: * are met:
38: * 1. Redistributions of source code must retain the above copyright
39: * notice, this list of conditions and the following disclaimer.
40: * 2. Redistributions in binary form must reproduce the above copyright
41: * notice, this list of conditions and the following disclaimer in the
42: * documentation and/or other materials provided with the distribution.
1.17 agc 43: * 3. Neither the name of the University nor the names of its contributors
1.1 perseant 44: * may be used to endorse or promote products derived from this software
45: * without specific prior written permission.
46: *
47: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57: * SUCH DAMAGE.
58: */
59:
60: /* #define DKTYPENAMES */
61: #define FSTYPENAMES
1.13 perseant 62: #include <sys/types.h>
1.1 perseant 63: #include <sys/param.h>
64: #include <sys/time.h>
1.13 perseant 65: #include <sys/buf.h>
66: #include <sys/mount.h>
67: #include <sys/queue.h>
1.1 perseant 68: #include <sys/stat.h>
69: #include <sys/ioctl.h>
70: #include <sys/disklabel.h>
1.37 mlelstv 71: #include <sys/disk.h>
1.1 perseant 72: #include <sys/file.h>
73:
1.13 perseant 74: #include <ufs/ufs/inode.h>
75: #include <ufs/ufs/ufsmount.h>
76: #define vnode uvnode
1.1 perseant 77: #include <ufs/lfs/lfs.h>
1.13 perseant 78: #undef vnode
1.1 perseant 79:
80: #include <ctype.h>
81: #include <err.h>
82: #include <errno.h>
83: #include <stdio.h>
84: #include <stdlib.h>
1.37 mlelstv 85: #include <unistd.h>
1.1 perseant 86: #include <string.h>
1.29 perseant 87: #include <time.h>
1.32 christos 88: #include <util.h>
1.1 perseant 89:
1.13 perseant 90: #include "bufcache.h"
91: #include "vnode.h"
1.26 christos 92: #include "lfs_user.h"
1.13 perseant 93:
1.1 perseant 94: #include "fsck.h"
95: #include "extern.h"
96: #include "fsutil.h"
97:
1.29 perseant 98: extern u_int32_t cksum(void *, size_t);
1.18 minoura 99: static uint64_t calcmaxfilesize(int);
1.1 perseant 100:
1.13 perseant 101: ufs_daddr_t *din_table;
102: SEGUSE *seg_table;
1.4 perseant 103:
1.1 perseant 104: #ifdef DKTYPENAMES
1.13 perseant 105: int useless(void);
1.1 perseant 106:
107: int
108: useless(void)
109: {
1.13 perseant 110: char **foo = (char **) dktypenames;
111: char **bar = (char **) fscknames;
1.1 perseant 112:
1.5 perseant 113: return foo - bar;
1.1 perseant 114: }
115: #endif
116:
1.18 minoura 117: /*
118: * calculate the maximum file size allowed with the specified block shift.
119: */
120: static uint64_t
121: calcmaxfilesize(int bshift)
122: {
123: uint64_t nptr; /* number of block pointers per block */
124: uint64_t maxblock;
125:
126: nptr = (1 << bshift) / sizeof(uint32_t);
1.39 ! dholland 127: maxblock = UFS_NDADDR + nptr + nptr * nptr + nptr * nptr * nptr;
1.18 minoura 128:
129: return maxblock << bshift;
130: }
1.20 perseant 131:
132: void
133: reset_maxino(ino_t len)
134: {
1.29 perseant 135: if (debug)
136: pwarn("maxino reset from %lld to %lld\n", (long long)maxino,
137: (long long)len);
138:
1.32 christos 139: din_table = erealloc(din_table, len * sizeof(*din_table));
140: statemap = erealloc(statemap, len * sizeof(char));
141: typemap = erealloc(typemap, len * sizeof(char));
142: lncntp = erealloc(lncntp, len * sizeof(int16_t));
1.20 perseant 143:
144: memset(din_table + maxino, 0, (len - maxino) * sizeof(*din_table));
1.29 perseant 145: memset(statemap + maxino, USTATE, (len - maxino) * sizeof(char));
1.20 perseant 146: memset(typemap + maxino, 0, (len - maxino) * sizeof(char));
147: memset(lncntp + maxino, 0, (len - maxino) * sizeof(int16_t));
148:
1.24 perseant 149: maxino = len;
150:
1.29 perseant 151: /*
152: * We can't roll forward after allocating new inodes in previous
153: * phases, or thy would conflict (lost+found, for example, might
154: * disappear to be replaced by a file found in roll-forward).
155: */
156: no_roll_forward = 1;
157:
1.20 perseant 158: return;
159: }
1.18 minoura 160:
1.29 perseant 161: extern time_t write_time;
162:
1.1 perseant 163: int
1.5 perseant 164: setup(const char *dev)
1.1 perseant 165: {
1.13 perseant 166: long bmapsize;
167: struct stat statb;
168: int doskipclean;
169: u_int64_t maxfilesize;
170: int open_flags;
171: struct uvnode *ivp;
172: struct ubuf *bp;
1.29 perseant 173: int i, isdirty;
174: long sn, curseg;
1.13 perseant 175: SEGUSE *sup;
1.1 perseant 176:
177: havesb = 0;
178: doskipclean = skipclean;
179: if (stat(dev, &statb) < 0) {
1.29 perseant 180: pfatal("Can't stat %s: %s\n", dev, strerror(errno));
1.1 perseant 181: return (0);
182: }
1.29 perseant 183: if (!S_ISCHR(statb.st_mode) && skipclean) {
1.1 perseant 184: pfatal("%s is not a character device", dev);
185: if (reply("CONTINUE") == 0)
186: return (0);
187: }
1.13 perseant 188: if (nflag)
189: open_flags = O_RDONLY;
190: else
191: open_flags = O_RDWR;
192:
193: if ((fsreadfd = open(dev, open_flags)) < 0) {
1.29 perseant 194: pfatal("Can't open %s: %s\n", dev, strerror(errno));
1.1 perseant 195: return (0);
196: }
1.13 perseant 197: if (nflag) {
1.1 perseant 198: if (preen)
199: pfatal("NO WRITE ACCESS");
1.21 perseant 200: printf("** %s (NO WRITE)\n", dev);
201: quiet = 0;
202: } else if (!preen && !quiet)
203: printf("** %s\n", dev);
204:
1.1 perseant 205: fsmodified = 0;
206: lfdir = 0;
1.13 perseant 207:
1.29 perseant 208: /* Initialize time in case we have to write */
209: time(&write_time);
210:
1.20 perseant 211: bufinit(0); /* XXX we could make a better guess */
1.19 perseant 212: fs = lfs_init(fsreadfd, bflag, idaddr, 0, debug);
1.13 perseant 213: if (fs == NULL) {
214: if (preen)
215: printf("%s: ", cdevname());
1.34 lukem 216: errexit("BAD SUPER BLOCK OR IFILE INODE NOT FOUND");
1.13 perseant 217: }
1.1 perseant 218:
1.20 perseant 219: /* Resize buffer cache now that we have a superblock to guess from. */
220: bufrehash((fs->lfs_segtabsz + maxino / fs->lfs_ifpb) << 4);
221:
1.13 perseant 222: if (fs->lfs_pflags & LFS_PF_CLEAN) {
223: if (doskipclean) {
1.21 perseant 224: if (!quiet)
225: pwarn("%sile system is clean; not checking\n",
226: preen ? "f" : "** F");
1.13 perseant 227: return (-1);
1.1 perseant 228: }
1.13 perseant 229: if (!preen)
230: pwarn("** File system is already clean\n");
231: }
1.9 perseant 232:
1.29 perseant 233: if (idaddr) {
234: daddr_t tdaddr;
235: SEGSUM *sp;
236: FINFO *fp;
237: int bc;
238:
239: if (debug)
240: pwarn("adjusting offset, serial for -i 0x%lx\n",
241: (unsigned long)idaddr);
242: tdaddr = sntod(fs, dtosn(fs, idaddr));
243: if (sntod(fs, dtosn(fs, tdaddr)) == tdaddr) {
1.30 perseant 244: if (tdaddr == fs->lfs_start)
245: tdaddr += btofsb(fs, LFS_LABELPAD);
1.29 perseant 246: for (i = 0; i < LFS_MAXNUMSB; i++) {
247: if (fs->lfs_sboffs[i] == tdaddr)
248: tdaddr += btofsb(fs, LFS_SBPAD);
249: if (fs->lfs_sboffs[i] > tdaddr)
250: break;
251: }
252: }
253: fs->lfs_offset = tdaddr;
254: if (debug)
255: pwarn("begin with offset/serial 0x%x/%d\n",
256: (int)fs->lfs_offset, (int)fs->lfs_serial);
257: while (tdaddr < idaddr) {
258: bread(fs->lfs_devvp, fsbtodb(fs, tdaddr),
259: fs->lfs_sumsize,
1.36 hannken 260: NULL, 0, &bp);
1.29 perseant 261: sp = (SEGSUM *)bp->b_data;
262: if (sp->ss_sumsum != cksum(&sp->ss_datasum,
263: fs->lfs_sumsize -
264: sizeof(sp->ss_sumsum))) {
1.33 ad 265: brelse(bp, 0);
1.30 perseant 266: if (debug)
267: printf("bad cksum at %x\n",
268: (unsigned)tdaddr);
1.29 perseant 269: break;
270: }
271: fp = (FINFO *)(sp + 1);
272: bc = howmany(sp->ss_ninos, INOPB(fs)) <<
273: (fs->lfs_version > 1 ? fs->lfs_ffshift :
274: fs->lfs_bshift);
275: for (i = 0; i < sp->ss_nfinfo; i++) {
276: bc += fp->fi_lastlength + ((fp->fi_nblocks - 1)
277: << fs->lfs_bshift);
278: fp = (FINFO *)(fp->fi_blocks + fp->fi_nblocks);
279: }
280:
281: tdaddr += btofsb(fs, bc) + 1;
282: fs->lfs_offset = tdaddr;
283: fs->lfs_serial = sp->ss_serial + 1;
1.33 ad 284: brelse(bp, 0);
1.29 perseant 285: }
286:
287: /*
288: * Set curseg, nextseg appropriately -- inlined from
289: * lfs_newseg()
290: */
291: curseg = dtosn(fs, fs->lfs_offset);
292: fs->lfs_curseg = sntod(fs, curseg);
293: for (sn = curseg + fs->lfs_interleave;;) {
294: sn = (sn + 1) % fs->lfs_nseg;
295: if (sn == curseg)
296: errx(1, "init: no clean segments");
297: LFS_SEGENTRY(sup, fs, sn, bp);
298: isdirty = sup->su_flags & SEGUSE_DIRTY;
1.33 ad 299: brelse(bp, 0);
1.29 perseant 300:
301: if (!isdirty)
302: break;
303: }
304:
305: /* Skip superblock if necessary */
306: for (i = 0; i < LFS_MAXNUMSB; i++)
307: if (fs->lfs_offset == fs->lfs_sboffs[i])
308: fs->lfs_offset += btofsb(fs, LFS_SBPAD);
309:
310: ++fs->lfs_nactive;
311: fs->lfs_nextseg = sntod(fs, sn);
312: if (debug) {
313: pwarn("offset = 0x%" PRIx32 ", serial = %" PRId64 "\n",
314: fs->lfs_offset, fs->lfs_serial);
315: pwarn("curseg = %" PRIx32 ", nextseg = %" PRIx32 "\n",
316: fs->lfs_curseg, fs->lfs_nextseg);
317: }
318:
319: if (!nflag && !skipclean) {
320: fs->lfs_idaddr = idaddr;
321: fsmodified = 1;
322: sbdirty();
323: }
324: }
325:
1.5 perseant 326: if (debug) {
1.29 perseant 327: pwarn("idaddr = 0x%lx\n", idaddr ? (unsigned long)idaddr :
1.15 perseant 328: (unsigned long)fs->lfs_idaddr);
1.29 perseant 329: pwarn("dev_bsize = %lu\n", dev_bsize);
330: pwarn("lfs_bsize = %lu\n", (unsigned long) fs->lfs_bsize);
331: pwarn("lfs_fsize = %lu\n", (unsigned long) fs->lfs_fsize);
332: pwarn("lfs_frag = %lu\n", (unsigned long) fs->lfs_frag);
333: pwarn("lfs_inopb = %lu\n", (unsigned long) fs->lfs_inopb);
1.13 perseant 334: }
335: if (fs->lfs_version == 1)
336: maxfsblock = fs->lfs_size * (fs->lfs_bsize / dev_bsize);
337: else
338: maxfsblock = fs->lfs_size;
1.18 minoura 339: maxfilesize = calcmaxfilesize(fs->lfs_bshift);
1.31 christos 340: if (/* fs->lfs_minfree < 0 || */ fs->lfs_minfree > 99) {
1.1 perseant 341: pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK",
1.13 perseant 342: fs->lfs_minfree);
1.1 perseant 343: if (reply("SET TO DEFAULT") == 1) {
1.13 perseant 344: fs->lfs_minfree = 10;
1.1 perseant 345: sbdirty();
346: }
347: }
1.13 perseant 348: if (fs->lfs_bmask != fs->lfs_bsize - 1) {
1.29 perseant 349: pwarn("INCORRECT BMASK=0x%x IN SUPERBLOCK (SHOULD BE 0x%x)",
1.13 perseant 350: (unsigned int) fs->lfs_bmask,
351: (unsigned int) fs->lfs_bsize - 1);
352: fs->lfs_bmask = fs->lfs_bsize - 1;
1.1 perseant 353: if (preen)
354: printf(" (FIXED)\n");
355: if (preen || reply("FIX") == 1) {
356: sbdirty();
357: }
358: }
1.13 perseant 359: if (fs->lfs_ffmask != fs->lfs_fsize - 1) {
360: pwarn("INCORRECT FFMASK=%" PRId64 " IN SUPERBLOCK",
361: fs->lfs_ffmask);
362: fs->lfs_ffmask = fs->lfs_fsize - 1;
1.1 perseant 363: if (preen)
364: printf(" (FIXED)\n");
365: if (preen || reply("FIX") == 1) {
366: sbdirty();
367: }
368: }
1.13 perseant 369: if (fs->lfs_fbmask != (1 << fs->lfs_fbshift) - 1) {
1.38 bouyer 370: pwarn("INCORRECT FBMASK=%" PRId64 " IN SUPERBLOCK",
371: fs->lfs_fbmask);
1.13 perseant 372: fs->lfs_fbmask = (1 << fs->lfs_fbshift) - 1;
373: if (preen)
374: printf(" (FIXED)\n");
375: if (preen || reply("FIX") == 1) {
376: sbdirty();
377: }
378: }
379: if (fs->lfs_maxfilesize != maxfilesize) {
1.8 lukem 380: pwarn(
1.29 perseant 381: "INCORRECT MAXFILESIZE=%llu IN SUPERBLOCK (SHOULD BE %llu WITH BSHIFT %d)",
1.13 perseant 382: (unsigned long long) fs->lfs_maxfilesize,
1.20 perseant 383: (unsigned long long) maxfilesize, (int)fs->lfs_bshift);
1.5 perseant 384: if (preen)
385: printf(" (FIXED)\n");
386: if (preen || reply("FIX") == 1) {
1.20 perseant 387: fs->lfs_maxfilesize = maxfilesize;
1.5 perseant 388: sbdirty();
1.1 perseant 389: }
1.5 perseant 390: }
1.39 ! dholland 391: if (fs->lfs_maxsymlinklen != UFS1_MAXSYMLINKLEN) {
1.5 perseant 392: pwarn("INCORRECT MAXSYMLINKLEN=%d IN SUPERBLOCK",
1.13 perseant 393: fs->lfs_maxsymlinklen);
1.39 ! dholland 394: fs->lfs_maxsymlinklen = UFS1_MAXSYMLINKLEN;
1.5 perseant 395: if (preen)
396: printf(" (FIXED)\n");
397: if (preen || reply("FIX") == 1) {
398: sbdirty();
1.1 perseant 399: }
1.5 perseant 400: }
1.13 perseant 401:
402: /*
403: * Read in the Ifile; we'll be using it a lot.
404: * XXX If the Ifile is corrupted we are in bad shape. We need to
405: * XXX run through the segment headers of the entire disk to
406: * XXX reconstruct the inode table, then pretend all segments are
407: * XXX dirty while we do the rest.
408: */
409: ivp = fs->lfs_ivnode;
1.16 fvdl 410: maxino = ((VTOI(ivp)->i_ffs1_size - (fs->lfs_cleansz + fs->lfs_segtabsz)
1.13 perseant 411: * fs->lfs_bsize) / fs->lfs_bsize) * fs->lfs_ifpb;
412: if (debug)
1.29 perseant 413: pwarn("maxino = %llu\n", (unsigned long long)maxino);
1.16 fvdl 414: for (i = 0; i < VTOI(ivp)->i_ffs1_size; i += fs->lfs_bsize) {
1.36 hannken 415: bread(ivp, i >> fs->lfs_bshift, fs->lfs_bsize, NOCRED, 0, &bp);
1.13 perseant 416: /* XXX check B_ERROR */
1.33 ad 417: brelse(bp, 0);
1.13 perseant 418: }
419:
1.1 perseant 420: /*
421: * allocate and initialize the necessary maps
422: */
1.32 christos 423: din_table = ecalloc(maxino, sizeof(*din_table));
424: seg_table = ecalloc(fs->lfs_nseg, sizeof(SEGUSE));
1.13 perseant 425: /* Get segment flags */
426: for (i = 0; i < fs->lfs_nseg; i++) {
427: LFS_SEGENTRY(sup, fs, i, bp);
428: seg_table[i].su_flags = sup->su_flags & ~SEGUSE_ACTIVE;
1.14 perseant 429: if (preen)
430: seg_table[i].su_nbytes = sup->su_nbytes;
1.33 ad 431: brelse(bp, 0);
1.13 perseant 432: }
433:
434: /* Initialize Ifile entry */
435: din_table[fs->lfs_ifile] = fs->lfs_idaddr;
1.16 fvdl 436: seg_table[dtosn(fs, fs->lfs_idaddr)].su_nbytes += DINODE1_SIZE;
1.13 perseant 437:
1.1 perseant 438: #ifndef VERBOSE_BLOCKMAP
439: bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t));
1.32 christos 440: blockmap = ecalloc(bmapsize, sizeof(char));
1.1 perseant 441: #else
1.5 perseant 442: bmapsize = maxfsblock * sizeof(ino_t);
1.32 christos 443: blockmap = ecalloc(maxfsblock, sizeof(ino_t));
1.1 perseant 444: #endif
1.32 christos 445: statemap = ecalloc(maxino, sizeof(char));
446: typemap = ecalloc(maxino, sizeof(char));
447: lncntp = ecalloc(maxino, sizeof(int16_t));
1.14 perseant 448:
449: if (preen) {
450: n_files = fs->lfs_nfiles;
451: n_blks = fs->lfs_dsize - fs->lfs_bfree;
452: numdirs = maxino;
453: inplast = 0;
454: listmax = numdirs + 10;
1.32 christos 455: inpsort = ecalloc(listmax, sizeof(struct inoinfo *));
456: inphead = ecalloc(numdirs, sizeof(struct inoinfo *));
1.14 perseant 457: }
458:
1.1 perseant 459: return (1);
460:
461: ckfini(0);
462: return (0);
463: }
464:
CVSweb <webmaster@jp.NetBSD.org>