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