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