1 /* $NetBSD: setup.c,v 1.16 2003/04/02 10:39:28 fvdl Exp $ */ 2 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 /* 39 * Copyright (c) 1980, 1986, 1993 40 * The Regents of the University of California. All rights reserved. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed by the University of 53 * California, Berkeley and its contributors. 54 * 4. Neither the name of the University nor the names of its contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 */ 70 71 /* #define DKTYPENAMES */ 72 #define FSTYPENAMES 73 #include <sys/types.h> 74 #include <sys/param.h> 75 #include <sys/time.h> 76 #include <sys/buf.h> 77 #include <sys/mount.h> 78 #include <sys/queue.h> 79 #include <sys/stat.h> 80 #include <sys/ioctl.h> 81 #include <sys/disklabel.h> 82 #include <sys/file.h> 83 84 #include <ufs/ufs/inode.h> 85 #include <ufs/ufs/ufsmount.h> 86 #define vnode uvnode 87 #include <ufs/lfs/lfs.h> 88 #undef vnode 89 90 #include <ctype.h> 91 #include <err.h> 92 #include <errno.h> 93 #include <stdio.h> 94 #include <stdlib.h> 95 #include <string.h> 96 97 #include "bufcache.h" 98 #include "vnode.h" 99 #include "lfs.h" 100 101 #include "fsck.h" 102 #include "extern.h" 103 #include "fsutil.h" 104 105 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 106 107 u_quad_t maxtable[] = { 108 /* 1 */ -1, 109 /* 2 */ -1, 110 /* 4 */ -1, 111 /* 8 */ -1, 112 /* 16 */ -1, 113 /* 32 */ -1, 114 /* 64 */ -1, 115 /* 128 */ -1, 116 /* 256 */ -1, 117 /* 512 */ NDADDR + 128 + 128 * 128 + 128 * 128 * 128, 118 /* 1024 */ NDADDR + 256 + 256 * 256 + 256 * 256 * 256, 119 /* 2048 */ NDADDR + 512 + 512 * 512 + 512 * 512 * 512, 120 /* 4096 */ NDADDR + 1024 + 1024 * 1024 + 1024 * 1024 * 1024, 121 /* 8192 */ 1 << 31, 122 /* 16 K */ 1 << 31, 123 /* 32 K */ 1 << 31, 124 }; 125 126 static struct disklabel *getdisklabel(const char *, int); 127 128 ufs_daddr_t *din_table; 129 SEGUSE *seg_table; 130 131 #ifdef DKTYPENAMES 132 int useless(void); 133 134 int 135 useless(void) 136 { 137 char **foo = (char **) dktypenames; 138 char **bar = (char **) fscknames; 139 140 return foo - bar; 141 } 142 #endif 143 144 int 145 setup(const char *dev) 146 { 147 long bmapsize; 148 struct disklabel *lp; 149 struct stat statb; 150 int doskipclean; 151 u_int64_t maxfilesize; 152 int open_flags; 153 struct uvnode *ivp; 154 struct ubuf *bp; 155 int i; 156 SEGUSE *sup; 157 158 havesb = 0; 159 doskipclean = skipclean; 160 if (stat(dev, &statb) < 0) { 161 printf("Can't stat %s: %s\n", dev, strerror(errno)); 162 return (0); 163 } 164 if (!S_ISCHR(statb.st_mode)) { 165 pfatal("%s is not a character device", dev); 166 if (reply("CONTINUE") == 0) 167 return (0); 168 } 169 if (nflag) 170 open_flags = O_RDONLY; 171 else 172 open_flags = O_RDWR; 173 174 if ((fsreadfd = open(dev, open_flags)) < 0) { 175 printf("Can't open %s: %s\n", dev, strerror(errno)); 176 return (0); 177 } 178 if (preen == 0) 179 printf("** %s", dev); 180 if (nflag) { 181 if (preen) 182 pfatal("NO WRITE ACCESS"); 183 printf(" (NO WRITE)"); 184 } 185 if (preen == 0) 186 printf("\n"); 187 fsmodified = 0; 188 lfdir = 0; 189 190 bufinit(); 191 fs = lfs_init(fsreadfd, bflag, idaddr, debug); 192 if (fs == NULL) { 193 if (preen) 194 printf("%s: ", cdevname()); 195 pfatal("BAD SUPER BLOCK\n"); 196 } 197 if ((lp = getdisklabel((char *) NULL, fsreadfd)) != NULL) 198 dev_bsize = secsize = lp->d_secsize; 199 else 200 dev_bsize = secsize = DEV_BSIZE; 201 202 #if 0 203 if (fs->lfs_pflags & LFS_PF_CLEAN) { 204 if (doskipclean) { 205 pwarn("%sile system is clean; not checking\n", 206 preen ? "f" : "** F"); 207 return (-1); 208 } 209 if (!preen) 210 pwarn("** File system is already clean\n"); 211 } 212 #endif 213 214 if (debug) { 215 printf("idaddr = 0x%lx\n", idaddr ? (unsigned long)idaddr : 216 (unsigned long)fs->lfs_idaddr); 217 printf("dev_bsize = %lu\n", dev_bsize); 218 printf("lfs_bsize = %lu\n", (unsigned long) fs->lfs_bsize); 219 printf("lfs_fsize = %lu\n", (unsigned long) fs->lfs_fsize); 220 printf("lfs_frag = %lu\n", (unsigned long) fs->lfs_frag); 221 printf("lfs_inopb = %lu\n", (unsigned long) fs->lfs_inopb); 222 } 223 if (fs->lfs_version == 1) 224 maxfsblock = fs->lfs_size * (fs->lfs_bsize / dev_bsize); 225 else 226 maxfsblock = fs->lfs_size; 227 maxfilesize = maxtable[fs->lfs_bshift] << fs->lfs_bshift; 228 if ((fs->lfs_minfree < 0 || fs->lfs_minfree > 99)) { 229 pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", 230 fs->lfs_minfree); 231 if (reply("SET TO DEFAULT") == 1) { 232 fs->lfs_minfree = 10; 233 sbdirty(); 234 } 235 } 236 if (fs->lfs_bmask != fs->lfs_bsize - 1) { 237 pwarn("INCORRECT BMASK=%x IN SUPERBLOCK (should be %x)", 238 (unsigned int) fs->lfs_bmask, 239 (unsigned int) fs->lfs_bsize - 1); 240 fs->lfs_bmask = fs->lfs_bsize - 1; 241 if (preen) 242 printf(" (FIXED)\n"); 243 if (preen || reply("FIX") == 1) { 244 sbdirty(); 245 } 246 } 247 if (fs->lfs_ffmask != fs->lfs_fsize - 1) { 248 pwarn("INCORRECT FFMASK=%" PRId64 " IN SUPERBLOCK", 249 fs->lfs_ffmask); 250 fs->lfs_ffmask = fs->lfs_fsize - 1; 251 if (preen) 252 printf(" (FIXED)\n"); 253 if (preen || reply("FIX") == 1) { 254 sbdirty(); 255 } 256 } 257 if (fs->lfs_fbmask != (1 << fs->lfs_fbshift) - 1) { 258 pwarn("INCORRECT FFMASK=%" PRId64 " IN SUPERBLOCK", 259 fs->lfs_ffmask); 260 fs->lfs_fbmask = (1 << fs->lfs_fbshift) - 1; 261 if (preen) 262 printf(" (FIXED)\n"); 263 if (preen || reply("FIX") == 1) { 264 sbdirty(); 265 } 266 } 267 if (fs->lfs_maxfilesize != maxfilesize) { 268 pwarn( 269 "INCORRECT MAXFILESIZE=%llu IN SUPERBLOCK (should be %llu)", 270 (unsigned long long) fs->lfs_maxfilesize, 271 (unsigned long long) maxfilesize); 272 fs->lfs_maxfilesize = maxfilesize; 273 if (preen) 274 printf(" (FIXED)\n"); 275 if (preen || reply("FIX") == 1) { 276 sbdirty(); 277 } 278 } 279 if (fs->lfs_maxsymlinklen != MAXSYMLINKLEN_UFS1) { 280 pwarn("INCORRECT MAXSYMLINKLEN=%d IN SUPERBLOCK", 281 fs->lfs_maxsymlinklen); 282 fs->lfs_maxsymlinklen = MAXSYMLINKLEN_UFS1; 283 if (preen) 284 printf(" (FIXED)\n"); 285 if (preen || reply("FIX") == 1) { 286 sbdirty(); 287 } 288 } 289 290 /* 291 * Read in the Ifile; we'll be using it a lot. 292 * XXX If the Ifile is corrupted we are in bad shape. We need to 293 * XXX run through the segment headers of the entire disk to 294 * XXX reconstruct the inode table, then pretend all segments are 295 * XXX dirty while we do the rest. 296 */ 297 ivp = fs->lfs_ivnode; 298 maxino = ((VTOI(ivp)->i_ffs1_size - (fs->lfs_cleansz + fs->lfs_segtabsz) 299 * fs->lfs_bsize) / fs->lfs_bsize) * fs->lfs_ifpb; 300 if (debug) 301 printf("maxino = %d\n", maxino); 302 for (i = 0; i < VTOI(ivp)->i_ffs1_size; i += fs->lfs_bsize) { 303 bread(ivp, i >> fs->lfs_bshift, fs->lfs_bsize, NOCRED, &bp); 304 /* XXX check B_ERROR */ 305 brelse(bp); 306 } 307 308 /* 309 * allocate and initialize the necessary maps 310 */ 311 din_table = (ufs_daddr_t *) malloc(maxino * sizeof(*din_table)); 312 memset(din_table, 0, maxino * sizeof(*din_table)); 313 seg_table = (SEGUSE *) malloc(fs->lfs_nseg * sizeof(SEGUSE)); 314 memset(seg_table, 0, fs->lfs_nseg * sizeof(SEGUSE)); 315 /* Get segment flags */ 316 for (i = 0; i < fs->lfs_nseg; i++) { 317 LFS_SEGENTRY(sup, fs, i, bp); 318 seg_table[i].su_flags = sup->su_flags & ~SEGUSE_ACTIVE; 319 if (preen) 320 seg_table[i].su_nbytes = sup->su_nbytes; 321 brelse(bp); 322 } 323 324 /* Initialize Ifile entry */ 325 din_table[fs->lfs_ifile] = fs->lfs_idaddr; 326 seg_table[dtosn(fs, fs->lfs_idaddr)].su_nbytes += DINODE1_SIZE; 327 328 #ifndef VERBOSE_BLOCKMAP 329 bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t)); 330 blockmap = calloc((unsigned) bmapsize, sizeof(char)); 331 #else 332 bmapsize = maxfsblock * sizeof(ino_t); 333 blockmap = (ino_t *) calloc(maxfsblock, sizeof(ino_t)); 334 #endif 335 if (blockmap == NULL) { 336 printf("cannot alloc %u bytes for blockmap\n", 337 (unsigned) bmapsize); 338 goto badsblabel; 339 } 340 statemap = calloc((unsigned) maxino, sizeof(char)); 341 if (statemap == NULL) { 342 printf("cannot alloc %u bytes for statemap\n", 343 (unsigned) maxino); 344 goto badsblabel; 345 } 346 typemap = calloc((unsigned) maxino, sizeof(char)); 347 if (typemap == NULL) { 348 printf("cannot alloc %u bytes for typemap\n", 349 (unsigned) maxino); 350 goto badsblabel; 351 } 352 lncntp = (int16_t *) calloc((unsigned) maxino, sizeof(int16_t)); 353 if (lncntp == NULL) { 354 printf("cannot alloc %lu bytes for lncntp\n", 355 (unsigned long) maxino * sizeof(int16_t)); 356 goto badsblabel; 357 } 358 359 if (preen) { 360 n_files = fs->lfs_nfiles; 361 n_blks = fs->lfs_dsize - fs->lfs_bfree; 362 numdirs = maxino; 363 inplast = 0; 364 listmax = numdirs + 10; 365 inpsort = (struct inoinfo **) calloc((unsigned) listmax, 366 sizeof(struct inoinfo *)); 367 inphead = (struct inoinfo **) calloc((unsigned) numdirs, 368 sizeof(struct inoinfo *)); 369 if (inpsort == NULL || inphead == NULL) { 370 printf("cannot alloc %lu bytes for inphead\n", 371 (unsigned long) numdirs * sizeof(struct inoinfo *)); 372 exit(1); 373 } 374 } 375 376 return (1); 377 378 badsblabel: 379 ckfini(0); 380 return (0); 381 } 382 383 static struct disklabel * 384 getdisklabel(const char *s, int fd) 385 { 386 static struct disklabel lab; 387 388 if (ioctl(fd, DIOCGDINFO, (char *) &lab) < 0) { 389 if (s == NULL) 390 return ((struct disklabel *) NULL); 391 pwarn("ioctl (GCINFO): %s\n", strerror(errno)); 392 return NULL; 393 } 394 return (&lab); 395 } 396