122ec2ef3SJuli Mallett /* 222ec2ef3SJuli Mallett * Copyright (c) 2003 Juli Mallett. All rights reserved. 322ec2ef3SJuli Mallett * 422ec2ef3SJuli Mallett * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 522ec2ef3SJuli Mallett * FreeBSD project. Redistribution and use in source and binary forms, with 622ec2ef3SJuli Mallett * or without modification, are permitted provided that the following 722ec2ef3SJuli Mallett * conditions are met: 822ec2ef3SJuli Mallett * 922ec2ef3SJuli Mallett * 1. Redistribution of source code must retain the above copyright notice, 1022ec2ef3SJuli Mallett * this list of conditions and the following disclaimer. 1122ec2ef3SJuli Mallett * 2. Redistribution in binary form must reproduce the above copyright 1222ec2ef3SJuli Mallett * notice, this list of conditions and the following disclaimer in the 1322ec2ef3SJuli Mallett * documentation and/or other materials provided with the distribution. 1422ec2ef3SJuli Mallett * 1522ec2ef3SJuli Mallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1622ec2ef3SJuli Mallett * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1722ec2ef3SJuli Mallett * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1822ec2ef3SJuli Mallett * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 1922ec2ef3SJuli Mallett * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2022ec2ef3SJuli Mallett * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2122ec2ef3SJuli Mallett * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2222ec2ef3SJuli Mallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2322ec2ef3SJuli Mallett * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 2422ec2ef3SJuli Mallett * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2522ec2ef3SJuli Mallett * POSSIBILITY OF SUCH DAMAGE. 2622ec2ef3SJuli Mallett */ 2722ec2ef3SJuli Mallett 2822ec2ef3SJuli Mallett #include <sys/cdefs.h> 2922ec2ef3SJuli Mallett __FBSDID("$FreeBSD$"); 3022ec2ef3SJuli Mallett 3122ec2ef3SJuli Mallett #include <sys/param.h> 3222ec2ef3SJuli Mallett #include <sys/mount.h> 3322ec2ef3SJuli Mallett #include <sys/disklabel.h> 3422ec2ef3SJuli Mallett #include <sys/stat.h> 3522ec2ef3SJuli Mallett 3622ec2ef3SJuli Mallett #include <ufs/ufs/ufsmount.h> 3722ec2ef3SJuli Mallett #include <ufs/ufs/dinode.h> 3822ec2ef3SJuli Mallett #include <ufs/ffs/fs.h> 3922ec2ef3SJuli Mallett 4022ec2ef3SJuli Mallett #include <errno.h> 4122ec2ef3SJuli Mallett #include <fcntl.h> 4222ec2ef3SJuli Mallett #include <stdio.h> 43*113db2ddSJeff Roberson #include <stdlib.h> 4422ec2ef3SJuli Mallett #include <string.h> 4522ec2ef3SJuli Mallett #include <unistd.h> 4622ec2ef3SJuli Mallett 4722ec2ef3SJuli Mallett #include <libufs.h> 4822ec2ef3SJuli Mallett 49*113db2ddSJeff Roberson ufs2_daddr_t 50*113db2ddSJeff Roberson cgballoc(struct uufsd *disk) 51*113db2ddSJeff Roberson { 52*113db2ddSJeff Roberson u_int8_t *blksfree; 53*113db2ddSJeff Roberson struct cg *cgp; 54*113db2ddSJeff Roberson struct fs *fs; 55*113db2ddSJeff Roberson long bno; 56*113db2ddSJeff Roberson 57*113db2ddSJeff Roberson fs = &disk->d_fs; 58*113db2ddSJeff Roberson cgp = &disk->d_cg; 59*113db2ddSJeff Roberson blksfree = cg_blksfree(cgp); 60*113db2ddSJeff Roberson for (bno = 0; bno < fs->fs_fpg / fs->fs_frag; bno++) 61*113db2ddSJeff Roberson if (ffs_isblock(fs, blksfree, bno)) 62*113db2ddSJeff Roberson goto gotit; 63*113db2ddSJeff Roberson return (0); 64*113db2ddSJeff Roberson gotit: 65*113db2ddSJeff Roberson fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; 66*113db2ddSJeff Roberson ffs_clrblock(fs, blksfree, (long)bno); 67*113db2ddSJeff Roberson ffs_clusteracct(fs, cgp, bno, -1); 68*113db2ddSJeff Roberson cgp->cg_cs.cs_nbfree--; 69*113db2ddSJeff Roberson fs->fs_cstotal.cs_nbfree--; 70*113db2ddSJeff Roberson fs->fs_fmod = 1; 71*113db2ddSJeff Roberson return (cgbase(fs, cgp->cg_cgx) + blkstofrags(fs, bno)); 72*113db2ddSJeff Roberson } 73*113db2ddSJeff Roberson 74*113db2ddSJeff Roberson int 75*113db2ddSJeff Roberson cgbfree(struct uufsd *disk, ufs2_daddr_t bno, long size) 76*113db2ddSJeff Roberson { 77*113db2ddSJeff Roberson u_int8_t *blksfree; 78*113db2ddSJeff Roberson struct fs *fs; 79*113db2ddSJeff Roberson struct cg *cgp; 80*113db2ddSJeff Roberson ufs1_daddr_t fragno, cgbno; 81*113db2ddSJeff Roberson int i, cg, blk, frags, bbase; 82*113db2ddSJeff Roberson 83*113db2ddSJeff Roberson fs = &disk->d_fs; 84*113db2ddSJeff Roberson cg = dtog(fs, bno); 85*113db2ddSJeff Roberson if (cgread1(disk, cg) != 1) 86*113db2ddSJeff Roberson return (-1); 87*113db2ddSJeff Roberson cgp = &disk->d_cg; 88*113db2ddSJeff Roberson cgbno = dtogd(fs, bno); 89*113db2ddSJeff Roberson blksfree = cg_blksfree(cgp); 90*113db2ddSJeff Roberson if (size == fs->fs_bsize) { 91*113db2ddSJeff Roberson fragno = fragstoblks(fs, cgbno); 92*113db2ddSJeff Roberson ffs_setblock(fs, blksfree, fragno); 93*113db2ddSJeff Roberson ffs_clusteracct(fs, cgp, fragno, 1); 94*113db2ddSJeff Roberson cgp->cg_cs.cs_nbfree++; 95*113db2ddSJeff Roberson fs->fs_cstotal.cs_nbfree++; 96*113db2ddSJeff Roberson fs->fs_cs(fs, cg).cs_nbfree++; 97*113db2ddSJeff Roberson } else { 98*113db2ddSJeff Roberson bbase = cgbno - fragnum(fs, cgbno); 99*113db2ddSJeff Roberson /* 100*113db2ddSJeff Roberson * decrement the counts associated with the old frags 101*113db2ddSJeff Roberson */ 102*113db2ddSJeff Roberson blk = blkmap(fs, blksfree, bbase); 103*113db2ddSJeff Roberson ffs_fragacct(fs, blk, cgp->cg_frsum, -1); 104*113db2ddSJeff Roberson /* 105*113db2ddSJeff Roberson * deallocate the fragment 106*113db2ddSJeff Roberson */ 107*113db2ddSJeff Roberson frags = numfrags(fs, size); 108*113db2ddSJeff Roberson for (i = 0; i < frags; i++) 109*113db2ddSJeff Roberson setbit(blksfree, cgbno + i); 110*113db2ddSJeff Roberson cgp->cg_cs.cs_nffree += i; 111*113db2ddSJeff Roberson fs->fs_cstotal.cs_nffree += i; 112*113db2ddSJeff Roberson fs->fs_cs(fs, cg).cs_nffree += i; 113*113db2ddSJeff Roberson /* 114*113db2ddSJeff Roberson * add back in counts associated with the new frags 115*113db2ddSJeff Roberson */ 116*113db2ddSJeff Roberson blk = blkmap(fs, blksfree, bbase); 117*113db2ddSJeff Roberson ffs_fragacct(fs, blk, cgp->cg_frsum, 1); 118*113db2ddSJeff Roberson /* 119*113db2ddSJeff Roberson * if a complete block has been reassembled, account for it 120*113db2ddSJeff Roberson */ 121*113db2ddSJeff Roberson fragno = fragstoblks(fs, bbase); 122*113db2ddSJeff Roberson if (ffs_isblock(fs, blksfree, fragno)) { 123*113db2ddSJeff Roberson cgp->cg_cs.cs_nffree -= fs->fs_frag; 124*113db2ddSJeff Roberson fs->fs_cstotal.cs_nffree -= fs->fs_frag; 125*113db2ddSJeff Roberson fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 126*113db2ddSJeff Roberson ffs_clusteracct(fs, cgp, fragno, 1); 127*113db2ddSJeff Roberson cgp->cg_cs.cs_nbfree++; 128*113db2ddSJeff Roberson fs->fs_cstotal.cs_nbfree++; 129*113db2ddSJeff Roberson fs->fs_cs(fs, cg).cs_nbfree++; 130*113db2ddSJeff Roberson } 131*113db2ddSJeff Roberson } 132*113db2ddSJeff Roberson return cgwrite(disk); 133*113db2ddSJeff Roberson } 134*113db2ddSJeff Roberson 135*113db2ddSJeff Roberson ino_t 136*113db2ddSJeff Roberson cgialloc(struct uufsd *disk) 137*113db2ddSJeff Roberson { 138*113db2ddSJeff Roberson struct ufs2_dinode *dp2; 139*113db2ddSJeff Roberson u_int8_t *inosused; 140*113db2ddSJeff Roberson struct cg *cgp; 141*113db2ddSJeff Roberson struct fs *fs; 142*113db2ddSJeff Roberson ino_t ino; 143*113db2ddSJeff Roberson int i; 144*113db2ddSJeff Roberson 145*113db2ddSJeff Roberson fs = &disk->d_fs; 146*113db2ddSJeff Roberson cgp = &disk->d_cg; 147*113db2ddSJeff Roberson inosused = cg_inosused(cgp); 148*113db2ddSJeff Roberson for (ino = 0; ino < fs->fs_ipg / NBBY; ino++) 149*113db2ddSJeff Roberson if (isclr(inosused, ino)) 150*113db2ddSJeff Roberson goto gotit; 151*113db2ddSJeff Roberson return (0); 152*113db2ddSJeff Roberson gotit: 153*113db2ddSJeff Roberson if (fs->fs_magic == FS_UFS2_MAGIC && 154*113db2ddSJeff Roberson ino + INOPB(fs) > cgp->cg_initediblk && 155*113db2ddSJeff Roberson cgp->cg_initediblk < cgp->cg_niblk) { 156*113db2ddSJeff Roberson char block[MAXBSIZE]; 157*113db2ddSJeff Roberson bzero(block, (int)fs->fs_bsize); 158*113db2ddSJeff Roberson dp2 = (struct ufs2_dinode *)█ 159*113db2ddSJeff Roberson for (i = 0; i < INOPB(fs); i++) { 160*113db2ddSJeff Roberson dp2->di_gen = arc4random() / 2 + 1; 161*113db2ddSJeff Roberson dp2++; 162*113db2ddSJeff Roberson } 163*113db2ddSJeff Roberson if (bwrite(disk, ino_to_fsba(fs, 164*113db2ddSJeff Roberson cgp->cg_cgx * fs->fs_ipg + cgp->cg_initediblk), 165*113db2ddSJeff Roberson block, fs->fs_bsize)) 166*113db2ddSJeff Roberson return (0); 167*113db2ddSJeff Roberson cgp->cg_initediblk += INOPB(fs); 168*113db2ddSJeff Roberson } 169*113db2ddSJeff Roberson 170*113db2ddSJeff Roberson setbit(inosused, ino); 171*113db2ddSJeff Roberson cgp->cg_irotor = ino; 172*113db2ddSJeff Roberson cgp->cg_cs.cs_nifree--; 173*113db2ddSJeff Roberson fs->fs_cstotal.cs_nifree--; 174*113db2ddSJeff Roberson fs->fs_cs(fs, cgp->cg_cgx).cs_nifree--; 175*113db2ddSJeff Roberson fs->fs_fmod = 1; 176*113db2ddSJeff Roberson 177*113db2ddSJeff Roberson return (ino + (cgp->cg_cgx * fs->fs_ipg)); 178*113db2ddSJeff Roberson } 179*113db2ddSJeff Roberson 18022ec2ef3SJuli Mallett int 18122ec2ef3SJuli Mallett cgread(struct uufsd *disk) 18222ec2ef3SJuli Mallett { 1831081253fSJuli Mallett return (cgread1(disk, disk->d_ccg++)); 18422ec2ef3SJuli Mallett } 18522ec2ef3SJuli Mallett 18622ec2ef3SJuli Mallett int 18722ec2ef3SJuli Mallett cgread1(struct uufsd *disk, int c) 18822ec2ef3SJuli Mallett { 18922ec2ef3SJuli Mallett struct fs *fs; 19022ec2ef3SJuli Mallett 19122ec2ef3SJuli Mallett fs = &disk->d_fs; 19222ec2ef3SJuli Mallett 19339098572SKirk McKusick if ((unsigned)c >= fs->fs_ncg) { 1941081253fSJuli Mallett return (0); 19522ec2ef3SJuli Mallett } 19622ec2ef3SJuli Mallett if (bread(disk, fsbtodb(fs, cgtod(fs, c)), disk->d_cgunion.d_buf, 19722ec2ef3SJuli Mallett fs->fs_bsize) == -1) { 19822ec2ef3SJuli Mallett ERROR(disk, "unable to read cylinder group"); 1991081253fSJuli Mallett return (-1); 20022ec2ef3SJuli Mallett } 201cc3dd528SJuli Mallett disk->d_lcg = c; 2021081253fSJuli Mallett return (1); 20322ec2ef3SJuli Mallett } 204cf4652e7SPawel Jakub Dawidek 205cf4652e7SPawel Jakub Dawidek int 206*113db2ddSJeff Roberson cgwrite(struct uufsd *disk) 207*113db2ddSJeff Roberson { 208*113db2ddSJeff Roberson return (cgwrite1(disk, disk->d_lcg)); 209*113db2ddSJeff Roberson } 210*113db2ddSJeff Roberson 211*113db2ddSJeff Roberson int 212cf4652e7SPawel Jakub Dawidek cgwrite1(struct uufsd *disk, int c) 213cf4652e7SPawel Jakub Dawidek { 214cf4652e7SPawel Jakub Dawidek struct fs *fs; 215cf4652e7SPawel Jakub Dawidek 216cf4652e7SPawel Jakub Dawidek fs = &disk->d_fs; 217cf4652e7SPawel Jakub Dawidek if (bwrite(disk, fsbtodb(fs, cgtod(fs, c)), 218cf4652e7SPawel Jakub Dawidek disk->d_cgunion.d_buf, fs->fs_bsize) == -1) { 219cf4652e7SPawel Jakub Dawidek ERROR(disk, "unable to write cylinder group"); 220cf4652e7SPawel Jakub Dawidek return (-1); 221cf4652e7SPawel Jakub Dawidek } 222cf4652e7SPawel Jakub Dawidek return (0); 223cf4652e7SPawel Jakub Dawidek } 224