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