gjournal.c revision 163849
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: head/sbin/fsck_ffs/gjournal.c 163849 2006-10-31 22:21:01Z pjd $"); 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; 89163849Spjdstatic 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 * Write current block of inodes. 100163849Spjd */ 101163849Spjdstatic int 102163849Spjdputino(struct uufsd *disk, ino_t inode) 103163849Spjd{ 104163849Spjd caddr_t inoblock; 105163849Spjd struct fs *fs; 106163849Spjd ssize_t ret; 107163849Spjd 108163849Spjd fs = &disk->d_fs; 109163849Spjd inoblock = disk->d_inoblock; 110163849Spjd 111163849Spjd assert(inoblock != NULL); 112163849Spjd assert(inode >= disk->d_inomin && inode <= disk->d_inomax); 113163849Spjd ret = bwrite(disk, fsbtodb(fs, ino_to_fsba(fs, inode)), inoblock, 114163849Spjd fs->fs_bsize); 115163849Spjd 116163849Spjd return (ret == -1 ? -1 : 0); 117163849Spjd} 118163849Spjd 119163849Spjd/* 120163849Spjd * Return cylinder group from the cache or load it if it is not in the 121163849Spjd * cache yet. 122163849Spjd * Don't cache more than MAX_CACHED_CGS cylinder groups. 123163849Spjd */ 124163849Spjdstatic struct cgchain * 125163849Spjdgetcg(int cg) 126163849Spjd{ 127163849Spjd struct cgchain *cgc; 128163849Spjd 129163849Spjd assert(disk != NULL && fs != NULL); 130163849Spjd LIST_FOREACH(cgc, &cglist, cgc_next) { 131163849Spjd if (cgc->cgc_cg.cg_cgx == cg) { 132163849Spjd //printf("%s: Found cg=%d\n", __func__, cg); 133163849Spjd return (cgc); 134163849Spjd } 135163849Spjd } 136163849Spjd /* 137163849Spjd * Our cache is full? Let's clean it up. 138163849Spjd */ 139163849Spjd if (ncgs >= MAX_CACHED_CGS) { 140163849Spjd //printf("%s: Flushing CGs.\n", __func__); 141163849Spjd putcgs(); 142163849Spjd } 143163849Spjd cgc = malloc(sizeof(*cgc)); 144163849Spjd if (cgc == NULL) { 145163849Spjd /* 146163849Spjd * Cannot allocate memory? 147163849Spjd * Let's put all currently loaded and not busy cylinder groups 148163849Spjd * on disk and try again. 149163849Spjd */ 150163849Spjd //printf("%s: No memory, flushing CGs.\n", __func__); 151163849Spjd putcgs(); 152163849Spjd cgc = malloc(sizeof(*cgc)); 153163849Spjd if (cgc == NULL) 154163849Spjd err(1, "malloc(%zu)", sizeof(*cgc)); 155163849Spjd } 156163849Spjd if (cgread1(disk, cg) == -1) 157163849Spjd err(1, "cgread1(%d)", cg); 158163849Spjd bcopy(&disk->d_cg, &cgc->cgc_cg, sizeof(cgc->cgc_union)); 159163849Spjd cgc->cgc_busy = 0; 160163849Spjd cgc->cgc_dirty = 0; 161163849Spjd LIST_INSERT_HEAD(&cglist, cgc, cgc_next); 162163849Spjd ncgs++; 163163849Spjd //printf("%s: Read cg=%d\n", __func__, cg); 164163849Spjd return (cgc); 165163849Spjd} 166163849Spjd 167163849Spjd/* 168163849Spjd * Mark cylinder group as dirty - it will be written back on putcgs(). 169163849Spjd */ 170163849Spjdstatic void 171163849Spjddirtycg(struct cgchain *cgc) 172163849Spjd{ 173163849Spjd 174163849Spjd cgc->cgc_dirty = 1; 175163849Spjd} 176163849Spjd 177163849Spjd/* 178163849Spjd * Mark cylinder group as busy - it will not be freed on putcgs(). 179163849Spjd */ 180163849Spjdstatic void 181163849Spjdbusycg(struct cgchain *cgc) 182163849Spjd{ 183163849Spjd 184163849Spjd cgc->cgc_busy = 1; 185163849Spjd} 186163849Spjd 187163849Spjd/* 188163849Spjd * Unmark the given cylinder group as busy. 189163849Spjd */ 190163849Spjdstatic void 191163849Spjdunbusycg(struct cgchain *cgc) 192163849Spjd{ 193163849Spjd 194163849Spjd cgc->cgc_busy = 0; 195163849Spjd} 196163849Spjd 197163849Spjd/* 198163849Spjd * Write back all dirty cylinder groups. 199163849Spjd * Free all non-busy cylinder groups. 200163849Spjd */ 201163849Spjdstatic void 202163849Spjdputcgs(void) 203163849Spjd{ 204163849Spjd struct cgchain *cgc, *cgc2; 205163849Spjd 206163849Spjd assert(disk != NULL && fs != NULL); 207163849Spjd LIST_FOREACH_SAFE(cgc, &cglist, cgc_next, cgc2) { 208163849Spjd if (cgc->cgc_busy) 209163849Spjd continue; 210163849Spjd LIST_REMOVE(cgc, cgc_next); 211163849Spjd ncgs--; 212163849Spjd if (cgc->cgc_dirty) { 213163849Spjd bcopy(&cgc->cgc_cg, &disk->d_cg, 214163849Spjd sizeof(cgc->cgc_union)); 215163849Spjd if (cgwrite1(disk, cgc->cgc_cg.cg_cgx) == -1) 216163849Spjd err(1, "cgwrite1(%d)", cgc->cgc_cg.cg_cgx); 217163849Spjd //printf("%s: Wrote cg=%d\n", __func__, 218163849Spjd // cgc->cgc_cg.cg_cgx); 219163849Spjd } 220163849Spjd free(cgc); 221163849Spjd } 222163849Spjd} 223163849Spjd 224163849Spjd#if 0 225163849Spjd/* 226163849Spjd * Free all non-busy cylinder groups without storing the dirty ones. 227163849Spjd */ 228163849Spjdstatic void 229163849Spjdcancelcgs(void) 230163849Spjd{ 231163849Spjd struct cgchain *cgc; 232163849Spjd 233163849Spjd assert(disk != NULL && fs != NULL); 234163849Spjd while ((cgc = LIST_FIRST(&cglist)) != NULL) { 235163849Spjd if (cgc->cgc_busy) 236163849Spjd continue; 237163849Spjd LIST_REMOVE(cgc, cgc_next); 238163849Spjd //printf("%s: Canceled cg=%d\n", __func__, cgc->cgc_cg.cg_cgx); 239163849Spjd free(cgc); 240163849Spjd } 241163849Spjd} 242163849Spjd#endif 243163849Spjd 244163849Spjd/* 245163849Spjd * Open the given provider, load statistics. 246163849Spjd */ 247163849Spjdstatic void 248163849Spjdgetdisk(void) 249163849Spjd{ 250163849Spjd int i; 251163849Spjd 252163849Spjd if (disk != NULL) 253163849Spjd return; 254163849Spjd disk = malloc(sizeof(*disk)); 255163849Spjd if (disk == NULL) 256163849Spjd err(1, "malloc(%zu)", sizeof(*disk)); 257163849Spjd if (ufs_disk_fillout(disk, devnam) == -1) { 258163849Spjd err(1, "ufs_disk_fillout(%s) failed: %s", devnam, 259163849Spjd disk->d_error); 260163849Spjd } 261163849Spjd fs = &disk->d_fs; 262163849Spjd fs->fs_csp = malloc((size_t)fs->fs_cssize); 263163849Spjd if (fs->fs_csp == NULL) 264163849Spjd err(1, "malloc(%zu)", (size_t)fs->fs_cssize); 265163849Spjd bzero(fs->fs_csp, (size_t)fs->fs_cssize); 266163849Spjd for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) { 267163849Spjd if (bread(disk, fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)), 268163849Spjd (void *)(((char *)fs->fs_csp) + i), 269163849Spjd (size_t)(fs->fs_cssize - i < fs->fs_bsize ? fs->fs_cssize - i : fs->fs_bsize)) == -1) { 270163849Spjd err(1, "bread: %s", disk->d_error); 271163849Spjd } 272163849Spjd } 273163849Spjd if (fs->fs_contigsumsize > 0) { 274163849Spjd fs->fs_maxcluster = malloc(fs->fs_ncg * sizeof(int32_t)); 275163849Spjd if (fs->fs_maxcluster == NULL) 276163849Spjd err(1, "malloc(%zu)", fs->fs_ncg * sizeof(int32_t)); 277163849Spjd for (i = 0; i < fs->fs_ncg; i++) 278163849Spjd fs->fs_maxcluster[i] = fs->fs_contigsumsize; 279163849Spjd } 280163849Spjd} 281163849Spjd 282163849Spjd/* 283163849Spjd * Mark file system as clean, write the super-block back, close the disk. 284163849Spjd */ 285163849Spjdstatic void 286163849Spjdclosedisk(void) 287163849Spjd{ 288163849Spjd 289163849Spjd free(fs->fs_csp); 290163849Spjd if (fs->fs_contigsumsize > 0) { 291163849Spjd free(fs->fs_maxcluster); 292163849Spjd fs->fs_maxcluster = NULL; 293163849Spjd } 294163849Spjd fs->fs_clean = 1; 295163849Spjd if (sbwrite(disk, 0) == -1) 296163849Spjd err(1, "sbwrite(%s)", devnam); 297163849Spjd if (ufs_disk_close(disk) == -1) 298163849Spjd err(1, "ufs_disk_close(%s)", devnam); 299163849Spjd free(disk); 300163849Spjd disk = NULL; 301163849Spjd fs = NULL; 302163849Spjd} 303163849Spjd 304163849Spjd/* 305163849Spjd * Write the statistics back, call closedisk(). 306163849Spjd */ 307163849Spjdstatic void 308163849Spjdputdisk(void) 309163849Spjd{ 310163849Spjd int i; 311163849Spjd 312163849Spjd assert(disk != NULL && fs != NULL); 313163849Spjd for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) { 314163849Spjd if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)), 315163849Spjd (void *)(((char *)fs->fs_csp) + i), 316163849Spjd (size_t)(fs->fs_cssize - i < fs->fs_bsize ? fs->fs_cssize - i : fs->fs_bsize)) == -1) { 317163849Spjd err(1, "bwrite: %s", disk->d_error); 318163849Spjd } 319163849Spjd } 320163849Spjd closedisk(); 321163849Spjd} 322163849Spjd 323163849Spjd#if 0 324163849Spjd/* 325163849Spjd * Free memory, close the disk, but don't write anything back. 326163849Spjd */ 327163849Spjdstatic void 328163849Spjdcanceldisk(void) 329163849Spjd{ 330163849Spjd int i; 331163849Spjd 332163849Spjd assert(disk != NULL && fs != NULL); 333163849Spjd free(fs->fs_csp); 334163849Spjd if (fs->fs_contigsumsize > 0) 335163849Spjd free(fs->fs_maxcluster); 336163849Spjd if (ufs_disk_close(disk) == -1) 337163849Spjd err(1, "ufs_disk_close(%s)", devnam); 338163849Spjd free(disk); 339163849Spjd disk = NULL; 340163849Spjd fs = NULL; 341163849Spjd} 342163849Spjd#endif 343163849Spjd 344163849Spjdstatic int 345163849Spjdisblock(unsigned char *cp, ufs1_daddr_t h) 346163849Spjd{ 347163849Spjd unsigned char mask; 348163849Spjd 349163849Spjd switch ((int)fs->fs_frag) { 350163849Spjd case 8: 351163849Spjd return (cp[h] == 0xff); 352163849Spjd case 4: 353163849Spjd mask = 0x0f << ((h & 0x1) << 2); 354163849Spjd return ((cp[h >> 1] & mask) == mask); 355163849Spjd case 2: 356163849Spjd mask = 0x03 << ((h & 0x3) << 1); 357163849Spjd return ((cp[h >> 2] & mask) == mask); 358163849Spjd case 1: 359163849Spjd mask = 0x01 << (h & 0x7); 360163849Spjd return ((cp[h >> 3] & mask) == mask); 361163849Spjd default: 362163849Spjd assert(!"isblock: invalid number of fragments"); 363163849Spjd } 364163849Spjd return (0); 365163849Spjd} 366163849Spjd 367163849Spjd/* 368163849Spjd * put a block into the map 369163849Spjd */ 370163849Spjdstatic void 371163849Spjdsetblock(unsigned char *cp, ufs1_daddr_t h) 372163849Spjd{ 373163849Spjd 374163849Spjd switch ((int)fs->fs_frag) { 375163849Spjd case 8: 376163849Spjd cp[h] = 0xff; 377163849Spjd return; 378163849Spjd case 4: 379163849Spjd cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 380163849Spjd return; 381163849Spjd case 2: 382163849Spjd cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 383163849Spjd return; 384163849Spjd case 1: 385163849Spjd cp[h >> 3] |= (0x01 << (h & 0x7)); 386163849Spjd return; 387163849Spjd default: 388163849Spjd assert(!"setblock: invalid number of fragments"); 389163849Spjd } 390163849Spjd} 391163849Spjd 392163849Spjd/* 393163849Spjd * check if a block is free 394163849Spjd */ 395163849Spjdstatic int 396163849Spjdisfreeblock(u_char *cp, ufs1_daddr_t h) 397163849Spjd{ 398163849Spjd 399163849Spjd switch ((int)fs->fs_frag) { 400163849Spjd case 8: 401163849Spjd return (cp[h] == 0); 402163849Spjd case 4: 403163849Spjd return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0); 404163849Spjd case 2: 405163849Spjd return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0); 406163849Spjd case 1: 407163849Spjd return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0); 408163849Spjd default: 409163849Spjd assert(!"isfreeblock: invalid number of fragments"); 410163849Spjd } 411163849Spjd return (0); 412163849Spjd} 413163849Spjd 414163849Spjd/* 415163849Spjd * Update the frsum fields to reflect addition or deletion 416163849Spjd * of some frags. 417163849Spjd */ 418163849Spjdvoid 419163849Spjdfragacct(int fragmap, int32_t fraglist[], int cnt) 420163849Spjd{ 421163849Spjd int inblk; 422163849Spjd int field, subfield; 423163849Spjd int siz, pos; 424163849Spjd 425163849Spjd inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 426163849Spjd fragmap <<= 1; 427163849Spjd for (siz = 1; siz < fs->fs_frag; siz++) { 428163849Spjd if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 429163849Spjd continue; 430163849Spjd field = around[siz]; 431163849Spjd subfield = inside[siz]; 432163849Spjd for (pos = siz; pos <= fs->fs_frag; pos++) { 433163849Spjd if ((fragmap & field) == subfield) { 434163849Spjd fraglist[siz] += cnt; 435163849Spjd pos += siz; 436163849Spjd field <<= siz; 437163849Spjd subfield <<= siz; 438163849Spjd } 439163849Spjd field <<= 1; 440163849Spjd subfield <<= 1; 441163849Spjd } 442163849Spjd } 443163849Spjd} 444163849Spjd 445163849Spjdstatic void 446163849Spjdclusteracct(struct cg *cgp, ufs1_daddr_t blkno) 447163849Spjd{ 448163849Spjd int32_t *sump; 449163849Spjd int32_t *lp; 450163849Spjd u_char *freemapp, *mapp; 451163849Spjd int i, start, end, forw, back, map, bit; 452163849Spjd 453163849Spjd if (fs->fs_contigsumsize <= 0) 454163849Spjd return; 455163849Spjd freemapp = cg_clustersfree(cgp); 456163849Spjd sump = cg_clustersum(cgp); 457163849Spjd /* 458163849Spjd * Clear the actual block. 459163849Spjd */ 460163849Spjd setbit(freemapp, blkno); 461163849Spjd /* 462163849Spjd * Find the size of the cluster going forward. 463163849Spjd */ 464163849Spjd start = blkno + 1; 465163849Spjd end = start + fs->fs_contigsumsize; 466163849Spjd if (end >= cgp->cg_nclusterblks) 467163849Spjd end = cgp->cg_nclusterblks; 468163849Spjd mapp = &freemapp[start / NBBY]; 469163849Spjd map = *mapp++; 470163849Spjd bit = 1 << (start % NBBY); 471163849Spjd for (i = start; i < end; i++) { 472163849Spjd if ((map & bit) == 0) 473163849Spjd break; 474163849Spjd if ((i & (NBBY - 1)) != (NBBY - 1)) { 475163849Spjd bit <<= 1; 476163849Spjd } else { 477163849Spjd map = *mapp++; 478163849Spjd bit = 1; 479163849Spjd } 480163849Spjd } 481163849Spjd forw = i - start; 482163849Spjd /* 483163849Spjd * Find the size of the cluster going backward. 484163849Spjd */ 485163849Spjd start = blkno - 1; 486163849Spjd end = start - fs->fs_contigsumsize; 487163849Spjd if (end < 0) 488163849Spjd end = -1; 489163849Spjd mapp = &freemapp[start / NBBY]; 490163849Spjd map = *mapp--; 491163849Spjd bit = 1 << (start % NBBY); 492163849Spjd for (i = start; i > end; i--) { 493163849Spjd if ((map & bit) == 0) 494163849Spjd break; 495163849Spjd if ((i & (NBBY - 1)) != 0) { 496163849Spjd bit >>= 1; 497163849Spjd } else { 498163849Spjd map = *mapp--; 499163849Spjd bit = 1 << (NBBY - 1); 500163849Spjd } 501163849Spjd } 502163849Spjd back = start - i; 503163849Spjd /* 504163849Spjd * Account for old cluster and the possibly new forward and 505163849Spjd * back clusters. 506163849Spjd */ 507163849Spjd i = back + forw + 1; 508163849Spjd if (i > fs->fs_contigsumsize) 509163849Spjd i = fs->fs_contigsumsize; 510163849Spjd sump[i]++; 511163849Spjd if (back > 0) 512163849Spjd sump[back]--; 513163849Spjd if (forw > 0) 514163849Spjd sump[forw]--; 515163849Spjd /* 516163849Spjd * Update cluster summary information. 517163849Spjd */ 518163849Spjd lp = &sump[fs->fs_contigsumsize]; 519163849Spjd for (i = fs->fs_contigsumsize; i > 0; i--) 520163849Spjd if (*lp-- > 0) 521163849Spjd break; 522163849Spjd fs->fs_maxcluster[cgp->cg_cgx] = i; 523163849Spjd} 524163849Spjd 525163849Spjdstatic void 526163849Spjdblkfree(ufs2_daddr_t bno, long size) 527163849Spjd{ 528163849Spjd struct cgchain *cgc; 529163849Spjd struct cg *cgp; 530163849Spjd ufs1_daddr_t fragno, cgbno; 531163849Spjd int i, cg, blk, frags, bbase; 532163849Spjd u_int8_t *blksfree; 533163849Spjd 534163849Spjd cg = dtog(fs, bno); 535163849Spjd cgc = getcg(cg); 536163849Spjd dirtycg(cgc); 537163849Spjd cgp = &cgc->cgc_cg; 538163849Spjd cgbno = dtogd(fs, bno); 539163849Spjd blksfree = cg_blksfree(cgp); 540163849Spjd if (size == fs->fs_bsize) { 541163849Spjd fragno = fragstoblks(fs, cgbno); 542163849Spjd if (!isfreeblock(blksfree, fragno)) 543163849Spjd assert(!"blkfree: freeing free block"); 544163849Spjd setblock(blksfree, fragno); 545163849Spjd clusteracct(cgp, fragno); 546163849Spjd cgp->cg_cs.cs_nbfree++; 547163849Spjd fs->fs_cstotal.cs_nbfree++; 548163849Spjd fs->fs_cs(fs, cg).cs_nbfree++; 549163849Spjd } else { 550163849Spjd bbase = cgbno - fragnum(fs, cgbno); 551163849Spjd /* 552163849Spjd * decrement the counts associated with the old frags 553163849Spjd */ 554163849Spjd blk = blkmap(fs, blksfree, bbase); 555163849Spjd fragacct(blk, cgp->cg_frsum, -1); 556163849Spjd /* 557163849Spjd * deallocate the fragment 558163849Spjd */ 559163849Spjd frags = numfrags(fs, size); 560163849Spjd for (i = 0; i < frags; i++) { 561163849Spjd if (isset(blksfree, cgbno + i)) 562163849Spjd assert(!"blkfree: freeing free frag"); 563163849Spjd setbit(blksfree, cgbno + i); 564163849Spjd } 565163849Spjd cgp->cg_cs.cs_nffree += i; 566163849Spjd fs->fs_cstotal.cs_nffree += i; 567163849Spjd fs->fs_cs(fs, cg).cs_nffree += i; 568163849Spjd /* 569163849Spjd * add back in counts associated with the new frags 570163849Spjd */ 571163849Spjd blk = blkmap(fs, blksfree, bbase); 572163849Spjd fragacct(blk, cgp->cg_frsum, 1); 573163849Spjd /* 574163849Spjd * if a complete block has been reassembled, account for it 575163849Spjd */ 576163849Spjd fragno = fragstoblks(fs, bbase); 577163849Spjd if (isblock(blksfree, fragno)) { 578163849Spjd cgp->cg_cs.cs_nffree -= fs->fs_frag; 579163849Spjd fs->fs_cstotal.cs_nffree -= fs->fs_frag; 580163849Spjd fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 581163849Spjd clusteracct(cgp, fragno); 582163849Spjd cgp->cg_cs.cs_nbfree++; 583163849Spjd fs->fs_cstotal.cs_nbfree++; 584163849Spjd fs->fs_cs(fs, cg).cs_nbfree++; 585163849Spjd } 586163849Spjd } 587163849Spjd} 588163849Spjd 589163849Spjd/* 590163849Spjd * Recursively free all indirect blocks. 591163849Spjd */ 592163849Spjdstatic void 593163849Spjdfreeindir(ufs2_daddr_t blk, int level) 594163849Spjd{ 595163849Spjd char sblks[MAXBSIZE]; 596163849Spjd ufs2_daddr_t *blks; 597163849Spjd int i; 598163849Spjd 599163849Spjd if (bread(disk, fsbtodb(fs, blk), (void *)&sblks, (size_t)fs->fs_bsize) == -1) 600163849Spjd err(1, "bread: %s", disk->d_error); 601163849Spjd blks = (ufs2_daddr_t *)&sblks; 602163849Spjd for (i = 0; i < howmany(fs->fs_bsize, sizeof(ufs2_daddr_t)); i++) { 603163849Spjd if (blks[i] == 0) 604163849Spjd break; 605163849Spjd if (level == 0) 606163849Spjd blkfree(blks[i], fs->fs_bsize); 607163849Spjd else 608163849Spjd freeindir(blks[i], level - 1); 609163849Spjd } 610163849Spjd blkfree(blk, fs->fs_bsize); 611163849Spjd} 612163849Spjd 613163849Spjd#define dblksize(fs, dino, lbn) \ 614163849Spjd ((dino)->di_size >= smalllblktosize(fs, (lbn) + 1) \ 615163849Spjd ? (fs)->fs_bsize \ 616163849Spjd : fragroundup(fs, blkoff(fs, (dino)->di_size))) 617163849Spjd 618163849Spjd/* 619163849Spjd * Free all blocks associated with the given inode. 620163849Spjd */ 621163849Spjdstatic void 622163849Spjdclear_inode(struct ufs2_dinode *dino) 623163849Spjd{ 624163849Spjd ufs2_daddr_t bn; 625163849Spjd int extblocks, i, level; 626163849Spjd off_t osize; 627163849Spjd long bsize; 628163849Spjd 629163849Spjd extblocks = 0; 630163849Spjd if (fs->fs_magic == FS_UFS2_MAGIC && dino->di_extsize > 0) 631163849Spjd extblocks = btodb(fragroundup(fs, dino->di_extsize)); 632163849Spjd /* deallocate external attributes blocks */ 633163849Spjd if (extblocks > 0) { 634163849Spjd osize = dino->di_extsize; 635163849Spjd dino->di_blocks -= extblocks; 636163849Spjd dino->di_extsize = 0; 637163849Spjd for (i = 0; i < NXADDR; i++) { 638163849Spjd if (dino->di_extb[i] == 0) 639163849Spjd continue; 640163849Spjd blkfree(dino->di_extb[i], sblksize(fs, osize, i)); 641163849Spjd } 642163849Spjd } 643163849Spjd#define SINGLE 0 /* index of single indirect block */ 644163849Spjd#define DOUBLE 1 /* index of double indirect block */ 645163849Spjd#define TRIPLE 2 /* index of triple indirect block */ 646163849Spjd /* deallocate indirect blocks */ 647163849Spjd for (level = SINGLE; level <= TRIPLE; level++) { 648163849Spjd if (dino->di_ib[level] == 0) 649163849Spjd break; 650163849Spjd freeindir(dino->di_ib[level], level); 651163849Spjd } 652163849Spjd /* deallocate direct blocks and fragments */ 653163849Spjd for (i = 0; i < NDADDR; i++) { 654163849Spjd bn = dino->di_db[i]; 655163849Spjd if (bn == 0) 656163849Spjd continue; 657163849Spjd bsize = dblksize(fs, dino, i); 658163849Spjd blkfree(bn, bsize); 659163849Spjd } 660163849Spjd} 661163849Spjd 662163849Spjdvoid 663163849Spjdgjournal_check(const char *filesys) 664163849Spjd{ 665163849Spjd struct ufs2_dinode *dino; 666163849Spjd struct cgchain *cgc; 667163849Spjd struct cg *cgp; 668163849Spjd uint8_t *inosused, *blksfree; 669163849Spjd ino_t cino, ino; 670163849Spjd int cg, mode; 671163849Spjd 672163849Spjd devnam = filesys; 673163849Spjd getdisk(); 674163849Spjd /* Are there any unreferenced inodes in this cylinder group? */ 675163849Spjd if (fs->fs_unrefs == 0) { 676163849Spjd //printf("No unreferenced inodes.\n"); 677163849Spjd closedisk(); 678163849Spjd return; 679163849Spjd } 680163849Spjd 681163849Spjd for (cg = 0; cg < fs->fs_ncg; cg++) { 682163849Spjd /* Show progress if requested. */ 683163849Spjd if (got_siginfo) { 684163849Spjd printf("%s: phase j: cyl group %d of %d (%d%%)\n", 685163849Spjd cdevname, cg, fs->fs_ncg, cg * 100 / fs->fs_ncg); 686163849Spjd got_siginfo = 0; 687163849Spjd } 688163849Spjd if (got_sigalarm) { 689163849Spjd setproctitle("%s pj %d%%", cdevname, 690163849Spjd cg * 100 / fs->fs_ncg); 691163849Spjd got_sigalarm = 0; 692163849Spjd } 693163849Spjd cgc = getcg(cg); 694163849Spjd cgp = &cgc->cgc_cg; 695163849Spjd /* Are there any unreferenced inodes in this cylinder group? */ 696163849Spjd if (cgp->cg_unrefs == 0) 697163849Spjd continue; 698163849Spjd //printf("Analizing cylinder group %d (count=%d)\n", cg, cgp->cg_unrefs); 699163849Spjd /* 700163849Spjd * We are going to modify this cylinder group, so we want it to 701163849Spjd * be written back. 702163849Spjd */ 703163849Spjd dirtycg(cgc); 704163849Spjd /* We don't want it to be freed in the meantime. */ 705163849Spjd busycg(cgc); 706163849Spjd inosused = cg_inosused(cgp); 707163849Spjd blksfree = cg_blksfree(cgp); 708163849Spjd /* 709163849Spjd * Now go through the list of all inodes in this cylinder group 710163849Spjd * to find unreferenced ones. 711163849Spjd */ 712163849Spjd for (cino = 0; cino < fs->fs_ipg; cino++) { 713163849Spjd ino = fs->fs_ipg * cg + cino; 714163849Spjd /* Unallocated? Skip it. */ 715163849Spjd if (isclr(inosused, cino)) 716163849Spjd continue; 717163849Spjd if (getino(disk, (void **)&dino, ino, &mode) == -1) 718163849Spjd err(1, "getino(cg=%d ino=%d)", cg, ino); 719163849Spjd /* Not a regular file nor directory? Skip it. */ 720163849Spjd if (!S_ISREG(dino->di_mode) && !S_ISDIR(dino->di_mode)) 721163849Spjd continue; 722163849Spjd /* Has reference(s)? Skip it. */ 723163849Spjd if (dino->di_nlink > 0) 724163849Spjd continue; 725163849Spjd //printf("Clearing inode=%d (size=%jd)\n", ino, (intmax_t)dino->di_size); 726163849Spjd /* Free inode's blocks. */ 727163849Spjd clear_inode(dino); 728163849Spjd /* Deallocate it. */ 729163849Spjd clrbit(inosused, cino); 730163849Spjd /* Update position of last used inode. */ 731163849Spjd if (ino < cgp->cg_irotor) 732163849Spjd cgp->cg_irotor = ino; 733163849Spjd /* Update statistics. */ 734163849Spjd cgp->cg_cs.cs_nifree++; 735163849Spjd fs->fs_cs(fs, cg).cs_nifree++; 736163849Spjd fs->fs_cstotal.cs_nifree++; 737163849Spjd cgp->cg_unrefs--; 738163849Spjd fs->fs_unrefs--; 739163849Spjd /* If this is directory, update related statistics. */ 740163849Spjd if (S_ISDIR(dino->di_mode)) { 741163849Spjd cgp->cg_cs.cs_ndir--; 742163849Spjd fs->fs_cs(fs, cg).cs_ndir--; 743163849Spjd fs->fs_cstotal.cs_ndir--; 744163849Spjd } 745163849Spjd /* Zero-fill the inode. */ 746163849Spjd *dino = ufs2_zino; 747163849Spjd /* Write the inode back. */ 748163849Spjd if (putino(disk, ino) == -1) 749163849Spjd err(1, "putino(cg=%d ino=%d)", cg, ino); 750163849Spjd if (cgp->cg_unrefs == 0) { 751163849Spjd //printf("No more unreferenced inodes in cg=%d.\n", cg); 752163849Spjd break; 753163849Spjd } 754163849Spjd } 755163849Spjd /* 756163849Spjd * We don't need this cylinder group anymore, so feel free to 757163849Spjd * free it if needed. 758163849Spjd */ 759163849Spjd unbusycg(cgc); 760163849Spjd /* 761163849Spjd * If there are no more unreferenced inodes, there is no need to 762163849Spjd * check other cylinder groups. 763163849Spjd */ 764163849Spjd if (fs->fs_unrefs == 0) { 765163849Spjd //printf("No more unreferenced inodes (cg=%d/%d).\n", cg, 766163849Spjd // fs->fs_ncg); 767163849Spjd break; 768163849Spjd } 769163849Spjd } 770163849Spjd /* Write back modified cylinder groups. */ 771163849Spjd putcgs(); 772163849Spjd /* Write back updated statistics and super-block. */ 773163849Spjd putdisk(); 774163849Spjd} 775