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 186 if (disk->d_ccg >= disk->d_fs.fs_ncg) 187 return (0); 188 return (cgread1(disk, disk->d_ccg++)); 189 } 190 191 int 192 cgread1(struct uufsd *disk, int c) 193 { 194 195 if ((cgget(disk, c, &disk->d_cg)) == 0) 196 return (1); 197 return (-1); 198 } 199 200 int 201 cgget(struct uufsd *disk, int cg, struct cg *cgp) 202 { 203 struct fs *fs; 204 uint32_t cghash, calchash; 205 206 fs = &disk->d_fs; 207 if (bread(disk, fsbtodb(fs, cgtod(fs, cg)), (void *)cgp, 208 fs->fs_cgsize) == -1) { 209 ERROR(disk, "unable to read cylinder group"); 210 return (-1); 211 } 212 calchash = cgp->cg_ckhash; 213 if ((fs->fs_metackhash & CK_CYLGRP) != 0) { 214 cghash = cgp->cg_ckhash; 215 cgp->cg_ckhash = 0; 216 calchash = calculate_crc32c(~0L, (void *)cgp, fs->fs_cgsize); 217 cgp->cg_ckhash = cghash; 218 } 219 if (cgp->cg_ckhash != calchash || !cg_chkmagic(cgp) || 220 cgp->cg_cgx != cg) { 221 ERROR(disk, "cylinder group checks failed"); 222 errno = EIO; 223 return (-1); 224 } 225 disk->d_lcg = cg; 226 return (0); 227 } 228 229 int 230 cgwrite(struct uufsd *disk) 231 { 232 233 return (cgput(disk, &disk->d_cg)); 234 } 235 236 int 237 cgwrite1(struct uufsd *disk, int cg) 238 { 239 static char errmsg[BUFSIZ]; 240 241 if (cg == disk->d_cg.cg_cgx) 242 return (cgput(disk, &disk->d_cg)); 243 snprintf(errmsg, BUFSIZ, "Cylinder group %d in buffer does not match " 244 "the cylinder group %d that cgwrite1 requested", 245 disk->d_cg.cg_cgx, cg); 246 ERROR(disk, errmsg); 247 errno = EDOOFUS; 248 return (-1); 249 } 250 251 int 252 cgput(struct uufsd *disk, struct cg *cgp) 253 { 254 struct fs *fs; 255 256 fs = &disk->d_fs; 257 if ((fs->fs_metackhash & CK_CYLGRP) != 0) { 258 cgp->cg_ckhash = 0; 259 cgp->cg_ckhash = 260 calculate_crc32c(~0L, (void *)cgp, fs->fs_cgsize); 261 } 262 if (bwrite(disk, fsbtodb(fs, cgtod(fs, cgp->cg_cgx)), cgp, 263 fs->fs_cgsize) == -1) { 264 ERROR(disk, "unable to write cylinder group"); 265 return (-1); 266 } 267 return (0); 268 } 269