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