1c8bc2536Smckusick /*
22b768bd7Sbostic * Copyright (c) 1982, 1986, 1989, 1993
32b768bd7Sbostic * The Regents of the University of California. All rights reserved.
4c8bc2536Smckusick *
58eb14236Sbostic * %sccs.include.redist.c%
6065083aeSmckusick *
7*5363fd5eSmckusick * @(#)ffs_subr.c 8.5 (Berkeley) 03/21/95
8c8bc2536Smckusick */
92fd425aeSroot
102fd425aeSroot #include <sys/param.h>
112c9a935dSmckusick #ifndef KERNEL
12*5363fd5eSmckusick #include <ufs/ufs/dinode.h>
13507878abSbostic #include <ufs/ffs/fs.h>
142c9a935dSmckusick #else
15507878abSbostic
16c470cd31Smckusick #include <sys/systm.h>
1748d0f8e9Smckusick #include <sys/vnode.h>
18e8e9bf15Smckusick #include <sys/buf.h>
19e8e9bf15Smckusick #include <ufs/ufs/quota.h>
20e8e9bf15Smckusick #include <ufs/ufs/inode.h>
212c9a935dSmckusick #include <ufs/ffs/fs.h>
222c9a935dSmckusick #include <ufs/ffs/ffs_extern.h>
23898d8e57Sbostic
24507878abSbostic /*
25507878abSbostic * Return buffer with the contents of block "offset" from the beginning of
26507878abSbostic * directory "ip". If "res" is non-zero, fill it in with a pointer to the
27507878abSbostic * remaining space in the directory.
28507878abSbostic */
29507878abSbostic int
ffs_blkatoff(ap)3042026a80Sheideman ffs_blkatoff(ap)
3177f5479aSmckusick struct vop_blkatoff_args /* {
3277f5479aSmckusick struct vnode *a_vp;
3377f5479aSmckusick off_t a_offset;
3477f5479aSmckusick char **a_res;
3577f5479aSmckusick struct buf **a_bpp;
3677f5479aSmckusick } */ *ap;
37507878abSbostic {
38297a81e4Smckusick struct inode *ip;
39507878abSbostic register struct fs *fs;
40507878abSbostic struct buf *bp;
412c9a935dSmckusick ufs_daddr_t lbn;
42507878abSbostic int bsize, error;
43507878abSbostic
44ffd50346Sheideman ip = VTOI(ap->a_vp);
45507878abSbostic fs = ip->i_fs;
46ffd50346Sheideman lbn = lblkno(fs, ap->a_offset);
47507878abSbostic bsize = blksize(fs, ip, lbn);
48507878abSbostic
49ffd50346Sheideman *ap->a_bpp = NULL;
50ffd50346Sheideman if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) {
51507878abSbostic brelse(bp);
52507878abSbostic return (error);
53507878abSbostic }
54ffd50346Sheideman if (ap->a_res)
558821b0ebSbostic *ap->a_res = (char *)bp->b_data + blkoff(fs, ap->a_offset);
56ffd50346Sheideman *ap->a_bpp = bp;
57507878abSbostic return (0);
58507878abSbostic }
59898d8e57Sbostic #endif
602fd425aeSroot
612fd425aeSroot /*
622fd425aeSroot * Update the frsum fields to reflect addition or deletion
632fd425aeSroot * of some frags.
642fd425aeSroot */
65507878abSbostic void
ffs_fragacct(fs,fragmap,fraglist,cnt)66507878abSbostic ffs_fragacct(fs, fragmap, fraglist, cnt)
672fd425aeSroot struct fs *fs;
682fd425aeSroot int fragmap;
69c7e57180Smckusick int32_t fraglist[];
702fd425aeSroot int cnt;
712fd425aeSroot {
722fd425aeSroot int inblk;
732fd425aeSroot register int field, subfield;
742fd425aeSroot register int siz, pos;
752fd425aeSroot
762fd425aeSroot inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
772fd425aeSroot fragmap <<= 1;
782fd425aeSroot for (siz = 1; siz < fs->fs_frag; siz++) {
792fd425aeSroot if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
802fd425aeSroot continue;
812fd425aeSroot field = around[siz];
822fd425aeSroot subfield = inside[siz];
832fd425aeSroot for (pos = siz; pos <= fs->fs_frag; pos++) {
842fd425aeSroot if ((fragmap & field) == subfield) {
852fd425aeSroot fraglist[siz] += cnt;
862fd425aeSroot pos += siz;
872fd425aeSroot field <<= siz;
882fd425aeSroot subfield <<= siz;
892fd425aeSroot }
902fd425aeSroot field <<= 1;
912fd425aeSroot subfield <<= 1;
922fd425aeSroot }
932fd425aeSroot }
942fd425aeSroot }
952fd425aeSroot
96898d8e57Sbostic #if defined(KERNEL) && defined(DIAGNOSTIC)
97507878abSbostic void
ffs_checkoverlap(bp,ip)98507878abSbostic ffs_checkoverlap(bp, ip)
99507878abSbostic struct buf *bp;
100507878abSbostic struct inode *ip;
101507878abSbostic {
102507878abSbostic register struct buf *ebp, *ep;
1032c9a935dSmckusick register ufs_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;
1132c9a935dSmckusick if (VOP_BMAP(ep->b_vp, (ufs_daddr_t)0, &vp, (ufs_daddr_t)0,
1142c9a935dSmckusick NULL))
115507878abSbostic continue;
116507878abSbostic if (vp != ip->i_devvp)
117507878abSbostic continue;
118507878abSbostic /* look for overlap */
119507878abSbostic if (ep->b_bcount == 0 || ep->b_blkno > last ||
120507878abSbostic ep->b_blkno + btodb(ep->b_bcount) <= start)
121507878abSbostic continue;
122507878abSbostic vprint("Disk overlap", vp);
123507878abSbostic (void)printf("\tstart %d, end %d overlap start %d, end %d\n",
124507878abSbostic start, last, ep->b_blkno,
125507878abSbostic ep->b_blkno + btodb(ep->b_bcount) - 1);
126507878abSbostic panic("Disk buffer overlap");
127507878abSbostic }
128507878abSbostic }
129507878abSbostic #endif /* DIAGNOSTIC */
130507878abSbostic
1312fd425aeSroot /*
1322fd425aeSroot * block operations
1332fd425aeSroot *
1342fd425aeSroot * check if a block is available
1352fd425aeSroot */
136507878abSbostic int
ffs_isblock(fs,cp,h)137507878abSbostic ffs_isblock(fs, cp, h)
1382fd425aeSroot struct fs *fs;
1392fd425aeSroot unsigned char *cp;
1402c9a935dSmckusick ufs_daddr_t h;
1412fd425aeSroot {
1422fd425aeSroot unsigned char mask;
1432fd425aeSroot
144c6f9bf5fSkarels switch ((int)fs->fs_frag) {
1452fd425aeSroot case 8:
1462fd425aeSroot return (cp[h] == 0xff);
1472fd425aeSroot case 4:
1482fd425aeSroot mask = 0x0f << ((h & 0x1) << 2);
1492fd425aeSroot return ((cp[h >> 1] & mask) == mask);
1502fd425aeSroot case 2:
1512fd425aeSroot mask = 0x03 << ((h & 0x3) << 1);
1522fd425aeSroot return ((cp[h >> 2] & mask) == mask);
1532fd425aeSroot case 1:
1542fd425aeSroot mask = 0x01 << (h & 0x7);
1552fd425aeSroot return ((cp[h >> 3] & mask) == mask);
1562fd425aeSroot default:
157507878abSbostic panic("ffs_isblock");
1582fd425aeSroot }
1592fd425aeSroot }
1602fd425aeSroot
1612fd425aeSroot /*
1622fd425aeSroot * take a block out of the map
1632fd425aeSroot */
164507878abSbostic void
ffs_clrblock(fs,cp,h)165507878abSbostic ffs_clrblock(fs, cp, h)
1662fd425aeSroot struct fs *fs;
16791257f00Sroot u_char *cp;
1682c9a935dSmckusick ufs_daddr_t h;
1692fd425aeSroot {
1702fd425aeSroot
171c6f9bf5fSkarels switch ((int)fs->fs_frag) {
1722fd425aeSroot case 8:
1732fd425aeSroot cp[h] = 0;
1742fd425aeSroot return;
1752fd425aeSroot case 4:
1762fd425aeSroot cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
1772fd425aeSroot return;
1782fd425aeSroot case 2:
1792fd425aeSroot cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
1802fd425aeSroot return;
1812fd425aeSroot case 1:
1822fd425aeSroot cp[h >> 3] &= ~(0x01 << (h & 0x7));
1832fd425aeSroot return;
1842fd425aeSroot default:
185507878abSbostic panic("ffs_clrblock");
1862fd425aeSroot }
1872fd425aeSroot }
1882fd425aeSroot
1892fd425aeSroot /*
1902fd425aeSroot * put a block into the map
1912fd425aeSroot */
192507878abSbostic void
ffs_setblock(fs,cp,h)193507878abSbostic ffs_setblock(fs, cp, h)
1942fd425aeSroot struct fs *fs;
1952fd425aeSroot unsigned char *cp;
1962c9a935dSmckusick ufs_daddr_t h;
1972fd425aeSroot {
1982fd425aeSroot
199c6f9bf5fSkarels switch ((int)fs->fs_frag) {
2002fd425aeSroot
2012fd425aeSroot case 8:
2022fd425aeSroot cp[h] = 0xff;
2032fd425aeSroot return;
2042fd425aeSroot case 4:
2052fd425aeSroot cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
2062fd425aeSroot return;
2072fd425aeSroot case 2:
2082fd425aeSroot cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
2092fd425aeSroot return;
2102fd425aeSroot case 1:
2112fd425aeSroot cp[h >> 3] |= (0x01 << (h & 0x7));
2122fd425aeSroot return;
2132fd425aeSroot default:
214507878abSbostic panic("ffs_setblock");
2152fd425aeSroot }
2162fd425aeSroot }
217