1 /* $NetBSD: ffs_subr.c,v 1.49 2016/05/07 11:59:08 maxv 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.49 2016/05/07 11:59:08 maxv 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, int32_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 correponding 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("ffs_isblock: unknown fs_fragshift %d", 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("ffs_isfreeblock: unknown fs_fragshift %d", 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("ffs_clrblock: unknown fs_fragshift %d", 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("ffs_setblock: unknown fs_fragshift %d", 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, bit; 291 const int needswap = UFS_FSNEEDSWAP(fs); 292 293 /* KASSERT(mutex_owned(&ump->um_lock)); */ 294 295 if (fs->fs_contigsumsize <= 0) 296 return; 297 freemapp = cg_clustersfree(cgp, needswap); 298 sump = cg_clustersum(cgp, needswap); 299 /* 300 * Allocate or clear the actual block. 301 */ 302 if (cnt > 0) 303 setbit(freemapp, blkno); 304 else 305 clrbit(freemapp, blkno); 306 /* 307 * Find the size of the cluster going forward. 308 */ 309 start = blkno + 1; 310 end = start + fs->fs_contigsumsize; 311 if ((uint32_t)end >= ufs_rw32(cgp->cg_nclusterblks, needswap)) 312 end = ufs_rw32(cgp->cg_nclusterblks, needswap); 313 mapp = &freemapp[start / NBBY]; 314 map = *mapp++; 315 bit = 1 << (start % NBBY); 316 for (i = start; i < end; i++) { 317 if ((map & bit) == 0) 318 break; 319 if ((i & (NBBY - 1)) != (NBBY - 1)) { 320 bit <<= 1; 321 } else { 322 map = *mapp++; 323 bit = 1; 324 } 325 } 326 forw = i - start; 327 /* 328 * Find the size of the cluster going backward. 329 */ 330 start = blkno - 1; 331 end = start - fs->fs_contigsumsize; 332 if (end < 0) 333 end = -1; 334 mapp = &freemapp[start / NBBY]; 335 map = *mapp--; 336 bit = 1 << (start % NBBY); 337 for (i = start; i > end; i--) { 338 if ((map & bit) == 0) 339 break; 340 if ((i & (NBBY - 1)) != 0) { 341 bit >>= 1; 342 } else { 343 map = *mapp--; 344 bit = 1 << (NBBY - 1); 345 } 346 } 347 back = start - i; 348 /* 349 * Account for old cluster and the possibly new forward and 350 * back clusters. 351 */ 352 i = back + forw + 1; 353 if (i > fs->fs_contigsumsize) 354 i = fs->fs_contigsumsize; 355 ufs_add32(sump[i], cnt, needswap); 356 if (back > 0) 357 ufs_add32(sump[back], -cnt, needswap); 358 if (forw > 0) 359 ufs_add32(sump[forw], -cnt, needswap); 360 361 /* 362 * Update cluster summary information. 363 */ 364 lp = &sump[fs->fs_contigsumsize]; 365 for (i = fs->fs_contigsumsize; i > 0; i--) 366 if (ufs_rw32(*lp--, needswap) > 0) 367 break; 368 #if defined(_KERNEL) 369 fs->fs_maxcluster[ufs_rw32(cgp->cg_cgx, needswap)] = i; 370 #endif 371 } 372