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