1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2003 Juli Mallett. All rights reserved. 5 * 6 * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 7 * FreeBSD project. Redistribution and use in source and binary forms, with 8 * or without modification, are permitted provided that the following 9 * conditions are met: 10 * 11 * 1. Redistribution of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 2. Redistribution in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/mount.h> 35 #include <sys/disklabel.h> 36 #include <sys/stat.h> 37 38 #include <ufs/ufs/ufsmount.h> 39 #include <ufs/ufs/dinode.h> 40 #include <ufs/ffs/fs.h> 41 42 #include <errno.h> 43 #include <fcntl.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 49 #include <libufs.h> 50 51 ufs2_daddr_t 52 cgballoc(struct uufsd *disk) 53 { 54 u_int8_t *blksfree; 55 struct cg *cgp; 56 struct fs *fs; 57 long bno; 58 59 fs = &disk->d_fs; 60 cgp = &disk->d_cg; 61 blksfree = cg_blksfree(cgp); 62 for (bno = 0; bno < fs->fs_fpg / fs->fs_frag; bno++) 63 if (ffs_isblock(fs, blksfree, bno)) 64 goto gotit; 65 return (0); 66 gotit: 67 fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; 68 ffs_clrblock(fs, blksfree, (long)bno); 69 ffs_clusteracct(fs, cgp, bno, -1); 70 cgp->cg_cs.cs_nbfree--; 71 fs->fs_cstotal.cs_nbfree--; 72 fs->fs_fmod = 1; 73 return (cgbase(fs, cgp->cg_cgx) + blkstofrags(fs, bno)); 74 } 75 76 int 77 cgbfree(struct uufsd *disk, ufs2_daddr_t bno, long size) 78 { 79 u_int8_t *blksfree; 80 struct fs *fs; 81 struct cg *cgp; 82 ufs1_daddr_t fragno, cgbno; 83 int i, cg, blk, frags, bbase; 84 85 fs = &disk->d_fs; 86 cg = dtog(fs, bno); 87 if (cgread1(disk, cg) != 1) 88 return (-1); 89 cgp = &disk->d_cg; 90 cgbno = dtogd(fs, bno); 91 blksfree = cg_blksfree(cgp); 92 if (size == fs->fs_bsize) { 93 fragno = fragstoblks(fs, cgbno); 94 ffs_setblock(fs, blksfree, fragno); 95 ffs_clusteracct(fs, cgp, fragno, 1); 96 cgp->cg_cs.cs_nbfree++; 97 fs->fs_cstotal.cs_nbfree++; 98 fs->fs_cs(fs, cg).cs_nbfree++; 99 } else { 100 bbase = cgbno - fragnum(fs, cgbno); 101 /* 102 * decrement the counts associated with the old frags 103 */ 104 blk = blkmap(fs, blksfree, bbase); 105 ffs_fragacct(fs, blk, cgp->cg_frsum, -1); 106 /* 107 * deallocate the fragment 108 */ 109 frags = numfrags(fs, size); 110 for (i = 0; i < frags; i++) 111 setbit(blksfree, cgbno + i); 112 cgp->cg_cs.cs_nffree += i; 113 fs->fs_cstotal.cs_nffree += i; 114 fs->fs_cs(fs, cg).cs_nffree += i; 115 /* 116 * add back in counts associated with the new frags 117 */ 118 blk = blkmap(fs, blksfree, bbase); 119 ffs_fragacct(fs, blk, cgp->cg_frsum, 1); 120 /* 121 * if a complete block has been reassembled, account for it 122 */ 123 fragno = fragstoblks(fs, bbase); 124 if (ffs_isblock(fs, blksfree, fragno)) { 125 cgp->cg_cs.cs_nffree -= fs->fs_frag; 126 fs->fs_cstotal.cs_nffree -= fs->fs_frag; 127 fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 128 ffs_clusteracct(fs, cgp, fragno, 1); 129 cgp->cg_cs.cs_nbfree++; 130 fs->fs_cstotal.cs_nbfree++; 131 fs->fs_cs(fs, cg).cs_nbfree++; 132 } 133 } 134 return cgwrite(disk); 135 } 136 137 ino_t 138 cgialloc(struct uufsd *disk) 139 { 140 struct ufs2_dinode *dp2; 141 u_int8_t *inosused; 142 struct cg *cgp; 143 struct fs *fs; 144 ino_t ino; 145 int i; 146 147 fs = &disk->d_fs; 148 cgp = &disk->d_cg; 149 inosused = cg_inosused(cgp); 150 for (ino = 0; ino < fs->fs_ipg; ino++) 151 if (isclr(inosused, ino)) 152 goto gotit; 153 return (0); 154 gotit: 155 if (fs->fs_magic == FS_UFS2_MAGIC && 156 ino + INOPB(fs) > cgp->cg_initediblk && 157 cgp->cg_initediblk < cgp->cg_niblk) { 158 char block[MAXBSIZE]; 159 bzero(block, (int)fs->fs_bsize); 160 dp2 = (struct ufs2_dinode *)█ 161 for (i = 0; i < INOPB(fs); i++) { 162 dp2->di_gen = arc4random(); 163 dp2++; 164 } 165 if (bwrite(disk, ino_to_fsba(fs, 166 cgp->cg_cgx * fs->fs_ipg + cgp->cg_initediblk), 167 block, fs->fs_bsize)) 168 return (0); 169 cgp->cg_initediblk += INOPB(fs); 170 } 171 172 setbit(inosused, ino); 173 cgp->cg_irotor = ino; 174 cgp->cg_cs.cs_nifree--; 175 fs->fs_cstotal.cs_nifree--; 176 fs->fs_cs(fs, cgp->cg_cgx).cs_nifree--; 177 fs->fs_fmod = 1; 178 179 return (ino + (cgp->cg_cgx * fs->fs_ipg)); 180 } 181 182 int 183 cgread(struct uufsd *disk) 184 { 185 return (cgread1(disk, disk->d_ccg++)); 186 } 187 188 int 189 cgread1(struct uufsd *disk, int c) 190 { 191 struct fs *fs; 192 193 fs = &disk->d_fs; 194 195 if ((unsigned)c >= fs->fs_ncg) { 196 return (0); 197 } 198 if (bread(disk, fsbtodb(fs, cgtod(fs, c)), disk->d_cgunion.d_buf, 199 fs->fs_bsize) == -1) { 200 ERROR(disk, "unable to read cylinder group"); 201 return (-1); 202 } 203 disk->d_lcg = c; 204 return (1); 205 } 206 207 int 208 cgwrite(struct uufsd *disk) 209 { 210 return (cgwrite1(disk, disk->d_lcg)); 211 } 212 213 int 214 cgwrite1(struct uufsd *disk, int c) 215 { 216 struct fs *fs; 217 218 fs = &disk->d_fs; 219 if ((fs->fs_metackhash & CK_CYLGRP) != 0) { 220 disk->d_cg.cg_ckhash = 0; 221 disk->d_cg.cg_ckhash = 222 calculate_crc32c(~0L, (void *)&disk->d_cg, fs->fs_cgsize); 223 } 224 if (bwrite(disk, fsbtodb(fs, cgtod(fs, c)), 225 disk->d_cgunion.d_buf, fs->fs_bsize) == -1) { 226 ERROR(disk, "unable to write cylinder group"); 227 return (-1); 228 } 229 return (0); 230 } 231