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