1163849Spjd/*- 2163849Spjd * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3163849Spjd * All rights reserved. 4163849Spjd * 5163849Spjd * Redistribution and use in source and binary forms, with or without 6163849Spjd * modification, are permitted provided that the following conditions 7163849Spjd * are met: 8163849Spjd * 1. Redistributions of source code must retain the above copyright 9163849Spjd * notice, this list of conditions and the following disclaimer. 10163849Spjd * 2. Redistributions in binary form must reproduce the above copyright 11163849Spjd * notice, this list of conditions and the following disclaimer in the 12163849Spjd * documentation and/or other materials provided with the distribution. 13163849Spjd * 14163849Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15163849Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16163849Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17163849Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18163849Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19163849Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20163849Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21163849Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22163849Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23163849Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24163849Spjd * SUCH DAMAGE. 25163849Spjd * 26163849Spjd * Copyright (c) 1982, 1986, 1989, 1993 27163849Spjd * The Regents of the University of California. All rights reserved. 28163849Spjd * 29163849Spjd * Redistribution and use in source and binary forms, with or without 30163849Spjd * modification, are permitted provided that the following conditions 31163849Spjd * are met: 32163849Spjd * 1. Redistributions of source code must retain the above copyright 33163849Spjd * notice, this list of conditions and the following disclaimer. 34163849Spjd * 2. Redistributions in binary form must reproduce the above copyright 35163849Spjd * notice, this list of conditions and the following disclaimer in the 36163849Spjd * documentation and/or other materials provided with the distribution. 37163849Spjd * 4. Neither the name of the University nor the names of its contributors 38163849Spjd * may be used to endorse or promote products derived from this software 39163849Spjd * without specific prior written permission. 40163849Spjd * 41163849Spjd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 42163849Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43163849Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44163849Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 45163849Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46163849Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47163849Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48163849Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49163849Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50163849Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51163849Spjd * SUCH DAMAGE. 52163849Spjd */ 53163849Spjd 54163849Spjd#include <sys/cdefs.h> 55163849Spjd__FBSDID("$FreeBSD$"); 56163849Spjd 57163849Spjd#include <sys/param.h> 58163849Spjd#include <sys/disklabel.h> 59163849Spjd#include <sys/mount.h> 60163849Spjd#include <sys/stat.h> 61163849Spjd 62163849Spjd#include <ufs/ufs/ufsmount.h> 63163849Spjd#include <ufs/ufs/dinode.h> 64163849Spjd#include <ufs/ffs/fs.h> 65163849Spjd 66163849Spjd#include <stdio.h> 67163849Spjd#include <stdlib.h> 68163849Spjd#include <stdint.h> 69163849Spjd#include <libufs.h> 70163849Spjd#include <strings.h> 71163849Spjd#include <err.h> 72163849Spjd#include <assert.h> 73163849Spjd 74163849Spjd#include "fsck.h" 75163849Spjd 76163849Spjdstruct cgchain { 77163849Spjd union { 78163849Spjd struct cg cgcu_cg; 79163849Spjd char cgcu_buf[MAXBSIZE]; 80163849Spjd } cgc_union; 81163849Spjd int cgc_busy; 82163849Spjd int cgc_dirty; 83163849Spjd LIST_ENTRY(cgchain) cgc_next; 84163849Spjd}; 85163849Spjd#define cgc_cg cgc_union.cgcu_cg 86163849Spjd 87163849Spjd#define MAX_CACHED_CGS 1024 88163849Spjdstatic unsigned ncgs = 0; 89201145Santoinestatic LIST_HEAD(, cgchain) cglist = LIST_HEAD_INITIALIZER(cglist); 90163849Spjd 91163849Spjdstatic const char *devnam; 92163849Spjdstatic struct uufsd *disk = NULL; 93163849Spjdstatic struct fs *fs = NULL; 94163849Spjdstruct ufs2_dinode ufs2_zino; 95163849Spjd 96163849Spjdstatic void putcgs(void); 97163849Spjd 98163849Spjd/* 99163849Spjd * Return cylinder group from the cache or load it if it is not in the 100163849Spjd * cache yet. 101163849Spjd * Don't cache more than MAX_CACHED_CGS cylinder groups. 102163849Spjd */ 103163849Spjdstatic struct cgchain * 104163849Spjdgetcg(int cg) 105163849Spjd{ 106163849Spjd struct cgchain *cgc; 107163849Spjd 108163849Spjd assert(disk != NULL && fs != NULL); 109163849Spjd LIST_FOREACH(cgc, &cglist, cgc_next) { 110163849Spjd if (cgc->cgc_cg.cg_cgx == cg) { 111163849Spjd //printf("%s: Found cg=%d\n", __func__, cg); 112163849Spjd return (cgc); 113163849Spjd } 114163849Spjd } 115163849Spjd /* 116163849Spjd * Our cache is full? Let's clean it up. 117163849Spjd */ 118163849Spjd if (ncgs >= MAX_CACHED_CGS) { 119163849Spjd //printf("%s: Flushing CGs.\n", __func__); 120163849Spjd putcgs(); 121163849Spjd } 122163849Spjd cgc = malloc(sizeof(*cgc)); 123163849Spjd if (cgc == NULL) { 124163849Spjd /* 125163849Spjd * Cannot allocate memory? 126163849Spjd * Let's put all currently loaded and not busy cylinder groups 127163849Spjd * on disk and try again. 128163849Spjd */ 129163849Spjd //printf("%s: No memory, flushing CGs.\n", __func__); 130163849Spjd putcgs(); 131163849Spjd cgc = malloc(sizeof(*cgc)); 132163849Spjd if (cgc == NULL) 133163849Spjd err(1, "malloc(%zu)", sizeof(*cgc)); 134163849Spjd } 135163849Spjd if (cgread1(disk, cg) == -1) 136163849Spjd err(1, "cgread1(%d)", cg); 137163849Spjd bcopy(&disk->d_cg, &cgc->cgc_cg, sizeof(cgc->cgc_union)); 138163849Spjd cgc->cgc_busy = 0; 139163849Spjd cgc->cgc_dirty = 0; 140163849Spjd LIST_INSERT_HEAD(&cglist, cgc, cgc_next); 141163849Spjd ncgs++; 142163849Spjd //printf("%s: Read cg=%d\n", __func__, cg); 143163849Spjd return (cgc); 144163849Spjd} 145163849Spjd 146163849Spjd/* 147163849Spjd * Mark cylinder group as dirty - it will be written back on putcgs(). 148163849Spjd */ 149163849Spjdstatic void 150163849Spjddirtycg(struct cgchain *cgc) 151163849Spjd{ 152163849Spjd 153163849Spjd cgc->cgc_dirty = 1; 154163849Spjd} 155163849Spjd 156163849Spjd/* 157163849Spjd * Mark cylinder group as busy - it will not be freed on putcgs(). 158163849Spjd */ 159163849Spjdstatic void 160163849Spjdbusycg(struct cgchain *cgc) 161163849Spjd{ 162163849Spjd 163163849Spjd cgc->cgc_busy = 1; 164163849Spjd} 165163849Spjd 166163849Spjd/* 167163849Spjd * Unmark the given cylinder group as busy. 168163849Spjd */ 169163849Spjdstatic void 170163849Spjdunbusycg(struct cgchain *cgc) 171163849Spjd{ 172163849Spjd 173163849Spjd cgc->cgc_busy = 0; 174163849Spjd} 175163849Spjd 176163849Spjd/* 177163849Spjd * Write back all dirty cylinder groups. 178163849Spjd * Free all non-busy cylinder groups. 179163849Spjd */ 180163849Spjdstatic void 181163849Spjdputcgs(void) 182163849Spjd{ 183163849Spjd struct cgchain *cgc, *cgc2; 184163849Spjd 185163849Spjd assert(disk != NULL && fs != NULL); 186163849Spjd LIST_FOREACH_SAFE(cgc, &cglist, cgc_next, cgc2) { 187163849Spjd if (cgc->cgc_busy) 188163849Spjd continue; 189163849Spjd LIST_REMOVE(cgc, cgc_next); 190163849Spjd ncgs--; 191163849Spjd if (cgc->cgc_dirty) { 192163849Spjd bcopy(&cgc->cgc_cg, &disk->d_cg, 193163849Spjd sizeof(cgc->cgc_union)); 194163849Spjd if (cgwrite1(disk, cgc->cgc_cg.cg_cgx) == -1) 195163849Spjd err(1, "cgwrite1(%d)", cgc->cgc_cg.cg_cgx); 196163849Spjd //printf("%s: Wrote cg=%d\n", __func__, 197163849Spjd // cgc->cgc_cg.cg_cgx); 198163849Spjd } 199163849Spjd free(cgc); 200163849Spjd } 201163849Spjd} 202163849Spjd 203163849Spjd#if 0 204163849Spjd/* 205163849Spjd * Free all non-busy cylinder groups without storing the dirty ones. 206163849Spjd */ 207163849Spjdstatic void 208163849Spjdcancelcgs(void) 209163849Spjd{ 210163849Spjd struct cgchain *cgc; 211163849Spjd 212163849Spjd assert(disk != NULL && fs != NULL); 213163849Spjd while ((cgc = LIST_FIRST(&cglist)) != NULL) { 214163849Spjd if (cgc->cgc_busy) 215163849Spjd continue; 216163849Spjd LIST_REMOVE(cgc, cgc_next); 217163849Spjd //printf("%s: Canceled cg=%d\n", __func__, cgc->cgc_cg.cg_cgx); 218163849Spjd free(cgc); 219163849Spjd } 220163849Spjd} 221163849Spjd#endif 222163849Spjd 223163849Spjd/* 224207141Sjeff * Open the given provider, load superblock. 225163849Spjd */ 226163849Spjdstatic void 227207141Sjeffopendisk(void) 228163849Spjd{ 229163849Spjd if (disk != NULL) 230163849Spjd return; 231163849Spjd disk = malloc(sizeof(*disk)); 232163849Spjd if (disk == NULL) 233163849Spjd err(1, "malloc(%zu)", sizeof(*disk)); 234163849Spjd if (ufs_disk_fillout(disk, devnam) == -1) { 235163849Spjd err(1, "ufs_disk_fillout(%s) failed: %s", devnam, 236163849Spjd disk->d_error); 237163849Spjd } 238163849Spjd fs = &disk->d_fs; 239163849Spjd} 240163849Spjd 241163849Spjd/* 242163849Spjd * Mark file system as clean, write the super-block back, close the disk. 243163849Spjd */ 244163849Spjdstatic void 245163849Spjdclosedisk(void) 246163849Spjd{ 247163849Spjd 248163849Spjd fs->fs_clean = 1; 249163849Spjd if (sbwrite(disk, 0) == -1) 250163849Spjd err(1, "sbwrite(%s)", devnam); 251163849Spjd if (ufs_disk_close(disk) == -1) 252163849Spjd err(1, "ufs_disk_close(%s)", devnam); 253163849Spjd free(disk); 254163849Spjd disk = NULL; 255163849Spjd fs = NULL; 256163849Spjd} 257163849Spjd 258163849Spjdstatic void 259163849Spjdblkfree(ufs2_daddr_t bno, long size) 260163849Spjd{ 261163849Spjd struct cgchain *cgc; 262163849Spjd struct cg *cgp; 263163849Spjd ufs1_daddr_t fragno, cgbno; 264163849Spjd int i, cg, blk, frags, bbase; 265163849Spjd u_int8_t *blksfree; 266163849Spjd 267163849Spjd cg = dtog(fs, bno); 268163849Spjd cgc = getcg(cg); 269163849Spjd dirtycg(cgc); 270163849Spjd cgp = &cgc->cgc_cg; 271163849Spjd cgbno = dtogd(fs, bno); 272163849Spjd blksfree = cg_blksfree(cgp); 273163849Spjd if (size == fs->fs_bsize) { 274163849Spjd fragno = fragstoblks(fs, cgbno); 275207141Sjeff if (!ffs_isfreeblock(fs, blksfree, fragno)) 276163849Spjd assert(!"blkfree: freeing free block"); 277207141Sjeff ffs_setblock(fs, blksfree, fragno); 278207141Sjeff ffs_clusteracct(fs, cgp, fragno, 1); 279163849Spjd cgp->cg_cs.cs_nbfree++; 280163849Spjd fs->fs_cstotal.cs_nbfree++; 281163849Spjd fs->fs_cs(fs, cg).cs_nbfree++; 282163849Spjd } else { 283163849Spjd bbase = cgbno - fragnum(fs, cgbno); 284163849Spjd /* 285163849Spjd * decrement the counts associated with the old frags 286163849Spjd */ 287163849Spjd blk = blkmap(fs, blksfree, bbase); 288207141Sjeff ffs_fragacct(fs, blk, cgp->cg_frsum, -1); 289163849Spjd /* 290163849Spjd * deallocate the fragment 291163849Spjd */ 292163849Spjd frags = numfrags(fs, size); 293163849Spjd for (i = 0; i < frags; i++) { 294163849Spjd if (isset(blksfree, cgbno + i)) 295163849Spjd assert(!"blkfree: freeing free frag"); 296163849Spjd setbit(blksfree, cgbno + i); 297163849Spjd } 298163849Spjd cgp->cg_cs.cs_nffree += i; 299163849Spjd fs->fs_cstotal.cs_nffree += i; 300163849Spjd fs->fs_cs(fs, cg).cs_nffree += i; 301163849Spjd /* 302163849Spjd * add back in counts associated with the new frags 303163849Spjd */ 304163849Spjd blk = blkmap(fs, blksfree, bbase); 305207141Sjeff ffs_fragacct(fs, blk, cgp->cg_frsum, 1); 306163849Spjd /* 307163849Spjd * if a complete block has been reassembled, account for it 308163849Spjd */ 309163849Spjd fragno = fragstoblks(fs, bbase); 310207141Sjeff if (ffs_isblock(fs, blksfree, fragno)) { 311163849Spjd cgp->cg_cs.cs_nffree -= fs->fs_frag; 312163849Spjd fs->fs_cstotal.cs_nffree -= fs->fs_frag; 313163849Spjd fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 314207141Sjeff ffs_clusteracct(fs, cgp, fragno, 1); 315163849Spjd cgp->cg_cs.cs_nbfree++; 316163849Spjd fs->fs_cstotal.cs_nbfree++; 317163849Spjd fs->fs_cs(fs, cg).cs_nbfree++; 318163849Spjd } 319163849Spjd } 320163849Spjd} 321163849Spjd 322163849Spjd/* 323163849Spjd * Recursively free all indirect blocks. 324163849Spjd */ 325163849Spjdstatic void 326163849Spjdfreeindir(ufs2_daddr_t blk, int level) 327163849Spjd{ 328163849Spjd char sblks[MAXBSIZE]; 329163849Spjd ufs2_daddr_t *blks; 330163849Spjd int i; 331163849Spjd 332163849Spjd if (bread(disk, fsbtodb(fs, blk), (void *)&sblks, (size_t)fs->fs_bsize) == -1) 333163849Spjd err(1, "bread: %s", disk->d_error); 334163849Spjd blks = (ufs2_daddr_t *)&sblks; 335207141Sjeff for (i = 0; i < NINDIR(fs); i++) { 336163849Spjd if (blks[i] == 0) 337163849Spjd break; 338163849Spjd if (level == 0) 339163849Spjd blkfree(blks[i], fs->fs_bsize); 340163849Spjd else 341163849Spjd freeindir(blks[i], level - 1); 342163849Spjd } 343163849Spjd blkfree(blk, fs->fs_bsize); 344163849Spjd} 345163849Spjd 346163849Spjd#define dblksize(fs, dino, lbn) \ 347163849Spjd ((dino)->di_size >= smalllblktosize(fs, (lbn) + 1) \ 348163849Spjd ? (fs)->fs_bsize \ 349163849Spjd : fragroundup(fs, blkoff(fs, (dino)->di_size))) 350163849Spjd 351163849Spjd/* 352163849Spjd * Free all blocks associated with the given inode. 353163849Spjd */ 354163849Spjdstatic void 355163849Spjdclear_inode(struct ufs2_dinode *dino) 356163849Spjd{ 357163849Spjd ufs2_daddr_t bn; 358163849Spjd int extblocks, i, level; 359163849Spjd off_t osize; 360163849Spjd long bsize; 361163849Spjd 362163849Spjd extblocks = 0; 363163849Spjd if (fs->fs_magic == FS_UFS2_MAGIC && dino->di_extsize > 0) 364163849Spjd extblocks = btodb(fragroundup(fs, dino->di_extsize)); 365163849Spjd /* deallocate external attributes blocks */ 366163849Spjd if (extblocks > 0) { 367163849Spjd osize = dino->di_extsize; 368163849Spjd dino->di_blocks -= extblocks; 369163849Spjd dino->di_extsize = 0; 370163849Spjd for (i = 0; i < NXADDR; i++) { 371163849Spjd if (dino->di_extb[i] == 0) 372163849Spjd continue; 373163849Spjd blkfree(dino->di_extb[i], sblksize(fs, osize, i)); 374163849Spjd } 375163849Spjd } 376163849Spjd#define SINGLE 0 /* index of single indirect block */ 377163849Spjd#define DOUBLE 1 /* index of double indirect block */ 378163849Spjd#define TRIPLE 2 /* index of triple indirect block */ 379163849Spjd /* deallocate indirect blocks */ 380163849Spjd for (level = SINGLE; level <= TRIPLE; level++) { 381163849Spjd if (dino->di_ib[level] == 0) 382163849Spjd break; 383163849Spjd freeindir(dino->di_ib[level], level); 384163849Spjd } 385163849Spjd /* deallocate direct blocks and fragments */ 386163849Spjd for (i = 0; i < NDADDR; i++) { 387163849Spjd bn = dino->di_db[i]; 388163849Spjd if (bn == 0) 389163849Spjd continue; 390163849Spjd bsize = dblksize(fs, dino, i); 391163849Spjd blkfree(bn, bsize); 392163849Spjd } 393163849Spjd} 394163849Spjd 395163849Spjdvoid 396163849Spjdgjournal_check(const char *filesys) 397163849Spjd{ 398163849Spjd struct ufs2_dinode *dino; 399163866Sru void *p; 400163849Spjd struct cgchain *cgc; 401163849Spjd struct cg *cgp; 402229918Seadler uint8_t *inosused; 403163849Spjd ino_t cino, ino; 404163849Spjd int cg, mode; 405163849Spjd 406163849Spjd devnam = filesys; 407207141Sjeff opendisk(); 408193372Spjd /* Are there any unreferenced inodes in this file system? */ 409163849Spjd if (fs->fs_unrefs == 0) { 410163849Spjd //printf("No unreferenced inodes.\n"); 411163849Spjd closedisk(); 412163849Spjd return; 413163849Spjd } 414163849Spjd 415163849Spjd for (cg = 0; cg < fs->fs_ncg; cg++) { 416163849Spjd /* Show progress if requested. */ 417163849Spjd if (got_siginfo) { 418163849Spjd printf("%s: phase j: cyl group %d of %d (%d%%)\n", 419163849Spjd cdevname, cg, fs->fs_ncg, cg * 100 / fs->fs_ncg); 420163849Spjd got_siginfo = 0; 421163849Spjd } 422163849Spjd if (got_sigalarm) { 423163849Spjd setproctitle("%s pj %d%%", cdevname, 424163849Spjd cg * 100 / fs->fs_ncg); 425163849Spjd got_sigalarm = 0; 426163849Spjd } 427163849Spjd cgc = getcg(cg); 428163849Spjd cgp = &cgc->cgc_cg; 429163849Spjd /* Are there any unreferenced inodes in this cylinder group? */ 430163849Spjd if (cgp->cg_unrefs == 0) 431163849Spjd continue; 432163849Spjd //printf("Analizing cylinder group %d (count=%d)\n", cg, cgp->cg_unrefs); 433163849Spjd /* 434163849Spjd * We are going to modify this cylinder group, so we want it to 435163849Spjd * be written back. 436163849Spjd */ 437163849Spjd dirtycg(cgc); 438163849Spjd /* We don't want it to be freed in the meantime. */ 439163849Spjd busycg(cgc); 440163849Spjd inosused = cg_inosused(cgp); 441163849Spjd /* 442163849Spjd * Now go through the list of all inodes in this cylinder group 443163849Spjd * to find unreferenced ones. 444163849Spjd */ 445163849Spjd for (cino = 0; cino < fs->fs_ipg; cino++) { 446163849Spjd ino = fs->fs_ipg * cg + cino; 447163849Spjd /* Unallocated? Skip it. */ 448163849Spjd if (isclr(inosused, cino)) 449163849Spjd continue; 450163866Sru if (getino(disk, &p, ino, &mode) == -1) 451241012Smdf err(1, "getino(cg=%d ino=%ju)", 452241012Smdf cg, (uintmax_t)ino); 453163866Sru dino = p; 454163849Spjd /* Not a regular file nor directory? Skip it. */ 455163849Spjd if (!S_ISREG(dino->di_mode) && !S_ISDIR(dino->di_mode)) 456163849Spjd continue; 457163849Spjd /* Has reference(s)? Skip it. */ 458163849Spjd if (dino->di_nlink > 0) 459163849Spjd continue; 460163849Spjd //printf("Clearing inode=%d (size=%jd)\n", ino, (intmax_t)dino->di_size); 461163849Spjd /* Free inode's blocks. */ 462163849Spjd clear_inode(dino); 463163849Spjd /* Deallocate it. */ 464163849Spjd clrbit(inosused, cino); 465163849Spjd /* Update position of last used inode. */ 466163849Spjd if (ino < cgp->cg_irotor) 467163849Spjd cgp->cg_irotor = ino; 468163849Spjd /* Update statistics. */ 469163849Spjd cgp->cg_cs.cs_nifree++; 470163849Spjd fs->fs_cs(fs, cg).cs_nifree++; 471163849Spjd fs->fs_cstotal.cs_nifree++; 472163849Spjd cgp->cg_unrefs--; 473163849Spjd fs->fs_unrefs--; 474163849Spjd /* If this is directory, update related statistics. */ 475163849Spjd if (S_ISDIR(dino->di_mode)) { 476163849Spjd cgp->cg_cs.cs_ndir--; 477163849Spjd fs->fs_cs(fs, cg).cs_ndir--; 478163849Spjd fs->fs_cstotal.cs_ndir--; 479163849Spjd } 480163849Spjd /* Zero-fill the inode. */ 481163849Spjd *dino = ufs2_zino; 482163849Spjd /* Write the inode back. */ 483207141Sjeff if (putino(disk) == -1) 484241012Smdf err(1, "putino(cg=%d ino=%ju)", 485241012Smdf cg, (uintmax_t)ino); 486163849Spjd if (cgp->cg_unrefs == 0) { 487163849Spjd //printf("No more unreferenced inodes in cg=%d.\n", cg); 488163849Spjd break; 489163849Spjd } 490163849Spjd } 491163849Spjd /* 492163849Spjd * We don't need this cylinder group anymore, so feel free to 493163849Spjd * free it if needed. 494163849Spjd */ 495163849Spjd unbusycg(cgc); 496163849Spjd /* 497163849Spjd * If there are no more unreferenced inodes, there is no need to 498163849Spjd * check other cylinder groups. 499163849Spjd */ 500163849Spjd if (fs->fs_unrefs == 0) { 501163849Spjd //printf("No more unreferenced inodes (cg=%d/%d).\n", cg, 502163849Spjd // fs->fs_ncg); 503163849Spjd break; 504163849Spjd } 505163849Spjd } 506163849Spjd /* Write back modified cylinder groups. */ 507163849Spjd putcgs(); 508163849Spjd /* Write back updated statistics and super-block. */ 509207141Sjeff closedisk(); 510163849Spjd} 511