ffs_subr.c revision 30474
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.5 (Berkeley) 3/21/95
34 * $Id: ffs_subr.c,v 1.12 1997/03/09 06:00:42 mpp Exp $
35 */
36
37#include <sys/param.h>
38
39#ifndef KERNEL
40#include <ufs/ufs/dinode.h>
41#include <ufs/ffs/fs.h>
42#else
43#include "opt_ddb.h"
44
45#include <sys/systm.h>
46#include <sys/vnode.h>
47#include <sys/buf.h>
48#include <ufs/ufs/quota.h>
49#include <ufs/ufs/inode.h>
50#include <ufs/ufs/dinode.h>
51#include <ufs/ffs/fs.h>
52#include <ufs/ffs/ffs_extern.h>
53
54/*
55 * Return buffer with the contents of block "offset" from the beginning of
56 * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
57 * remaining space in the directory.
58 */
59int
60ffs_blkatoff(vp, offset, res, bpp)
61	struct vnode *vp;
62	off_t offset;
63	char **res;
64	struct buf **bpp;
65{
66	struct inode *ip;
67	register struct fs *fs;
68	struct buf *bp;
69	ufs_daddr_t lbn;
70	int bsize, error;
71
72	ip = VTOI(vp);
73	fs = ip->i_fs;
74	lbn = lblkno(fs, offset);
75	bsize = blksize(fs, ip, lbn);
76
77	*bpp = NULL;
78	error = bread(vp, lbn, bsize, NOCRED, &bp);
79	if (error) {
80		brelse(bp);
81		return (error);
82	}
83	if (res)
84		*res = (char *)bp->b_data + blkoff(fs, offset);
85	*bpp = bp;
86	return (0);
87}
88#endif
89
90/*
91 * Update the frsum fields to reflect addition or deletion
92 * of some frags.
93 */
94void
95ffs_fragacct(fs, fragmap, fraglist, cnt)
96	struct fs *fs;
97	int fragmap;
98	int32_t fraglist[];
99	int cnt;
100{
101	int inblk;
102	register int field, subfield;
103	register int siz, pos;
104
105	inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
106	fragmap <<= 1;
107	for (siz = 1; siz < fs->fs_frag; siz++) {
108		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
109			continue;
110		field = around[siz];
111		subfield = inside[siz];
112		for (pos = siz; pos <= fs->fs_frag; pos++) {
113			if ((fragmap & field) == subfield) {
114				fraglist[siz] += cnt;
115				pos += siz;
116				field <<= siz;
117				subfield <<= siz;
118			}
119			field <<= 1;
120			subfield <<= 1;
121		}
122	}
123}
124
125#if defined(KERNEL) && defined(DIAGNOSTIC) && defined(DDB)
126void
127ffs_checkoverlap(bp, ip)
128	struct buf *bp;
129	struct inode *ip;
130{
131	register struct buf *ebp, *ep;
132	register ufs_daddr_t start, last;
133	struct vnode *vp;
134
135	ebp = &buf[nbuf];
136	start = bp->b_blkno;
137	last = start + btodb(bp->b_bcount) - 1;
138	for (ep = buf; ep < ebp; ep++) {
139		if (ep == bp || (ep->b_flags & B_INVAL) ||
140		    ep->b_vp == NULLVP)
141			continue;
142		if (VOP_BMAP(ep->b_vp, (ufs_daddr_t)0, &vp, (ufs_daddr_t)0,
143		    NULL, NULL))
144			continue;
145		if (vp != ip->i_devvp)
146			continue;
147		/* look for overlap */
148		if (ep->b_bcount == 0 || ep->b_blkno > last ||
149		    ep->b_blkno + btodb(ep->b_bcount) <= start)
150			continue;
151		vprint("Disk overlap", vp);
152		(void)printf("\tstart %lu, end %lu overlap start %lu, end %lu\n",
153			(u_long)start, (u_long)last, (u_long)ep->b_blkno,
154			(u_long)(ep->b_blkno + btodb(ep->b_bcount) - 1));
155		panic("ffs_checkoverlap: Disk buffer overlap");
156	}
157}
158#endif /* DIAGNOSTIC */
159
160/*
161 * block operations
162 *
163 * check if a block is available
164 */
165int
166ffs_isblock(fs, cp, h)
167	struct fs *fs;
168	unsigned char *cp;
169	ufs_daddr_t h;
170{
171	unsigned char mask;
172
173	switch ((int)fs->fs_frag) {
174	case 8:
175		return (cp[h] == 0xff);
176	case 4:
177		mask = 0x0f << ((h & 0x1) << 2);
178		return ((cp[h >> 1] & mask) == mask);
179	case 2:
180		mask = 0x03 << ((h & 0x3) << 1);
181		return ((cp[h >> 2] & mask) == mask);
182	case 1:
183		mask = 0x01 << (h & 0x7);
184		return ((cp[h >> 3] & mask) == mask);
185	default:
186		panic("ffs_isblock");
187	}
188}
189
190/*
191 * take a block out of the map
192 */
193void
194ffs_clrblock(fs, cp, h)
195	struct fs *fs;
196	u_char *cp;
197	ufs_daddr_t h;
198{
199
200	switch ((int)fs->fs_frag) {
201	case 8:
202		cp[h] = 0;
203		return;
204	case 4:
205		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
206		return;
207	case 2:
208		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
209		return;
210	case 1:
211		cp[h >> 3] &= ~(0x01 << (h & 0x7));
212		return;
213	default:
214		panic("ffs_clrblock");
215	}
216}
217
218/*
219 * put a block into the map
220 */
221void
222ffs_setblock(fs, cp, h)
223	struct fs *fs;
224	unsigned char *cp;
225	ufs_daddr_t h;
226{
227
228	switch ((int)fs->fs_frag) {
229
230	case 8:
231		cp[h] = 0xff;
232		return;
233	case 4:
234		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
235		return;
236	case 2:
237		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
238		return;
239	case 1:
240		cp[h >> 3] |= (0x01 << (h & 0x7));
241		return;
242	default:
243		panic("ffs_setblock");
244	}
245}
246