ffs_subr.c revision 13228
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 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *	@(#)ffs_subr.c	8.2 (Berkeley) 9/21/93
34 * $Id: ffs_subr.c,v 1.6 1995/12/17 21:09:31 phk Exp $
35 */
36
37#include <sys/param.h>
38#include <ufs/ffs/fs.h>
39
40#ifdef KERNEL
41#include "opt_ddb.h"
42
43#include <sys/systm.h>
44#include <sys/vnode.h>
45#include <ufs/ffs/ffs_extern.h>
46#include <sys/buf.h>
47#include <ufs/ufs/quota.h>
48#include <ufs/ufs/inode.h>
49
50/*
51 * Return buffer with the contents of block "offset" from the beginning of
52 * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
53 * remaining space in the directory.
54 */
55int
56ffs_blkatoff(ap)
57	struct vop_blkatoff_args /* {
58		struct vnode *a_vp;
59		off_t a_offset;
60		char **a_res;
61		struct buf **a_bpp;
62	} */ *ap;
63{
64	struct inode *ip;
65	register struct fs *fs;
66	struct buf *bp;
67	daddr_t lbn;
68	int bsize, error;
69
70	ip = VTOI(ap->a_vp);
71	fs = ip->i_fs;
72	lbn = lblkno(fs, ap->a_offset);
73	bsize = blksize(fs, ip, lbn);
74
75	*ap->a_bpp = NULL;
76	error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp);
77	if (error) {
78		brelse(bp);
79		return (error);
80	}
81	if (ap->a_res)
82		*ap->a_res = (char *)bp->b_data + blkoff(fs, ap->a_offset);
83	*ap->a_bpp = bp;
84	return (0);
85}
86#endif
87
88/*
89 * Update the frsum fields to reflect addition or deletion
90 * of some frags.
91 */
92void
93ffs_fragacct(fs, fragmap, fraglist, cnt)
94	struct fs *fs;
95	int fragmap;
96	long fraglist[];
97	int cnt;
98{
99	int inblk;
100	register int field, subfield;
101	register int siz, pos;
102
103	inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
104	fragmap <<= 1;
105	for (siz = 1; siz < fs->fs_frag; siz++) {
106		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
107			continue;
108		field = around[siz];
109		subfield = inside[siz];
110		for (pos = siz; pos <= fs->fs_frag; pos++) {
111			if ((fragmap & field) == subfield) {
112				fraglist[siz] += cnt;
113				pos += siz;
114				field <<= siz;
115				subfield <<= siz;
116			}
117			field <<= 1;
118			subfield <<= 1;
119		}
120	}
121}
122
123#if defined(KERNEL) && defined(DIAGNOSTIC) && defined(DDB)
124void
125ffs_checkoverlap(bp, ip)
126	struct buf *bp;
127	struct inode *ip;
128{
129	register struct buf *ebp, *ep;
130	register daddr_t start, last;
131	struct vnode *vp;
132
133	ebp = &buf[nbuf];
134	start = bp->b_blkno;
135	last = start + btodb(bp->b_bcount) - 1;
136	for (ep = buf; ep < ebp; ep++) {
137		if (ep == bp || (ep->b_flags & B_INVAL) ||
138		    ep->b_vp == NULLVP)
139			continue;
140		if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0, NULL, NULL))
141			continue;
142		if (vp != ip->i_devvp)
143			continue;
144		/* look for overlap */
145		if (ep->b_bcount == 0 || ep->b_blkno > last ||
146		    ep->b_blkno + btodb(ep->b_bcount) <= start)
147			continue;
148		vprint("Disk overlap", vp);
149		(void)printf("\tstart %lu, end %lu overlap start %lu, end %lu\n",
150			(u_long)start, (u_long)last, (u_long)ep->b_blkno,
151			(u_long)(ep->b_blkno + btodb(ep->b_bcount) - 1));
152		panic("Disk buffer overlap");
153	}
154}
155#endif /* DIAGNOSTIC */
156
157/*
158 * block operations
159 *
160 * check if a block is available
161 */
162int
163ffs_isblock(fs, cp, h)
164	struct fs *fs;
165	unsigned char *cp;
166	daddr_t h;
167{
168	unsigned char mask;
169
170	switch ((int)fs->fs_frag) {
171	case 8:
172		return (cp[h] == 0xff);
173	case 4:
174		mask = 0x0f << ((h & 0x1) << 2);
175		return ((cp[h >> 1] & mask) == mask);
176	case 2:
177		mask = 0x03 << ((h & 0x3) << 1);
178		return ((cp[h >> 2] & mask) == mask);
179	case 1:
180		mask = 0x01 << (h & 0x7);
181		return ((cp[h >> 3] & mask) == mask);
182	default:
183		panic("ffs_isblock");
184	}
185}
186
187/*
188 * take a block out of the map
189 */
190void
191ffs_clrblock(fs, cp, h)
192	struct fs *fs;
193	u_char *cp;
194	daddr_t h;
195{
196
197	switch ((int)fs->fs_frag) {
198	case 8:
199		cp[h] = 0;
200		return;
201	case 4:
202		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
203		return;
204	case 2:
205		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
206		return;
207	case 1:
208		cp[h >> 3] &= ~(0x01 << (h & 0x7));
209		return;
210	default:
211		panic("ffs_clrblock");
212	}
213}
214
215/*
216 * put a block into the map
217 */
218void
219ffs_setblock(fs, cp, h)
220	struct fs *fs;
221	unsigned char *cp;
222	daddr_t h;
223{
224
225	switch ((int)fs->fs_frag) {
226
227	case 8:
228		cp[h] = 0xff;
229		return;
230	case 4:
231		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
232		return;
233	case 2:
234		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
235		return;
236	case 1:
237		cp[h >> 3] |= (0x01 << (h & 0x7));
238		return;
239	default:
240		panic("ffs_setblock");
241	}
242}
243