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 int 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 -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 int 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 = sblock.fs_ipg < 2 * INOPB(&sblock) ? 352 sblock.fs_ipg : 2 * INOPB(&sblock); 353 acg.cg_ndblk = dmax - cbase; 354 if (sblock.fs_contigsumsize > 0) 355 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; 356 start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); 357 if (sblock.fs_magic == FS_UFS2_MAGIC) { 358 acg.cg_iusedoff = start; 359 } else { 360 acg.cg_old_ncyl = sblock.fs_old_cpg; 361 acg.cg_old_time = acg.cg_time; 362 acg.cg_time = 0; 363 acg.cg_old_niblk = acg.cg_niblk; 364 acg.cg_niblk = 0; 365 acg.cg_initediblk = 0; 366 acg.cg_old_btotoff = start; 367 acg.cg_old_boff = acg.cg_old_btotoff + 368 sblock.fs_old_cpg * sizeof(int32_t); 369 acg.cg_iusedoff = acg.cg_old_boff + 370 sblock.fs_old_cpg * sizeof(u_int16_t); 371 } 372 acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT); 373 acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT); 374 if (sblock.fs_contigsumsize > 0) { 375 acg.cg_clustersumoff = 376 roundup(acg.cg_nextfreeoff, sizeof(u_int32_t)); 377 acg.cg_clustersumoff -= sizeof(u_int32_t); 378 acg.cg_clusteroff = acg.cg_clustersumoff + 379 (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t); 380 acg.cg_nextfreeoff = acg.cg_clusteroff + 381 howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT); 382 } 383 if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) { 384 /* 385 * This should never happen as we would have had that panic 386 * already on file system creation 387 */ 388 errx(37, "panic: cylinder group too big"); 389 } 390 acg.cg_cs.cs_nifree += sblock.fs_ipg; 391 if (cylno == 0) 392 for (ino = 0; ino < ROOTINO; ino++) { 393 setbit(cg_inosused(&acg), ino); 394 acg.cg_cs.cs_nifree--; 395 } 396 /* 397 * For the old file system, we have to initialize all the inodes. 398 */ 399 if (sblock.fs_magic == FS_UFS1_MAGIC) { 400 bzero(iobuf, sblock.fs_bsize); 401 for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); 402 i += sblock.fs_frag) { 403 dp1 = (struct ufs1_dinode *)(void *)iobuf; 404 for (j = 0; j < INOPB(&sblock); j++) { 405 dp1->di_gen = arc4random(); 406 dp1++; 407 } 408 wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), 409 sblock.fs_bsize, iobuf, fso, Nflag); 410 } 411 } 412 if (cylno > 0) { 413 /* 414 * In cylno 0, beginning space is reserved 415 * for boot and super blocks. 416 */ 417 for (d = 0; d < dlower; d += sblock.fs_frag) { 418 blkno = d / sblock.fs_frag; 419 setblock(&sblock, cg_blksfree(&acg), blkno); 420 if (sblock.fs_contigsumsize > 0) 421 setbit(cg_clustersfree(&acg), blkno); 422 acg.cg_cs.cs_nbfree++; 423 } 424 sblock.fs_dsize += dlower; 425 } 426 sblock.fs_dsize += acg.cg_ndblk - dupper; 427 if ((i = dupper % sblock.fs_frag)) { 428 acg.cg_frsum[sblock.fs_frag - i]++; 429 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { 430 setbit(cg_blksfree(&acg), dupper); 431 acg.cg_cs.cs_nffree++; 432 } 433 } 434 for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk; 435 d += sblock.fs_frag) { 436 blkno = d / sblock.fs_frag; 437 setblock(&sblock, cg_blksfree(&acg), blkno); 438 if (sblock.fs_contigsumsize > 0) 439 setbit(cg_clustersfree(&acg), blkno); 440 acg.cg_cs.cs_nbfree++; 441 } 442 if (d < acg.cg_ndblk) { 443 acg.cg_frsum[acg.cg_ndblk - d]++; 444 for (; d < acg.cg_ndblk; d++) { 445 setbit(cg_blksfree(&acg), d); 446 acg.cg_cs.cs_nffree++; 447 } 448 } 449 if (sblock.fs_contigsumsize > 0) { 450 int32_t *sump = cg_clustersum(&acg); 451 u_char *mapp = cg_clustersfree(&acg); 452 int map = *mapp++; 453 int bit = 1; 454 int run = 0; 455 456 for (i = 0; i < acg.cg_nclusterblks; i++) { 457 if ((map & bit) != 0) 458 run++; 459 else if (run != 0) { 460 if (run > sblock.fs_contigsumsize) 461 run = sblock.fs_contigsumsize; 462 sump[run]++; 463 run = 0; 464 } 465 if ((i & (CHAR_BIT - 1)) != CHAR_BIT - 1) 466 bit <<= 1; 467 else { 468 map = *mapp++; 469 bit = 1; 470 } 471 } 472 if (run != 0) { 473 if (run > sblock.fs_contigsumsize) 474 run = sblock.fs_contigsumsize; 475 sump[run]++; 476 } 477 } 478 sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 479 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 480 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 481 sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 482 *cs = acg.cg_cs; 483 484 memcpy(iobuf, &acg, sblock.fs_cgsize); 485 memset(iobuf + sblock.fs_cgsize, '\0', 486 sblock.fs_bsize * 3 - sblock.fs_cgsize); 487 488 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 489 sblock.fs_bsize * 3, iobuf, fso, Nflag); 490 DBG_DUMP_CG(&sblock, "new cg", &acg); 491 492 DBG_LEAVE; 493 return; 494 } 495 496 /* 497 * Here we add or subtract (sign +1/-1) the available fragments in a given 498 * block to or from the fragment statistics. By subtracting before and adding 499 * after an operation on the free frag map we can easy update the fragment 500 * statistic, which seems to be otherwise a rather complex operation. 501 */ 502 static void 503 frag_adjust(ufs2_daddr_t frag, int sign) 504 { 505 DBG_FUNC("frag_adjust") 506 int fragsize; 507 int f; 508 509 DBG_ENTER; 510 511 fragsize = 0; 512 /* 513 * Here frag only needs to point to any fragment in the block we want 514 * to examine. 515 */ 516 for (f = rounddown(frag, sblock.fs_frag); 517 f < roundup(frag + 1, sblock.fs_frag); f++) { 518 /* 519 * Count contiguous free fragments. 520 */ 521 if (isset(cg_blksfree(&acg), f)) { 522 fragsize++; 523 } else { 524 if (fragsize && fragsize < sblock.fs_frag) { 525 /* 526 * We found something in between. 527 */ 528 acg.cg_frsum[fragsize] += sign; 529 DBG_PRINT2("frag_adjust [%d]+=%d\n", 530 fragsize, sign); 531 } 532 fragsize = 0; 533 } 534 } 535 if (fragsize && fragsize < sblock.fs_frag) { 536 /* 537 * We found something. 538 */ 539 acg.cg_frsum[fragsize] += sign; 540 DBG_PRINT2("frag_adjust [%d]+=%d\n", fragsize, sign); 541 } 542 DBG_PRINT2("frag_adjust [[%d]]+=%d\n", fragsize, sign); 543 544 DBG_LEAVE; 545 return; 546 } 547 548 /* 549 * Here we do all needed work for the former last cylinder group. It has to be 550 * changed in any case, even if the file system ended exactly on the end of 551 * this group, as there is some slightly inconsistent handling of the number 552 * of cylinders in the cylinder group. We start again by reading the cylinder 553 * group from disk. If the last block was not fully available, we first handle 554 * the missing fragments, then we handle all new full blocks in that file 555 * system and finally we handle the new last fragmented block in the file 556 * system. We again have to handle the fragment statistics rotational layout 557 * tables and cluster summary during all those operations. 558 */ 559 static void 560 updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag) 561 { 562 DBG_FUNC("updjcg") 563 ufs2_daddr_t cbase, dmax, dupper; 564 struct csum *cs; 565 int i, k; 566 int j = 0; 567 568 DBG_ENTER; 569 570 /* 571 * Read the former last (joining) cylinder group from disk, and make 572 * a copy. 573 */ 574 rdfs(fsbtodb(&osblock, cgtod(&osblock, cylno)), 575 (size_t)osblock.fs_cgsize, (void *)&aocg, fsi); 576 DBG_PRINT0("jcg read\n"); 577 DBG_DUMP_CG(&sblock, "old joining cg", &aocg); 578 579 memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2)); 580 581 /* 582 * If the cylinder group had already its new final size almost 583 * nothing is to be done ... except: 584 * For some reason the value of cg_ncyl in the last cylinder group has 585 * to be zero instead of fs_cpg. As this is now no longer the last 586 * cylinder group we have to change that value now to fs_cpg. 587 */ 588 589 if (cgbase(&osblock, cylno + 1) == osblock.fs_size) { 590 if (sblock.fs_magic == FS_UFS1_MAGIC) 591 acg.cg_old_ncyl = sblock.fs_old_cpg; 592 593 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 594 (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); 595 DBG_PRINT0("jcg written\n"); 596 DBG_DUMP_CG(&sblock, "new joining cg", &acg); 597 598 DBG_LEAVE; 599 return; 600 } 601 602 /* 603 * Set up some variables needed later. 604 */ 605 cbase = cgbase(&sblock, cylno); 606 dmax = cbase + sblock.fs_fpg; 607 if (dmax > sblock.fs_size) 608 dmax = sblock.fs_size; 609 dupper = cgdmin(&sblock, cylno) - cbase; 610 if (cylno == 0) /* XXX fscs may be relocated */ 611 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 612 613 /* 614 * Set pointer to the cylinder summary for our cylinder group. 615 */ 616 cs = fscs + cylno; 617 618 /* 619 * Touch the cylinder group, update all fields in the cylinder group as 620 * needed, update the free space in the superblock. 621 */ 622 acg.cg_time = modtime; 623 if ((unsigned)cylno == sblock.fs_ncg - 1) { 624 /* 625 * This is still the last cylinder group. 626 */ 627 if (sblock.fs_magic == FS_UFS1_MAGIC) 628 acg.cg_old_ncyl = 629 sblock.fs_old_ncyl % sblock.fs_old_cpg; 630 } else { 631 acg.cg_old_ncyl = sblock.fs_old_cpg; 632 } 633 DBG_PRINT2("jcg dbg: %d %u", cylno, sblock.fs_ncg); 634 #ifdef FS_DEBUG 635 if (sblock.fs_magic == FS_UFS1_MAGIC) 636 DBG_PRINT2("%d %u", acg.cg_old_ncyl, sblock.fs_old_cpg); 637 #endif 638 DBG_PRINT0("\n"); 639 acg.cg_ndblk = dmax - cbase; 640 sblock.fs_dsize += acg.cg_ndblk - aocg.cg_ndblk; 641 if (sblock.fs_contigsumsize > 0) 642 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; 643 644 /* 645 * Now we have to update the free fragment bitmap for our new free 646 * space. There again we have to handle the fragmentation and also 647 * the rotational layout tables and the cluster summary. This is 648 * also done per fragment for the first new block if the old file 649 * system end was not on a block boundary, per fragment for the new 650 * last block if the new file system end is not on a block boundary, 651 * and per block for all space in between. 652 * 653 * Handle the first new block here if it was partially available 654 * before. 655 */ 656 if (osblock.fs_size % sblock.fs_frag) { 657 if (roundup(osblock.fs_size, sblock.fs_frag) <= 658 sblock.fs_size) { 659 /* 660 * The new space is enough to fill at least this 661 * block 662 */ 663 j = 0; 664 for (i = roundup(osblock.fs_size - cbase, 665 sblock.fs_frag) - 1; i >= osblock.fs_size - cbase; 666 i--) { 667 setbit(cg_blksfree(&acg), i); 668 acg.cg_cs.cs_nffree++; 669 j++; 670 } 671 672 /* 673 * Check if the fragment just created could join an 674 * already existing fragment at the former end of the 675 * file system. 676 */ 677 if (isblock(&sblock, cg_blksfree(&acg), 678 ((osblock.fs_size - cgbase(&sblock, cylno)) / 679 sblock.fs_frag))) { 680 /* 681 * The block is now completely available. 682 */ 683 DBG_PRINT0("block was\n"); 684 acg.cg_frsum[osblock.fs_size % sblock.fs_frag]--; 685 acg.cg_cs.cs_nbfree++; 686 acg.cg_cs.cs_nffree -= sblock.fs_frag; 687 k = rounddown(osblock.fs_size - cbase, 688 sblock.fs_frag); 689 updclst((osblock.fs_size - cbase) / 690 sblock.fs_frag); 691 } else { 692 /* 693 * Lets rejoin a possible partially growed 694 * fragment. 695 */ 696 k = 0; 697 while (isset(cg_blksfree(&acg), i) && 698 (i >= rounddown(osblock.fs_size - cbase, 699 sblock.fs_frag))) { 700 i--; 701 k++; 702 } 703 if (k) 704 acg.cg_frsum[k]--; 705 acg.cg_frsum[k + j]++; 706 } 707 } else { 708 /* 709 * We only grow by some fragments within this last 710 * block. 711 */ 712 for (i = sblock.fs_size - cbase - 1; 713 i >= osblock.fs_size - cbase; i--) { 714 setbit(cg_blksfree(&acg), i); 715 acg.cg_cs.cs_nffree++; 716 j++; 717 } 718 /* 719 * Lets rejoin a possible partially growed fragment. 720 */ 721 k = 0; 722 while (isset(cg_blksfree(&acg), i) && 723 (i >= rounddown(osblock.fs_size - cbase, 724 sblock.fs_frag))) { 725 i--; 726 k++; 727 } 728 if (k) 729 acg.cg_frsum[k]--; 730 acg.cg_frsum[k + j]++; 731 } 732 } 733 734 /* 735 * Handle all new complete blocks here. 736 */ 737 for (i = roundup(osblock.fs_size - cbase, sblock.fs_frag); 738 i + sblock.fs_frag <= dmax - cbase; /* XXX <= or only < ? */ 739 i += sblock.fs_frag) { 740 j = i / sblock.fs_frag; 741 setblock(&sblock, cg_blksfree(&acg), j); 742 updclst(j); 743 acg.cg_cs.cs_nbfree++; 744 } 745 746 /* 747 * Handle the last new block if there are stll some new fragments left. 748 * Here we don't have to bother about the cluster summary or the even 749 * the rotational layout table. 750 */ 751 if (i < (dmax - cbase)) { 752 acg.cg_frsum[dmax - cbase - i]++; 753 for (; i < dmax - cbase; i++) { 754 setbit(cg_blksfree(&acg), i); 755 acg.cg_cs.cs_nffree++; 756 } 757 } 758 759 sblock.fs_cstotal.cs_nffree += 760 (acg.cg_cs.cs_nffree - aocg.cg_cs.cs_nffree); 761 sblock.fs_cstotal.cs_nbfree += 762 (acg.cg_cs.cs_nbfree - aocg.cg_cs.cs_nbfree); 763 /* 764 * The following statistics are not changed here: 765 * sblock.fs_cstotal.cs_ndir 766 * sblock.fs_cstotal.cs_nifree 767 * As the statistics for this cylinder group are ready, copy it to 768 * the summary information array. 769 */ 770 *cs = acg.cg_cs; 771 772 /* 773 * Write the updated "joining" cylinder group back to disk. 774 */ 775 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), (size_t)sblock.fs_cgsize, 776 (void *)&acg, fso, Nflag); 777 DBG_PRINT0("jcg written\n"); 778 DBG_DUMP_CG(&sblock, "new joining cg", &acg); 779 780 DBG_LEAVE; 781 return; 782 } 783 784 /* 785 * Here we update the location of the cylinder summary. We have two possible 786 * ways of growing the cylinder summary: 787 * (1) We can try to grow the summary in the current location, and relocate 788 * possibly used blocks within the current cylinder group. 789 * (2) Alternatively we can relocate the whole cylinder summary to the first 790 * new completely empty cylinder group. Once the cylinder summary is no 791 * longer in the beginning of the first cylinder group you should never 792 * use a version of fsck which is not aware of the possibility to have 793 * this structure in a non standard place. 794 * Option (2) is considered to be less intrusive to the structure of the file- 795 * system, so that's the one being used. 796 */ 797 static void 798 updcsloc(time_t modtime, int fsi, int fso, unsigned int Nflag) 799 { 800 DBG_FUNC("updcsloc") 801 struct csum *cs; 802 int ocscg, ncscg; 803 ufs2_daddr_t d; 804 int lcs = 0; 805 int block; 806 807 DBG_ENTER; 808 809 if (howmany(sblock.fs_cssize, sblock.fs_fsize) == 810 howmany(osblock.fs_cssize, osblock.fs_fsize)) { 811 /* 812 * No new fragment needed. 813 */ 814 DBG_LEAVE; 815 return; 816 } 817 ocscg = dtog(&osblock, osblock.fs_csaddr); 818 cs = fscs + ocscg; 819 820 /* 821 * Read original cylinder group from disk, and make a copy. 822 * XXX If Nflag is set in some very rare cases we now miss 823 * some changes done in updjcg by reading the unmodified 824 * block from disk. 825 */ 826 rdfs(fsbtodb(&osblock, cgtod(&osblock, ocscg)), 827 (size_t)osblock.fs_cgsize, (void *)&aocg, fsi); 828 DBG_PRINT0("oscg read\n"); 829 DBG_DUMP_CG(&sblock, "old summary cg", &aocg); 830 831 memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2)); 832 833 /* 834 * Touch the cylinder group, set up local variables needed later 835 * and update the superblock. 836 */ 837 acg.cg_time = modtime; 838 839 /* 840 * XXX In the case of having active snapshots we may need much more 841 * blocks for the copy on write. We need each block twice, and 842 * also up to 8*3 blocks for indirect blocks for all possible 843 * references. 844 */ 845 /* 846 * There is not enough space in the old cylinder group to 847 * relocate all blocks as needed, so we relocate the whole 848 * cylinder group summary to a new group. We try to use the 849 * first complete new cylinder group just created. Within the 850 * cylinder group we align the area immediately after the 851 * cylinder group information location in order to be as 852 * close as possible to the original implementation of ffs. 853 * 854 * First we have to make sure we'll find enough space in the 855 * new cylinder group. If not, then we currently give up. 856 * We start with freeing everything which was used by the 857 * fragments of the old cylinder summary in the current group. 858 * Now we write back the group meta data, read in the needed 859 * meta data from the new cylinder group, and start allocating 860 * within that group. Here we can assume, the group to be 861 * completely empty. Which makes the handling of fragments and 862 * clusters a lot easier. 863 */ 864 DBG_TRC; 865 if (sblock.fs_ncg - osblock.fs_ncg < 2) 866 errx(2, "panic: not enough space"); 867 868 /* 869 * Point "d" to the first fragment not used by the cylinder 870 * summary. 871 */ 872 d = osblock.fs_csaddr + (osblock.fs_cssize / osblock.fs_fsize); 873 874 /* 875 * Set up last cluster size ("lcs") already here. Calculate 876 * the size for the trailing cluster just behind where "d" 877 * points to. 878 */ 879 if (sblock.fs_contigsumsize > 0) { 880 for (block = howmany(d % sblock.fs_fpg, sblock.fs_frag), 881 lcs = 0; lcs < sblock.fs_contigsumsize; block++, lcs++) { 882 if (isclr(cg_clustersfree(&acg), block)) 883 break; 884 } 885 } 886 887 /* 888 * Point "d" to the last frag used by the cylinder summary. 889 */ 890 d--; 891 892 DBG_PRINT1("d=%jd\n", (intmax_t)d); 893 if ((d + 1) % sblock.fs_frag) { 894 /* 895 * The end of the cylinder summary is not a complete 896 * block. 897 */ 898 DBG_TRC; 899 frag_adjust(d % sblock.fs_fpg, -1); 900 for (; (d + 1) % sblock.fs_frag; d--) { 901 DBG_PRINT1("d=%jd\n", (intmax_t)d); 902 setbit(cg_blksfree(&acg), d % sblock.fs_fpg); 903 acg.cg_cs.cs_nffree++; 904 sblock.fs_cstotal.cs_nffree++; 905 } 906 /* 907 * Point "d" to the last fragment of the last 908 * (incomplete) block of the cylinder summary. 909 */ 910 d++; 911 frag_adjust(d % sblock.fs_fpg, 1); 912 913 if (isblock(&sblock, cg_blksfree(&acg), 914 (d % sblock.fs_fpg) / sblock.fs_frag)) { 915 DBG_PRINT1("d=%jd\n", (intmax_t)d); 916 acg.cg_cs.cs_nffree -= sblock.fs_frag; 917 acg.cg_cs.cs_nbfree++; 918 sblock.fs_cstotal.cs_nffree -= sblock.fs_frag; 919 sblock.fs_cstotal.cs_nbfree++; 920 if (sblock.fs_contigsumsize > 0) { 921 setbit(cg_clustersfree(&acg), 922 (d % sblock.fs_fpg) / sblock.fs_frag); 923 if (lcs < sblock.fs_contigsumsize) { 924 if (lcs) 925 cg_clustersum(&acg)[lcs]--; 926 lcs++; 927 cg_clustersum(&acg)[lcs]++; 928 } 929 } 930 } 931 /* 932 * Point "d" to the first fragment of the block before 933 * the last incomplete block. 934 */ 935 d--; 936 } 937 938 DBG_PRINT1("d=%jd\n", (intmax_t)d); 939 for (d = rounddown(d, sblock.fs_frag); d >= osblock.fs_csaddr; 940 d -= sblock.fs_frag) { 941 DBG_TRC; 942 DBG_PRINT1("d=%jd\n", (intmax_t)d); 943 setblock(&sblock, cg_blksfree(&acg), 944 (d % sblock.fs_fpg) / sblock.fs_frag); 945 acg.cg_cs.cs_nbfree++; 946 sblock.fs_cstotal.cs_nbfree++; 947 if (sblock.fs_contigsumsize > 0) { 948 setbit(cg_clustersfree(&acg), 949 (d % sblock.fs_fpg) / sblock.fs_frag); 950 /* 951 * The last cluster size is already set up. 952 */ 953 if (lcs < sblock.fs_contigsumsize) { 954 if (lcs) 955 cg_clustersum(&acg)[lcs]--; 956 lcs++; 957 cg_clustersum(&acg)[lcs]++; 958 } 959 } 960 } 961 *cs = acg.cg_cs; 962 963 /* 964 * Now write the former cylinder group containing the cylinder 965 * summary back to disk. 966 */ 967 wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)), 968 (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); 969 DBG_PRINT0("oscg written\n"); 970 DBG_DUMP_CG(&sblock, "old summary cg", &acg); 971 972 /* 973 * Find the beginning of the new cylinder group containing the 974 * cylinder summary. 975 */ 976 sblock.fs_csaddr = cgdmin(&sblock, osblock.fs_ncg); 977 ncscg = dtog(&sblock, sblock.fs_csaddr); 978 cs = fscs + ncscg; 979 980 /* 981 * If Nflag is specified, we would now read random data instead 982 * of an empty cg structure from disk. So we can't simulate that 983 * part for now. 984 */ 985 if (Nflag) { 986 DBG_PRINT0("nscg update skipped\n"); 987 DBG_LEAVE; 988 return; 989 } 990 991 /* 992 * Read the future cylinder group containing the cylinder 993 * summary from disk, and make a copy. 994 */ 995 rdfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)), 996 (size_t)sblock.fs_cgsize, (void *)&aocg, fsi); 997 DBG_PRINT0("nscg read\n"); 998 DBG_DUMP_CG(&sblock, "new summary cg", &aocg); 999 1000 memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2)); 1001 1002 /* 1003 * Allocate all complete blocks used by the new cylinder 1004 * summary. 1005 */ 1006 for (d = sblock.fs_csaddr; d + sblock.fs_frag <= 1007 sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize); 1008 d += sblock.fs_frag) { 1009 clrblock(&sblock, cg_blksfree(&acg), 1010 (d % sblock.fs_fpg) / sblock.fs_frag); 1011 acg.cg_cs.cs_nbfree--; 1012 sblock.fs_cstotal.cs_nbfree--; 1013 if (sblock.fs_contigsumsize > 0) { 1014 clrbit(cg_clustersfree(&acg), 1015 (d % sblock.fs_fpg) / sblock.fs_frag); 1016 } 1017 } 1018 1019 /* 1020 * Allocate all fragments used by the cylinder summary in the 1021 * last block. 1022 */ 1023 if (d < sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize)) { 1024 for (; d - sblock.fs_csaddr < 1025 sblock.fs_cssize/sblock.fs_fsize; d++) { 1026 clrbit(cg_blksfree(&acg), d % sblock.fs_fpg); 1027 acg.cg_cs.cs_nffree--; 1028 sblock.fs_cstotal.cs_nffree--; 1029 } 1030 acg.cg_cs.cs_nbfree--; 1031 acg.cg_cs.cs_nffree += sblock.fs_frag; 1032 sblock.fs_cstotal.cs_nbfree--; 1033 sblock.fs_cstotal.cs_nffree += sblock.fs_frag; 1034 if (sblock.fs_contigsumsize > 0) 1035 clrbit(cg_clustersfree(&acg), 1036 (d % sblock.fs_fpg) / sblock.fs_frag); 1037 1038 frag_adjust(d % sblock.fs_fpg, 1); 1039 } 1040 /* 1041 * XXX Handle the cluster statistics here in the case this 1042 * cylinder group is now almost full, and the remaining 1043 * space is less then the maximum cluster size. This is 1044 * probably not needed, as you would hardly find a file 1045 * system which has only MAXCSBUFS+FS_MAXCONTIG of free 1046 * space right behind the cylinder group information in 1047 * any new cylinder group. 1048 */ 1049 1050 /* 1051 * Update our statistics in the cylinder summary. 1052 */ 1053 *cs = acg.cg_cs; 1054 1055 /* 1056 * Write the new cylinder group containing the cylinder summary 1057 * back to disk. 1058 */ 1059 wtfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)), 1060 (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); 1061 DBG_PRINT0("nscg written\n"); 1062 DBG_DUMP_CG(&sblock, "new summary cg", &acg); 1063 1064 DBG_LEAVE; 1065 return; 1066 } 1067 1068 /* 1069 * Here we read some block(s) from disk. 1070 */ 1071 static void 1072 rdfs(ufs2_daddr_t bno, size_t size, void *bf, int fsi) 1073 { 1074 DBG_FUNC("rdfs") 1075 ssize_t n; 1076 1077 DBG_ENTER; 1078 1079 if (bno < 0) 1080 err(32, "rdfs: attempting to read negative block number"); 1081 if (lseek(fsi, (off_t)bno * DEV_BSIZE, 0) < 0) 1082 err(33, "rdfs: seek error: %jd", (intmax_t)bno); 1083 n = read(fsi, bf, size); 1084 if (n != (ssize_t)size) 1085 err(34, "rdfs: read error: %jd", (intmax_t)bno); 1086 1087 DBG_LEAVE; 1088 return; 1089 } 1090 1091 /* 1092 * Here we write some block(s) to disk. 1093 */ 1094 static void 1095 wtfs(ufs2_daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag) 1096 { 1097 DBG_FUNC("wtfs") 1098 ssize_t n; 1099 1100 DBG_ENTER; 1101 1102 if (Nflag) { 1103 DBG_LEAVE; 1104 return; 1105 } 1106 if (lseek(fso, (off_t)bno * DEV_BSIZE, SEEK_SET) < 0) 1107 err(35, "wtfs: seek error: %ld", (long)bno); 1108 n = write(fso, bf, size); 1109 if (n != (ssize_t)size) 1110 err(36, "wtfs: write error: %ld", (long)bno); 1111 1112 DBG_LEAVE; 1113 return; 1114 } 1115 1116 /* 1117 * Here we check if all frags of a block are free. For more details again 1118 * please see the source of newfs(8), as this function is taken over almost 1119 * unchanged. 1120 */ 1121 static int 1122 isblock(struct fs *fs, unsigned char *cp, int h) 1123 { 1124 DBG_FUNC("isblock") 1125 unsigned char mask; 1126 1127 DBG_ENTER; 1128 1129 switch (fs->fs_frag) { 1130 case 8: 1131 DBG_LEAVE; 1132 return (cp[h] == 0xff); 1133 case 4: 1134 mask = 0x0f << ((h & 0x1) << 2); 1135 DBG_LEAVE; 1136 return ((cp[h >> 1] & mask) == mask); 1137 case 2: 1138 mask = 0x03 << ((h & 0x3) << 1); 1139 DBG_LEAVE; 1140 return ((cp[h >> 2] & mask) == mask); 1141 case 1: 1142 mask = 0x01 << (h & 0x7); 1143 DBG_LEAVE; 1144 return ((cp[h >> 3] & mask) == mask); 1145 default: 1146 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 1147 DBG_LEAVE; 1148 return (0); 1149 } 1150 } 1151 1152 /* 1153 * Here we allocate a complete block in the block map. For more details again 1154 * please see the source of newfs(8), as this function is taken over almost 1155 * unchanged. 1156 */ 1157 static void 1158 clrblock(struct fs *fs, unsigned char *cp, int h) 1159 { 1160 DBG_FUNC("clrblock") 1161 1162 DBG_ENTER; 1163 1164 switch ((fs)->fs_frag) { 1165 case 8: 1166 cp[h] = 0; 1167 break; 1168 case 4: 1169 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 1170 break; 1171 case 2: 1172 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 1173 break; 1174 case 1: 1175 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 1176 break; 1177 default: 1178 warnx("clrblock bad fs_frag %d", fs->fs_frag); 1179 break; 1180 } 1181 1182 DBG_LEAVE; 1183 return; 1184 } 1185 1186 /* 1187 * Here we free a complete block in the free block map. For more details again 1188 * please see the source of newfs(8), as this function is taken over almost 1189 * unchanged. 1190 */ 1191 static void 1192 setblock(struct fs *fs, unsigned char *cp, int h) 1193 { 1194 DBG_FUNC("setblock") 1195 1196 DBG_ENTER; 1197 1198 switch (fs->fs_frag) { 1199 case 8: 1200 cp[h] = 0xff; 1201 break; 1202 case 4: 1203 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 1204 break; 1205 case 2: 1206 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 1207 break; 1208 case 1: 1209 cp[h >> 3] |= (0x01 << (h & 0x7)); 1210 break; 1211 default: 1212 warnx("setblock bad fs_frag %d", fs->fs_frag); 1213 break; 1214 } 1215 1216 DBG_LEAVE; 1217 return; 1218 } 1219 1220 /* 1221 * Figure out how many lines our current terminal has. For more details again 1222 * please see the source of newfs(8), as this function is taken over almost 1223 * unchanged. 1224 */ 1225 static int 1226 charsperline(void) 1227 { 1228 DBG_FUNC("charsperline") 1229 int columns; 1230 char *cp; 1231 struct winsize ws; 1232 1233 DBG_ENTER; 1234 1235 columns = 0; 1236 if (ioctl(0, TIOCGWINSZ, &ws) != -1) 1237 columns = ws.ws_col; 1238 if (columns == 0 && (cp = getenv("COLUMNS"))) 1239 columns = atoi(cp); 1240 if (columns == 0) 1241 columns = 80; /* last resort */ 1242 1243 DBG_LEAVE; 1244 return (columns); 1245 } 1246 1247 static int 1248 is_dev(const char *name) 1249 { 1250 struct stat devstat; 1251 1252 if (stat(name, &devstat) != 0) 1253 return (0); 1254 if (!S_ISCHR(devstat.st_mode)) 1255 return (0); 1256 return (1); 1257 } 1258 1259 /* 1260 * Return mountpoint on which the device is currently mounted. 1261 */ 1262 static const struct statfs * 1263 dev_to_statfs(const char *dev) 1264 { 1265 struct stat devstat, mntdevstat; 1266 struct statfs *mntbuf, *statfsp; 1267 char device[MAXPATHLEN]; 1268 char *mntdevname; 1269 int i, mntsize; 1270 1271 /* 1272 * First check the mounted filesystems. 1273 */ 1274 if (stat(dev, &devstat) != 0) 1275 return (NULL); 1276 if (!S_ISCHR(devstat.st_mode) && !S_ISBLK(devstat.st_mode)) 1277 return (NULL); 1278 1279 mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 1280 for (i = 0; i < mntsize; i++) { 1281 statfsp = &mntbuf[i]; 1282 mntdevname = statfsp->f_mntfromname; 1283 if (*mntdevname != '/') { 1284 strcpy(device, _PATH_DEV); 1285 strcat(device, mntdevname); 1286 mntdevname = device; 1287 } 1288 if (stat(mntdevname, &mntdevstat) == 0 && 1289 mntdevstat.st_rdev == devstat.st_rdev) 1290 return (statfsp); 1291 } 1292 1293 return (NULL); 1294 } 1295 1296 static const char * 1297 mountpoint_to_dev(const char *mountpoint) 1298 { 1299 struct statfs *mntbuf, *statfsp; 1300 struct fstab *fs; 1301 int i, mntsize; 1302 1303 /* 1304 * First check the mounted filesystems. 1305 */ 1306 mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 1307 for (i = 0; i < mntsize; i++) { 1308 statfsp = &mntbuf[i]; 1309 1310 if (strcmp(statfsp->f_mntonname, mountpoint) == 0) 1311 return (statfsp->f_mntfromname); 1312 } 1313 1314 /* 1315 * Check the fstab. 1316 */ 1317 fs = getfsfile(mountpoint); 1318 if (fs != NULL) 1319 return (fs->fs_spec); 1320 1321 return (NULL); 1322 } 1323 1324 static const char * 1325 getdev(const char *name) 1326 { 1327 static char device[MAXPATHLEN]; 1328 const char *cp, *dev; 1329 1330 if (is_dev(name)) 1331 return (name); 1332 1333 cp = strrchr(name, '/'); 1334 if (cp == 0) { 1335 snprintf(device, sizeof(device), "%s%s", _PATH_DEV, name); 1336 if (is_dev(device)) 1337 return (device); 1338 } 1339 1340 dev = mountpoint_to_dev(name); 1341 if (dev != NULL && is_dev(dev)) 1342 return (dev); 1343 1344 return (NULL); 1345 } 1346 1347 /* 1348 * growfs(8) is a utility which allows to increase the size of an existing 1349 * ufs file system. Currently this can only be done on unmounted file system. 1350 * It recognizes some command line options to specify the new desired size, 1351 * and it does some basic checkings. The old file system size is determined 1352 * and after some more checks like we can really access the new last block 1353 * on the disk etc. we calculate the new parameters for the superblock. After 1354 * having done this we just call growfs() which will do the work. 1355 * We still have to provide support for snapshots. Therefore we first have to 1356 * understand what data structures are always replicated in the snapshot on 1357 * creation, for all other blocks we touch during our procedure, we have to 1358 * keep the old blocks unchanged somewhere available for the snapshots. If we 1359 * are lucky, then we only have to handle our blocks to be relocated in that 1360 * way. 1361 * Also we have to consider in what order we actually update the critical 1362 * data structures of the file system to make sure, that in case of a disaster 1363 * fsck(8) is still able to restore any lost data. 1364 * The foreseen last step then will be to provide for growing even mounted 1365 * file systems. There we have to extend the mount() system call to provide 1366 * userland access to the file system locking facility. 1367 */ 1368 int 1369 main(int argc, char **argv) 1370 { 1371 DBG_FUNC("main") 1372 const char *device; 1373 const struct statfs *statfsp; 1374 uint64_t size = 0; 1375 off_t mediasize; 1376 int error, i, j, fsi, fso, ch, Nflag = 0, yflag = 0; 1377 char *p, reply[5], oldsizebuf[6], newsizebuf[6]; 1378 void *testbuf; 1379 1380 DBG_ENTER; 1381 1382 while ((ch = getopt(argc, argv, "Ns:vy")) != -1) { 1383 switch(ch) { 1384 case 'N': 1385 Nflag = 1; 1386 break; 1387 case 's': 1388 size = (off_t)strtoumax(optarg, &p, 0); 1389 if (p == NULL || *p == '\0') 1390 size *= DEV_BSIZE; 1391 else if (*p == 'b' || *p == 'B') 1392 ; /* do nothing */ 1393 else if (*p == 'k' || *p == 'K') 1394 size <<= 10; 1395 else if (*p == 'm' || *p == 'M') 1396 size <<= 20; 1397 else if (*p == 'g' || *p == 'G') 1398 size <<= 30; 1399 else if (*p == 't' || *p == 'T') { 1400 size <<= 30; 1401 size <<= 10; 1402 } else 1403 errx(1, "unknown suffix on -s argument"); 1404 break; 1405 case 'v': /* for compatibility to newfs */ 1406 break; 1407 case 'y': 1408 yflag = 1; 1409 break; 1410 case '?': 1411 /* FALLTHROUGH */ 1412 default: 1413 usage(); 1414 } 1415 } 1416 argc -= optind; 1417 argv += optind; 1418 1419 if (argc != 1) 1420 usage(); 1421 1422 /* 1423 * Now try to guess the device name. 1424 */ 1425 device = getdev(*argv); 1426 if (device == NULL) 1427 errx(1, "cannot find special device for %s", *argv); 1428 1429 statfsp = dev_to_statfs(device); 1430 1431 fsi = open(device, O_RDONLY); 1432 if (fsi < 0) 1433 err(1, "%s", device); 1434 1435 /* 1436 * Try to guess the slice size if not specified. 1437 */ 1438 if (ioctl(fsi, DIOCGMEDIASIZE, &mediasize) == -1) 1439 err(1,"DIOCGMEDIASIZE"); 1440 1441 /* 1442 * Check if that partition is suitable for growing a file system. 1443 */ 1444 if (mediasize < 1) 1445 errx(1, "partition is unavailable"); 1446 1447 /* 1448 * Read the current superblock, and take a backup. 1449 */ 1450 for (i = 0; sblock_try[i] != -1; i++) { 1451 sblockloc = sblock_try[i] / DEV_BSIZE; 1452 rdfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&(osblock), fsi); 1453 if ((osblock.fs_magic == FS_UFS1_MAGIC || 1454 (osblock.fs_magic == FS_UFS2_MAGIC && 1455 osblock.fs_sblockloc == sblock_try[i])) && 1456 osblock.fs_bsize <= MAXBSIZE && 1457 osblock.fs_bsize >= (int32_t) sizeof(struct fs)) 1458 break; 1459 } 1460 if (sblock_try[i] == -1) 1461 errx(1, "superblock not recognized"); 1462 memcpy((void *)&fsun1, (void *)&fsun2, sizeof(fsun2)); 1463 1464 DBG_OPEN("/tmp/growfs.debug"); /* already here we need a superblock */ 1465 DBG_DUMP_FS(&sblock, "old sblock"); 1466 1467 /* 1468 * Determine size to grow to. Default to the device size. 1469 */ 1470 if (size == 0) 1471 size = mediasize; 1472 else { 1473 if (size > (uint64_t)mediasize) { 1474 humanize_number(oldsizebuf, sizeof(oldsizebuf), size, 1475 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1476 humanize_number(newsizebuf, sizeof(newsizebuf), 1477 mediasize, 1478 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1479 1480 errx(1, "requested size %s is larger " 1481 "than the available %s", oldsizebuf, newsizebuf); 1482 } 1483 } 1484 1485 /* 1486 * Make sure the new size is a multiple of fs_fsize; /dev/ufssuspend 1487 * only supports fragment-aligned IO requests. 1488 */ 1489 size -= size % osblock.fs_fsize; 1490 1491 if (size <= (uint64_t)(osblock.fs_size * osblock.fs_fsize)) { 1492 humanize_number(oldsizebuf, sizeof(oldsizebuf), 1493 osblock.fs_size * osblock.fs_fsize, 1494 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1495 humanize_number(newsizebuf, sizeof(newsizebuf), size, 1496 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1497 1498 errx(1, "requested size %s is not larger than the current " 1499 "filesystem size %s", newsizebuf, oldsizebuf); 1500 } 1501 1502 sblock.fs_size = dbtofsb(&osblock, size / DEV_BSIZE); 1503 sblock.fs_providersize = dbtofsb(&osblock, mediasize / DEV_BSIZE); 1504 1505 /* 1506 * Are we really growing? 1507 */ 1508 if (osblock.fs_size >= sblock.fs_size) { 1509 errx(1, "we are not growing (%jd->%jd)", 1510 (intmax_t)osblock.fs_size, (intmax_t)sblock.fs_size); 1511 } 1512 1513 /* 1514 * Check if we find an active snapshot. 1515 */ 1516 if (yflag == 0) { 1517 for (j = 0; j < FSMAXSNAP; j++) { 1518 if (sblock.fs_snapinum[j]) { 1519 errx(1, "active snapshot found in file system; " 1520 "please remove all snapshots before " 1521 "using growfs"); 1522 } 1523 if (!sblock.fs_snapinum[j]) /* list is dense */ 1524 break; 1525 } 1526 } 1527 1528 if (yflag == 0 && Nflag == 0) { 1529 if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) 1530 printf("Device is mounted read-write; resizing will " 1531 "result in temporary write suspension for %s.\n", 1532 statfsp->f_mntonname); 1533 printf("It's strongly recommended to make a backup " 1534 "before growing the file system.\n" 1535 "OK to grow filesystem on %s", device); 1536 if (statfsp != NULL) 1537 printf(", mounted on %s,", statfsp->f_mntonname); 1538 humanize_number(oldsizebuf, sizeof(oldsizebuf), 1539 osblock.fs_size * osblock.fs_fsize, 1540 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1541 humanize_number(newsizebuf, sizeof(newsizebuf), 1542 sblock.fs_size * sblock.fs_fsize, 1543 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1544 printf(" from %s to %s? [Yes/No] ", oldsizebuf, newsizebuf); 1545 fflush(stdout); 1546 fgets(reply, (int)sizeof(reply), stdin); 1547 if (strcmp(reply, "Yes\n")){ 1548 printf("\nNothing done\n"); 1549 exit (0); 1550 } 1551 } 1552 1553 /* 1554 * Try to access our device for writing. If it's not mounted, 1555 * or mounted read-only, simply open it; otherwise, use UFS 1556 * suspension mechanism. 1557 */ 1558 if (Nflag) { 1559 fso = -1; 1560 } else { 1561 if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) { 1562 fso = open(_PATH_UFSSUSPEND, O_RDWR); 1563 if (fso == -1) 1564 err(1, "unable to open %s", _PATH_UFSSUSPEND); 1565 error = ioctl(fso, UFSSUSPEND, &statfsp->f_fsid); 1566 if (error != 0) 1567 err(1, "UFSSUSPEND"); 1568 } else { 1569 fso = open(device, O_WRONLY); 1570 if (fso < 0) 1571 err(1, "%s", device); 1572 } 1573 } 1574 1575 /* 1576 * Try to access our new last block in the file system. 1577 */ 1578 testbuf = malloc(sblock.fs_fsize); 1579 if (testbuf == NULL) 1580 err(1, "malloc"); 1581 rdfs((ufs2_daddr_t)((size - sblock.fs_fsize) / DEV_BSIZE), 1582 sblock.fs_fsize, testbuf, fsi); 1583 wtfs((ufs2_daddr_t)((size - sblock.fs_fsize) / DEV_BSIZE), 1584 sblock.fs_fsize, testbuf, fso, Nflag); 1585 free(testbuf); 1586 1587 /* 1588 * Now calculate new superblock values and check for reasonable 1589 * bound for new file system size: 1590 * fs_size: is derived from user input 1591 * fs_dsize: should get updated in the routines creating or 1592 * updating the cylinder groups on the fly 1593 * fs_cstotal: should get updated in the routines creating or 1594 * updating the cylinder groups 1595 */ 1596 1597 /* 1598 * Update the number of cylinders and cylinder groups in the file system. 1599 */ 1600 if (sblock.fs_magic == FS_UFS1_MAGIC) { 1601 sblock.fs_old_ncyl = 1602 sblock.fs_size * sblock.fs_old_nspf / sblock.fs_old_spc; 1603 if (sblock.fs_size * sblock.fs_old_nspf > 1604 sblock.fs_old_ncyl * sblock.fs_old_spc) 1605 sblock.fs_old_ncyl++; 1606 } 1607 sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg); 1608 1609 /* 1610 * Allocate last cylinder group only if there is enough room 1611 * for at least one data block. 1612 */ 1613 if (sblock.fs_size % sblock.fs_fpg != 0 && 1614 sblock.fs_size <= cgdmin(&sblock, sblock.fs_ncg - 1)) { 1615 humanize_number(oldsizebuf, sizeof(oldsizebuf), 1616 (sblock.fs_size % sblock.fs_fpg) * sblock.fs_fsize, 1617 "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 1618 warnx("no room to allocate last cylinder group; " 1619 "leaving %s unused", oldsizebuf); 1620 sblock.fs_ncg--; 1621 if (sblock.fs_magic == FS_UFS1_MAGIC) 1622 sblock.fs_old_ncyl = sblock.fs_ncg * sblock.fs_old_cpg; 1623 sblock.fs_size = sblock.fs_ncg * sblock.fs_fpg; 1624 } 1625 1626 /* 1627 * Update the space for the cylinder group summary information in the 1628 * respective cylinder group data area. 1629 */ 1630 sblock.fs_cssize = 1631 fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 1632 1633 if (osblock.fs_size >= sblock.fs_size) 1634 errx(1, "not enough new space"); 1635 1636 DBG_PRINT0("sblock calculated\n"); 1637 1638 /* 1639 * Ok, everything prepared, so now let's do the tricks. 1640 */ 1641 growfs(fsi, fso, Nflag); 1642 1643 close(fsi); 1644 if (fso > -1) { 1645 if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) { 1646 error = ioctl(fso, UFSRESUME); 1647 if (error != 0) 1648 err(1, "UFSRESUME"); 1649 } 1650 error = close(fso); 1651 if (error != 0) 1652 err(1, "close"); 1653 if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0) 1654 mount_reload(statfsp); 1655 } 1656 1657 DBG_CLOSE; 1658 1659 DBG_LEAVE; 1660 return (0); 1661 } 1662 1663 /* 1664 * Dump a line of usage. 1665 */ 1666 static void 1667 usage(void) 1668 { 1669 DBG_FUNC("usage") 1670 1671 DBG_ENTER; 1672 1673 fprintf(stderr, "usage: growfs [-Ny] [-s size] special | filesystem\n"); 1674 1675 DBG_LEAVE; 1676 exit(1); 1677 } 1678 1679 /* 1680 * This updates most parameters and the bitmap related to cluster. We have to 1681 * assume that sblock, osblock, acg are set up. 1682 */ 1683 static void 1684 updclst(int block) 1685 { 1686 DBG_FUNC("updclst") 1687 static int lcs = 0; 1688 1689 DBG_ENTER; 1690 1691 if (sblock.fs_contigsumsize < 1) /* no clustering */ 1692 return; 1693 /* 1694 * update cluster allocation map 1695 */ 1696 setbit(cg_clustersfree(&acg), block); 1697 1698 /* 1699 * update cluster summary table 1700 */ 1701 if (!lcs) { 1702 /* 1703 * calculate size for the trailing cluster 1704 */ 1705 for (block--; lcs < sblock.fs_contigsumsize; block--, lcs++ ) { 1706 if (isclr(cg_clustersfree(&acg), block)) 1707 break; 1708 } 1709 } 1710 if (lcs < sblock.fs_contigsumsize) { 1711 if (lcs) 1712 cg_clustersum(&acg)[lcs]--; 1713 lcs++; 1714 cg_clustersum(&acg)[lcs]++; 1715 } 1716 1717 DBG_LEAVE; 1718 return; 1719 } 1720 1721 static void 1722 mount_reload(const struct statfs *stfs) 1723 { 1724 char errmsg[255]; 1725 struct iovec *iov; 1726 int iovlen; 1727 1728 iov = NULL; 1729 iovlen = 0; 1730 *errmsg = '\0'; 1731 build_iovec(&iov, &iovlen, "fstype", __DECONST(char *, "ffs"), 4); 1732 build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, stfs->f_mntonname), (size_t)-1); 1733 build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); 1734 build_iovec(&iov, &iovlen, "update", NULL, 0); 1735 build_iovec(&iov, &iovlen, "reload", NULL, 0); 1736 1737 if (nmount(iov, iovlen, stfs->f_flags) < 0) { 1738 errmsg[sizeof(errmsg) - 1] = '\0'; 1739 err(9, "%s: cannot reload filesystem%s%s", stfs->f_mntonname, 1740 *errmsg != '\0' ? ": " : "", errmsg); 1741 } 1742 } 1743