1 /* $NetBSD: ffs_subr.c,v 1.54 2023/01/07 19:41:30 chs Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95 32 */ 33 34 #if HAVE_NBTOOL_CONFIG_H 35 #include "nbtool_config.h" 36 #endif 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: ffs_subr.c,v 1.54 2023/01/07 19:41:30 chs Exp $"); 40 41 #include <sys/param.h> 42 43 /* in ffs_tables.c */ 44 extern const int inside[], around[]; 45 extern const u_char * const fragtbl[]; 46 47 #ifndef _KERNEL 48 #define FFS_EI /* always include byteswapped filesystems support */ 49 #endif 50 #include <ufs/ffs/fs.h> 51 #include <ufs/ffs/ffs_extern.h> 52 #include <ufs/ufs/ufs_bswap.h> 53 54 #ifndef _KERNEL 55 #include <ufs/ufs/dinode.h> 56 void panic(const char *, ...) 57 __attribute__((__noreturn__,__format__(__printf__,1,2))); 58 59 #else /* _KERNEL */ 60 #include <sys/systm.h> 61 #include <sys/vnode.h> 62 #include <sys/mount.h> 63 #include <sys/buf.h> 64 #include <sys/inttypes.h> 65 #include <sys/pool.h> 66 #include <sys/fstrans.h> 67 #include <ufs/ufs/inode.h> 68 #include <ufs/ufs/ufsmount.h> 69 #include <ufs/ufs/ufs_extern.h> 70 71 /* 72 * Load up the contents of an inode and copy the appropriate pieces 73 * to the incore copy. 74 */ 75 void 76 ffs_load_inode(struct buf *bp, struct inode *ip, struct fs *fs, ino_t ino) 77 { 78 struct ufs1_dinode *dp1; 79 struct ufs2_dinode *dp2; 80 81 if (ip->i_ump->um_fstype == UFS1) { 82 dp1 = (struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino); 83 #ifdef FFS_EI 84 if (UFS_FSNEEDSWAP(fs)) 85 ffs_dinode1_swap(dp1, ip->i_din.ffs1_din); 86 else 87 #endif 88 *ip->i_din.ffs1_din = *dp1; 89 90 ip->i_mode = ip->i_ffs1_mode; 91 ip->i_nlink = ip->i_ffs1_nlink; 92 ip->i_size = ip->i_ffs1_size; 93 ip->i_flags = ip->i_ffs1_flags; 94 ip->i_gen = ip->i_ffs1_gen; 95 ip->i_uid = ip->i_ffs1_uid; 96 ip->i_gid = ip->i_ffs1_gid; 97 } else { 98 dp2 = (struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino); 99 #ifdef FFS_EI 100 if (UFS_FSNEEDSWAP(fs)) 101 ffs_dinode2_swap(dp2, ip->i_din.ffs2_din); 102 else 103 #endif 104 *ip->i_din.ffs2_din = *dp2; 105 106 ip->i_mode = ip->i_ffs2_mode; 107 ip->i_nlink = ip->i_ffs2_nlink; 108 ip->i_size = ip->i_ffs2_size; 109 ip->i_flags = ip->i_ffs2_flags; 110 ip->i_gen = ip->i_ffs2_gen; 111 ip->i_uid = ip->i_ffs2_uid; 112 ip->i_gid = ip->i_ffs2_gid; 113 } 114 } 115 116 int 117 ffs_getblk(struct vnode *vp, daddr_t lblkno, daddr_t blkno, int size, 118 bool clearbuf, buf_t **bpp) 119 { 120 int error = 0; 121 122 KASSERT(blkno >= 0 || blkno == FFS_NOBLK); 123 124 if ((*bpp = getblk(vp, lblkno, size, 0, 0)) == NULL) 125 return ENOMEM; 126 if (blkno != FFS_NOBLK) 127 (*bpp)->b_blkno = blkno; 128 if (clearbuf) 129 clrbuf(*bpp); 130 if ((*bpp)->b_blkno >= 0 && (error = fscow_run(*bpp, false)) != 0) { 131 brelse(*bpp, BC_INVAL); 132 *bpp = NULL; 133 } 134 return error; 135 } 136 137 #endif /* _KERNEL */ 138 139 /* 140 * Update the frsum fields to reflect addition or deletion 141 * of some frags. 142 */ 143 void 144 ffs_fragacct(struct fs *fs, int fragmap, uint32_t fraglist[], int cnt, 145 int needswap) 146 { 147 int inblk; 148 int field, subfield; 149 int siz, pos; 150 151 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 152 fragmap <<= 1; 153 for (siz = 1; siz < fs->fs_frag; siz++) { 154 if ((inblk & (1 << (siz + (fs->fs_frag & (NBBY - 1))))) == 0) 155 continue; 156 field = around[siz]; 157 subfield = inside[siz]; 158 for (pos = siz; pos <= fs->fs_frag; pos++) { 159 if ((fragmap & field) == subfield) { 160 fraglist[siz] = ufs_rw32( 161 ufs_rw32(fraglist[siz], needswap) + cnt, 162 needswap); 163 pos += siz; 164 field <<= siz; 165 subfield <<= siz; 166 } 167 field <<= 1; 168 subfield <<= 1; 169 } 170 } 171 } 172 173 /* 174 * block operations 175 * 176 * check if a block is available 177 * returns true if all the corresponding bits in the free map are 1 178 * returns false if any corresponding bit in the free map is 0 179 */ 180 int 181 ffs_isblock(struct fs *fs, u_char *cp, int32_t h) 182 { 183 u_char mask; 184 185 switch ((int)fs->fs_fragshift) { 186 case 3: 187 return (cp[h] == 0xff); 188 case 2: 189 mask = 0x0f << ((h & 0x1) << 2); 190 return ((cp[h >> 1] & mask) == mask); 191 case 1: 192 mask = 0x03 << ((h & 0x3) << 1); 193 return ((cp[h >> 2] & mask) == mask); 194 case 0: 195 mask = 0x01 << (h & 0x7); 196 return ((cp[h >> 3] & mask) == mask); 197 default: 198 panic("%s: unknown fs_fragshift %d", __func__, 199 (int)fs->fs_fragshift); 200 } 201 } 202 203 /* 204 * check if a block is completely allocated 205 * returns true if all the corresponding bits in the free map are 0 206 * returns false if any corresponding bit in the free map is 1 207 */ 208 int 209 ffs_isfreeblock(struct fs *fs, u_char *cp, int32_t h) 210 { 211 212 switch ((int)fs->fs_fragshift) { 213 case 3: 214 return (cp[h] == 0); 215 case 2: 216 return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0); 217 case 1: 218 return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0); 219 case 0: 220 return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0); 221 default: 222 panic("%s: unknown fs_fragshift %d", __func__, 223 (int)fs->fs_fragshift); 224 } 225 } 226 227 /* 228 * take a block out of the map 229 */ 230 void 231 ffs_clrblock(struct fs *fs, u_char *cp, int32_t h) 232 { 233 234 switch ((int)fs->fs_fragshift) { 235 case 3: 236 cp[h] = 0; 237 return; 238 case 2: 239 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 240 return; 241 case 1: 242 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 243 return; 244 case 0: 245 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 246 return; 247 default: 248 panic("%s: unknown fs_fragshift %d", __func__, 249 (int)fs->fs_fragshift); 250 } 251 } 252 253 /* 254 * put a block into the map 255 */ 256 void 257 ffs_setblock(struct fs *fs, u_char *cp, int32_t h) 258 { 259 260 switch ((int)fs->fs_fragshift) { 261 case 3: 262 cp[h] = 0xff; 263 return; 264 case 2: 265 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 266 return; 267 case 1: 268 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 269 return; 270 case 0: 271 cp[h >> 3] |= (0x01 << (h & 0x7)); 272 return; 273 default: 274 panic("%s: unknown fs_fragshift %d", __func__, 275 (int)fs->fs_fragshift); 276 } 277 } 278 279 /* 280 * Update the cluster map because of an allocation or free. 281 * 282 * Cnt == 1 means free; cnt == -1 means allocating. 283 */ 284 void 285 ffs_clusteracct(struct fs *fs, struct cg *cgp, int32_t blkno, int cnt) 286 { 287 int32_t *sump; 288 int32_t *lp; 289 u_char *freemapp, *mapp; 290 int i, start, end, forw, back, map; 291 unsigned int bit; 292 const int needswap = UFS_FSNEEDSWAP(fs); 293 294 /* KASSERT(mutex_owned(&ump->um_lock)); */ 295 296 if (fs->fs_contigsumsize <= 0) 297 return; 298 freemapp = cg_clustersfree(cgp, needswap); 299 sump = cg_clustersum(cgp, needswap); 300 /* 301 * Allocate or clear the actual block. 302 */ 303 if (cnt > 0) 304 setbit(freemapp, blkno); 305 else 306 clrbit(freemapp, blkno); 307 /* 308 * Find the size of the cluster going forward. 309 */ 310 start = blkno + 1; 311 end = start + fs->fs_contigsumsize; 312 if ((uint32_t)end >= ufs_rw32(cgp->cg_nclusterblks, needswap)) 313 end = ufs_rw32(cgp->cg_nclusterblks, needswap); 314 mapp = &freemapp[start / NBBY]; 315 map = *mapp++; 316 bit = 1U << ((unsigned int)start % NBBY); 317 for (i = start; i < end; i++) { 318 if ((map & bit) == 0) 319 break; 320 if ((i & (NBBY - 1)) != (NBBY - 1)) { 321 bit <<= 1; 322 } else { 323 map = *mapp++; 324 bit = 1; 325 } 326 } 327 forw = i - start; 328 /* 329 * Find the size of the cluster going backward. 330 */ 331 start = blkno - 1; 332 end = start - fs->fs_contigsumsize; 333 if (end < 0) 334 end = -1; 335 mapp = &freemapp[start / NBBY]; 336 map = *mapp--; 337 bit = 1U << ((unsigned int)start % NBBY); 338 for (i = start; i > end; i--) { 339 if ((map & bit) == 0) 340 break; 341 if ((i & (NBBY - 1)) != 0) { 342 bit >>= 1; 343 } else { 344 map = *mapp--; 345 bit = 1U << (NBBY - 1); 346 } 347 } 348 back = start - i; 349 /* 350 * Account for old cluster and the possibly new forward and 351 * back clusters. 352 */ 353 i = back + forw + 1; 354 if (i > fs->fs_contigsumsize) 355 i = fs->fs_contigsumsize; 356 ufs_add32(sump[i], cnt, needswap); 357 if (back > 0) 358 ufs_add32(sump[back], -cnt, needswap); 359 if (forw > 0) 360 ufs_add32(sump[forw], -cnt, needswap); 361 362 /* 363 * Update cluster summary information. 364 */ 365 lp = &sump[fs->fs_contigsumsize]; 366 for (i = fs->fs_contigsumsize; i > 0; i--) 367 if (ufs_rw32(*lp--, needswap) > 0) 368 break; 369 #if defined(_KERNEL) 370 fs->fs_maxcluster[ufs_rw32(cgp->cg_cgx, needswap)] = i; 371 #endif 372 } 373