1 /* $NetBSD: make_lfs.c,v 1.59 2015/10/15 06:24:33 dholland 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 * 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 */ 31 /*- 32 * Copyright (c) 1991, 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. 43 * 3. Neither the name of the University nor the names of its contributors 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 #include <sys/cdefs.h> 61 #ifndef lint 62 #if 0 63 static char sccsid[] = "@(#)lfs.c 8.5 (Berkeley) 5/24/95"; 64 #else 65 __RCSID("$NetBSD: make_lfs.c,v 1.59 2015/10/15 06:24:33 dholland Exp $"); 66 #endif 67 #endif /* not lint */ 68 69 #include <sys/param.h> 70 #include <sys/disk.h> 71 #include <sys/time.h> 72 #include <sys/mount.h> 73 #include <sys/stat.h> 74 75 /* Override certain things to make <ufs/lfs/lfs.h> work */ 76 # undef simple_lock 77 # define simple_lock(x) 78 # undef simple_unlock 79 # define simple_unlock(x) 80 # define vnode uvnode 81 # define buf ubuf 82 # define panic call_panic 83 #include <ufs/lfs/lfs.h> 84 #include <ufs/lfs/lfs_accessors.h> 85 #include <ufs/lfs/lfs_inode.h> 86 87 #include <err.h> 88 #include <errno.h> 89 #include <stdio.h> 90 #include <stdlib.h> 91 #include <string.h> 92 #include <time.h> 93 #include <unistd.h> 94 95 #include "config.h" 96 #include "extern.h" 97 98 #include "bufcache.h" 99 #include "vnode.h" 100 #include "lfs_user.h" 101 #include "segwrite.h" 102 103 extern int Nflag; /* Don't write anything */ 104 105 static blkcnt_t ifibc; /* How many indirect blocks */ 106 107 #ifdef MAKE_LF_DIR 108 # define HIGHEST_USED_INO LOSTFOUNDINO 109 #else 110 # define HIGHEST_USED_INO ULFS_ROOTINO 111 #endif 112 113 static const struct dlfs dlfs32_default = { 114 .dlfs_magic = LFS_MAGIC, 115 .dlfs_version = LFS_VERSION, 116 .dlfs_size = 0, 117 .dlfs_ssize = DFL_LFSSEG, 118 .dlfs_dsize = 0, 119 .dlfs_bsize = DFL_LFSBLOCK, 120 .dlfs_fsize = DFL_LFSFRAG, 121 .dlfs_frag = DFL_LFSBLOCK/DFL_LFSFRAG, 122 .dlfs_freehd = HIGHEST_USED_INO + 1, 123 .dlfs_bfree = 0, 124 .dlfs_nfiles = 0, 125 .dlfs_avail = 0, 126 .dlfs_uinodes = 0, 127 .dlfs_idaddr = 0, 128 .dlfs_ifile = LFS_IFILE_INUM, 129 .dlfs_lastseg = 0, 130 .dlfs_nextseg = 0, 131 .dlfs_curseg = 0, 132 .dlfs_offset = 0, 133 .dlfs_lastpseg = 0, 134 .dlfs_inopf = 0, 135 .dlfs_minfree = MINFREE, 136 .dlfs_maxfilesize = 0, 137 .dlfs_fsbpseg = 0, 138 .dlfs_inopb = DFL_LFSBLOCK/sizeof(struct lfs32_dinode), 139 .dlfs_ifpb = DFL_LFSBLOCK/sizeof(IFILE32), 140 .dlfs_sepb = DFL_LFSBLOCK/sizeof(SEGUSE), 141 .dlfs_nindir = DFL_LFSBLOCK/sizeof(int32_t), 142 .dlfs_nseg = 0, 143 .dlfs_nspf = 0, 144 .dlfs_cleansz = 0, 145 .dlfs_segtabsz = 0, 146 .dlfs_segmask = DFL_LFSSEG_MASK, 147 .dlfs_segshift = DFL_LFSSEG_SHIFT, 148 .dlfs_bshift = DFL_LFSBLOCK_SHIFT, 149 .dlfs_ffshift = DFL_LFS_FFSHIFT, 150 .dlfs_fbshift = DFL_LFS_FBSHIFT, 151 .dlfs_bmask = DFL_LFSBLOCK_MASK, 152 .dlfs_ffmask = DFL_LFS_FFMASK, 153 .dlfs_fbmask = DFL_LFS_FBMASK, 154 .dlfs_blktodb = 0, 155 .dlfs_sushift = 0, 156 .dlfs_maxsymlinklen = LFS32_MAXSYMLINKLEN, 157 .dlfs_sboffs = { 0 }, 158 .dlfs_nclean = 0, 159 .dlfs_fsmnt = { 0 }, 160 .dlfs_pflags = LFS_PF_CLEAN, 161 .dlfs_dmeta = 0, 162 .dlfs_minfreeseg = 0, 163 .dlfs_sumsize = 0, 164 .dlfs_serial = 0, 165 .dlfs_ibsize = DFL_LFSFRAG, 166 .dlfs_s0addr = 0, 167 .dlfs_tstamp = 0, 168 .dlfs_inodefmt = LFS_44INODEFMT, 169 .dlfs_interleave = 0, 170 .dlfs_ident = 0, 171 .dlfs_fsbtodb = 0, 172 .dlfs_resvseg = 0, 173 174 .dlfs_pad = { 0 }, 175 .dlfs_cksum = 0 176 }; 177 178 static const struct dlfs64 dlfs64_default = { 179 .dlfs_magic = LFS64_MAGIC, 180 .dlfs_version = LFS_VERSION, 181 .dlfs_size = 0, 182 .dlfs_dsize = 0, 183 .dlfs_ssize = DFL_LFSSEG, 184 .dlfs_bsize = DFL_LFSBLOCK, 185 .dlfs_fsize = DFL_LFSFRAG, 186 .dlfs_frag = DFL_LFSBLOCK/DFL_LFSFRAG, 187 .dlfs_freehd = HIGHEST_USED_INO + 1, 188 .dlfs_nfiles = 0, 189 .dlfs_bfree = 0, 190 .dlfs_avail = 0, 191 .dlfs_idaddr = 0, 192 .dlfs_uinodes = 0, 193 .dlfs_unused_0 = 0, 194 .dlfs_lastseg = 0, 195 .dlfs_nextseg = 0, 196 .dlfs_curseg = 0, 197 .dlfs_offset = 0, 198 .dlfs_lastpseg = 0, 199 .dlfs_inopf = 0, 200 .dlfs_minfree = MINFREE, 201 .dlfs_maxfilesize = 0, 202 .dlfs_fsbpseg = 0, 203 .dlfs_inopb = DFL_LFSBLOCK/sizeof(struct lfs64_dinode), 204 .dlfs_ifpb = DFL_LFSBLOCK/sizeof(IFILE64), 205 .dlfs_sepb = DFL_LFSBLOCK/sizeof(SEGUSE), 206 .dlfs_nindir = DFL_LFSBLOCK/sizeof(int64_t), 207 .dlfs_nseg = 0, 208 .dlfs_nspf = 0, 209 .dlfs_cleansz = 0, 210 .dlfs_segtabsz = 0, 211 .dlfs_bshift = DFL_LFSBLOCK_SHIFT, 212 .dlfs_ffshift = DFL_LFS_FFSHIFT, 213 .dlfs_fbshift = DFL_LFS_FBSHIFT, 214 .dlfs_bmask = DFL_LFSBLOCK_MASK, 215 .dlfs_ffmask = DFL_LFS_FFMASK, 216 .dlfs_fbmask = DFL_LFS_FBMASK, 217 .dlfs_blktodb = 0, 218 .dlfs_sushift = 0, 219 .dlfs_sboffs = { 0 }, 220 .dlfs_maxsymlinklen = LFS64_MAXSYMLINKLEN, 221 .dlfs_nclean = 0, 222 .dlfs_fsmnt = { 0 }, 223 .dlfs_pflags = LFS_PF_CLEAN, 224 .dlfs_dmeta = 0, 225 .dlfs_minfreeseg = 0, 226 .dlfs_sumsize = 0, 227 .dlfs_ibsize = DFL_LFSFRAG, 228 .dlfs_inodefmt = LFS_44INODEFMT, 229 .dlfs_serial = 0, 230 .dlfs_s0addr = 0, 231 .dlfs_tstamp = 0, 232 .dlfs_interleave = 0, 233 .dlfs_ident = 0, 234 .dlfs_fsbtodb = 0, 235 .dlfs_resvseg = 0, 236 237 .dlfs_pad = { 0 }, 238 .dlfs_cksum = 0 239 }; 240 241 static const struct lfs lfs_default; 242 243 #define UMASK 0755 244 245 struct dirproto { 246 ino_t dp_ino; 247 const char *dp_name; 248 unsigned dp_type; 249 }; 250 251 static const struct dirproto lfs_root_dir[] = { 252 { ULFS_ROOTINO, ".", LFS_DT_DIR }, 253 { ULFS_ROOTINO, "..", LFS_DT_DIR }, 254 /*{ LFS_IFILE_INUM, "ifile", LFS_DT_REG },*/ 255 #ifdef MAKE_LF_DIR 256 { LOSTFOUNDINO, "lost+found", LFS_DT_DIR }, 257 #endif 258 }; 259 260 #ifdef MAKE_LF_DIR 261 static const struct dirproto lfs_lf_dir[] = { 262 { LOSTFOUNDINO, ".", LFS_DT_DIR }, 263 { ULFS_ROOTINO, "..", LFS_DT_DIR }, 264 }; 265 #endif 266 267 void pwarn(const char *, ...); 268 static void make_dinode(ino_t, union lfs_dinode *, int, struct lfs *); 269 static void make_dir(struct lfs *, void *, 270 const struct dirproto *, unsigned); 271 272 /* 273 * calculate the maximum file size allowed with the specified block shift. 274 */ 275 static uint64_t 276 maxfilesize(struct lfs *fs, int bshift) 277 { 278 uint64_t nptr; /* number of block pointers per block */ 279 uint64_t maxblock; 280 281 nptr = (1 << bshift) / LFS_BLKPTRSIZE(fs); 282 maxblock = ULFS_NDADDR + nptr + nptr * nptr + nptr * nptr * nptr; 283 284 return maxblock << bshift; 285 } 286 287 /* 288 * Create the root directory for this file system and the lost+found 289 * directory. 290 */ 291 static void 292 make_dinode(ino_t ino, union lfs_dinode *dip, int nfrags, struct lfs *fs) 293 { 294 int i; 295 int nblocks, bb, base, factor, lvl; 296 time_t t; 297 298 nblocks = howmany(nfrags, lfs_sb_getfrag(fs)); 299 if (nblocks >= ULFS_NDADDR) 300 nfrags = roundup(nfrags, lfs_sb_getfrag(fs)); 301 302 lfs_dino_setnlink(fs, dip, 1); 303 lfs_dino_setblocks(fs, dip, nfrags); 304 305 lfs_dino_setsize(fs, dip, nfrags << lfs_sb_getffshift(fs)); 306 t = lfs_sb_gettstamp(fs); 307 lfs_dino_setatime(fs, dip, t); 308 lfs_dino_setmtime(fs, dip, t); 309 lfs_dino_setctime(fs, dip, t); 310 lfs_dino_setatimensec(fs, dip, 0); 311 lfs_dino_setmtimensec(fs, dip, 0); 312 lfs_dino_setctimensec(fs, dip, 0); 313 lfs_dino_setinumber(fs, dip, ino); 314 lfs_dino_setgen(fs, dip, 1); 315 316 if (ULFS_NDADDR < nblocks) { 317 /* Count up how many indirect blocks we need, recursively */ 318 /* XXX We are only called with nblocks > 1 for Ifile */ 319 bb = nblocks - ULFS_NDADDR; 320 while (bb > 0) { 321 bb = howmany(bb, LFS_NINDIR(fs)); 322 ifibc += bb; 323 --bb; 324 } 325 lfs_dino_setblocks(fs, dip, 326 lfs_dino_getblocks(fs, dip) + lfs_blkstofrags(fs, ifibc)); 327 } 328 329 /* Assign the block addresses for the ifile */ 330 for (i = 0; i < MIN(nblocks,ULFS_NDADDR); i++) { 331 lfs_dino_setdb(fs, dip, i, 0x0); 332 } 333 if (nblocks > ULFS_NDADDR) { 334 lfs_dino_setib(fs, dip, 0, 0x0); 335 bb = howmany(nblocks - ULFS_NDADDR, LFS_NINDIR(fs)) - 1; 336 factor = LFS_NINDIR(fs); 337 base = -ULFS_NDADDR - factor; 338 lvl = 1; 339 while (bb > 0) { 340 lfs_dino_setib(fs, dip, lvl, 0x0); 341 bb = howmany(bb, LFS_NINDIR(fs)); 342 --bb; 343 factor *= LFS_NINDIR(fs); 344 base -= factor; 345 ++lvl; 346 } 347 } 348 } 349 350 /* 351 * Construct a set of directory entries in "bufp". We assume that all the 352 * entries in protodir fit in the first DIRBLKSIZ. 353 */ 354 static void 355 make_dir(struct lfs *fs, void *bufp, 356 const struct dirproto *protodir, unsigned numentries) 357 { 358 LFS_DIRHEADER *ep; 359 unsigned spaceleft; 360 unsigned namlen, reclen; 361 unsigned i; 362 363 spaceleft = LFS_DIRBLKSIZ; 364 ep = bufp; 365 for (i = 0; i < numentries; i++) { 366 namlen = strlen(protodir[i].dp_name); 367 reclen = LFS_DIRECTSIZ(fs, namlen); 368 if (spaceleft < reclen) 369 fatal("%s: %s", special, "directory too big"); 370 371 /* Last entry includes all the free space. */ 372 if (i + 1 == numentries) { 373 reclen = spaceleft; 374 } 375 spaceleft -= reclen; 376 377 lfs_dir_setino(fs, ep, protodir[i].dp_ino); 378 lfs_dir_setreclen(fs, ep, reclen); 379 lfs_dir_settype(fs, ep, protodir[i].dp_type); 380 lfs_dir_setnamlen(fs, ep, namlen); 381 lfs_copydirname(fs, lfs_dir_nameptr(fs, ep), protodir[i].dp_name, 382 namlen, reclen); 383 ep = LFS_NEXTDIR(fs, ep); 384 } 385 assert(spaceleft == 0); 386 } 387 388 int 389 make_lfs(int devfd, uint secsize, struct dkwedge_info *dkw, int minfree, 390 int block_size, int frag_size, int seg_size, int minfreeseg, 391 int resvseg, int version, daddr_t start, int ibsize, int interleave, 392 u_int32_t roll_id, int bitwidth) 393 { 394 union lfs_dinode *dip; /* Pointer to a disk inode */ 395 CLEANERINFO *cip; /* Segment cleaner information table */ 396 IFILE *ipall; /* Pointer to array of ifile structures */ 397 IFILE64 *ip64 = NULL; 398 IFILE32 *ip32 = NULL; 399 IFILE_V1 *ip_v1 = NULL; 400 struct lfs *fs; /* Superblock */ 401 SEGUSE *segp; /* Segment usage table */ 402 daddr_t sb_addr; /* Address of superblocks */ 403 daddr_t seg_addr; /* Address of current segment */ 404 int bsize; /* Block size */ 405 int fsize; /* Fragment size */ 406 int db_per_blk; /* Disk blocks per file block */ 407 int i, j; 408 int sb_interval; /* number of segs between super blocks */ 409 int ssize; /* Segment size */ 410 double fssize; 411 int warned_segtoobig=0; 412 int label_fsb, sb_fsb; 413 int curw, ww; 414 char tbuf[BUFSIZ]; 415 struct ubuf *bp; 416 struct uvnode *vp, *save_devvp; 417 daddr_t bb, ubb; 418 int dmeta, labelskew; 419 u_int64_t tsepb, tnseg; 420 time_t stamp; 421 bool is64; 422 bool dobyteswap = false; /* XXX notyet */ 423 424 is64 = (bitwidth == 64); 425 426 /* 427 * Initialize buffer cache. Use a ballpark guess of the length of 428 * the segment table for the number of hash chains. 429 */ 430 tnseg = dkw->dkw_size / ((seg_size ? seg_size : DFL_LFSSEG) / secsize); 431 tsepb = (block_size ? block_size : DFL_LFSBLOCK) / sizeof(SEGSUM32); 432 if (tnseg == 0) 433 fatal("zero size partition"); 434 bufinit(tnseg / tsepb); 435 436 /* Initialize LFS subsystem with blank superblock and ifile. */ 437 fs = lfs_init(devfd, start, 0, 1, 1/* XXX debug*/); 438 save_devvp = fs->lfs_devvp; 439 vp = fs->lfs_ivnode; 440 /* XXX this seems like a rubbish */ 441 *fs = lfs_default; 442 if (is64) { 443 fs->lfs_dlfs_u.u_64 = dlfs64_default; 444 } else { 445 fs->lfs_dlfs_u.u_32 = dlfs32_default; 446 } 447 fs->lfs_is64 = is64; 448 fs->lfs_dobyteswap = dobyteswap; 449 fs->lfs_hasolddirfmt = false; 450 fs->lfs_ivnode = vp; 451 fs->lfs_devvp = save_devvp; 452 453 454 /* Set version first of all since it is used to compute other fields */ 455 lfs_sb_setversion(fs, version); 456 457 /* If partition is not an LFS partition, warn that that is the case */ 458 if (strcmp(dkw->dkw_ptype, DKW_PTYPE_LFS) != 0) { 459 fatal("partition label indicated fs type \"%s\", " 460 "expected \"%s\"", dkw->dkw_ptype, DKW_PTYPE_LFS); 461 } 462 463 if (!(bsize = block_size)) { 464 bsize = DFL_LFSBLOCK; 465 if (dkw->dkw_size <= SMALL_FSSIZE) 466 bsize = SMALL_LFSBLOCK; 467 } 468 if (!(fsize = frag_size)) { 469 fsize = DFL_LFSFRAG; 470 if (dkw->dkw_size <= SMALL_FSSIZE) 471 fsize = SMALL_LFSFRAG; 472 } 473 if (!(ssize = seg_size)) { 474 ssize = DFL_LFSSEG; 475 if (dkw->dkw_size <= SMALL_FSSIZE) 476 ssize = SMALL_LFSSEG; 477 } 478 if (version > 1) { 479 if (ibsize == 0) 480 ibsize = fsize; 481 if (ibsize <= 0 || ibsize % fsize) 482 fatal("illegal inode block size: %d\n", ibsize); 483 } else if (ibsize && ibsize != bsize) 484 fatal("cannot specify inode block size when version == 1\n"); 485 486 /* Sanity check: fsize<=bsize<ssize */ 487 if (fsize > bsize) { 488 /* Only complain if fsize was explicitly set */ 489 if(frag_size) 490 fatal("fragment size must be <= block size %d", bsize); 491 fsize = bsize; 492 } 493 if (bsize >= ssize) { 494 /* Only fatal if ssize was explicitly set */ 495 if(seg_size) 496 fatal("block size must be < segment size"); 497 warnx("%s: disklabel segment size (%d) too small, using default (%d)", 498 progname, ssize, DFL_LFSSEG); 499 ssize = DFL_LFSSEG; 500 } 501 if (start < 0 || start >= dkw->dkw_size) 502 fatal("filesystem offset %ld out of range", (long)start); 503 if (version == 1) { 504 if (start) 505 warnx("filesystem offset ignored for version 1 filesystem"); 506 start = LFS_LABELPAD / secsize; 507 } 508 509 tryagain: 510 /* Modify parts of superblock overridden by command line arguments */ 511 if (bsize != DFL_LFSBLOCK || fsize != DFL_LFSFRAG) { 512 lfs_sb_setbshift(fs, lfs_log2(bsize)); 513 if (1 << lfs_sb_getbshift(fs) != bsize) 514 fatal("%d: block size not a power of 2", bsize); 515 lfs_sb_setbsize(fs, bsize); 516 lfs_sb_setfsize(fs, fsize); 517 lfs_sb_setbmask(fs, bsize - 1); 518 lfs_sb_setffmask(fs, fsize - 1); 519 lfs_sb_setffshift(fs, lfs_log2(fsize)); 520 if (1 << lfs_sb_getffshift(fs) != fsize) 521 fatal("%d: frag size not a power of 2", fsize); 522 lfs_sb_setfrag(fs, lfs_numfrags(fs, bsize)); 523 lfs_sb_setfbmask(fs, lfs_sb_getfrag(fs) - 1); 524 lfs_sb_setfbshift(fs, lfs_log2(lfs_sb_getfrag(fs))); 525 lfs_sb_setifpb(fs, bsize / IFILE_ENTRYSIZE(fs)); 526 lfs_sb_setnindir(fs, bsize / LFS_BLKPTRSIZE(fs)); 527 } 528 529 if (lfs_sb_getversion(fs) == 1) { 530 lfs_sb_setsumsize(fs, LFS_V1_SUMMARY_SIZE); 531 if (!is64) { 532 unsigned segshift; 533 534 segshift = lfs_log2(ssize); 535 if (1 << segshift != ssize) 536 fatal("%d: segment size not power of 2", 537 ssize); 538 fs->lfs_dlfs_u.u_32.dlfs_segshift = segshift; 539 fs->lfs_dlfs_u.u_32.dlfs_segmask = ssize - 1; 540 } 541 lfs_sb_setifpb(fs, lfs_sb_getbsize(fs) / sizeof(IFILE_V1)); 542 lfs_sb_setibsize(fs, lfs_sb_getbsize(fs)); 543 lfs_sb_setsepb(fs, bsize / sizeof(SEGUSE_V1)); 544 lfs_sb_setssize(fs, ssize >> lfs_sb_getbshift(fs)); 545 } else { 546 if (ssize % fsize) { 547 fprintf(stderr, 548 "Segment size %d is not a multiple of frag size; ", 549 ssize); 550 ssize = roundup(ssize, fsize); 551 fprintf(stderr, "trying size %d.\n", ssize); 552 goto tryagain; 553 } 554 lfs_sb_setsumsize(fs, fsize); 555 if (!is64) { 556 /* these do not exist in the 64-bit superblock */ 557 fs->lfs_dlfs_u.u_32.dlfs_segshift = 0; 558 fs->lfs_dlfs_u.u_32.dlfs_segmask = 0; 559 } 560 lfs_sb_setsepb(fs, bsize / sizeof(SEGUSE)); 561 lfs_sb_setssize(fs, ssize); 562 lfs_sb_setibsize(fs, ibsize); 563 } 564 lfs_sb_setinopb(fs, lfs_sb_getibsize(fs) / DINOSIZE(fs)); 565 lfs_sb_setminfree(fs, minfree); 566 567 if (version > 1) { 568 lfs_sb_setinopf(fs, secsize/DINOSIZE(fs)); 569 lfs_sb_setinterleave(fs, interleave); 570 if (roll_id == 0) 571 roll_id = arc4random(); 572 lfs_sb_setident(fs, roll_id); 573 } 574 575 /* 576 * Fill in parts of superblock that can be computed from file system 577 * size, disk geometry and current time. 578 * 579 * XXX: this seems to set dlfs_size wrong for version 1... as in, 580 * sets it and then overwrites it a few lines later. 581 */ 582 db_per_blk = bsize/secsize; 583 lfs_sb_setblktodb(fs, lfs_log2(db_per_blk)); 584 lfs_sb_setfsbtodb(fs, lfs_log2(fsize / secsize)); 585 if (version == 1) { 586 lfs_sb_setsushift(fs, lfs_log2(lfs_sb_getsepb(fs))); 587 lfs_sb_setfsbtodb(fs, 0); 588 lfs_sb_setsize(fs, dkw->dkw_size >> lfs_sb_getblktodb(fs)); 589 } 590 label_fsb = lfs_btofsb(fs, roundup(LFS_LABELPAD, fsize)); 591 sb_fsb = lfs_btofsb(fs, roundup(LFS_SBPAD, fsize)); 592 lfs_sb_setfsbpseg(fs, LFS_DBTOFSB(fs, ssize / secsize)); 593 lfs_sb_setsize(fs, dkw->dkw_size >> lfs_sb_getfsbtodb(fs)); 594 lfs_sb_setdsize(fs, LFS_DBTOFSB(fs, dkw->dkw_size) - 595 MAX(label_fsb, LFS_DBTOFSB(fs, start))); 596 lfs_sb_setnseg(fs, lfs_sb_getdsize(fs) / lfs_segtod(fs, 1)); 597 598 lfs_sb_setnclean(fs, lfs_sb_getnseg(fs) - 1); 599 lfs_sb_setmaxfilesize(fs, maxfilesize(fs, lfs_sb_getbshift(fs))); 600 601 if (minfreeseg == 0) 602 lfs_sb_setminfreeseg(fs, lfs_sb_getnseg(fs) / DFL_MIN_FREE_SEGS); 603 else 604 lfs_sb_setminfreeseg(fs, minfreeseg); 605 if (lfs_sb_getminfreeseg(fs) < MIN_FREE_SEGS) 606 lfs_sb_setminfreeseg(fs, MIN_FREE_SEGS); 607 608 if (resvseg == 0) 609 lfs_sb_setresvseg(fs, lfs_sb_getminfreeseg(fs) / 2 + 1); 610 else 611 lfs_sb_setresvseg(fs, resvseg); 612 if (lfs_sb_getresvseg(fs) < MIN_RESV_SEGS) 613 lfs_sb_setresvseg(fs, MIN_RESV_SEGS); 614 615 if(lfs_sb_getnseg(fs) < (4 * lfs_sb_getminfreeseg(fs)) 616 || lfs_sb_getnseg(fs) < LFS_MIN_SBINTERVAL + 1) 617 { 618 if(seg_size == 0 && ssize > (bsize<<1)) { 619 if(!warned_segtoobig) { 620 fprintf(stderr,"Segment size %d is too large; " 621 "trying smaller sizes.\n", ssize); 622 if (ssize == (bsize << 16)) { 623 fprintf(stderr, "(Did you perhaps " 624 "accidentally leave \"16\" " 625 "in the disklabel's sgs " 626 "field?)\n"); 627 } 628 } 629 ++warned_segtoobig; 630 ssize >>= 1; 631 goto tryagain; 632 } 633 fatal("Could not allocate enough segments with segment " 634 "size %d and block size %d;\nplease decrease the " 635 "segment size.\n", ssize, lfs_sb_getbsize(fs)); 636 } 637 if(warned_segtoobig) 638 fprintf(stderr,"Using segment size %d, block size %d, frag size %d.\n", ssize, bsize, fsize); 639 640 /* 641 * Now that we've determined what we're going to do, announce it 642 * to the user. 643 */ 644 printf("Creating a version %d LFS%d", lfs_sb_getversion(fs), bitwidth); 645 if (lfs_sb_getversion(fs) > 1) 646 printf(" with roll-forward ident 0x%x", lfs_sb_getident(fs)); 647 printf("\n"); 648 if (bitwidth == 64) { 649 printf("WARNING: The LFS64 on-disk format is not final.\n"); 650 printf("WARNING: 64-bit volumes should be used only for " 651 "testing.\n"); 652 } 653 fssize = (double)lfs_sb_getnseg(fs); 654 fssize *= (double)ssize; 655 fssize /= 1048576.0; 656 printf("%.1fMB in %d segments of size %d\n", fssize, 657 lfs_sb_getnseg(fs), ssize); 658 659 /* 660 * The number of free blocks is set from the number of segments 661 * times the segment size - lfs_minfreesegs (that we never write 662 * because we need to make sure the cleaner can run). Then 663 * we'll subtract off the room for the superblocks ifile entries 664 * and segment usage table, and half a block per segment that can't 665 * be written due to fragmentation. 666 */ 667 lfs_sb_setdsize(fs, 668 lfs_segtod(fs, lfs_sb_getnseg(fs) - lfs_sb_getminfreeseg(fs))); 669 lfs_sb_setbfree(fs, lfs_sb_getdsize(fs)); 670 lfs_sb_subbfree(fs, LFS_DBTOFSB(fs, ((lfs_sb_getnseg(fs) / 2) << 671 lfs_sb_getblktodb(fs)))); 672 673 lfs_sb_setsegtabsz(fs, SEGTABSIZE_SU(fs)); 674 lfs_sb_setcleansz(fs, CLEANSIZE_SU(fs)); 675 if (time(&stamp) == -1) 676 fatal("time: %s", strerror(errno)); 677 lfs_sb_settstamp(fs, stamp); 678 if (version == 1) 679 lfs_sb_setotstamp(fs, stamp); 680 681 if ((sb_interval = lfs_sb_getnseg(fs) / LFS_MAXNUMSB) < LFS_MIN_SBINTERVAL) 682 sb_interval = LFS_MIN_SBINTERVAL; 683 684 /* 685 * Figure out where the superblocks are going to live. 686 * 687 * Make segment 0 start at either zero, or LFS_LABELPAD, or 688 * >= LFS_SBPAD+LFS_LABELPAD, in order to prevent segment 0 689 * from having half a superblock in it. 690 */ 691 if (LFS_FSBTODB(fs, LFS_DBTOFSB(fs, start)) != start) 692 fatal("Segment 0 offset is not multiple of frag size\n"); 693 if (start != 0 && dbtob(start) != LFS_LABELPAD && 694 dbtob(start) < LFS_SBPAD + LFS_LABELPAD) { 695 fatal("Using flags \"-O %" PRId64 "\" would result in the " 696 "first segment containing only\npart of a superblock. " 697 "Please choose an offset of 0, %d, or %d or more,\n", 698 start, btodb(LFS_LABELPAD), 699 btodb(LFS_LABELPAD + LFS_SBPAD)); 700 } 701 lfs_sb_setsboff(fs, 0, label_fsb); 702 if (version == 1) 703 lfs_sb_sets0addr(fs, lfs_sb_getsboff(fs, 0)); 704 else 705 lfs_sb_sets0addr(fs, LFS_DBTOFSB(fs, start)); 706 lfs_sb_subdsize(fs, sb_fsb); 707 for (i = 1; i < LFS_MAXNUMSB; i++) { 708 sb_addr = ((i * sb_interval) * lfs_segtod(fs, 1)) 709 + lfs_sb_getsboff(fs, 0); 710 /* Segment 0 eats the label, except for version 1 */ 711 if (lfs_sb_getversion(fs) > 1 && lfs_sb_gets0addr(fs) < label_fsb) 712 sb_addr -= label_fsb - start; 713 if (sb_addr + sizeof(struct dlfs) 714 >= LFS_DBTOFSB(fs, dkw->dkw_size)) 715 break; 716 lfs_sb_setsboff(fs, i, sb_addr); 717 lfs_sb_subdsize(fs, sb_fsb); 718 } 719 720 /* We need >= 2 superblocks */ 721 if (lfs_sb_getsboff(fs, 1) == 0x0) { 722 fatal("Could not assign a disk address for the second " 723 "superblock.\nPlease decrease the segment size.\n"); 724 } 725 726 lfs_sb_setlastseg(fs, lfs_sntod(fs, lfs_sb_getnseg(fs) - 2)); 727 lfs_sb_setcurseg(fs, lfs_sntod(fs, lfs_sb_getnseg(fs) - 1)); 728 lfs_sb_setoffset(fs, lfs_sntod(fs, lfs_sb_getnseg(fs))); 729 lfs_sb_setnextseg(fs, lfs_sntod(fs, 0)); 730 731 /* 732 * Initialize the Ifile inode. Do this before we do anything 733 * with the Ifile or segment tables. 734 * 735 * XXX: is there some reason this allocates a new dinode? we 736 * already have an empty one generated by vget. 737 */ 738 dip = malloc(sizeof(*dip)); 739 if (dip == NULL) 740 err(1, NULL); 741 memset(dip, 0, sizeof(*dip)); 742 743 VTOI(fs->lfs_ivnode)->i_din = dip; 744 745 lfs_dino_setmode(fs, dip, LFS_IFREG | 0600); 746 lfs_dino_setflags(fs, dip, SF_IMMUTABLE); 747 make_dinode(LFS_IFILE_INUM, dip, 748 lfs_blkstofrags(fs, lfs_sb_getcleansz(fs) + lfs_sb_getsegtabsz(fs) + 1), fs); 749 lfs_dino_setsize(fs, dip, (lfs_sb_getcleansz(fs) + lfs_sb_getsegtabsz(fs) + 1) << lfs_sb_getbshift(fs)); 750 for (i = 0; i < ULFS_NDADDR && i < (lfs_dino_getsize(fs, dip) >> lfs_sb_getbshift(fs)); i++) 751 VTOI(fs->lfs_ivnode)->i_lfs_fragsize[i] = lfs_sb_getbsize(fs); 752 753 /* 754 * Set up in-superblock segment usage cache 755 */ 756 fs->lfs_suflags = (u_int32_t **) malloc(2 * sizeof(u_int32_t *)); 757 if (fs->lfs_suflags == NULL) 758 err(1, NULL); 759 fs->lfs_suflags[0] = (u_int32_t *) malloc(lfs_sb_getnseg(fs) * sizeof(u_int32_t)); 760 if (fs->lfs_suflags[0] == NULL) 761 err(1, NULL); 762 fs->lfs_suflags[1] = (u_int32_t *) malloc(lfs_sb_getnseg(fs) * sizeof(u_int32_t)); 763 if (fs->lfs_suflags[1] == NULL) 764 err(1, NULL); 765 766 /* 767 * Initialize the cleanerinfo block 768 */ 769 LFS_CLEANERINFO(cip, fs, bp); 770 lfs_ci_setclean(fs, cip, lfs_sb_getnseg(fs)); 771 lfs_ci_setdirty(fs, cip, 0); 772 if (version > 1) { 773 lfs_ci_setfree_head(fs, cip, HIGHEST_USED_INO + 1); 774 lfs_ci_setfree_tail(fs, cip, lfs_sb_getifpb(fs) - 1); 775 } 776 LFS_SYNC_CLEANERINFO(cip, fs, bp, 1); 777 778 /* 779 * Run through segment table and initialize that 780 */ 781 for (i = j = 0; i < lfs_sb_getnseg(fs); i++) { 782 LFS_SEGENTRY(segp, fs, i, bp); 783 784 if (i == 0 && 785 lfs_sb_gets0addr(fs) < lfs_btofsb(fs, LFS_LABELPAD + LFS_SBPAD)) { 786 segp->su_flags = SEGUSE_SUPERBLOCK; 787 lfs_sb_subbfree(fs, sb_fsb); 788 ++j; 789 } 790 if (i > 0) { 791 if ((i % sb_interval) == 0 && j < LFS_MAXNUMSB) { 792 segp->su_flags = SEGUSE_SUPERBLOCK; 793 lfs_sb_subbfree(fs, sb_fsb); 794 ++j; 795 } else 796 segp->su_flags = 0; 797 } 798 segp->su_lastmod = 0; 799 segp->su_nbytes = 0; 800 segp->su_ninos = 0; 801 segp->su_nsums = 0; 802 803 LFS_WRITESEGENTRY(segp, fs, i, bp); 804 } 805 806 /* Initialize root directory */ 807 vp = lfs_raw_vget(fs, ULFS_ROOTINO, devfd, 0x0); 808 dip = VTOI(vp)->i_din; 809 make_dinode(ULFS_ROOTINO, dip, howmany(LFS_DIRBLKSIZ, lfs_sb_getfsize(fs)), fs); 810 lfs_dino_setmode(fs, dip, LFS_IFDIR | UMASK); 811 VTOI(vp)->i_lfs_osize = LFS_DIRBLKSIZ; 812 #ifdef MAKE_LF_DIR 813 VTOI(vp)->i_nlink = 3; 814 #else 815 VTOI(vp)->i_nlink = 2; 816 #endif 817 VTOI(vp)->i_lfs_effnblks = 818 lfs_btofsb(fs, roundup(LFS_DIRBLKSIZ, lfs_sb_getfsize(fs))); 819 lfs_dino_setsize(fs, dip, VTOI(vp)->i_lfs_osize); 820 lfs_dino_setnlink(fs, dip, VTOI(vp)->i_nlink); 821 lfs_dino_setblocks(fs, dip, VTOI(vp)->i_lfs_effnblks); 822 for (i = 0; i < ULFS_NDADDR && i < howmany(LFS_DIRBLKSIZ, lfs_sb_getbsize(fs)); i++) 823 VTOI(vp)->i_lfs_fragsize[i] = lfs_sb_getbsize(fs); 824 if (LFS_DIRBLKSIZ < lfs_sb_getbsize(fs)) 825 VTOI(vp)->i_lfs_fragsize[i - 1] = 826 roundup(LFS_DIRBLKSIZ, lfs_sb_getfsize(fs)); 827 bread(vp, 0, lfs_sb_getfsize(fs), 0, &bp); 828 make_dir(fs, bp->b_data, lfs_root_dir, __arraycount(lfs_root_dir)); 829 VOP_BWRITE(bp); 830 831 #ifdef MAKE_LF_DIR 832 /* Initialize lost+found directory */ 833 vp = lfs_raw_vget(fs, LOSTFOUNDINO, devfd, 0x0); 834 dip = VTOI(vp)->i_din.ffs1_din; 835 make_dinode(LOSTFOUNDINO, dip, howmany(DIRBLKSIZ,fs->lfs_fsize), fs); 836 dip->di_mode = IFDIR | UMASK; 837 VTOI(vp)->i_lfs_osize = dip->di_size = DIRBLKSIZ; 838 VTOI(vp)->i_nlink = dip->di_nlink = 2; 839 VTOI(vp)->i_lfs_effnblks = dip->di_blocks = 840 lfs_btofsb(fs, roundup(DIRBLKSIZ,fs->lfs_fsize)); 841 for (i = 0; i < ULFS_NDADDR && i < howmany(DIRBLKSIZ, lfs_sb_getbsize(fs)); i++) 842 VTOI(vp)->i_lfs_fragsize[i] = lfs_sb_getbsize(fs); 843 if (DIRBLKSIZ < lfs_sb_getbsize(fs)) 844 VTOI(vp)->i_lfs_fragsize[i - 1] = 845 roundup(DIRBLKSIZ,fs->lfs_fsize); 846 bread(vp, 0, fs->lfs_fsize, 0, &bp); 847 make_dir(fs, bp->b_data, lfs_lf_dir, __arraycount(lfs_lf_dir)); 848 VOP_BWRITE(bp); 849 #endif /* MAKE_LF_DIR */ 850 851 /* Set their IFILE entry version numbers to 1 */ 852 LFS_IENTRY(ipall, fs, 1, bp); 853 if (is64) { 854 ip64 = &ipall->u_64; 855 for (i = LFS_IFILE_INUM; i <= HIGHEST_USED_INO; i++) { 856 ip64->if_version = 1; 857 ip64->if_daddr = 0x0; 858 ip64->if_nextfree = 0; 859 ++ip64; 860 } 861 } else if (version > 1) { 862 ip32 = &ipall->u_32; 863 for (i = LFS_IFILE_INUM; i <= HIGHEST_USED_INO; i++) { 864 ip32->if_version = 1; 865 ip32->if_daddr = 0x0; 866 ip32->if_nextfree = 0; 867 ++ip32; 868 } 869 } else { 870 ip_v1 = &ipall->u_v1; 871 for (i = LFS_IFILE_INUM; i <= HIGHEST_USED_INO; i++) { 872 ip_v1->if_version = 1; 873 ip_v1->if_daddr = 0x0; 874 ip_v1->if_nextfree = 0; 875 ++ip_v1; 876 } 877 } 878 /* Link remaining IFILE entries in free list */ 879 if (is64) { 880 for (; 881 i < lfs_sb_getifpb(fs); ++ip64) { 882 ip64->if_version = 1; 883 ip64->if_daddr = LFS_UNUSED_DADDR; 884 ip64->if_nextfree = ++i; 885 } 886 --ip64; 887 ip64->if_nextfree = LFS_UNUSED_INUM; 888 } else if (version > 1) { 889 for (; 890 i < lfs_sb_getifpb(fs); ++ip32) { 891 ip32->if_version = 1; 892 ip32->if_daddr = LFS_UNUSED_DADDR; 893 ip32->if_nextfree = ++i; 894 } 895 --ip32; 896 ip32->if_nextfree = LFS_UNUSED_INUM; 897 } else { 898 for (; 899 i < lfs_sb_getifpb(fs); ++ip_v1) { 900 ip_v1->if_version = 1; 901 ip_v1->if_daddr = LFS_UNUSED_DADDR; 902 ip_v1->if_nextfree = ++i; 903 } 904 --ip_v1; 905 ip_v1->if_nextfree = LFS_UNUSED_INUM; 906 } 907 VOP_BWRITE(bp); 908 909 /* Write it all to disk. */ 910 if (!Nflag) 911 lfs_segwrite(fs, SEGM_CKP); 912 913 /* 914 * Now that we've written everything, look to see what's available 915 * for writing. 916 */ 917 lfs_sb_setavail(fs, 0); 918 bb = ubb = dmeta = 0; 919 for (i = 0; i < lfs_sb_getnseg(fs); i++) { 920 LFS_SEGENTRY(segp, fs, i, bp); 921 if (segp->su_flags & SEGUSE_DIRTY) { 922 bb += lfs_btofsb(fs, segp->su_nbytes + 923 segp->su_nsums * lfs_sb_getsumsize(fs)); 924 ubb += lfs_btofsb(fs, segp->su_nbytes + 925 segp->su_nsums * lfs_sb_getsumsize(fs) + 926 segp->su_ninos * lfs_sb_getibsize(fs)); 927 dmeta += lfs_btofsb(fs, 928 lfs_sb_getsumsize(fs) * segp->su_nsums); 929 dmeta += lfs_btofsb(fs, 930 lfs_sb_getibsize(fs) * segp->su_ninos); 931 } else { 932 lfs_sb_addavail(fs, lfs_segtod(fs, 1)); 933 if (segp->su_flags & SEGUSE_SUPERBLOCK) 934 lfs_sb_subavail(fs, lfs_btofsb(fs, LFS_SBPAD)); 935 if (i == 0 && lfs_sb_getversion(fs) > 1 && 936 lfs_sb_gets0addr(fs) < lfs_btofsb(fs, LFS_LABELPAD)) 937 lfs_sb_subavail(fs, lfs_btofsb(fs, LFS_LABELPAD) - 938 lfs_sb_gets0addr(fs)); 939 } 940 brelse(bp, 0); 941 } 942 /* Also may be available bytes in current seg */ 943 i = lfs_dtosn(fs, lfs_sb_getoffset(fs)); 944 lfs_sb_addavail(fs, lfs_sntod(fs, i + 1) - lfs_sb_getoffset(fs)); 945 /* But do not count minfreesegs */ 946 lfs_sb_subavail(fs, lfs_segtod(fs, (lfs_sb_getminfreeseg(fs) - (lfs_sb_getminfreeseg(fs) / 2)))); 947 948 labelskew = 0; 949 if (lfs_sb_getversion(fs) > 1 && lfs_sb_gets0addr(fs) < lfs_btofsb(fs, LFS_LABELPAD)) 950 labelskew = lfs_btofsb(fs, LFS_LABELPAD); 951 lfs_sb_setbfree(fs, lfs_sb_getdsize(fs) - labelskew - (ubb + bb) / 2); 952 953 /* Put that in the Ifile version too, and write it */ 954 LFS_CLEANERINFO(cip, fs, bp); 955 lfs_ci_setbfree(fs, cip, lfs_sb_getbfree(fs)); 956 lfs_ci_setavail(fs, cip, lfs_sb_getavail(fs)); 957 LFS_SYNC_CLEANERINFO(cip, fs, bp, 1); 958 if (!Nflag) 959 lfs_segwrite(fs, SEGM_CKP); 960 961 /* 962 * Finally write out superblocks. 963 */ 964 printf("super-block backups (for fsck -b #) at:\n"); 965 curw = 0; 966 for (i = 0; i < LFS_MAXNUMSB; i++) { 967 seg_addr = lfs_sb_getsboff(fs, i); 968 if (seg_addr == 0) 969 break; 970 971 if (i != 0) 972 curw += printf(", "); 973 ww = snprintf(tbuf, sizeof(tbuf), "%lld", 974 (long long)LFS_FSBTODB(fs, seg_addr)); 975 curw += ww; 976 if (curw >= 78) { 977 printf("\n%s", tbuf); 978 curw = ww; 979 } else 980 printf("%s", tbuf); 981 fflush(stdout); 982 983 /* Leave the time stamp on the alt sb, zero the rest */ 984 if (i == 2) { 985 lfs_sb_settstamp(fs, 0); 986 lfs_sb_setcksum(fs, lfs_sb_cksum(fs)); 987 } 988 if (!Nflag) 989 lfs_writesuper(fs, seg_addr); 990 } 991 printf(".\n"); 992 993 return 0; 994 } 995 996 /* 997 * Compatibility with fsck_lfs, since the "generic" LFS userland code uses it. 998 */ 999 void 1000 pwarn(const char *fmt, ...) 1001 { 1002 va_list ap; 1003 1004 va_start(ap, fmt); 1005 vfprintf(stderr, fmt, ap); 1006 va_end(ap); 1007 } 1008