1109509Sjmallett/* 2109509Sjmallett * Copyright (c) 2003 Juli Mallett. All rights reserved. 3109509Sjmallett * 4109509Sjmallett * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 5109509Sjmallett * FreeBSD project. Redistribution and use in source and binary forms, with 6109509Sjmallett * or without modification, are permitted provided that the following 7109509Sjmallett * conditions are met: 8109509Sjmallett * 9109509Sjmallett * 1. Redistribution of source code must retain the above copyright notice, 10109509Sjmallett * this list of conditions and the following disclaimer. 11109509Sjmallett * 2. Redistribution in binary form must reproduce the above copyright 12109509Sjmallett * notice, this list of conditions and the following disclaimer in the 13109509Sjmallett * documentation and/or other materials provided with the distribution. 14109509Sjmallett * 15109509Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16109509Sjmallett * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17109509Sjmallett * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18109509Sjmallett * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19109509Sjmallett * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20109509Sjmallett * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21109509Sjmallett * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22109509Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23109509Sjmallett * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 24109509Sjmallett * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25109509Sjmallett * POSSIBILITY OF SUCH DAMAGE. 26109509Sjmallett */ 27109509Sjmallett 28109509Sjmallett#include <sys/cdefs.h> 29109509Sjmallett__FBSDID("$FreeBSD$"); 30109509Sjmallett 31109509Sjmallett#include <sys/param.h> 32109509Sjmallett#include <sys/mount.h> 33109509Sjmallett#include <sys/disklabel.h> 34109509Sjmallett#include <sys/stat.h> 35109509Sjmallett 36109509Sjmallett#include <ufs/ufs/ufsmount.h> 37109509Sjmallett#include <ufs/ufs/dinode.h> 38109509Sjmallett#include <ufs/ffs/fs.h> 39109509Sjmallett 40109509Sjmallett#include <errno.h> 41109509Sjmallett#include <fcntl.h> 42109509Sjmallett#include <stdio.h> 43207141Sjeff#include <stdlib.h> 44109509Sjmallett#include <string.h> 45109509Sjmallett#include <unistd.h> 46109509Sjmallett 47109509Sjmallett#include <libufs.h> 48109509Sjmallett 49207141Sjeffufs2_daddr_t 50207141Sjeffcgballoc(struct uufsd *disk) 51207141Sjeff{ 52207141Sjeff u_int8_t *blksfree; 53207141Sjeff struct cg *cgp; 54207141Sjeff struct fs *fs; 55207141Sjeff long bno; 56207141Sjeff 57207141Sjeff fs = &disk->d_fs; 58207141Sjeff cgp = &disk->d_cg; 59207141Sjeff blksfree = cg_blksfree(cgp); 60207141Sjeff for (bno = 0; bno < fs->fs_fpg / fs->fs_frag; bno++) 61207141Sjeff if (ffs_isblock(fs, blksfree, bno)) 62207141Sjeff goto gotit; 63207141Sjeff return (0); 64207141Sjeffgotit: 65207141Sjeff fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; 66207141Sjeff ffs_clrblock(fs, blksfree, (long)bno); 67207141Sjeff ffs_clusteracct(fs, cgp, bno, -1); 68207141Sjeff cgp->cg_cs.cs_nbfree--; 69207141Sjeff fs->fs_cstotal.cs_nbfree--; 70207141Sjeff fs->fs_fmod = 1; 71207141Sjeff return (cgbase(fs, cgp->cg_cgx) + blkstofrags(fs, bno)); 72207141Sjeff} 73207141Sjeff 74109509Sjmallettint 75207141Sjeffcgbfree(struct uufsd *disk, ufs2_daddr_t bno, long size) 76207141Sjeff{ 77207141Sjeff u_int8_t *blksfree; 78207141Sjeff struct fs *fs; 79207141Sjeff struct cg *cgp; 80207141Sjeff ufs1_daddr_t fragno, cgbno; 81207141Sjeff int i, cg, blk, frags, bbase; 82207141Sjeff 83207141Sjeff fs = &disk->d_fs; 84207141Sjeff cg = dtog(fs, bno); 85207141Sjeff if (cgread1(disk, cg) != 1) 86207141Sjeff return (-1); 87207141Sjeff cgp = &disk->d_cg; 88207141Sjeff cgbno = dtogd(fs, bno); 89207141Sjeff blksfree = cg_blksfree(cgp); 90207141Sjeff if (size == fs->fs_bsize) { 91207141Sjeff fragno = fragstoblks(fs, cgbno); 92207141Sjeff ffs_setblock(fs, blksfree, fragno); 93207141Sjeff ffs_clusteracct(fs, cgp, fragno, 1); 94207141Sjeff cgp->cg_cs.cs_nbfree++; 95207141Sjeff fs->fs_cstotal.cs_nbfree++; 96207141Sjeff fs->fs_cs(fs, cg).cs_nbfree++; 97207141Sjeff } else { 98207141Sjeff bbase = cgbno - fragnum(fs, cgbno); 99207141Sjeff /* 100207141Sjeff * decrement the counts associated with the old frags 101207141Sjeff */ 102207141Sjeff blk = blkmap(fs, blksfree, bbase); 103207141Sjeff ffs_fragacct(fs, blk, cgp->cg_frsum, -1); 104207141Sjeff /* 105207141Sjeff * deallocate the fragment 106207141Sjeff */ 107207141Sjeff frags = numfrags(fs, size); 108207141Sjeff for (i = 0; i < frags; i++) 109207141Sjeff setbit(blksfree, cgbno + i); 110207141Sjeff cgp->cg_cs.cs_nffree += i; 111207141Sjeff fs->fs_cstotal.cs_nffree += i; 112207141Sjeff fs->fs_cs(fs, cg).cs_nffree += i; 113207141Sjeff /* 114207141Sjeff * add back in counts associated with the new frags 115207141Sjeff */ 116207141Sjeff blk = blkmap(fs, blksfree, bbase); 117207141Sjeff ffs_fragacct(fs, blk, cgp->cg_frsum, 1); 118207141Sjeff /* 119207141Sjeff * if a complete block has been reassembled, account for it 120207141Sjeff */ 121207141Sjeff fragno = fragstoblks(fs, bbase); 122207141Sjeff if (ffs_isblock(fs, blksfree, fragno)) { 123207141Sjeff cgp->cg_cs.cs_nffree -= fs->fs_frag; 124207141Sjeff fs->fs_cstotal.cs_nffree -= fs->fs_frag; 125207141Sjeff fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 126207141Sjeff ffs_clusteracct(fs, cgp, fragno, 1); 127207141Sjeff cgp->cg_cs.cs_nbfree++; 128207141Sjeff fs->fs_cstotal.cs_nbfree++; 129207141Sjeff fs->fs_cs(fs, cg).cs_nbfree++; 130207141Sjeff } 131207141Sjeff } 132207141Sjeff return cgwrite(disk); 133207141Sjeff} 134207141Sjeff 135207141Sjeffino_t 136207141Sjeffcgialloc(struct uufsd *disk) 137207141Sjeff{ 138207141Sjeff struct ufs2_dinode *dp2; 139207141Sjeff u_int8_t *inosused; 140207141Sjeff struct cg *cgp; 141207141Sjeff struct fs *fs; 142207141Sjeff ino_t ino; 143207141Sjeff int i; 144207141Sjeff 145207141Sjeff fs = &disk->d_fs; 146207141Sjeff cgp = &disk->d_cg; 147207141Sjeff inosused = cg_inosused(cgp); 148207476Semaste for (ino = 0; ino < fs->fs_ipg; ino++) 149207141Sjeff if (isclr(inosused, ino)) 150207141Sjeff goto gotit; 151207141Sjeff return (0); 152207141Sjeffgotit: 153207141Sjeff if (fs->fs_magic == FS_UFS2_MAGIC && 154207141Sjeff ino + INOPB(fs) > cgp->cg_initediblk && 155207141Sjeff cgp->cg_initediblk < cgp->cg_niblk) { 156207141Sjeff char block[MAXBSIZE]; 157207141Sjeff bzero(block, (int)fs->fs_bsize); 158207141Sjeff dp2 = (struct ufs2_dinode *)█ 159207141Sjeff for (i = 0; i < INOPB(fs); i++) { 160207141Sjeff dp2->di_gen = arc4random() / 2 + 1; 161207141Sjeff dp2++; 162207141Sjeff } 163207141Sjeff if (bwrite(disk, ino_to_fsba(fs, 164207141Sjeff cgp->cg_cgx * fs->fs_ipg + cgp->cg_initediblk), 165207141Sjeff block, fs->fs_bsize)) 166207141Sjeff return (0); 167207141Sjeff cgp->cg_initediblk += INOPB(fs); 168207141Sjeff } 169207141Sjeff 170207141Sjeff setbit(inosused, ino); 171207141Sjeff cgp->cg_irotor = ino; 172207141Sjeff cgp->cg_cs.cs_nifree--; 173207141Sjeff fs->fs_cstotal.cs_nifree--; 174207141Sjeff fs->fs_cs(fs, cgp->cg_cgx).cs_nifree--; 175207141Sjeff fs->fs_fmod = 1; 176207141Sjeff 177207141Sjeff return (ino + (cgp->cg_cgx * fs->fs_ipg)); 178207141Sjeff} 179207141Sjeff 180207141Sjeffint 181109509Sjmallettcgread(struct uufsd *disk) 182109509Sjmallett{ 183116084Sjmallett return (cgread1(disk, disk->d_ccg++)); 184109509Sjmallett} 185109509Sjmallett 186109509Sjmallettint 187109509Sjmallettcgread1(struct uufsd *disk, int c) 188109509Sjmallett{ 189109509Sjmallett struct fs *fs; 190109509Sjmallett 191109509Sjmallett fs = &disk->d_fs; 192109509Sjmallett 193203768Smckusick if ((unsigned)c >= fs->fs_ncg) { 194116084Sjmallett return (0); 195109509Sjmallett } 196109509Sjmallett if (bread(disk, fsbtodb(fs, cgtod(fs, c)), disk->d_cgunion.d_buf, 197109509Sjmallett fs->fs_bsize) == -1) { 198109509Sjmallett ERROR(disk, "unable to read cylinder group"); 199116084Sjmallett return (-1); 200109509Sjmallett } 201109518Sjmallett disk->d_lcg = c; 202116084Sjmallett return (1); 203109509Sjmallett} 204163835Spjd 205163835Spjdint 206207141Sjeffcgwrite(struct uufsd *disk) 207207141Sjeff{ 208207141Sjeff return (cgwrite1(disk, disk->d_lcg)); 209207141Sjeff} 210207141Sjeff 211207141Sjeffint 212163835Spjdcgwrite1(struct uufsd *disk, int c) 213163835Spjd{ 214163835Spjd struct fs *fs; 215163835Spjd 216163835Spjd fs = &disk->d_fs; 217163835Spjd if (bwrite(disk, fsbtodb(fs, cgtod(fs, c)), 218163835Spjd disk->d_cgunion.d_buf, fs->fs_bsize) == -1) { 219163835Spjd ERROR(disk, "unable to write cylinder group"); 220163835Spjd return (-1); 221163835Spjd } 222163835Spjd return (0); 223163835Spjd} 224