1c8bc2536Smckusick /* 2065083aeSmckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3065083aeSmckusick * All rights reserved. 4c8bc2536Smckusick * 58eb14236Sbostic * %sccs.include.redist.c% 6065083aeSmckusick * 7*42026a80Sheideman * @(#)ffs_subr.c 7.19 (Berkeley) 05/14/92 8c8bc2536Smckusick */ 92fd425aeSroot 102fd425aeSroot #include <sys/param.h> 11f07aac44Sheideman #include <sys/vnode.h> 12507878abSbostic #include <ufs/ffs/fs.h> 13507878abSbostic #include <ufs/ffs/ffs_extern.h> 14507878abSbostic 15898d8e57Sbostic #ifdef KERNEL 16e8e9bf15Smckusick #include <sys/buf.h> 17e8e9bf15Smckusick #include <ufs/ufs/quota.h> 18e8e9bf15Smckusick #include <ufs/ufs/inode.h> 19898d8e57Sbostic 20507878abSbostic /* 21507878abSbostic * Return buffer with the contents of block "offset" from the beginning of 22507878abSbostic * directory "ip". If "res" is non-zero, fill it in with a pointer to the 23507878abSbostic * remaining space in the directory. 24507878abSbostic */ 25507878abSbostic int 26*42026a80Sheideman ffs_blkatoff (ap) 27*42026a80Sheideman struct vop_blkatoff_args *ap; 28*42026a80Sheideman #define vp (ap->a_vp) 29*42026a80Sheideman #define offset (ap->a_offset) 30*42026a80Sheideman #define res (ap->a_res) 31*42026a80Sheideman #define bpp (ap->a_bpp) 32507878abSbostic { 33297a81e4Smckusick struct inode *ip; 34507878abSbostic register struct fs *fs; 35507878abSbostic struct buf *bp; 36507878abSbostic daddr_t lbn; 37507878abSbostic int bsize, error; 38507878abSbostic 39297a81e4Smckusick ip = VTOI(vp); 40507878abSbostic fs = ip->i_fs; 41507878abSbostic lbn = lblkno(fs, offset); 42507878abSbostic bsize = blksize(fs, ip, lbn); 43507878abSbostic 44507878abSbostic *bpp = NULL; 45297a81e4Smckusick if (error = bread(vp, lbn, bsize, NOCRED, &bp)) { 46507878abSbostic brelse(bp); 47507878abSbostic return (error); 48507878abSbostic } 49507878abSbostic if (res) 50507878abSbostic *res = bp->b_un.b_addr + blkoff(fs, offset); 51507878abSbostic *bpp = bp; 52507878abSbostic return (0); 53507878abSbostic } 54*42026a80Sheideman #undef vp 55*42026a80Sheideman #undef offset 56*42026a80Sheideman #undef res 57*42026a80Sheideman #undef bpp 58898d8e57Sbostic #endif 592fd425aeSroot 602fd425aeSroot /* 612fd425aeSroot * Update the frsum fields to reflect addition or deletion 622fd425aeSroot * of some frags. 632fd425aeSroot */ 64507878abSbostic void 65507878abSbostic ffs_fragacct(fs, fragmap, fraglist, cnt) 662fd425aeSroot struct fs *fs; 672fd425aeSroot int fragmap; 682fd425aeSroot long fraglist[]; 692fd425aeSroot int cnt; 702fd425aeSroot { 712fd425aeSroot int inblk; 722fd425aeSroot register int field, subfield; 732fd425aeSroot register int siz, pos; 742fd425aeSroot 752fd425aeSroot inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 762fd425aeSroot fragmap <<= 1; 772fd425aeSroot for (siz = 1; siz < fs->fs_frag; siz++) { 782fd425aeSroot if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 792fd425aeSroot continue; 802fd425aeSroot field = around[siz]; 812fd425aeSroot subfield = inside[siz]; 822fd425aeSroot for (pos = siz; pos <= fs->fs_frag; pos++) { 832fd425aeSroot if ((fragmap & field) == subfield) { 842fd425aeSroot fraglist[siz] += cnt; 852fd425aeSroot pos += siz; 862fd425aeSroot field <<= siz; 872fd425aeSroot subfield <<= siz; 882fd425aeSroot } 892fd425aeSroot field <<= 1; 902fd425aeSroot subfield <<= 1; 912fd425aeSroot } 922fd425aeSroot } 932fd425aeSroot } 942fd425aeSroot 95898d8e57Sbostic #if defined(KERNEL) && defined(DIAGNOSTIC) 96507878abSbostic void 97507878abSbostic ffs_checkoverlap(bp, ip) 98507878abSbostic struct buf *bp; 99507878abSbostic struct inode *ip; 100507878abSbostic { 101*42026a80Sheideman USES_VOP_BMAP; 102507878abSbostic register struct buf *ebp, *ep; 103507878abSbostic register daddr_t start, last; 104507878abSbostic struct vnode *vp; 105507878abSbostic 106507878abSbostic ebp = &buf[nbuf]; 107507878abSbostic start = bp->b_blkno; 108507878abSbostic last = start + btodb(bp->b_bcount) - 1; 109507878abSbostic for (ep = buf; ep < ebp; ep++) { 110507878abSbostic if (ep == bp || (ep->b_flags & B_INVAL) || 111507878abSbostic ep->b_vp == NULLVP) 112507878abSbostic continue; 113507878abSbostic if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0)) 114507878abSbostic continue; 115507878abSbostic if (vp != ip->i_devvp) 116507878abSbostic continue; 117507878abSbostic /* look for overlap */ 118507878abSbostic if (ep->b_bcount == 0 || ep->b_blkno > last || 119507878abSbostic ep->b_blkno + btodb(ep->b_bcount) <= start) 120507878abSbostic continue; 121507878abSbostic vprint("Disk overlap", vp); 122507878abSbostic (void)printf("\tstart %d, end %d overlap start %d, end %d\n", 123507878abSbostic start, last, ep->b_blkno, 124507878abSbostic ep->b_blkno + btodb(ep->b_bcount) - 1); 125507878abSbostic panic("Disk buffer overlap"); 126507878abSbostic } 127507878abSbostic } 128507878abSbostic #endif /* DIAGNOSTIC */ 129507878abSbostic 1302fd425aeSroot /* 1312fd425aeSroot * block operations 1322fd425aeSroot * 1332fd425aeSroot * check if a block is available 1342fd425aeSroot */ 135507878abSbostic int 136507878abSbostic ffs_isblock(fs, cp, h) 1372fd425aeSroot struct fs *fs; 1382fd425aeSroot unsigned char *cp; 1392fd425aeSroot daddr_t h; 1402fd425aeSroot { 1412fd425aeSroot unsigned char mask; 1422fd425aeSroot 143c6f9bf5fSkarels switch ((int)fs->fs_frag) { 1442fd425aeSroot case 8: 1452fd425aeSroot return (cp[h] == 0xff); 1462fd425aeSroot case 4: 1472fd425aeSroot mask = 0x0f << ((h & 0x1) << 2); 1482fd425aeSroot return ((cp[h >> 1] & mask) == mask); 1492fd425aeSroot case 2: 1502fd425aeSroot mask = 0x03 << ((h & 0x3) << 1); 1512fd425aeSroot return ((cp[h >> 2] & mask) == mask); 1522fd425aeSroot case 1: 1532fd425aeSroot mask = 0x01 << (h & 0x7); 1542fd425aeSroot return ((cp[h >> 3] & mask) == mask); 1552fd425aeSroot default: 156507878abSbostic panic("ffs_isblock"); 1572fd425aeSroot } 1582fd425aeSroot } 1592fd425aeSroot 1602fd425aeSroot /* 1612fd425aeSroot * take a block out of the map 1622fd425aeSroot */ 163507878abSbostic void 164507878abSbostic ffs_clrblock(fs, cp, h) 1652fd425aeSroot struct fs *fs; 16691257f00Sroot u_char *cp; 1672fd425aeSroot daddr_t h; 1682fd425aeSroot { 1692fd425aeSroot 170c6f9bf5fSkarels switch ((int)fs->fs_frag) { 1712fd425aeSroot case 8: 1722fd425aeSroot cp[h] = 0; 1732fd425aeSroot return; 1742fd425aeSroot case 4: 1752fd425aeSroot cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 1762fd425aeSroot return; 1772fd425aeSroot case 2: 1782fd425aeSroot cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 1792fd425aeSroot return; 1802fd425aeSroot case 1: 1812fd425aeSroot cp[h >> 3] &= ~(0x01 << (h & 0x7)); 1822fd425aeSroot return; 1832fd425aeSroot default: 184507878abSbostic panic("ffs_clrblock"); 1852fd425aeSroot } 1862fd425aeSroot } 1872fd425aeSroot 1882fd425aeSroot /* 1892fd425aeSroot * put a block into the map 1902fd425aeSroot */ 191507878abSbostic void 192507878abSbostic ffs_setblock(fs, cp, h) 1932fd425aeSroot struct fs *fs; 1942fd425aeSroot unsigned char *cp; 1952fd425aeSroot daddr_t h; 1962fd425aeSroot { 1972fd425aeSroot 198c6f9bf5fSkarels switch ((int)fs->fs_frag) { 1992fd425aeSroot 2002fd425aeSroot case 8: 2012fd425aeSroot cp[h] = 0xff; 2022fd425aeSroot return; 2032fd425aeSroot case 4: 2042fd425aeSroot cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 2052fd425aeSroot return; 2062fd425aeSroot case 2: 2072fd425aeSroot cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 2082fd425aeSroot return; 2092fd425aeSroot case 1: 2102fd425aeSroot cp[h >> 3] |= (0x01 << (h & 0x7)); 2112fd425aeSroot return; 2122fd425aeSroot default: 213507878abSbostic panic("ffs_setblock"); 2142fd425aeSroot } 2152fd425aeSroot } 2160c465d6dSsam 217e25934f4Smckusick #if (!defined(vax) && !defined(tahoe) && !defined(hp300)) \ 218e25934f4Smckusick || defined(VAX630) || defined(VAX650) 219aa9e473eSmckusick /* 2204767510aSkarels * C definitions of special instructions. 2214767510aSkarels * Normally expanded with inline. 222aa9e473eSmckusick */ 223507878abSbostic int 224aa9e473eSmckusick scanc(size, cp, table, mask) 225aa9e473eSmckusick u_int size; 226aa9e473eSmckusick register u_char *cp, table[]; 227aa9e473eSmckusick register u_char mask; 228aa9e473eSmckusick { 229aa9e473eSmckusick register u_char *end = &cp[size]; 230aa9e473eSmckusick 231aa9e473eSmckusick while (cp < end && (table[*cp] & mask) == 0) 232aa9e473eSmckusick cp++; 233aa9e473eSmckusick return (end - cp); 234aa9e473eSmckusick } 2357381b39dSkridle #endif 2367381b39dSkridle 237e25934f4Smckusick #if !defined(vax) && !defined(tahoe) && !defined(hp300) 238507878abSbostic int 239aa9e473eSmckusick skpc(mask, size, cp) 240aa9e473eSmckusick register u_char mask; 241aa9e473eSmckusick u_int size; 242aa9e473eSmckusick register u_char *cp; 243aa9e473eSmckusick { 244aa9e473eSmckusick register u_char *end = &cp[size]; 245aa9e473eSmckusick 246aa9e473eSmckusick while (cp < end && *cp == mask) 247aa9e473eSmckusick cp++; 248aa9e473eSmckusick return (end - cp); 249aa9e473eSmckusick } 250aa9e473eSmckusick 251507878abSbostic int 252aa9e473eSmckusick locc(mask, size, cp) 253aa9e473eSmckusick register u_char mask; 254aa9e473eSmckusick u_int size; 255aa9e473eSmckusick register u_char *cp; 256aa9e473eSmckusick { 257aa9e473eSmckusick register u_char *end = &cp[size]; 258aa9e473eSmckusick 259aa9e473eSmckusick while (cp < end && *cp != mask) 260aa9e473eSmckusick cp++; 261aa9e473eSmckusick return (end - cp); 262aa9e473eSmckusick } 2634767510aSkarels #endif 264