xref: /original-bsd/sys/ufs/ffs/ffs_subr.c (revision 42026a80)
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