1 /*- 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include <sys/param.h> 36 37 #ifndef _KERNEL 38 #include <ufs/ufs/dinode.h> 39 #include <ufs/ffs/fs.h> 40 #else 41 #include <sys/systm.h> 42 #include <sys/lock.h> 43 #include <sys/malloc.h> 44 #include <sys/mount.h> 45 #include <sys/vnode.h> 46 #include <sys/bio.h> 47 #include <sys/buf.h> 48 #include <sys/ucred.h> 49 50 #include <ufs/ufs/quota.h> 51 #include <ufs/ufs/inode.h> 52 #include <ufs/ufs/extattr.h> 53 #include <ufs/ufs/ufsmount.h> 54 #include <ufs/ufs/ufs_extern.h> 55 #include <ufs/ffs/ffs_extern.h> 56 #include <ufs/ffs/fs.h> 57 58 #ifdef KDB 59 void ffs_checkoverlap(struct buf *, struct inode *); 60 #endif 61 62 /* 63 * Return buffer with the contents of block "offset" from the beginning of 64 * directory "ip". If "res" is non-zero, fill it in with a pointer to the 65 * remaining space in the directory. 66 */ 67 int 68 ffs_blkatoff(vp, offset, res, bpp) 69 struct vnode *vp; 70 off_t offset; 71 char **res; 72 struct buf **bpp; 73 { 74 struct inode *ip; 75 struct fs *fs; 76 struct buf *bp; 77 ufs_lbn_t lbn; 78 int bsize, error; 79 80 ip = VTOI(vp); 81 fs = ip->i_fs; 82 lbn = lblkno(fs, offset); 83 bsize = blksize(fs, ip, lbn); 84 85 *bpp = NULL; 86 error = bread(vp, lbn, bsize, NOCRED, &bp); 87 if (error) { 88 brelse(bp); 89 return (error); 90 } 91 if (res) 92 *res = (char *)bp->b_data + blkoff(fs, offset); 93 *bpp = bp; 94 return (0); 95 } 96 97 /* 98 * Load up the contents of an inode and copy the appropriate pieces 99 * to the incore copy. 100 */ 101 void 102 ffs_load_inode(bp, ip, fs, ino) 103 struct buf *bp; 104 struct inode *ip; 105 struct fs *fs; 106 ino_t ino; 107 { 108 109 if (ip->i_ump->um_fstype == UFS1) { 110 *ip->i_din1 = 111 *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 112 ip->i_mode = ip->i_din1->di_mode; 113 ip->i_nlink = ip->i_din1->di_nlink; 114 ip->i_size = ip->i_din1->di_size; 115 ip->i_flags = ip->i_din1->di_flags; 116 ip->i_gen = ip->i_din1->di_gen; 117 ip->i_uid = ip->i_din1->di_uid; 118 ip->i_gid = ip->i_din1->di_gid; 119 } else { 120 *ip->i_din2 = 121 *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 122 ip->i_mode = ip->i_din2->di_mode; 123 ip->i_nlink = ip->i_din2->di_nlink; 124 ip->i_size = ip->i_din2->di_size; 125 ip->i_flags = ip->i_din2->di_flags; 126 ip->i_gen = ip->i_din2->di_gen; 127 ip->i_uid = ip->i_din2->di_uid; 128 ip->i_gid = ip->i_din2->di_gid; 129 } 130 } 131 #endif /* KERNEL */ 132 133 /* 134 * Update the frsum fields to reflect addition or deletion 135 * of some frags. 136 */ 137 void 138 ffs_fragacct(fs, fragmap, fraglist, cnt) 139 struct fs *fs; 140 int fragmap; 141 int32_t fraglist[]; 142 int cnt; 143 { 144 int inblk; 145 int field, subfield; 146 int siz, pos; 147 148 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 149 fragmap <<= 1; 150 for (siz = 1; siz < fs->fs_frag; siz++) { 151 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 152 continue; 153 field = around[siz]; 154 subfield = inside[siz]; 155 for (pos = siz; pos <= fs->fs_frag; pos++) { 156 if ((fragmap & field) == subfield) { 157 fraglist[siz] += cnt; 158 pos += siz; 159 field <<= siz; 160 subfield <<= siz; 161 } 162 field <<= 1; 163 subfield <<= 1; 164 } 165 } 166 } 167 168 #ifdef KDB 169 void 170 ffs_checkoverlap(bp, ip) 171 struct buf *bp; 172 struct inode *ip; 173 { 174 struct buf *ebp, *ep; 175 ufs2_daddr_t start, last; 176 struct vnode *vp; 177 178 ebp = &buf[nbuf]; 179 start = bp->b_blkno; 180 last = start + btodb(bp->b_bcount) - 1; 181 for (ep = buf; ep < ebp; ep++) { 182 if (ep == bp || (ep->b_flags & B_INVAL) || 183 ep->b_vp == NULLVP) 184 continue; 185 vp = ip->i_devvp; 186 /* look for overlap */ 187 if (ep->b_bcount == 0 || ep->b_blkno > last || 188 ep->b_blkno + btodb(ep->b_bcount) <= start) 189 continue; 190 vprint("Disk overlap", vp); 191 printf("\tstart %jd, end %jd overlap start %jd, end %jd\n", 192 (intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno, 193 (intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1)); 194 panic("ffs_checkoverlap: Disk buffer overlap"); 195 } 196 } 197 #endif /* KDB */ 198 199 /* 200 * block operations 201 * 202 * check if a block is available 203 */ 204 int 205 ffs_isblock(fs, cp, h) 206 struct fs *fs; 207 unsigned char *cp; 208 ufs1_daddr_t h; 209 { 210 unsigned char mask; 211 212 switch ((int)fs->fs_frag) { 213 case 8: 214 return (cp[h] == 0xff); 215 case 4: 216 mask = 0x0f << ((h & 0x1) << 2); 217 return ((cp[h >> 1] & mask) == mask); 218 case 2: 219 mask = 0x03 << ((h & 0x3) << 1); 220 return ((cp[h >> 2] & mask) == mask); 221 case 1: 222 mask = 0x01 << (h & 0x7); 223 return ((cp[h >> 3] & mask) == mask); 224 default: 225 #ifdef _KERNEL 226 panic("ffs_isblock"); 227 #endif 228 break; 229 } 230 return (0); 231 } 232 233 /* 234 * check if a block is free 235 */ 236 int 237 ffs_isfreeblock(fs, cp, h) 238 struct fs *fs; 239 u_char *cp; 240 ufs1_daddr_t h; 241 { 242 243 switch ((int)fs->fs_frag) { 244 case 8: 245 return (cp[h] == 0); 246 case 4: 247 return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0); 248 case 2: 249 return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0); 250 case 1: 251 return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0); 252 default: 253 #ifdef _KERNEL 254 panic("ffs_isfreeblock"); 255 #endif 256 break; 257 } 258 return (0); 259 } 260 261 /* 262 * take a block out of the map 263 */ 264 void 265 ffs_clrblock(fs, cp, h) 266 struct fs *fs; 267 u_char *cp; 268 ufs1_daddr_t h; 269 { 270 271 switch ((int)fs->fs_frag) { 272 case 8: 273 cp[h] = 0; 274 return; 275 case 4: 276 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 277 return; 278 case 2: 279 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 280 return; 281 case 1: 282 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 283 return; 284 default: 285 #ifdef _KERNEL 286 panic("ffs_clrblock"); 287 #endif 288 break; 289 } 290 } 291 292 /* 293 * put a block into the map 294 */ 295 void 296 ffs_setblock(fs, cp, h) 297 struct fs *fs; 298 unsigned char *cp; 299 ufs1_daddr_t h; 300 { 301 302 switch ((int)fs->fs_frag) { 303 304 case 8: 305 cp[h] = 0xff; 306 return; 307 case 4: 308 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 309 return; 310 case 2: 311 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 312 return; 313 case 1: 314 cp[h >> 3] |= (0x01 << (h & 0x7)); 315 return; 316 default: 317 #ifdef _KERNEL 318 panic("ffs_setblock"); 319 #endif 320 break; 321 } 322 } 323 324 /* 325 * Update the cluster map because of an allocation or free. 326 * 327 * Cnt == 1 means free; cnt == -1 means allocating. 328 */ 329 void 330 ffs_clusteracct(fs, cgp, blkno, cnt) 331 struct fs *fs; 332 struct cg *cgp; 333 ufs1_daddr_t blkno; 334 int cnt; 335 { 336 int32_t *sump; 337 int32_t *lp; 338 u_char *freemapp, *mapp; 339 int i, start, end, forw, back, map, bit; 340 341 if (fs->fs_contigsumsize <= 0) 342 return; 343 freemapp = cg_clustersfree(cgp); 344 sump = cg_clustersum(cgp); 345 /* 346 * Allocate or clear the actual block. 347 */ 348 if (cnt > 0) 349 setbit(freemapp, blkno); 350 else 351 clrbit(freemapp, blkno); 352 /* 353 * Find the size of the cluster going forward. 354 */ 355 start = blkno + 1; 356 end = start + fs->fs_contigsumsize; 357 if (end >= cgp->cg_nclusterblks) 358 end = cgp->cg_nclusterblks; 359 mapp = &freemapp[start / NBBY]; 360 map = *mapp++; 361 bit = 1 << (start % NBBY); 362 for (i = start; i < end; i++) { 363 if ((map & bit) == 0) 364 break; 365 if ((i & (NBBY - 1)) != (NBBY - 1)) { 366 bit <<= 1; 367 } else { 368 map = *mapp++; 369 bit = 1; 370 } 371 } 372 forw = i - start; 373 /* 374 * Find the size of the cluster going backward. 375 */ 376 start = blkno - 1; 377 end = start - fs->fs_contigsumsize; 378 if (end < 0) 379 end = -1; 380 mapp = &freemapp[start / NBBY]; 381 map = *mapp--; 382 bit = 1 << (start % NBBY); 383 for (i = start; i > end; i--) { 384 if ((map & bit) == 0) 385 break; 386 if ((i & (NBBY - 1)) != 0) { 387 bit >>= 1; 388 } else { 389 map = *mapp--; 390 bit = 1 << (NBBY - 1); 391 } 392 } 393 back = start - i; 394 /* 395 * Account for old cluster and the possibly new forward and 396 * back clusters. 397 */ 398 i = back + forw + 1; 399 if (i > fs->fs_contigsumsize) 400 i = fs->fs_contigsumsize; 401 sump[i] += cnt; 402 if (back > 0) 403 sump[back] -= cnt; 404 if (forw > 0) 405 sump[forw] -= cnt; 406 /* 407 * Update cluster summary information. 408 */ 409 lp = &sump[fs->fs_contigsumsize]; 410 for (i = fs->fs_contigsumsize; i > 0; i--) 411 if (*lp-- > 0) 412 break; 413 fs->fs_maxcluster[cgp->cg_cgx] = i; 414 } 415