1 /*- 2 * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * Copyright (c) 1982, 1986, 1989, 1993 27 * The Regents of the University of California. All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 2. Redistributions in binary form must reproduce the above copyright 35 * notice, this list of conditions and the following disclaimer in the 36 * documentation and/or other materials provided with the distribution. 37 * 4. Neither the name of the University nor the names of its contributors 38 * may be used to endorse or promote products derived from this software 39 * without specific prior written permission. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 */ 53 54 #include <sys/cdefs.h> 55 __FBSDID("$FreeBSD$"); 56 57 #include <sys/param.h> 58 #include <sys/disklabel.h> 59 #include <sys/mount.h> 60 #include <sys/stat.h> 61 62 #include <ufs/ufs/ufsmount.h> 63 #include <ufs/ufs/dinode.h> 64 #include <ufs/ffs/fs.h> 65 66 #include <stdio.h> 67 #include <stdlib.h> 68 #include <stdint.h> 69 #include <libufs.h> 70 #include <strings.h> 71 #include <err.h> 72 #include <assert.h> 73 74 #include "fsck.h" 75 76 struct cgchain { 77 union { 78 struct cg cgcu_cg; 79 char cgcu_buf[MAXBSIZE]; 80 } cgc_union; 81 int cgc_busy; 82 int cgc_dirty; 83 LIST_ENTRY(cgchain) cgc_next; 84 }; 85 #define cgc_cg cgc_union.cgcu_cg 86 87 #define MAX_CACHED_CGS 1024 88 static unsigned ncgs = 0; 89 static LIST_HEAD(, cgchain) cglist = LIST_HEAD_INITIALIZER(&cglist); 90 91 static const char *devnam; 92 static struct uufsd *disk = NULL; 93 static struct fs *fs = NULL; 94 struct ufs2_dinode ufs2_zino; 95 96 static void putcgs(void); 97 98 /* 99 * Write current block of inodes. 100 */ 101 static int 102 putino(struct uufsd *disk, ino_t inode) 103 { 104 caddr_t inoblock; 105 struct fs *fs; 106 ssize_t ret; 107 108 fs = &disk->d_fs; 109 inoblock = disk->d_inoblock; 110 111 assert(inoblock != NULL); 112 assert(inode >= disk->d_inomin && inode <= disk->d_inomax); 113 ret = bwrite(disk, fsbtodb(fs, ino_to_fsba(fs, inode)), inoblock, 114 fs->fs_bsize); 115 116 return (ret == -1 ? -1 : 0); 117 } 118 119 /* 120 * Return cylinder group from the cache or load it if it is not in the 121 * cache yet. 122 * Don't cache more than MAX_CACHED_CGS cylinder groups. 123 */ 124 static struct cgchain * 125 getcg(int cg) 126 { 127 struct cgchain *cgc; 128 129 assert(disk != NULL && fs != NULL); 130 LIST_FOREACH(cgc, &cglist, cgc_next) { 131 if (cgc->cgc_cg.cg_cgx == cg) { 132 //printf("%s: Found cg=%d\n", __func__, cg); 133 return (cgc); 134 } 135 } 136 /* 137 * Our cache is full? Let's clean it up. 138 */ 139 if (ncgs >= MAX_CACHED_CGS) { 140 //printf("%s: Flushing CGs.\n", __func__); 141 putcgs(); 142 } 143 cgc = malloc(sizeof(*cgc)); 144 if (cgc == NULL) { 145 /* 146 * Cannot allocate memory? 147 * Let's put all currently loaded and not busy cylinder groups 148 * on disk and try again. 149 */ 150 //printf("%s: No memory, flushing CGs.\n", __func__); 151 putcgs(); 152 cgc = malloc(sizeof(*cgc)); 153 if (cgc == NULL) 154 err(1, "malloc(%zu)", sizeof(*cgc)); 155 } 156 if (cgread1(disk, cg) == -1) 157 err(1, "cgread1(%d)", cg); 158 bcopy(&disk->d_cg, &cgc->cgc_cg, sizeof(cgc->cgc_union)); 159 cgc->cgc_busy = 0; 160 cgc->cgc_dirty = 0; 161 LIST_INSERT_HEAD(&cglist, cgc, cgc_next); 162 ncgs++; 163 //printf("%s: Read cg=%d\n", __func__, cg); 164 return (cgc); 165 } 166 167 /* 168 * Mark cylinder group as dirty - it will be written back on putcgs(). 169 */ 170 static void 171 dirtycg(struct cgchain *cgc) 172 { 173 174 cgc->cgc_dirty = 1; 175 } 176 177 /* 178 * Mark cylinder group as busy - it will not be freed on putcgs(). 179 */ 180 static void 181 busycg(struct cgchain *cgc) 182 { 183 184 cgc->cgc_busy = 1; 185 } 186 187 /* 188 * Unmark the given cylinder group as busy. 189 */ 190 static void 191 unbusycg(struct cgchain *cgc) 192 { 193 194 cgc->cgc_busy = 0; 195 } 196 197 /* 198 * Write back all dirty cylinder groups. 199 * Free all non-busy cylinder groups. 200 */ 201 static void 202 putcgs(void) 203 { 204 struct cgchain *cgc, *cgc2; 205 206 assert(disk != NULL && fs != NULL); 207 LIST_FOREACH_SAFE(cgc, &cglist, cgc_next, cgc2) { 208 if (cgc->cgc_busy) 209 continue; 210 LIST_REMOVE(cgc, cgc_next); 211 ncgs--; 212 if (cgc->cgc_dirty) { 213 bcopy(&cgc->cgc_cg, &disk->d_cg, 214 sizeof(cgc->cgc_union)); 215 if (cgwrite1(disk, cgc->cgc_cg.cg_cgx) == -1) 216 err(1, "cgwrite1(%d)", cgc->cgc_cg.cg_cgx); 217 //printf("%s: Wrote cg=%d\n", __func__, 218 // cgc->cgc_cg.cg_cgx); 219 } 220 free(cgc); 221 } 222 } 223 224 #if 0 225 /* 226 * Free all non-busy cylinder groups without storing the dirty ones. 227 */ 228 static void 229 cancelcgs(void) 230 { 231 struct cgchain *cgc; 232 233 assert(disk != NULL && fs != NULL); 234 while ((cgc = LIST_FIRST(&cglist)) != NULL) { 235 if (cgc->cgc_busy) 236 continue; 237 LIST_REMOVE(cgc, cgc_next); 238 //printf("%s: Canceled cg=%d\n", __func__, cgc->cgc_cg.cg_cgx); 239 free(cgc); 240 } 241 } 242 #endif 243 244 /* 245 * Open the given provider, load statistics. 246 */ 247 static void 248 getdisk(void) 249 { 250 int i; 251 252 if (disk != NULL) 253 return; 254 disk = malloc(sizeof(*disk)); 255 if (disk == NULL) 256 err(1, "malloc(%zu)", sizeof(*disk)); 257 if (ufs_disk_fillout(disk, devnam) == -1) { 258 err(1, "ufs_disk_fillout(%s) failed: %s", devnam, 259 disk->d_error); 260 } 261 fs = &disk->d_fs; 262 fs->fs_csp = malloc((size_t)fs->fs_cssize); 263 if (fs->fs_csp == NULL) 264 err(1, "malloc(%zu)", (size_t)fs->fs_cssize); 265 bzero(fs->fs_csp, (size_t)fs->fs_cssize); 266 for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) { 267 if (bread(disk, fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)), 268 (void *)(((char *)fs->fs_csp) + i), 269 (size_t)(fs->fs_cssize - i < fs->fs_bsize ? fs->fs_cssize - i : fs->fs_bsize)) == -1) { 270 err(1, "bread: %s", disk->d_error); 271 } 272 } 273 if (fs->fs_contigsumsize > 0) { 274 fs->fs_maxcluster = malloc(fs->fs_ncg * sizeof(int32_t)); 275 if (fs->fs_maxcluster == NULL) 276 err(1, "malloc(%zu)", fs->fs_ncg * sizeof(int32_t)); 277 for (i = 0; i < fs->fs_ncg; i++) 278 fs->fs_maxcluster[i] = fs->fs_contigsumsize; 279 } 280 } 281 282 /* 283 * Mark file system as clean, write the super-block back, close the disk. 284 */ 285 static void 286 closedisk(void) 287 { 288 289 free(fs->fs_csp); 290 if (fs->fs_contigsumsize > 0) { 291 free(fs->fs_maxcluster); 292 fs->fs_maxcluster = NULL; 293 } 294 fs->fs_clean = 1; 295 if (sbwrite(disk, 0) == -1) 296 err(1, "sbwrite(%s)", devnam); 297 if (ufs_disk_close(disk) == -1) 298 err(1, "ufs_disk_close(%s)", devnam); 299 free(disk); 300 disk = NULL; 301 fs = NULL; 302 } 303 304 /* 305 * Write the statistics back, call closedisk(). 306 */ 307 static void 308 putdisk(void) 309 { 310 int i; 311 312 assert(disk != NULL && fs != NULL); 313 for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) { 314 if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)), 315 (void *)(((char *)fs->fs_csp) + i), 316 (size_t)(fs->fs_cssize - i < fs->fs_bsize ? fs->fs_cssize - i : fs->fs_bsize)) == -1) { 317 err(1, "bwrite: %s", disk->d_error); 318 } 319 } 320 closedisk(); 321 } 322 323 #if 0 324 /* 325 * Free memory, close the disk, but don't write anything back. 326 */ 327 static void 328 canceldisk(void) 329 { 330 int i; 331 332 assert(disk != NULL && fs != NULL); 333 free(fs->fs_csp); 334 if (fs->fs_contigsumsize > 0) 335 free(fs->fs_maxcluster); 336 if (ufs_disk_close(disk) == -1) 337 err(1, "ufs_disk_close(%s)", devnam); 338 free(disk); 339 disk = NULL; 340 fs = NULL; 341 } 342 #endif 343 344 static int 345 isblock(unsigned char *cp, ufs1_daddr_t h) 346 { 347 unsigned char mask; 348 349 switch ((int)fs->fs_frag) { 350 case 8: 351 return (cp[h] == 0xff); 352 case 4: 353 mask = 0x0f << ((h & 0x1) << 2); 354 return ((cp[h >> 1] & mask) == mask); 355 case 2: 356 mask = 0x03 << ((h & 0x3) << 1); 357 return ((cp[h >> 2] & mask) == mask); 358 case 1: 359 mask = 0x01 << (h & 0x7); 360 return ((cp[h >> 3] & mask) == mask); 361 default: 362 assert(!"isblock: invalid number of fragments"); 363 } 364 return (0); 365 } 366 367 /* 368 * put a block into the map 369 */ 370 static void 371 setblock(unsigned char *cp, ufs1_daddr_t h) 372 { 373 374 switch ((int)fs->fs_frag) { 375 case 8: 376 cp[h] = 0xff; 377 return; 378 case 4: 379 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 380 return; 381 case 2: 382 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 383 return; 384 case 1: 385 cp[h >> 3] |= (0x01 << (h & 0x7)); 386 return; 387 default: 388 assert(!"setblock: invalid number of fragments"); 389 } 390 } 391 392 /* 393 * check if a block is free 394 */ 395 static int 396 isfreeblock(u_char *cp, ufs1_daddr_t h) 397 { 398 399 switch ((int)fs->fs_frag) { 400 case 8: 401 return (cp[h] == 0); 402 case 4: 403 return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0); 404 case 2: 405 return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0); 406 case 1: 407 return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0); 408 default: 409 assert(!"isfreeblock: invalid number of fragments"); 410 } 411 return (0); 412 } 413 414 /* 415 * Update the frsum fields to reflect addition or deletion 416 * of some frags. 417 */ 418 void 419 fragacct(int fragmap, int32_t fraglist[], int cnt) 420 { 421 int inblk; 422 int field, subfield; 423 int siz, pos; 424 425 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 426 fragmap <<= 1; 427 for (siz = 1; siz < fs->fs_frag; siz++) { 428 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 429 continue; 430 field = around[siz]; 431 subfield = inside[siz]; 432 for (pos = siz; pos <= fs->fs_frag; pos++) { 433 if ((fragmap & field) == subfield) { 434 fraglist[siz] += cnt; 435 pos += siz; 436 field <<= siz; 437 subfield <<= siz; 438 } 439 field <<= 1; 440 subfield <<= 1; 441 } 442 } 443 } 444 445 static void 446 clusteracct(struct cg *cgp, ufs1_daddr_t blkno) 447 { 448 int32_t *sump; 449 int32_t *lp; 450 u_char *freemapp, *mapp; 451 int i, start, end, forw, back, map, bit; 452 453 if (fs->fs_contigsumsize <= 0) 454 return; 455 freemapp = cg_clustersfree(cgp); 456 sump = cg_clustersum(cgp); 457 /* 458 * Clear the actual block. 459 */ 460 setbit(freemapp, blkno); 461 /* 462 * Find the size of the cluster going forward. 463 */ 464 start = blkno + 1; 465 end = start + fs->fs_contigsumsize; 466 if (end >= cgp->cg_nclusterblks) 467 end = cgp->cg_nclusterblks; 468 mapp = &freemapp[start / NBBY]; 469 map = *mapp++; 470 bit = 1 << (start % NBBY); 471 for (i = start; i < end; i++) { 472 if ((map & bit) == 0) 473 break; 474 if ((i & (NBBY - 1)) != (NBBY - 1)) { 475 bit <<= 1; 476 } else { 477 map = *mapp++; 478 bit = 1; 479 } 480 } 481 forw = i - start; 482 /* 483 * Find the size of the cluster going backward. 484 */ 485 start = blkno - 1; 486 end = start - fs->fs_contigsumsize; 487 if (end < 0) 488 end = -1; 489 mapp = &freemapp[start / NBBY]; 490 map = *mapp--; 491 bit = 1 << (start % NBBY); 492 for (i = start; i > end; i--) { 493 if ((map & bit) == 0) 494 break; 495 if ((i & (NBBY - 1)) != 0) { 496 bit >>= 1; 497 } else { 498 map = *mapp--; 499 bit = 1 << (NBBY - 1); 500 } 501 } 502 back = start - i; 503 /* 504 * Account for old cluster and the possibly new forward and 505 * back clusters. 506 */ 507 i = back + forw + 1; 508 if (i > fs->fs_contigsumsize) 509 i = fs->fs_contigsumsize; 510 sump[i]++; 511 if (back > 0) 512 sump[back]--; 513 if (forw > 0) 514 sump[forw]--; 515 /* 516 * Update cluster summary information. 517 */ 518 lp = &sump[fs->fs_contigsumsize]; 519 for (i = fs->fs_contigsumsize; i > 0; i--) 520 if (*lp-- > 0) 521 break; 522 fs->fs_maxcluster[cgp->cg_cgx] = i; 523 } 524 525 static void 526 blkfree(ufs2_daddr_t bno, long size) 527 { 528 struct cgchain *cgc; 529 struct cg *cgp; 530 ufs1_daddr_t fragno, cgbno; 531 int i, cg, blk, frags, bbase; 532 u_int8_t *blksfree; 533 534 cg = dtog(fs, bno); 535 cgc = getcg(cg); 536 dirtycg(cgc); 537 cgp = &cgc->cgc_cg; 538 cgbno = dtogd(fs, bno); 539 blksfree = cg_blksfree(cgp); 540 if (size == fs->fs_bsize) { 541 fragno = fragstoblks(fs, cgbno); 542 if (!isfreeblock(blksfree, fragno)) 543 assert(!"blkfree: freeing free block"); 544 setblock(blksfree, fragno); 545 clusteracct(cgp, fragno); 546 cgp->cg_cs.cs_nbfree++; 547 fs->fs_cstotal.cs_nbfree++; 548 fs->fs_cs(fs, cg).cs_nbfree++; 549 } else { 550 bbase = cgbno - fragnum(fs, cgbno); 551 /* 552 * decrement the counts associated with the old frags 553 */ 554 blk = blkmap(fs, blksfree, bbase); 555 fragacct(blk, cgp->cg_frsum, -1); 556 /* 557 * deallocate the fragment 558 */ 559 frags = numfrags(fs, size); 560 for (i = 0; i < frags; i++) { 561 if (isset(blksfree, cgbno + i)) 562 assert(!"blkfree: freeing free frag"); 563 setbit(blksfree, cgbno + i); 564 } 565 cgp->cg_cs.cs_nffree += i; 566 fs->fs_cstotal.cs_nffree += i; 567 fs->fs_cs(fs, cg).cs_nffree += i; 568 /* 569 * add back in counts associated with the new frags 570 */ 571 blk = blkmap(fs, blksfree, bbase); 572 fragacct(blk, cgp->cg_frsum, 1); 573 /* 574 * if a complete block has been reassembled, account for it 575 */ 576 fragno = fragstoblks(fs, bbase); 577 if (isblock(blksfree, fragno)) { 578 cgp->cg_cs.cs_nffree -= fs->fs_frag; 579 fs->fs_cstotal.cs_nffree -= fs->fs_frag; 580 fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 581 clusteracct(cgp, fragno); 582 cgp->cg_cs.cs_nbfree++; 583 fs->fs_cstotal.cs_nbfree++; 584 fs->fs_cs(fs, cg).cs_nbfree++; 585 } 586 } 587 } 588 589 /* 590 * Recursively free all indirect blocks. 591 */ 592 static void 593 freeindir(ufs2_daddr_t blk, int level) 594 { 595 char sblks[MAXBSIZE]; 596 ufs2_daddr_t *blks; 597 int i; 598 599 if (bread(disk, fsbtodb(fs, blk), (void *)&sblks, (size_t)fs->fs_bsize) == -1) 600 err(1, "bread: %s", disk->d_error); 601 blks = (ufs2_daddr_t *)&sblks; 602 for (i = 0; i < howmany(fs->fs_bsize, sizeof(ufs2_daddr_t)); i++) { 603 if (blks[i] == 0) 604 break; 605 if (level == 0) 606 blkfree(blks[i], fs->fs_bsize); 607 else 608 freeindir(blks[i], level - 1); 609 } 610 blkfree(blk, fs->fs_bsize); 611 } 612 613 #define dblksize(fs, dino, lbn) \ 614 ((dino)->di_size >= smalllblktosize(fs, (lbn) + 1) \ 615 ? (fs)->fs_bsize \ 616 : fragroundup(fs, blkoff(fs, (dino)->di_size))) 617 618 /* 619 * Free all blocks associated with the given inode. 620 */ 621 static void 622 clear_inode(struct ufs2_dinode *dino) 623 { 624 ufs2_daddr_t bn; 625 int extblocks, i, level; 626 off_t osize; 627 long bsize; 628 629 extblocks = 0; 630 if (fs->fs_magic == FS_UFS2_MAGIC && dino->di_extsize > 0) 631 extblocks = btodb(fragroundup(fs, dino->di_extsize)); 632 /* deallocate external attributes blocks */ 633 if (extblocks > 0) { 634 osize = dino->di_extsize; 635 dino->di_blocks -= extblocks; 636 dino->di_extsize = 0; 637 for (i = 0; i < NXADDR; i++) { 638 if (dino->di_extb[i] == 0) 639 continue; 640 blkfree(dino->di_extb[i], sblksize(fs, osize, i)); 641 } 642 } 643 #define SINGLE 0 /* index of single indirect block */ 644 #define DOUBLE 1 /* index of double indirect block */ 645 #define TRIPLE 2 /* index of triple indirect block */ 646 /* deallocate indirect blocks */ 647 for (level = SINGLE; level <= TRIPLE; level++) { 648 if (dino->di_ib[level] == 0) 649 break; 650 freeindir(dino->di_ib[level], level); 651 } 652 /* deallocate direct blocks and fragments */ 653 for (i = 0; i < NDADDR; i++) { 654 bn = dino->di_db[i]; 655 if (bn == 0) 656 continue; 657 bsize = dblksize(fs, dino, i); 658 blkfree(bn, bsize); 659 } 660 } 661 662 void 663 gjournal_check(const char *filesys) 664 { 665 struct ufs2_dinode *dino; 666 void *p; 667 struct cgchain *cgc; 668 struct cg *cgp; 669 uint8_t *inosused, *blksfree; 670 ino_t cino, ino; 671 int cg, mode; 672 673 devnam = filesys; 674 getdisk(); 675 /* Are there any unreferenced inodes in this cylinder group? */ 676 if (fs->fs_unrefs == 0) { 677 //printf("No unreferenced inodes.\n"); 678 closedisk(); 679 return; 680 } 681 682 for (cg = 0; cg < fs->fs_ncg; cg++) { 683 /* Show progress if requested. */ 684 if (got_siginfo) { 685 printf("%s: phase j: cyl group %d of %d (%d%%)\n", 686 cdevname, cg, fs->fs_ncg, cg * 100 / fs->fs_ncg); 687 got_siginfo = 0; 688 } 689 if (got_sigalarm) { 690 setproctitle("%s pj %d%%", cdevname, 691 cg * 100 / fs->fs_ncg); 692 got_sigalarm = 0; 693 } 694 cgc = getcg(cg); 695 cgp = &cgc->cgc_cg; 696 /* Are there any unreferenced inodes in this cylinder group? */ 697 if (cgp->cg_unrefs == 0) 698 continue; 699 //printf("Analizing cylinder group %d (count=%d)\n", cg, cgp->cg_unrefs); 700 /* 701 * We are going to modify this cylinder group, so we want it to 702 * be written back. 703 */ 704 dirtycg(cgc); 705 /* We don't want it to be freed in the meantime. */ 706 busycg(cgc); 707 inosused = cg_inosused(cgp); 708 blksfree = cg_blksfree(cgp); 709 /* 710 * Now go through the list of all inodes in this cylinder group 711 * to find unreferenced ones. 712 */ 713 for (cino = 0; cino < fs->fs_ipg; cino++) { 714 ino = fs->fs_ipg * cg + cino; 715 /* Unallocated? Skip it. */ 716 if (isclr(inosused, cino)) 717 continue; 718 if (getino(disk, &p, ino, &mode) == -1) 719 err(1, "getino(cg=%d ino=%d)", cg, ino); 720 dino = p; 721 /* Not a regular file nor directory? Skip it. */ 722 if (!S_ISREG(dino->di_mode) && !S_ISDIR(dino->di_mode)) 723 continue; 724 /* Has reference(s)? Skip it. */ 725 if (dino->di_nlink > 0) 726 continue; 727 //printf("Clearing inode=%d (size=%jd)\n", ino, (intmax_t)dino->di_size); 728 /* Free inode's blocks. */ 729 clear_inode(dino); 730 /* Deallocate it. */ 731 clrbit(inosused, cino); 732 /* Update position of last used inode. */ 733 if (ino < cgp->cg_irotor) 734 cgp->cg_irotor = ino; 735 /* Update statistics. */ 736 cgp->cg_cs.cs_nifree++; 737 fs->fs_cs(fs, cg).cs_nifree++; 738 fs->fs_cstotal.cs_nifree++; 739 cgp->cg_unrefs--; 740 fs->fs_unrefs--; 741 /* If this is directory, update related statistics. */ 742 if (S_ISDIR(dino->di_mode)) { 743 cgp->cg_cs.cs_ndir--; 744 fs->fs_cs(fs, cg).cs_ndir--; 745 fs->fs_cstotal.cs_ndir--; 746 } 747 /* Zero-fill the inode. */ 748 *dino = ufs2_zino; 749 /* Write the inode back. */ 750 if (putino(disk, ino) == -1) 751 err(1, "putino(cg=%d ino=%d)", cg, ino); 752 if (cgp->cg_unrefs == 0) { 753 //printf("No more unreferenced inodes in cg=%d.\n", cg); 754 break; 755 } 756 } 757 /* 758 * We don't need this cylinder group anymore, so feel free to 759 * free it if needed. 760 */ 761 unbusycg(cgc); 762 /* 763 * If there are no more unreferenced inodes, there is no need to 764 * check other cylinder groups. 765 */ 766 if (fs->fs_unrefs == 0) { 767 //printf("No more unreferenced inodes (cg=%d/%d).\n", cg, 768 // fs->fs_ncg); 769 break; 770 } 771 } 772 /* Write back modified cylinder groups. */ 773 putcgs(); 774 /* Write back updated statistics and super-block. */ 775 putdisk(); 776 } 777