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> 43113db2ddSJeff Roberson #include <stdlib.h> 4422ec2ef3SJuli Mallett #include <string.h> 4522ec2ef3SJuli Mallett #include <unistd.h> 4622ec2ef3SJuli Mallett 4722ec2ef3SJuli Mallett #include <libufs.h> 4822ec2ef3SJuli Mallett 49113db2ddSJeff Roberson ufs2_daddr_t 50113db2ddSJeff Roberson cgballoc(struct uufsd *disk) 51113db2ddSJeff Roberson { 52113db2ddSJeff Roberson u_int8_t *blksfree; 53113db2ddSJeff Roberson struct cg *cgp; 54113db2ddSJeff Roberson struct fs *fs; 55113db2ddSJeff Roberson long bno; 56113db2ddSJeff Roberson 57113db2ddSJeff Roberson fs = &disk->d_fs; 58113db2ddSJeff Roberson cgp = &disk->d_cg; 59113db2ddSJeff Roberson blksfree = cg_blksfree(cgp); 60113db2ddSJeff Roberson for (bno = 0; bno < fs->fs_fpg / fs->fs_frag; bno++) 61113db2ddSJeff Roberson if (ffs_isblock(fs, blksfree, bno)) 62113db2ddSJeff Roberson goto gotit; 63113db2ddSJeff Roberson return (0); 64113db2ddSJeff Roberson gotit: 65113db2ddSJeff Roberson fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; 66113db2ddSJeff Roberson ffs_clrblock(fs, blksfree, (long)bno); 67113db2ddSJeff Roberson ffs_clusteracct(fs, cgp, bno, -1); 68113db2ddSJeff Roberson cgp->cg_cs.cs_nbfree--; 69113db2ddSJeff Roberson fs->fs_cstotal.cs_nbfree--; 70113db2ddSJeff Roberson fs->fs_fmod = 1; 71113db2ddSJeff Roberson return (cgbase(fs, cgp->cg_cgx) + blkstofrags(fs, bno)); 72113db2ddSJeff Roberson } 73113db2ddSJeff Roberson 74113db2ddSJeff Roberson int 75113db2ddSJeff Roberson cgbfree(struct uufsd *disk, ufs2_daddr_t bno, long size) 76113db2ddSJeff Roberson { 77113db2ddSJeff Roberson u_int8_t *blksfree; 78113db2ddSJeff Roberson struct fs *fs; 79113db2ddSJeff Roberson struct cg *cgp; 80113db2ddSJeff Roberson ufs1_daddr_t fragno, cgbno; 81113db2ddSJeff Roberson int i, cg, blk, frags, bbase; 82113db2ddSJeff Roberson 83113db2ddSJeff Roberson fs = &disk->d_fs; 84113db2ddSJeff Roberson cg = dtog(fs, bno); 85113db2ddSJeff Roberson if (cgread1(disk, cg) != 1) 86113db2ddSJeff Roberson return (-1); 87113db2ddSJeff Roberson cgp = &disk->d_cg; 88113db2ddSJeff Roberson cgbno = dtogd(fs, bno); 89113db2ddSJeff Roberson blksfree = cg_blksfree(cgp); 90113db2ddSJeff Roberson if (size == fs->fs_bsize) { 91113db2ddSJeff Roberson fragno = fragstoblks(fs, cgbno); 92113db2ddSJeff Roberson ffs_setblock(fs, blksfree, fragno); 93113db2ddSJeff Roberson ffs_clusteracct(fs, cgp, fragno, 1); 94113db2ddSJeff Roberson cgp->cg_cs.cs_nbfree++; 95113db2ddSJeff Roberson fs->fs_cstotal.cs_nbfree++; 96113db2ddSJeff Roberson fs->fs_cs(fs, cg).cs_nbfree++; 97113db2ddSJeff Roberson } else { 98113db2ddSJeff Roberson bbase = cgbno - fragnum(fs, cgbno); 99113db2ddSJeff Roberson /* 100113db2ddSJeff Roberson * decrement the counts associated with the old frags 101113db2ddSJeff Roberson */ 102113db2ddSJeff Roberson blk = blkmap(fs, blksfree, bbase); 103113db2ddSJeff Roberson ffs_fragacct(fs, blk, cgp->cg_frsum, -1); 104113db2ddSJeff Roberson /* 105113db2ddSJeff Roberson * deallocate the fragment 106113db2ddSJeff Roberson */ 107113db2ddSJeff Roberson frags = numfrags(fs, size); 108113db2ddSJeff Roberson for (i = 0; i < frags; i++) 109113db2ddSJeff Roberson setbit(blksfree, cgbno + i); 110113db2ddSJeff Roberson cgp->cg_cs.cs_nffree += i; 111113db2ddSJeff Roberson fs->fs_cstotal.cs_nffree += i; 112113db2ddSJeff Roberson fs->fs_cs(fs, cg).cs_nffree += i; 113113db2ddSJeff Roberson /* 114113db2ddSJeff Roberson * add back in counts associated with the new frags 115113db2ddSJeff Roberson */ 116113db2ddSJeff Roberson blk = blkmap(fs, blksfree, bbase); 117113db2ddSJeff Roberson ffs_fragacct(fs, blk, cgp->cg_frsum, 1); 118113db2ddSJeff Roberson /* 119113db2ddSJeff Roberson * if a complete block has been reassembled, account for it 120113db2ddSJeff Roberson */ 121113db2ddSJeff Roberson fragno = fragstoblks(fs, bbase); 122113db2ddSJeff Roberson if (ffs_isblock(fs, blksfree, fragno)) { 123113db2ddSJeff Roberson cgp->cg_cs.cs_nffree -= fs->fs_frag; 124113db2ddSJeff Roberson fs->fs_cstotal.cs_nffree -= fs->fs_frag; 125113db2ddSJeff Roberson fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 126113db2ddSJeff Roberson ffs_clusteracct(fs, cgp, fragno, 1); 127113db2ddSJeff Roberson cgp->cg_cs.cs_nbfree++; 128113db2ddSJeff Roberson fs->fs_cstotal.cs_nbfree++; 129113db2ddSJeff Roberson fs->fs_cs(fs, cg).cs_nbfree++; 130113db2ddSJeff Roberson } 131113db2ddSJeff Roberson } 132113db2ddSJeff Roberson return cgwrite(disk); 133113db2ddSJeff Roberson } 134113db2ddSJeff Roberson 135113db2ddSJeff Roberson ino_t 136113db2ddSJeff Roberson cgialloc(struct uufsd *disk) 137113db2ddSJeff Roberson { 138113db2ddSJeff Roberson struct ufs2_dinode *dp2; 139113db2ddSJeff Roberson u_int8_t *inosused; 140113db2ddSJeff Roberson struct cg *cgp; 141113db2ddSJeff Roberson struct fs *fs; 142113db2ddSJeff Roberson ino_t ino; 143113db2ddSJeff Roberson int i; 144113db2ddSJeff Roberson 145113db2ddSJeff Roberson fs = &disk->d_fs; 146113db2ddSJeff Roberson cgp = &disk->d_cg; 147113db2ddSJeff Roberson inosused = cg_inosused(cgp); 148b97e003fSEd Maste for (ino = 0; ino < fs->fs_ipg; ino++) 149113db2ddSJeff Roberson if (isclr(inosused, ino)) 150113db2ddSJeff Roberson goto gotit; 151113db2ddSJeff Roberson return (0); 152113db2ddSJeff Roberson gotit: 153113db2ddSJeff Roberson if (fs->fs_magic == FS_UFS2_MAGIC && 154113db2ddSJeff Roberson ino + INOPB(fs) > cgp->cg_initediblk && 155113db2ddSJeff Roberson cgp->cg_initediblk < cgp->cg_niblk) { 156113db2ddSJeff Roberson char block[MAXBSIZE]; 157113db2ddSJeff Roberson bzero(block, (int)fs->fs_bsize); 158113db2ddSJeff Roberson dp2 = (struct ufs2_dinode *)█ 159113db2ddSJeff Roberson for (i = 0; i < INOPB(fs); i++) { 160*44444759SPedro F. Giffuni dp2->di_gen = arc4random(); 161113db2ddSJeff Roberson dp2++; 162113db2ddSJeff Roberson } 163113db2ddSJeff Roberson if (bwrite(disk, ino_to_fsba(fs, 164113db2ddSJeff Roberson cgp->cg_cgx * fs->fs_ipg + cgp->cg_initediblk), 165113db2ddSJeff Roberson block, fs->fs_bsize)) 166113db2ddSJeff Roberson return (0); 167113db2ddSJeff Roberson cgp->cg_initediblk += INOPB(fs); 168113db2ddSJeff Roberson } 169113db2ddSJeff Roberson 170113db2ddSJeff Roberson setbit(inosused, ino); 171113db2ddSJeff Roberson cgp->cg_irotor = ino; 172113db2ddSJeff Roberson cgp->cg_cs.cs_nifree--; 173113db2ddSJeff Roberson fs->fs_cstotal.cs_nifree--; 174113db2ddSJeff Roberson fs->fs_cs(fs, cgp->cg_cgx).cs_nifree--; 175113db2ddSJeff Roberson fs->fs_fmod = 1; 176113db2ddSJeff Roberson 177113db2ddSJeff Roberson return (ino + (cgp->cg_cgx * fs->fs_ipg)); 178113db2ddSJeff Roberson } 179113db2ddSJeff 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 206113db2ddSJeff Roberson cgwrite(struct uufsd *disk) 207113db2ddSJeff Roberson { 208113db2ddSJeff Roberson return (cgwrite1(disk, disk->d_lcg)); 209113db2ddSJeff Roberson } 210113db2ddSJeff Roberson 211113db2ddSJeff 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