123402Smckusick /* 237737Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337737Smckusick * All rights reserved. 423402Smckusick * 544539Sbostic * %sccs.include.redist.c% 637737Smckusick * 7*53521Sheideman * @(#)ffs_subr.c 7.19 (Berkeley) 05/14/92 823402Smckusick */ 98719Sroot 108719Sroot #include <sys/param.h> 1153511Sheideman #include <sys/vnode.h> 1251471Sbostic #include <ufs/ffs/fs.h> 1351471Sbostic #include <ufs/ffs/ffs_extern.h> 1451471Sbostic 1551636Sbostic #ifdef KERNEL 1651956Smckusick #include <sys/buf.h> 1751956Smckusick #include <ufs/ufs/quota.h> 1851956Smckusick #include <ufs/ufs/inode.h> 1951636Sbostic 208719Sroot /* 2151471Sbostic * Return buffer with the contents of block "offset" from the beginning of 2251471Sbostic * directory "ip". If "res" is non-zero, fill it in with a pointer to the 2351471Sbostic * remaining space in the directory. 2451471Sbostic */ 2551471Sbostic int 26*53521Sheideman ffs_blkatoff (ap) 27*53521Sheideman struct vop_blkatoff_args *ap; 28*53521Sheideman #define vp (ap->a_vp) 29*53521Sheideman #define offset (ap->a_offset) 30*53521Sheideman #define res (ap->a_res) 31*53521Sheideman #define bpp (ap->a_bpp) 3251471Sbostic { 3351543Smckusick struct inode *ip; 3451471Sbostic register struct fs *fs; 3551471Sbostic struct buf *bp; 3651471Sbostic daddr_t lbn; 3751471Sbostic int bsize, error; 3851471Sbostic 3951543Smckusick ip = VTOI(vp); 4051471Sbostic fs = ip->i_fs; 4151471Sbostic lbn = lblkno(fs, offset); 4251471Sbostic bsize = blksize(fs, ip, lbn); 4351471Sbostic 4451471Sbostic *bpp = NULL; 4551543Smckusick if (error = bread(vp, lbn, bsize, NOCRED, &bp)) { 4651471Sbostic brelse(bp); 4751471Sbostic return (error); 4851471Sbostic } 4951471Sbostic if (res) 5051471Sbostic *res = bp->b_un.b_addr + blkoff(fs, offset); 5151471Sbostic *bpp = bp; 5251471Sbostic return (0); 5351471Sbostic } 54*53521Sheideman #undef vp 55*53521Sheideman #undef offset 56*53521Sheideman #undef res 57*53521Sheideman #undef bpp 5851636Sbostic #endif 5951471Sbostic 6051471Sbostic /* 618719Sroot * Update the frsum fields to reflect addition or deletion 628719Sroot * of some frags. 638719Sroot */ 6451471Sbostic void 6551471Sbostic ffs_fragacct(fs, fragmap, fraglist, cnt) 668719Sroot struct fs *fs; 678719Sroot int fragmap; 688719Sroot long fraglist[]; 698719Sroot int cnt; 708719Sroot { 718719Sroot int inblk; 728719Sroot register int field, subfield; 738719Sroot register int siz, pos; 748719Sroot 758719Sroot inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 768719Sroot fragmap <<= 1; 778719Sroot for (siz = 1; siz < fs->fs_frag; siz++) { 788719Sroot if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 798719Sroot continue; 808719Sroot field = around[siz]; 818719Sroot subfield = inside[siz]; 828719Sroot for (pos = siz; pos <= fs->fs_frag; pos++) { 838719Sroot if ((fragmap & field) == subfield) { 848719Sroot fraglist[siz] += cnt; 858719Sroot pos += siz; 868719Sroot field <<= siz; 878719Sroot subfield <<= siz; 888719Sroot } 898719Sroot field <<= 1; 908719Sroot subfield <<= 1; 918719Sroot } 928719Sroot } 938719Sroot } 948719Sroot 9551636Sbostic #if defined(KERNEL) && defined(DIAGNOSTIC) 9651471Sbostic void 9751471Sbostic ffs_checkoverlap(bp, ip) 9851471Sbostic struct buf *bp; 9951471Sbostic struct inode *ip; 10051471Sbostic { 101*53521Sheideman USES_VOP_BMAP; 10251471Sbostic register struct buf *ebp, *ep; 10351471Sbostic register daddr_t start, last; 10451471Sbostic struct vnode *vp; 10551471Sbostic 10651471Sbostic ebp = &buf[nbuf]; 10751471Sbostic start = bp->b_blkno; 10851471Sbostic last = start + btodb(bp->b_bcount) - 1; 10951471Sbostic for (ep = buf; ep < ebp; ep++) { 11051471Sbostic if (ep == bp || (ep->b_flags & B_INVAL) || 11151471Sbostic ep->b_vp == NULLVP) 11251471Sbostic continue; 11351471Sbostic if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0)) 11451471Sbostic continue; 11551471Sbostic if (vp != ip->i_devvp) 11651471Sbostic continue; 11751471Sbostic /* look for overlap */ 11851471Sbostic if (ep->b_bcount == 0 || ep->b_blkno > last || 11951471Sbostic ep->b_blkno + btodb(ep->b_bcount) <= start) 12051471Sbostic continue; 12151471Sbostic vprint("Disk overlap", vp); 12251471Sbostic (void)printf("\tstart %d, end %d overlap start %d, end %d\n", 12351471Sbostic start, last, ep->b_blkno, 12451471Sbostic ep->b_blkno + btodb(ep->b_bcount) - 1); 12551471Sbostic panic("Disk buffer overlap"); 12651471Sbostic } 12751471Sbostic } 12851471Sbostic #endif /* DIAGNOSTIC */ 12951471Sbostic 1308719Sroot /* 1318719Sroot * block operations 1328719Sroot * 1338719Sroot * check if a block is available 1348719Sroot */ 13551471Sbostic int 13651471Sbostic ffs_isblock(fs, cp, h) 1378719Sroot struct fs *fs; 1388719Sroot unsigned char *cp; 1398719Sroot daddr_t h; 1408719Sroot { 1418719Sroot unsigned char mask; 1428719Sroot 14326309Skarels switch ((int)fs->fs_frag) { 1448719Sroot case 8: 1458719Sroot return (cp[h] == 0xff); 1468719Sroot case 4: 1478719Sroot mask = 0x0f << ((h & 0x1) << 2); 1488719Sroot return ((cp[h >> 1] & mask) == mask); 1498719Sroot case 2: 1508719Sroot mask = 0x03 << ((h & 0x3) << 1); 1518719Sroot return ((cp[h >> 2] & mask) == mask); 1528719Sroot case 1: 1538719Sroot mask = 0x01 << (h & 0x7); 1548719Sroot return ((cp[h >> 3] & mask) == mask); 1558719Sroot default: 15651471Sbostic panic("ffs_isblock"); 1578719Sroot } 1588719Sroot } 1598719Sroot 1608719Sroot /* 1618719Sroot * take a block out of the map 1628719Sroot */ 16351471Sbostic void 16451471Sbostic ffs_clrblock(fs, cp, h) 1658719Sroot struct fs *fs; 1668770Sroot u_char *cp; 1678719Sroot daddr_t h; 1688719Sroot { 1698719Sroot 17026309Skarels switch ((int)fs->fs_frag) { 1718719Sroot case 8: 1728719Sroot cp[h] = 0; 1738719Sroot return; 1748719Sroot case 4: 1758719Sroot cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 1768719Sroot return; 1778719Sroot case 2: 1788719Sroot cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 1798719Sroot return; 1808719Sroot case 1: 1818719Sroot cp[h >> 3] &= ~(0x01 << (h & 0x7)); 1828719Sroot return; 1838719Sroot default: 18451471Sbostic panic("ffs_clrblock"); 1858719Sroot } 1868719Sroot } 1878719Sroot 1888719Sroot /* 1898719Sroot * put a block into the map 1908719Sroot */ 19151471Sbostic void 19251471Sbostic ffs_setblock(fs, cp, h) 1938719Sroot struct fs *fs; 1948719Sroot unsigned char *cp; 1958719Sroot daddr_t h; 1968719Sroot { 1978719Sroot 19826309Skarels switch ((int)fs->fs_frag) { 1998719Sroot 2008719Sroot case 8: 2018719Sroot cp[h] = 0xff; 2028719Sroot return; 2038719Sroot case 4: 2048719Sroot cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 2058719Sroot return; 2068719Sroot case 2: 2078719Sroot cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 2088719Sroot return; 2098719Sroot case 1: 2108719Sroot cp[h >> 3] |= (0x01 << (h & 0x7)); 2118719Sroot return; 2128719Sroot default: 21351471Sbostic panic("ffs_setblock"); 2148719Sroot } 2158719Sroot } 2169167Ssam 21741537Smckusick #if (!defined(vax) && !defined(tahoe) && !defined(hp300)) \ 21841537Smckusick || defined(VAX630) || defined(VAX650) 21921090Smckusick /* 22029947Skarels * C definitions of special instructions. 22129947Skarels * Normally expanded with inline. 22221090Smckusick */ 22351471Sbostic int 22421090Smckusick scanc(size, cp, table, mask) 22521090Smckusick u_int size; 22621090Smckusick register u_char *cp, table[]; 22721090Smckusick register u_char mask; 22821090Smckusick { 22921090Smckusick register u_char *end = &cp[size]; 23021090Smckusick 23121090Smckusick while (cp < end && (table[*cp] & mask) == 0) 23221090Smckusick cp++; 23321090Smckusick return (end - cp); 23421090Smckusick } 23527476Skridle #endif 23627476Skridle 23741537Smckusick #if !defined(vax) && !defined(tahoe) && !defined(hp300) 23851471Sbostic int 23921090Smckusick skpc(mask, size, cp) 24021090Smckusick register u_char mask; 24121090Smckusick u_int size; 24221090Smckusick register u_char *cp; 24321090Smckusick { 24421090Smckusick register u_char *end = &cp[size]; 24521090Smckusick 24621090Smckusick while (cp < end && *cp == mask) 24721090Smckusick cp++; 24821090Smckusick return (end - cp); 24921090Smckusick } 25021090Smckusick 25151471Sbostic int 25221090Smckusick locc(mask, size, cp) 25321090Smckusick register u_char mask; 25421090Smckusick u_int size; 25521090Smckusick register u_char *cp; 25621090Smckusick { 25721090Smckusick register u_char *end = &cp[size]; 25821090Smckusick 25921090Smckusick while (cp < end && *cp != mask) 26021090Smckusick cp++; 26121090Smckusick return (end - cp); 26221090Smckusick } 26329947Skarels #endif 264