1 /*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright (c) 1980, 1989, 1993 The Regents of the University of California. 5 * Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz 6 * Copyright (c) 2012 The FreeBSD Foundation 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt. 11 * 12 * Portions of this software were developed by Edward Tomasz Napierala 13 * under sponsorship from the FreeBSD Foundation. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 3. All advertising materials mentioning features or use of this software 24 * must display the following acknowledgment: 25 * This product includes software developed by the University of 26 * California, Berkeley and its contributors, as well as Christoph 27 * Herrmann and Thomas-Henning von Kamptz. 28 * 4. Neither the name of the University nor the names of its contributors 29 * may be used to endorse or promote products derived from this software 30 * without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 * 44 * $TSHeader: src/sbin/growfs/growfs.c,v 1.5 2000/12/12 19:31:00 tomsoft Exp $ 45 * 46 */ 47 48 #ifndef lint 49 static const char copyright[] = 50 "@(#) Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz\n\ 51 Copyright (c) 1980, 1989, 1993 The Regents of the University of California.\n\ 52 All rights reserved.\n"; 53 #endif /* not lint */ 54 55 #include <sys/cdefs.h> 56 __FBSDID("$FreeBSD$"); 57 58 #include <sys/param.h> 59 #include <sys/ioctl.h> 60 #include <sys/stat.h> 61 #include <sys/disk.h> 62 #include <sys/ucred.h> 63 #include <sys/mount.h> 64 65 #include <stdio.h> 66 #include <paths.h> 67 #include <ctype.h> 68 #include <err.h> 69 #include <errno.h> 70 #include <fcntl.h> 71 #include <fstab.h> 72 #include <inttypes.h> 73 #include <limits.h> 74 #include <mntopts.h> 75 #include <paths.h> 76 #include <stdlib.h> 77 #include <stdint.h> 78 #include <string.h> 79 #include <time.h> 80 #include <unistd.h> 81 #include <ufs/ufs/dinode.h> 82 #include <ufs/ffs/fs.h> 83 #include <libutil.h> 84 #include <libufs.h> 85 86 #include "debug.h" 87 88 #ifdef FS_DEBUG 89 int _dbg_lvl_ = (DL_INFO); /* DL_TRC */ 90 #endif /* FS_DEBUG */ 91 92 static union { 93 struct fs fs; 94 char pad[SBLOCKSIZE]; 95 } fsun1, fsun2; 96 #define sblock fsun1.fs /* the new superblock */ 97 #define osblock fsun2.fs /* the old superblock */ 98 99 static union { 100 struct cg cg; 101 char pad[MAXBSIZE]; 102 } cgun1, cgun2; 103 #define acg cgun1.cg /* a cylinder cgroup (new) */ 104 #define aocg cgun2.cg /* an old cylinder group */ 105 106 static struct csum *fscs; /* cylinder summary */ 107 108 static void growfs(int, int, unsigned int); 109 static void rdfs(ufs2_daddr_t, size_t, void *, int); 110 static void wtfs(ufs2_daddr_t, size_t, void *, int, unsigned int); 111 static int charsperline(void); 112 static void usage(void); 113 static int isblock(struct fs *, unsigned char *, int); 114 static void clrblock(struct fs *, unsigned char *, int); 115 static void setblock(struct fs *, unsigned char *, int); 116 static void initcg(int, time_t, int, unsigned int); 117 static void updjcg(int, time_t, int, int, unsigned int); 118 static void updcsloc(time_t, int, int, unsigned int); 119 static void frag_adjust(ufs2_daddr_t, int); 120 static void updclst(int); 121 static void mount_reload(const struct statfs *stfs); 122 static void cgckhash(struct cg *); 123 124 /* 125 * Here we actually start growing the file system. We basically read the 126 * cylinder summary from the first cylinder group as we want to update 127 * this on the fly during our various operations. First we handle the 128 * changes in the former last cylinder group. Afterwards we create all new 129 * cylinder groups. Now we handle the cylinder group containing the 130 * cylinder summary which might result in a relocation of the whole 131 * structure. In the end we write back the updated cylinder summary, the 132 * new superblock, and slightly patched versions of the super block 133 * copies. 134 */ 135 static void 136 growfs(int fsi, int fso, unsigned int Nflag) 137 { 138 DBG_FUNC("growfs") 139 time_t modtime; 140 uint cylno; 141 int i, j, width; 142 char tmpbuf[100]; 143 144 DBG_ENTER; 145 146 time(&modtime); 147 148 /* 149 * Get the cylinder summary into the memory. 150 */ 151 fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize); 152 if (fscs == NULL) 153 errx(1, "calloc failed"); 154 memcpy(fscs, osblock.fs_csp, osblock.fs_cssize); 155 free(osblock.fs_csp); 156 osblock.fs_csp = NULL; 157 sblock.fs_csp = fscs; 158 159 #ifdef FS_DEBUG 160 { 161 struct csum *dbg_csp; 162 u_int32_t dbg_csc; 163 char dbg_line[80]; 164 165 dbg_csp = fscs; 166 167 for (dbg_csc = 0; dbg_csc < osblock.fs_ncg; dbg_csc++) { 168 snprintf(dbg_line, sizeof(dbg_line), 169 "%d. old csum in old location", dbg_csc); 170 DBG_DUMP_CSUM(&osblock, dbg_line, dbg_csp++); 171 } 172 } 173 #endif /* FS_DEBUG */ 174 DBG_PRINT0("fscs read\n"); 175 176 /* 177 * Do all needed changes in the former last cylinder group. 178 */ 179 updjcg(osblock.fs_ncg - 1, modtime, fsi, fso, Nflag); 180 181 /* 182 * Dump out summary information about file system. 183 */ 184 #ifdef FS_DEBUG 185 #define B2MBFACTOR (1 / (1024.0 * 1024.0)) 186 printf("growfs: %.1fMB (%jd sectors) block size %d, fragment size %d\n", 187 (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, 188 (intmax_t)fsbtodb(&sblock, sblock.fs_size), sblock.fs_bsize, 189 sblock.fs_fsize); 190 printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n", 191 sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, 192 sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg); 193 if (sblock.fs_flags & FS_DOSOFTDEP) 194 printf("\twith soft updates\n"); 195 #undef B2MBFACTOR 196 #endif /* FS_DEBUG */ 197 198 /* 199 * Now build the cylinders group blocks and 200 * then print out indices of cylinder groups. 201 */ 202 printf("super-block backups (for fsck_ffs -b #) at:\n"); 203 i = 0; 204 width = charsperline(); 205 206 /* 207 * Iterate for only the new cylinder groups. 208 */ 209 for (cylno = osblock.fs_ncg; cylno < sblock.fs_ncg; cylno++) { 210 initcg(cylno, modtime, fso, Nflag); 211 j = sprintf(tmpbuf, " %jd%s", 212 (intmax_t)fsbtodb(&sblock, cgsblock(&sblock, cylno)), 213 cylno < (sblock.fs_ncg - 1) ? "," : "" ); 214 if (i + j >= width) { 215 printf("\n"); 216 i = 0; 217 } 218 i += j; 219 printf("%s", tmpbuf); 220 fflush(stdout); 221 } 222 printf("\n"); 223 224 /* 225 * Do all needed changes in the first cylinder group. 226 * allocate blocks in new location 227 */ 228 updcsloc(modtime, fsi, fso, Nflag); 229 230 /* 231 * Clean up the dynamic fields in our superblock. 232 * 233 * XXX 234 * The following fields are currently distributed from the superblock 235 * to the copies: 236 * fs_minfree 237 * fs_rotdelay 238 * fs_maxcontig 239 * fs_maxbpg 240 * fs_minfree, 241 * fs_optim 242 * fs_flags 243 * 244 * We probably should rather change the summary for the cylinder group 245 * statistics here to the value of what would be in there, if the file 246 * system were created initially with the new size. Therefor we still 247 * need to find an easy way of calculating that. 248 * Possibly we can try to read the first superblock copy and apply the 249 * "diffed" stats between the old and new superblock by still copying 250 * certain parameters onto that. 251 */ 252 sblock.fs_time = modtime; 253 sblock.fs_fmod = 0; 254 sblock.fs_clean = 1; 255 sblock.fs_ronly = 0; 256 sblock.fs_cgrotor = 0; 257 sblock.fs_state = 0; 258 memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt)); 259 260 /* 261 * Now write the new superblock, its summary information, 262 * and all the alternates back to disk. 263 */ 264 if (!Nflag && sbput(fso, &sblock, sblock.fs_ncg) != 0) 265 errc(2, EIO, "could not write updated superblock"); 266 DBG_PRINT0("fscs written\n"); 267 268 #ifdef FS_DEBUG 269 { 270 struct csum *dbg_csp; 271 u_int32_t dbg_csc; 272 char dbg_line[80]; 273 274 dbg_csp = fscs; 275 for (dbg_csc = 0; dbg_csc < sblock.fs_ncg; dbg_csc++) { 276 snprintf(dbg_line, sizeof(dbg_line), 277 "%d. new csum in new location", dbg_csc); 278 DBG_DUMP_CSUM(&sblock, dbg_line, dbg_csp++); 279 } 280 } 281 #endif /* FS_DEBUG */ 282 283 DBG_PRINT0("sblock written\n"); 284 DBG_DUMP_FS(&sblock, "new initial sblock"); 285 286 DBG_PRINT0("sblock copies written\n"); 287 DBG_DUMP_FS(&sblock, "new other sblocks"); 288 289 DBG_LEAVE; 290 return; 291 } 292 293 /* 294 * This creates a new cylinder group structure, for more details please see 295 * the source of newfs(8), as this function is taken over almost unchanged. 296 * As this is never called for the first cylinder group, the special 297 * provisions for that case are removed here. 298 */ 299 static void 300 initcg(int cylno, time_t modtime, int fso, unsigned int Nflag) 301 { 302 DBG_FUNC("initcg") 303 static caddr_t iobuf; 304 static long iobufsize; 305 long blkno, start; 306 ino_t ino; 307 ufs2_daddr_t i, cbase, dmax; 308 struct ufs1_dinode *dp1; 309 struct ufs2_dinode *dp2; 310 struct csum *cs; 311 uint j, d, dupper, dlower; 312 313 if (iobuf == NULL) { 314 iobufsize = 2 * sblock.fs_bsize; 315 if ((iobuf = malloc(iobufsize)) == NULL) 316 errx(37, "panic: cannot allocate I/O buffer"); 317 memset(iobuf, '\0', iobufsize); 318 } 319 /* 320 * Determine block bounds for cylinder group. 321 * Allow space for super block summary information in first 322 * cylinder group. 323 */ 324 cbase = cgbase(&sblock, cylno); 325 dmax = cbase + sblock.fs_fpg; 326 if (dmax > sblock.fs_size) 327 dmax = sblock.fs_size; 328 dlower = cgsblock(&sblock, cylno) - cbase; 329 dupper = cgdmin(&sblock, cylno) - cbase; 330 if (cylno == 0) /* XXX fscs may be relocated */ 331 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 332 cs = &fscs[cylno]; 333 memset(&acg, 0, sblock.fs_cgsize); 334 acg.cg_time = modtime; 335 acg.cg_magic = CG_MAGIC; 336 acg.cg_cgx = cylno; 337 acg.cg_niblk = sblock.fs_ipg; 338 acg.cg_initediblk = MIN(sblock.fs_ipg, 2 * INOPB(&sblock)); 339 acg.cg_ndblk = dmax - cbase; 340 if (sblock.fs_contigsumsize > 0) 341 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; 342 start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); 343 if (sblock.fs_magic == FS_UFS2_MAGIC) { 344 acg.cg_iusedoff = start; 345 } else { 346 acg.cg_old_ncyl = sblock.fs_old_cpg; 347 acg.cg_old_time = acg.cg_time; 348 acg.cg_time = 0; 349 acg.cg_old_niblk = acg.cg_niblk; 350 acg.cg_niblk = 0; 351 acg.cg_initediblk = 0; 352 acg.cg_old_btotoff = start; 353 acg.cg_old_boff = acg.cg_old_btotoff + 354 sblock.fs_old_cpg * sizeof(int32_t); 355 acg.cg_iusedoff = acg.cg_old_boff + 356 sblock.fs_old_cpg * sizeof(u_int16_t); 357 } 358 acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT); 359 acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT); 360 if (sblock.fs_contigsumsize > 0) { 361 acg.cg_clustersumoff = 362 roundup(acg.cg_nextfreeoff, sizeof(u_int32_t)); 363 acg.cg_clustersumoff -= sizeof(u_int32_t); 364 acg.cg_clusteroff = acg.cg_clustersumoff + 365 (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t); 366 acg.cg_nextfreeoff = acg.cg_clusteroff + 367 howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT); 368 } 369 if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) { 370 /* 371 * This should never happen as we would have had that panic 372 * already on file system creation 373 */ 374 errx(37, "panic: cylinder group too big"); 375 } 376 acg.cg_cs.cs_nifree += sblock.fs_ipg; 377 if (cylno == 0) 378 for (ino = 0; ino < UFS_ROOTINO; ino++) { 379 setbit(cg_inosused(&acg), ino); 380 acg.cg_cs.cs_nifree--; 381 } 382 /* 383 * Initialize the initial inode blocks. 384 */ 385 dp1 = (struct ufs1_dinode *)(void *)iobuf; 386 dp2 = (struct ufs2_dinode *)(void *)iobuf; 387 for (i = 0; i < acg.cg_initediblk; i++) { 388 if (sblock.fs_magic == FS_UFS1_MAGIC) { 389 dp1->di_gen = arc4random(); 390 dp1++; 391 } else { 392 dp2->di_gen = arc4random(); 393 dp2++; 394 } 395 } 396 wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno)), iobufsize, iobuf, 397 fso, Nflag); 398 /* 399 * For the old file system, we have to initialize all the inodes. 400 */ 401 if (sblock.fs_magic == FS_UFS1_MAGIC && 402 sblock.fs_ipg > 2 * INOPB(&sblock)) { 403 for (i = 2 * sblock.fs_frag; 404 i < sblock.fs_ipg / INOPF(&sblock); 405 i += sblock.fs_frag) { 406 dp1 = (struct ufs1_dinode *)(void *)iobuf; 407 for (j = 0; j < INOPB(&sblock); j++) { 408 dp1->di_gen = arc4random(); 409 dp1++; 410 } 411 wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), 412 sblock.fs_bsize, iobuf, fso, Nflag); 413 } 414 } 415 if (cylno > 0) { 416 /* 417 * In cylno 0, beginning space is reserved 418 * for boot and super blocks. 419 */ 420 for (d = 0; d < dlower; d += sblock.fs_frag) { 421 blkno = d / sblock.fs_frag; 422 setblock(&sblock, cg_blksfree(&acg), blkno); 423 if (sblock.fs_contigsumsize > 0) 424 setbit(cg_clustersfree(&acg), blkno); 425 acg.cg_cs.cs_nbfree++; 426 } 427 sblock.fs_dsize += dlower; 428 } 429 sblock.fs_dsize += acg.cg_ndblk - dupper; 430 sblock.fs_old_dsize = sblock.fs_dsize; 431 if ((i = dupper % sblock.fs_frag)) { 432 acg.cg_frsum[sblock.fs_frag - i]++; 433 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { 434 setbit(cg_blksfree(&acg), dupper); 435 acg.cg_cs.cs_nffree++; 436 } 437 } 438 for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk; 439 d += sblock.fs_frag) { 440 blkno = d / sblock.fs_frag; 441 setblock(&sblock, cg_blksfree(&acg), blkno); 442 if (sblock.fs_contigsumsize > 0) 443 setbit(cg_clustersfree(&acg), blkno); 444 acg.cg_cs.cs_nbfree++; 445 } 446 if (d < acg.cg_ndblk) { 447 acg.cg_frsum[acg.cg_ndblk - d]++; 448 for (; d < acg.cg_ndblk; d++) { 449 setbit(cg_blksfree(&acg), d); 450 acg.cg_cs.cs_nffree++; 451 } 452 } 453 if (sblock.fs_contigsumsize > 0) { 454 int32_t *sump = cg_clustersum(&acg); 455 u_char *mapp = cg_clustersfree(&acg); 456 int map = *mapp++; 457 int bit = 1; 458 int run = 0; 459 460 for (i = 0; i < acg.cg_nclusterblks; i++) { 461 if ((map & bit) != 0) 462 run++; 463 else if (run != 0) { 464 if (run > sblock.fs_contigsumsize) 465 run = sblock.fs_contigsumsize; 466 sump[run]++; 467 run = 0; 468 } 469 if ((i & (CHAR_BIT - 1)) != CHAR_BIT - 1) 470 bit <<= 1; 471 else { 472 map = *mapp++; 473 bit = 1; 474 } 475 } 476 if (run != 0) { 477 if (run > sblock.fs_contigsumsize) 478 run = sblock.fs_contigsumsize; 479 sump[run]++; 480 } 481 } 482 sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 483 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 484 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 485 sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 486 *cs = acg.cg_cs; 487 488 cgckhash(&acg); 489 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), sblock.fs_cgsize, &acg, 490 fso, Nflag); 491 DBG_DUMP_CG(&sblock, "new cg", &acg); 492 493 DBG_LEAVE; 494 return; 495 } 496 497 /* 498 * Here we add or subtract (sign +1/-1) the available fragments in a given 499 * block to or from the fragment statistics. By subtracting before and adding 500 * after an operation on the free frag map we can easy update the fragment 501 * statistic, which seems to be otherwise a rather complex operation. 502 */ 503 static void 504 frag_adjust(ufs2_daddr_t frag, int sign) 505 { 506 DBG_FUNC("frag_adjust") 507 int fragsize; 508 int f; 509 510 DBG_ENTER; 511 512 fragsize = 0; 513 /* 514 * Here frag only needs to point to any fragment in the block we want 515 * to examine. 516 */ 517 for (f = rounddown(frag, sblock.fs_frag); 518 f < roundup(frag + 1, sblock.fs_frag); f++) { 519 /* 520 * Count contiguous free fragments. 521 */ 522 if (isset(cg_blksfree(&acg), f)) { 523 fragsize++; 524 } else { 525 if (fragsize && fragsize < sblock.fs_frag) { 526 /* 527 * We found something in between. 528 */ 529 acg.cg_frsum[fragsize] += sign; 530 DBG_PRINT2("frag_adjust [%d]+=%d\n", 531 fragsize, sign); 532 } 533 fragsize = 0; 534 } 535 } 536 if (fragsize && fragsize < sblock.fs_frag) { 537 /* 538 * We found something. 539 */ 540 acg.cg_frsum[fragsize] += sign; 541 DBG_PRINT2("frag_adjust [%d]+=%d\n", fragsize, sign); 542 } 543 DBG_PRINT2("frag_adjust [[%d]]+=%d\n", fragsize, sign); 544 545 DBG_LEAVE; 546 return; 547 } 548 549 /* 550 * Here we do all needed work for the former last cylinder group. It has to be 551 * changed in any case, even if the file system ended exactly on the end of 552 * this group, as there is some slightly inconsistent handling of the number 553 * of cylinders in the cylinder group. We start again by reading the cylinder 554 * group from disk. If the last block was not fully available, we first handle 555 * the missing fragments, then we handle all new full blocks in that file 556 * system and finally we handle the new last fragmented block in the file 557 * system. We again have to handle the fragment statistics rotational layout 558 * tables and cluster summary during all those operations. 559 */ 560 static void 561 updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag) 562 { 563 DBG_FUNC("updjcg") 564 ufs2_daddr_t cbase, dmax; 565 struct csum *cs; 566 int i, k; 567 int j = 0; 568 569 DBG_ENTER; 570 571 /* 572 * Read the former last (joining) cylinder group from disk, and make 573 * a copy. 574 */ 575 rdfs(fsbtodb(&osblock, cgtod(&osblock, cylno)), 576 (size_t)osblock.fs_cgsize, (void *)&aocg, fsi); 577 DBG_PRINT0("jcg read\n"); 578 DBG_DUMP_CG(&sblock, "old joining cg", &aocg); 579 580 memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2)); 581 582 /* 583 * If the cylinder group had already its new final size almost 584 * nothing is to be done ... except: 585 * For some reason the value of cg_ncyl in the last cylinder group has 586 * to be zero instead of fs_cpg. As this is now no longer the last 587 * cylinder group we have to change that value now to fs_cpg. 588 */ 589 590 if (cgbase(&osblock, cylno + 1) == osblock.fs_size) { 591 if (sblock.fs_magic == FS_UFS1_MAGIC) 592 acg.cg_old_ncyl = sblock.fs_old_cpg; 593 594 cgckhash(&acg); 595 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 596 (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); 597 DBG_PRINT0("jcg written\n"); 598 DBG_DUMP_CG(&sblock, "new joining cg", &acg); 599 600 DBG_LEAVE; 601 return; 602 } 603 604 /* 605 * Set up some variables needed later. 606 */ 607 cbase = cgbase(&sblock, cylno); 608 dmax = cbase + sblock.fs_fpg; 609 if (dmax > sblock.fs_size) 610 dmax = sblock.fs_size; 611 612 /* 613 * Set pointer to the cylinder summary for our cylinder group. 614 */ 615 cs = fscs + cylno; 616 617 /* 618 * Touch the cylinder group, update all fields in the cylinder group as 619 * needed, update the free space in the superblock. 620 */ 621 acg.cg_time = modtime; 622 if ((unsigned)cylno == sblock.fs_ncg - 1) { 623 /* 624 * This is still the last cylinder group. 625 */ 626 if (sblock.fs_magic == FS_UFS1_MAGIC) 627 acg.cg_old_ncyl = 628 sblock.fs_old_ncyl % sblock.fs_old_cpg; 629 } else { 630 acg.cg_old_ncyl = sblock.fs_old_cpg; 631 } 632 DBG_PRINT2("jcg dbg: %d %u", cylno, sblock.fs_ncg); 633 #ifdef FS_DEBUG 634 if (sblock.fs_magic == FS_UFS1_MAGIC) 635 DBG_PRINT2("%d %u", acg.cg_old_ncyl, sblock.fs_old_cpg); 636 #endif 637 DBG_PRINT0("\n"); 638 acg.cg_ndblk = dmax - cbase; 639 sblock.fs_dsize += acg.cg_ndblk - aocg.cg_ndblk; 640 sblock.fs_old_dsize = sblock.fs_dsize; 641 if (sblock.fs_contigsumsize > 0) 642 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; 643 644 /* 645 * Now we have to update the free fragment bitmap for our new free 646 * space. There again we have to handle the fragmentation and also 647 * the rotational layout tables and the cluster summary. This is 648 * also done per fragment for the first new block if the old file 649 * system end was not on a block boundary, per fragment for the new 650 * last block if the new file system end is not on a block boundary, 651 * and per block for all space in between. 652 * 653 * Handle the first new block here if it was partially available 654 * before. 655 */ 656 if (osblock.fs_size % sblock.fs_frag) { 657 if (roundup(osblock.fs_size, sblock.fs_frag) <= 658 sblock.fs_size) { 659 /* 660 * The new space is enough to fill at least this 661 * block 662 */ 663 j = 0; 664 for (i = roundup(osblock.fs_size - cbase, 665 sblock.fs_frag) - 1; i >= osblock.fs_size - cbase; 666 i--) { 667 setbit(cg_blksfree(&acg), i); 668 acg.cg_cs.cs_nffree++; 669 j++; 670 } 671 672 /* 673 * Check if the fragment just created could join an 674 * already existing fragment at the former end of the 675 * file system. 676 */ 677 if (isblock(&sblock, cg_blksfree(&acg), 678 ((osblock.fs_size - cgbase(&sblock, cylno)) / 679 sblock.fs_frag))) { 680 /* 681 * The block is now completely available. 682 */ 683 DBG_PRINT0("block was\n"); 684 acg.cg_frsum[osblock.fs_size % sblock.fs_frag]--; 685 acg.cg_cs.cs_nbfree++; 686 acg.cg_cs.cs_nffree -= sblock.fs_frag; 687 k = rounddown(osblock.fs_size - cbase, 688 sblock.fs_frag); 689 updclst((osblock.fs_size - cbase) / 690 sblock.fs_frag); 691 } else { 692 /* 693 * Lets rejoin a possible partially growed 694 * fragment. 695 */ 696 k = 0; 697 while (isset(cg_blksfree(&acg), i) && 698 (i >= rounddown(osblock.fs_size - cbase, 699 sblock.fs_frag))) { 700 i--; 701 k++; 702 } 703 if (k) 704 acg.cg_frsum[k]--; 705 acg.cg_frsum[k + j]++; 706 } 707 } else { 708 /* 709 * We only grow by some fragments within this last 710 * block. 711 */ 712 for (i = sblock.fs_size - cbase - 1; 713 i >= osblock.fs_size - cbase; i--) { 714 setbit(cg_blksfree(&acg), i); 715 acg.cg_cs.cs_nffree++; 716 j++; 717 } 718 /* 719 * Lets rejoin a possible partially growed fragment. 720 */ 721 k = 0; 722 while (isset(cg_blksfree(&acg), i) && 723 (i >= rounddown(osblock.fs_size - cbase, 724 sblock.fs_frag))) { 725 i--; 726 k++; 727 } 728 if (k) 729 acg.cg_frsum[k]--; 730 acg.cg_frsum[k + j]++; 731 } 732 } 733 734 /* 735 * Handle all new complete blocks here. 736 */ 737 for (i = roundup(osblock.fs_size - cbase, sblock.fs_frag); 738 i + sblock.fs_frag <= dmax - cbase; /* XXX <= or only < ? */ 739 i += sblock.fs_frag) { 740 j = i / sblock.fs_frag; 741 setblock(&sblock, cg_blksfree(&acg), j); 742 updclst(j); 743 acg.cg_cs.cs_nbfree++; 744 } 745 746 /* 747 * Handle the last new block if there are stll some new fragments left. 748 * Here we don't have to bother about the cluster summary or the even 749 * the rotational layout table. 750 */ 751 if (i < (dmax - cbase)) { 752 acg.cg_frsum[dmax - cbase - i]++; 753 for (; i < dmax - cbase; i++) { 754 setbit(cg_blksfree(&acg), i); 755 acg.cg_cs.cs_nffree++; 756 } 757 } 758 759 sblock.fs_cstotal.cs_nffree += 760 (acg.cg_cs.cs_nffree - aocg.cg_cs.cs_nffree); 761 sblock.fs_cstotal.cs_nbfree += 762 (acg.cg_cs.cs_nbfree - aocg.cg_cs.cs_nbfree); 763 /* 764 * The following statistics are not changed here: 765 * sblock.fs_cstotal.cs_ndir 766 * sblock.fs_cstotal.cs_nifree 767 * As the statistics for this cylinder group are ready, copy it to 768 * the summary information array. 769 */ 770 *cs = acg.cg_cs; 771 772 /* 773 * Write the updated "joining" cylinder group back to disk. 774 */ 775 cgckhash(&acg); 776 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), (size_t)sblock.fs_cgsize, 777 (void *)&acg, fso, Nflag); 778 DBG_PRINT0("jcg written\n"); 779 DBG_DUMP_CG(&sblock, "new joining cg", &acg); 780 781 DBG_LEAVE; 782 return; 783 } 784 785 /* 786 * Here we update the location of the cylinder summary. We have two possible 787 * ways of growing the cylinder summary: 788 * (1) We can try to grow the summary in the current location, and relocate 789 * possibly used blocks within the current cylinder group. 790 * (2) Alternatively we can relocate the whole cylinder summary to the first 791 * new completely empty cylinder group. Once the cylinder summary is no 792 * longer in the beginning of the first cylinder group you should never 793 * use a version of fsck which is not aware of the possibility to have 794 * this structure in a non standard place. 795 * Option (2) is considered to be less intrusive to the structure of the file- 796 * system, so that's the one being used. 797 */ 798 static void 799 updcsloc(time_t modtime, int fsi, int fso, unsigned int Nflag) 800 { 801 DBG_FUNC("updcsloc") 802 struct csum *cs; 803 int ocscg, ncscg; 804 ufs2_daddr_t d; 805 int lcs = 0; 806 int block; 807 808 DBG_ENTER; 809 810 if (howmany(sblock.fs_cssize, sblock.fs_fsize) == 811 howmany(osblock.fs_cssize, osblock.fs_fsize)) { 812 /* 813 * No new fragment needed. 814 */ 815 DBG_LEAVE; 816 return; 817 } 818 /* Adjust fs_dsize by added summary blocks */ 819 sblock.fs_dsize -= howmany(sblock.fs_cssize, sblock.fs_fsize) - 820 howmany(osblock.fs_cssize, osblock.fs_fsize); 821 sblock.fs_old_dsize = sblock.fs_dsize; 822 ocscg = dtog(&osblock, osblock.fs_csaddr); 823 cs = fscs + ocscg; 824 825 /* 826 * Read original cylinder group from disk, and make a copy. 827 * XXX If Nflag is set in some very rare cases we now miss 828 * some changes done in updjcg by reading the unmodified 829 * block from disk. 830 */ 831 rdfs(fsbtodb(&osblock, cgtod(&osblock, ocscg)), 832 (size_t)osblock.fs_cgsize, (void *)&aocg, fsi); 833 DBG_PRINT0("oscg read\n"); 834 DBG_DUMP_CG(&sblock, "old summary cg", &aocg); 835 836 memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2)); 837 838 /* 839 * Touch the cylinder group, set up local variables needed later 840 * and update the superblock. 841 */ 842 acg.cg_time = modtime; 843 844 /* 845 * XXX In the case of having active snapshots we may need much more 846 * blocks for the copy on write. We need each block twice, and 847 * also up to 8*3 blocks for indirect blocks for all possible 848 * references. 849 */ 850 /* 851 * There is not enough space in the old cylinder group to 852 * relocate all blocks as needed, so we relocate the whole 853 * cylinder group summary to a new group. We try to use the 854 * first complete new cylinder group just created. Within the 855 * cylinder group we align the area immediately after the 856 * cylinder group information location in order to be as 857 * close as possible to the original implementation of ffs. 858 * 859 * First we have to make sure we'll find enough space in the 860 * new cylinder group. If not, then we currently give up. 861 * We start with freeing everything which was used by the 862 * fragments of the old cylinder summary in the current group. 863 * Now we write back the group meta data, read in the needed 864 * meta data from the new cylinder group, and start allocating 865 * within that group. Here we can assume, the group to be 866 * completely empty. Which makes the handling of fragments and 867 * clusters a lot easier. 868 */ 869 DBG_TRC; 870 if (sblock.fs_ncg - osblock.fs_ncg < 2) 871 errx(2, "panic: not enough space"); 872 873 /* 874 * Point "d" to the first fragment not used by the cylinder 875 * summary. 876 */ 877 d = osblock.fs_csaddr + (osblock.fs_cssize / osblock.fs_fsize); 878 879 /* 880 * Set up last cluster size ("lcs") already here. Calculate 881 * the size for the trailing cluster just behind where "d" 882 * points to. 883 */ 884 if (sblock.fs_contigsumsize > 0) { 885 for (block = howmany(d % sblock.fs_fpg, sblock.fs_frag), 886 lcs = 0; lcs < sblock.fs_contigsumsize; block++, lcs++) { 887 if (isclr(cg_clustersfree(&acg), block)) 888 break; 889 } 890 } 891 892 /* 893 * Point "d" to the last frag used by the cylinder summary. 894 */ 895 d--; 896 897 DBG_PRINT1("d=%jd\n", (intmax_t)d); 898 if ((d + 1) % sblock.fs_frag) { 899 /* 900 * The end of the cylinder summary is not a complete 901 * block. 902 */ 903 DBG_TRC; 904 frag_adjust(d % sblock.fs_fpg, -1); 905 for (; (d + 1) % sblock.fs_frag; d--) { 906 DBG_PRINT1("d=%jd\n", (intmax_t)d); 907 setbit(cg_blksfree(&acg), d % sblock.fs_fpg); 908 acg.cg_cs.cs_nffree++; 909 sblock.fs_cstotal.cs_nffree++; 910 } 911 /* 912 * Point "d" to the last fragment of the last 913 * (incomplete) block of the cylinder summary. 914 */ 915 d++; 916 frag_adjust(d % sblock.fs_fpg, 1); 917 918 if (isblock(&sblock, cg_blksfree(&acg), 919 (d % sblock.fs_fpg) / sblock.fs_frag)) { 920 DBG_PRINT1("d=%jd\n", (intmax_t)d); 921 acg.cg_cs.cs_nffree -= sblock.fs_frag; 922 acg.cg_cs.cs_nbfree++; 923 sblock.fs_cstotal.cs_nffree -= sblock.fs_frag; 924 sblock.fs_cstotal.cs_nbfree++; 925 if (sblock.fs_contigsumsize > 0) { 926 setbit(cg_clustersfree(&acg), 927 (d % sblock.fs_fpg) / sblock.fs_frag); 928 if (lcs < sblock.fs_contigsumsize) { 929 if (lcs) 930 cg_clustersum(&acg)[lcs]--; 931 lcs++; 932 cg_clustersum(&acg)[lcs]++; 933 } 934 } 935 } 936 /* 937 * Point "d" to the first fragment of the block before 938 * the last incomplete block. 939 */ 940 d--; 941 } 942 943 DBG_PRINT1("d=%jd\n", (intmax_t)d); 944 for (d = rounddown(d, sblock.fs_frag); d >= osblock.fs_csaddr; 945 d -= sblock.fs_frag) { 946 DBG_TRC; 947 DBG_PRINT1("d=%jd\n", (intmax_t)d); 948 setblock(&sblock, cg_blksfree(&acg), 949 (d % sblock.fs_fpg) / sblock.fs_frag); 950 acg.cg_cs.cs_nbfree++; 951 sblock.fs_cstotal.cs_nbfree++; 952 if (sblock.fs_contigsumsize > 0) { 953 setbit(cg_clustersfree(&acg), 954 (d % sblock.fs_fpg) / sblock.fs_frag); 955 /* 956 * The last cluster size is already set up. 957 */ 958 if (lcs < sblock.fs_contigsumsize) { 959 if (lcs) 960 cg_clustersum(&acg)[lcs]--; 961 lcs++; 962 cg_clustersum(&acg)[lcs]++; 963 } 964 } 965 } 966 *cs = acg.cg_cs; 967 968 /* 969 * Now write the former cylinder group containing the cylinder 970 * summary back to disk. 971 */ 972 cgckhash(&acg); 973 wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)), 974 (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); 975 DBG_PRINT0("oscg written\n"); 976 DBG_DUMP_CG(&sblock, "old summary cg", &acg); 977 978 /* 979 * Find the beginning of the new cylinder group containing the 980 * cylinder summary. 981 */ 982 sblock.fs_csaddr = cgdmin(&sblock, osblock.fs_ncg); 983 ncscg = dtog(&sblock, sblock.fs_csaddr); 984 cs = fscs + ncscg; 985 986 /* 987 * If Nflag is specified, we would now read random data instead 988 * of an empty cg structure from disk. So we can't simulate that 989 * part for now. 990 */ 991 if (Nflag) { 992 DBG_PRINT0("nscg update skipped\n"); 993 DBG_LEAVE; 994 return; 995 } 996 997 /* 998 * Read the future cylinder group containing the cylinder 999 * summary from disk, and make a copy. 1000 */ 1001 rdfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)), 1002 (size_t)sblock.fs_cgsize, (void *)&aocg, fsi); 1003 DBG_PRINT0("nscg read\n"); 1004 DBG_DUMP_CG(&sblock, "new summary cg", &aocg); 1005 1006 memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2)); 1007 1008 /* 1009 * Allocate all complete blocks used by the new cylinder 1010 * summary. 1011 */ 1012 for (d = sblock.fs_csaddr; d + sblock.fs_frag <= 1013 sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize); 1014 d += sblock.fs_frag) { 1015 clrblock(&sblock, cg_blksfree(&acg), 1016 (d % sblock.fs_fpg) / sblock.fs_frag); 1017 acg.cg_cs.cs_nbfree--; 1018 sblock.fs_cstotal.cs_nbfree--; 1019 if (sblock.fs_contigsumsize > 0) { 1020 clrbit(cg_clustersfree(&acg), 1021 (d % sblock.fs_fpg) / sblock.fs_frag); 1022 } 1023 } 1024 1025 /* 1026 * Allocate all fragments used by the cylinder summary in the 1027 * last block. 1028 */ 1029 if (d < sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize)) { 1030 for (; d - sblock.fs_csaddr < 1031 sblock.fs_cssize/sblock.fs_fsize; d++) { 1032 clrbit(cg_blksfree(&acg), d % sblock.fs_fpg); 1033 acg.cg_cs.cs_nffree--; 1034 sblock.fs_cstotal.cs_nffree--; 1035 } 1036 acg.cg_cs.cs_nbfree--; 1037 acg.cg_cs.cs_nffree += sblock.fs_frag; 1038 sblock.fs_cstotal.cs_nbfree--; 1039 sblock.fs_cstotal.cs_nffree += sblock.fs_frag; 1040 if (sblock.fs_contigsumsize > 0) 1041 clrbit(cg_clustersfree(&acg), 1042 (d % sblock.fs_fpg) / sblock.fs_frag); 1043 1044 frag_adjust(d % sblock.fs_fpg, 1); 1045 } 1046 /* 1047 * XXX Handle the cluster statistics here in the case this 1048 * cylinder group is now almost full, and the remaining 1049 * space is less then the maximum cluster size. This is 1050 * probably not needed, as you would hardly find a file 1051 * system which has only MAXCSBUFS+FS_MAXCONTIG of free 1052 * space right behind the cylinder group information in 1053 * any new cylinder group. 1054 */ 1055 1056 /* 1057 * Update our statistics in the cylinder summary. 1058 */ 1059 *cs = acg.cg_cs; 1060 1061 /* 1062 * Write the new cylinder group containing the cylinder summary 1063 * back to disk. 1064 */ 1065 cgckhash(&acg); 1066 wtfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)), 1067 (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); 1068 DBG_PRINT0("nscg written\n"); 1069 DBG_DUMP_CG(&sblock, "new summary cg", &acg); 1070 1071 DBG_LEAVE; 1072 return; 1073 } 1074 1075 /* 1076 * Here we read some block(s) from disk. 1077 */ 1078 static void 1079 rdfs(ufs2_daddr_t bno, size_t size, void *bf, int fsi) 1080 { 1081 DBG_FUNC("rdfs") 1082 ssize_t n; 1083 1084 DBG_ENTER; 1085 1086 if (bno < 0) 1087 err(32, "rdfs: attempting to read negative block number"); 1088 if (lseek(fsi, (off_t)bno * DEV_BSIZE, 0) < 0) 1089 err(33, "rdfs: seek error: %jd", (intmax_t)bno); 1090 n = read(fsi, bf, size); 1091 if (n != (ssize_t)size) 1092 err(34, "rdfs: read error: %jd", (intmax_t)bno); 1093 1094 DBG_LEAVE; 1095 return; 1096 } 1097 1098 /* 1099 * Here we write some block(s) to disk. 1100 */ 1101 static void 1102 wtfs(ufs2_daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag) 1103 { 1104 DBG_FUNC("wtfs") 1105 ssize_t n; 1106 1107 DBG_ENTER; 1108 1109 if (Nflag) { 1110 DBG_LEAVE; 1111 return; 1112 } 1113 if (lseek(fso, (off_t)bno * DEV_BSIZE, SEEK_SET) < 0) 1114 err(35, "wtfs: seek error: %ld", (long)bno); 1115 n = write(fso, bf, size); 1116 if (n != (ssize_t)size) 1117 err(36, "wtfs: write error: %ld", (long)bno); 1118 1119 DBG_LEAVE; 1120 return; 1121 } 1122 1123 /* 1124 * Here we check if all frags of a block are free. For more details again 1125 * please see the source of newfs(8), as this function is taken over almost 1126 * unchanged. 1127 */ 1128 static int 1129 isblock(struct fs *fs, unsigned char *cp, int h) 1130 { 1131 DBG_FUNC("isblock") 1132 unsigned char mask; 1133 1134 DBG_ENTER; 1135 1136 switch (fs->fs_frag) { 1137 case 8: 1138 DBG_LEAVE; 1139 return (cp[h] == 0xff); 1140 case 4: 1141 mask = 0x0f << ((h & 0x1) << 2); 1142 DBG_LEAVE; 1143 return ((cp[h >> 1] & mask) == mask); 1144 case 2: 1145 mask = 0x03 << ((h & 0x3) << 1); 1146 DBG_LEAVE; 1147 return ((cp[h >> 2] & mask) == mask); 1148 case 1: 1149 mask = 0x01 << (h & 0x7); 1150 DBG_LEAVE; 1151 return ((cp[h >> 3] & mask) == mask); 1152 default: 1153 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 1154 DBG_LEAVE; 1155 return (0); 1156 } 1157 } 1158 1159 /* 1160 * Here we allocate a complete block in the block map. For more details again 1161 * please see the source of newfs(8), as this function is taken over almost 1162 * unchanged. 1163 */ 1164 static void 1165 clrblock(struct fs *fs, unsigned char *cp, int h) 1166 { 1167 DBG_FUNC("clrblock") 1168 1169 DBG_ENTER; 1170 1171 switch ((fs)->fs_frag) { 1172 case 8: 1173 cp[h] = 0; 1174 break; 1175 case 4: 1176 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 1177 break; 1178 case 2: 1179 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 1180 break; 1181 case 1: 1182 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 1183 break; 1184 default: 1185 warnx("clrblock bad fs_frag %d", fs->fs_frag); 1186 break; 1187 } 1188 1189 DBG_LEAVE; 1190 return; 1191 } 1192 1193 /* 1194 * Here we free a complete block in the free block map. For more details again 1195 * please see the source of newfs(8), as this function is taken over almost 1196 * unchanged. 1197 */ 1198 static void 1199 setblock(struct fs *fs, unsigned char *cp, int h) 1200 { 1201 DBG_FUNC("setblock") 1202 1203 DBG_ENTER; 1204 1205 switch (fs->fs_frag) { 1206 case 8: 1207 cp[h] = 0xff; 1208 break; 1209 case 4: 1210 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 1211 break; 1212 case 2: 1213 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 1214 break; 1215 case 1: 1216 cp[h >> 3] |= (0x01 << (h & 0x7)); 1217 break; 1218 default: 1219 warnx("setblock bad fs_frag %d", fs->fs_frag); 1220 break; 1221 } 1222 1223 DBG_LEAVE; 1224 return; 1225 } 1226 1227 /* 1228 * Figure out how many lines our current terminal has. For more details again 1229 * please see the source of newfs(8), as this function is taken over almost 1230 * unchanged. 1231 */ 1232 static int 1233 charsperline(void) 1234 { 1235 DBG_FUNC("charsperline") 1236 int columns; 1237 char *cp; 1238 struct winsize ws; 1239 1240 DBG_ENTER; 1241 1242 columns = 0; 1243 if (ioctl(0, TIOCGWINSZ, &ws) != -1) 1244 columns = ws.ws_col; 1245 if (columns == 0 && (cp = getenv("COLUMNS"))) 1246 columns = atoi(cp); 1247 if (columns == 0) 1248 columns = 80; /* last resort */ 1249 1250 DBG_LEAVE; 1251 return (columns); 1252 } 1253 1254 static int 1255 is_dev(const char *name) 1256 { 1257 struct stat devstat; 1258 1259 if (stat(name, &devstat) != 0) 1260 return (0); 1261 if (!S_ISCHR(devstat.st_mode)) 1262 return (0); 1263 return (1); 1264 } 1265 1266 /* 1267 * Return mountpoint on which the device is currently mounted. 1268 */ 1269 static const struct statfs * 1270 dev_to_statfs(const char *dev) 1271 { 1272 struct stat devstat, mntdevstat; 1273 struct statfs *mntbuf, *statfsp; 1274 char device[MAXPATHLEN]; 1275 char *mntdevname; 1276 int i, mntsize; 1277 1278 /* 1279 * First check the mounted filesystems. 1280 */ 1281 if (stat(dev, &devstat) != 0) 1282 return (NULL); 1283 if (!S_ISCHR(devstat.st_mode) && !S_ISBLK(devstat.st_mode)) 1284 return (NULL); 1285 1286 mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 1287 for (i = 0; i < mntsize; i++) { 1288 statfsp = &mntbuf[i]; 1289 mntdevname = statfsp->f_mntfromname; 1290 if (*mntdevname != '/') { 1291 strcpy(device, _PATH_DEV); 1292 strcat(device, mntdevname); 1293 mntdevname = device; 1294 } 1295 if (stat(mntdevname, &mntdevstat) == 0 && 1296 mntdevstat.st_rdev == devstat.st_rdev) 1297 return (statfsp); 1298 } 1299 1300 return (NULL); 1301 } 1302 1303 static const char * 1304 mountpoint_to_dev(const char *mountpoint) 1305 { 1306 struct statfs *mntbuf, *statfsp; 1307 struct fstab *fs; 1308 int i, mntsize; 1309 1310 /* 1311 * First check the mounted filesystems. 1312 */ 1313 mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 1314 for (i = 0; i < mntsize; i++) { 1315 statfsp = &mntbuf[i]; 1316 1317 if (strcmp(statfsp->f_mntonname, mountpoint) == 0) 1318 return (statfsp->f_mntfromname); 1319 } 1320 1321 /* 1322 * Check the fstab. 1323 */ 1324 fs = getfsfile(mountpoint); 1325 if (fs != NULL) 1326 return (fs->fs_spec); 1327 1328 return (NULL); 1329 } 1330 1331 static const char * 1332 getdev(const char *name) 1333 { 1334 static char device[MAXPATHLEN]; 1335 const char *cp, *dev; 1336 1337 if (is_dev(name)) 1338 return (name); 1339 1340 cp = strrchr(name, '/'); 1341 if (cp == NULL) { 1342 snprintf(device, sizeof(device), "%s%s", _PATH_DEV, name); 1343 if (is_dev(device)) 1344 return (device); 1345 } 1346 1347 dev = mountpoint_to_dev(name); 1348 if (dev != NULL && is_dev(dev)) 1349 return (dev); 1350 1351 return (NULL); 1352 } 1353 1354 /* 1355 * growfs(8) is a utility which allows to increase the size of an existing 1356 * ufs file system. Currently this can only be done on unmounted file system. 1357 * It recognizes some command line options to specify the new desired size, 1358 * and it does some basic checkings. The old file system size is determined 1359 * and after some more checks like we can really access the new last block 1360 * on the disk etc. we calculate the new parameters for the superblock. After 1361 * having done this we just call growfs() which will do the work. 1362 * We still have to provide support for snapshots. Therefore we first have to 1363 * understand what data structures are always replicated in the snapshot on 1364 * creation, for all other blocks we touch during our procedure, we have to 1365 * keep the old blocks unchanged somewhere available for the snapshots. If we 1366 * are lucky, then we only have to handle our blocks to be relocated in that 1367 * way. 1368 * Also we have to consider in what order we actually update the critical 1369 * data structures of the file system to make sure, that in case of a disaster 1370 * fsck(8) is still able to restore any lost data. 1371 * The foreseen last step then will be to provide for growing even mounted 1372 * file systems. There we have to extend the mount() system call to provide 1373 * userland access to the file system locking facility. 1374 */ 1375 int 1376 main(int argc, char **argv) 1377 { 1378 DBG_FUNC("main") 1379 struct fs *fs; 1380 const char *device; 1381 const struct statfs *statfsp; 1382 uint64_t size = 0; 1383 off_t mediasize; 1384 int error, j, fsi, fso, ch, ret, Nflag = 0, yflag = 0; 1385 char *p, reply[5], oldsizebuf[6], newsizebuf[6]; 1386 void *testbuf; 1387 1388 DBG_ENTER; 1389 1390 while ((ch = getopt(argc, argv, "Ns:vy")) != -1) { 1391 switch(ch) { 1392 case 'N': 1393 Nflag = 1; 1394 break; 1395 case 's': 1396 size = (off_t)strtoumax(optarg, &p, 0); 1397 if (p == NULL || *p == '\0') 1398 size *= DEV_BSIZE; 1399 else if (*p == 'b' || *p == 'B') 1400 ; /* do nothing */ 1401 else if (*p == 'k' || *p == 'K') 1402 size <<= 10; 1403 else if (*p == 'm' || *p == 'M') 1404 size <<= 20; 1405 else if (*p == 'g' || *p == 'G') 1406 size <<= 30; 1407 else if (*p == 't' || *p == 'T') { 1408 size <<= 30; 1409 size <<= 10; 1410 } else 1411 errx(1, "unknown suffix on -s argument"); 1412 break; 1413 case 'v': /* for compatibility to newfs */ 1414 break; 1415 case 'y': 1416 yflag = 1; 1417 break; 1418 case '?': 1419 /* FALLTHROUGH */ 1420 default: 1421 usage(); 1422 } 1423 } 1424 argc -= optind; 1425 argv += optind; 1426 1427 if (argc != 1) 1428 usage(); 1429 1430 /* 1431 * Now try to guess the device name. 1432 */ 1433 device = getdev(*argv); 1434 if (device == NULL) 1435 errx(1, "cannot find special device for %s", *argv); 1436 1437 statfsp = dev_to_statfs(device); 1438 1439 fsi = open(device, O_RDONLY); 1440 if (fsi < 0) 1441 err(1, "%s", device); 1442 1443 /* 1444 * Try to guess the slice size if not specified. 1445 */ 1446 if (ioctl(fsi, DIOCGMEDIASIZE, &mediasize) == -1) 1447 err(1,"DIOCGMEDIASIZE"); 1448 1449 /* 1450 * Check if that partition is suitable for growing a file system. 1451 */ 1452 if (mediasize < 1) 1453 errx(1, "partition is unavailable"); 1454 1455 /* 1456 * Read the current superblock, and take a backup. 1457 */ 1458 if ((ret = sbget(fsi, &fs, UFS_STDSB, 0)) != 0) { 1459 switch (ret) { 1460 case ENOENT: 1461 errx(1, "superblock not recognized"); 1462 default: 1463 errc(1, ret, "unable to read superblock"); 1464 } 1465 } 1466 /* 1467 * Check for filesystem that was unclean at mount time. 1468 */ 1469 if ((fs->fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) != 0) 1470 errx(1, "%s is not clean - run fsck.\n", *argv); 1471 memcpy(&osblock, fs, fs->fs_sbsize); 1472 free(fs); 1473 memcpy((void *)&fsun1, (void *)&fsun2, osblock.fs_sbsize); 1474 1475 DBG_OPEN("/tmp/growfs.debug"); /* already here we need a superblock */ 1476 DBG_DUMP_FS(&sblock, "old sblock"); 1477 1478 /* 1479 * Determine size to grow to. Default to the device size. 1480 */ 1481 if (size == 0) 1482 size = mediasize; 1483 else { 1484 if (size > (uint64_t)mediasize) { 1485 humanize_number(oldsizebuf, sizeof(oldsizebuf), size, 1486 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1487 humanize_number(newsizebuf, sizeof(newsizebuf), 1488 mediasize, 1489 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1490 1491 errx(1, "requested size %s is larger " 1492 "than the available %s", oldsizebuf, newsizebuf); 1493 } 1494 } 1495 1496 /* 1497 * Make sure the new size is a multiple of fs_fsize; /dev/ufssuspend 1498 * only supports fragment-aligned IO requests. 1499 */ 1500 size -= size % osblock.fs_fsize; 1501 1502 if (size <= (uint64_t)(osblock.fs_size * osblock.fs_fsize)) { 1503 humanize_number(oldsizebuf, sizeof(oldsizebuf), 1504 osblock.fs_size * osblock.fs_fsize, 1505 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1506 humanize_number(newsizebuf, sizeof(newsizebuf), size, 1507 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1508 1509 if (size == (uint64_t)(osblock.fs_size * osblock.fs_fsize)) 1510 errx(0, "requested size %s is equal to the current " 1511 "filesystem size %s", newsizebuf, oldsizebuf); 1512 errx(1, "requested size %s is smaller than the current " 1513 "filesystem size %s", newsizebuf, oldsizebuf); 1514 } 1515 1516 sblock.fs_old_size = sblock.fs_size = 1517 dbtofsb(&osblock, size / DEV_BSIZE); 1518 sblock.fs_providersize = dbtofsb(&osblock, mediasize / DEV_BSIZE); 1519 1520 /* 1521 * Are we really growing? 1522 */ 1523 if (osblock.fs_size >= sblock.fs_size) { 1524 errx(1, "we are not growing (%jd->%jd)", 1525 (intmax_t)osblock.fs_size, (intmax_t)sblock.fs_size); 1526 } 1527 1528 /* 1529 * Check if we find an active snapshot. 1530 */ 1531 if (yflag == 0) { 1532 for (j = 0; j < FSMAXSNAP; j++) { 1533 if (sblock.fs_snapinum[j]) { 1534 errx(1, "active snapshot found in file system; " 1535 "please remove all snapshots before " 1536 "using growfs"); 1537 } 1538 if (!sblock.fs_snapinum[j]) /* list is dense */ 1539 break; 1540 } 1541 } 1542 1543 if (yflag == 0 && Nflag == 0) { 1544 if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) 1545 printf("Device is mounted read-write; resizing will " 1546 "result in temporary write suspension for %s.\n", 1547 statfsp->f_mntonname); 1548 printf("It's strongly recommended to make a backup " 1549 "before growing the file system.\n" 1550 "OK to grow filesystem on %s", device); 1551 if (statfsp != NULL) 1552 printf(", mounted on %s,", statfsp->f_mntonname); 1553 humanize_number(oldsizebuf, sizeof(oldsizebuf), 1554 osblock.fs_size * osblock.fs_fsize, 1555 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1556 humanize_number(newsizebuf, sizeof(newsizebuf), 1557 sblock.fs_size * sblock.fs_fsize, 1558 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1559 printf(" from %s to %s? [yes/no] ", oldsizebuf, newsizebuf); 1560 fflush(stdout); 1561 fgets(reply, (int)sizeof(reply), stdin); 1562 if (strcasecmp(reply, "yes\n")){ 1563 printf("Response other than \"yes\"; aborting\n"); 1564 exit(0); 1565 } 1566 } 1567 1568 /* 1569 * Try to access our device for writing. If it's not mounted, 1570 * or mounted read-only, simply open it; otherwise, use UFS 1571 * suspension mechanism. 1572 */ 1573 if (Nflag) { 1574 fso = -1; 1575 } else { 1576 if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) { 1577 fso = open(_PATH_UFSSUSPEND, O_RDWR); 1578 if (fso == -1) 1579 err(1, "unable to open %s", _PATH_UFSSUSPEND); 1580 error = ioctl(fso, UFSSUSPEND, &statfsp->f_fsid); 1581 if (error != 0) 1582 err(1, "UFSSUSPEND"); 1583 } else { 1584 fso = open(device, O_WRONLY); 1585 if (fso < 0) 1586 err(1, "%s", device); 1587 } 1588 } 1589 1590 /* 1591 * Try to access our new last block in the file system. 1592 */ 1593 testbuf = malloc(sblock.fs_fsize); 1594 if (testbuf == NULL) 1595 err(1, "malloc"); 1596 rdfs((ufs2_daddr_t)((size - sblock.fs_fsize) / DEV_BSIZE), 1597 sblock.fs_fsize, testbuf, fsi); 1598 wtfs((ufs2_daddr_t)((size - sblock.fs_fsize) / DEV_BSIZE), 1599 sblock.fs_fsize, testbuf, fso, Nflag); 1600 free(testbuf); 1601 1602 /* 1603 * Now calculate new superblock values and check for reasonable 1604 * bound for new file system size: 1605 * fs_size: is derived from user input 1606 * fs_dsize: should get updated in the routines creating or 1607 * updating the cylinder groups on the fly 1608 * fs_cstotal: should get updated in the routines creating or 1609 * updating the cylinder groups 1610 */ 1611 1612 /* 1613 * Update the number of cylinders and cylinder groups in the file system. 1614 */ 1615 if (sblock.fs_magic == FS_UFS1_MAGIC) { 1616 sblock.fs_old_ncyl = 1617 sblock.fs_size * sblock.fs_old_nspf / sblock.fs_old_spc; 1618 if (sblock.fs_size * sblock.fs_old_nspf > 1619 sblock.fs_old_ncyl * sblock.fs_old_spc) 1620 sblock.fs_old_ncyl++; 1621 } 1622 sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg); 1623 1624 /* 1625 * Allocate last cylinder group only if there is enough room 1626 * for at least one data block. 1627 */ 1628 if (sblock.fs_size % sblock.fs_fpg != 0 && 1629 sblock.fs_size <= cgdmin(&sblock, sblock.fs_ncg - 1)) { 1630 humanize_number(oldsizebuf, sizeof(oldsizebuf), 1631 (sblock.fs_size % sblock.fs_fpg) * sblock.fs_fsize, 1632 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1633 warnx("no room to allocate last cylinder group; " 1634 "leaving %s unused", oldsizebuf); 1635 sblock.fs_ncg--; 1636 if (sblock.fs_magic == FS_UFS1_MAGIC) 1637 sblock.fs_old_ncyl = sblock.fs_ncg * sblock.fs_old_cpg; 1638 sblock.fs_old_size = sblock.fs_size = 1639 sblock.fs_ncg * sblock.fs_fpg; 1640 } 1641 1642 /* 1643 * Update the space for the cylinder group summary information in the 1644 * respective cylinder group data area. 1645 */ 1646 sblock.fs_cssize = 1647 fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 1648 1649 if (osblock.fs_size >= sblock.fs_size) 1650 errx(1, "not enough new space"); 1651 1652 DBG_PRINT0("sblock calculated\n"); 1653 1654 /* 1655 * Ok, everything prepared, so now let's do the tricks. 1656 */ 1657 growfs(fsi, fso, Nflag); 1658 1659 close(fsi); 1660 if (fso > -1) { 1661 if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) { 1662 error = ioctl(fso, UFSRESUME); 1663 if (error != 0) 1664 err(1, "UFSRESUME"); 1665 } 1666 error = close(fso); 1667 if (error != 0) 1668 err(1, "close"); 1669 if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0) 1670 mount_reload(statfsp); 1671 } 1672 1673 DBG_CLOSE; 1674 1675 DBG_LEAVE; 1676 return (0); 1677 } 1678 1679 /* 1680 * Dump a line of usage. 1681 */ 1682 static void 1683 usage(void) 1684 { 1685 DBG_FUNC("usage") 1686 1687 DBG_ENTER; 1688 1689 fprintf(stderr, "usage: growfs [-Ny] [-s size] special | filesystem\n"); 1690 1691 DBG_LEAVE; 1692 exit(1); 1693 } 1694 1695 /* 1696 * This updates most parameters and the bitmap related to cluster. We have to 1697 * assume that sblock, osblock, acg are set up. 1698 */ 1699 static void 1700 updclst(int block) 1701 { 1702 DBG_FUNC("updclst") 1703 static int lcs = 0; 1704 1705 DBG_ENTER; 1706 1707 if (sblock.fs_contigsumsize < 1) /* no clustering */ 1708 return; 1709 /* 1710 * update cluster allocation map 1711 */ 1712 setbit(cg_clustersfree(&acg), block); 1713 1714 /* 1715 * update cluster summary table 1716 */ 1717 if (!lcs) { 1718 /* 1719 * calculate size for the trailing cluster 1720 */ 1721 for (block--; lcs < sblock.fs_contigsumsize; block--, lcs++ ) { 1722 if (isclr(cg_clustersfree(&acg), block)) 1723 break; 1724 } 1725 } 1726 if (lcs < sblock.fs_contigsumsize) { 1727 if (lcs) 1728 cg_clustersum(&acg)[lcs]--; 1729 lcs++; 1730 cg_clustersum(&acg)[lcs]++; 1731 } 1732 1733 DBG_LEAVE; 1734 return; 1735 } 1736 1737 static void 1738 mount_reload(const struct statfs *stfs) 1739 { 1740 char errmsg[255]; 1741 struct iovec *iov; 1742 int iovlen; 1743 1744 iov = NULL; 1745 iovlen = 0; 1746 *errmsg = '\0'; 1747 build_iovec(&iov, &iovlen, "fstype", __DECONST(char *, "ffs"), 4); 1748 build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, stfs->f_mntonname), (size_t)-1); 1749 build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); 1750 build_iovec(&iov, &iovlen, "update", NULL, 0); 1751 build_iovec(&iov, &iovlen, "reload", NULL, 0); 1752 1753 if (nmount(iov, iovlen, stfs->f_flags) < 0) { 1754 errmsg[sizeof(errmsg) - 1] = '\0'; 1755 err(9, "%s: cannot reload filesystem%s%s", stfs->f_mntonname, 1756 *errmsg != '\0' ? ": " : "", errmsg); 1757 } 1758 } 1759 1760 /* 1761 * Calculate the check-hash of the cylinder group. 1762 */ 1763 static void 1764 cgckhash(struct cg *cgp) 1765 { 1766 1767 if ((sblock.fs_metackhash & CK_CYLGRP) == 0) 1768 return; 1769 cgp->cg_ckhash = 0; 1770 cgp->cg_ckhash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize); 1771 } 1772