kernel: Remove the inclusion of opt_ddb.h from where it is unnecessary.
[dragonfly.git] / sys / vfs / ufs / ffs_subr.c
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  * $FreeBSD: src/sys/ufs/ffs/ffs_subr.c,v 1.25 1999/12/29 04:55:04 peter Exp $
35  */
36
37 #include <sys/param.h>
38
39 #ifndef _KERNEL
40 #include "dinode.h"
41 #include "fs.h"
42 extern void panic(const char *, ...);
43 #else
44 #include <sys/systm.h>
45 #include <sys/lock.h>
46 #include <sys/vnode.h>
47 #include <sys/buf.h>
48 #include <sys/ucred.h>
49 #include <sys/mount.h>
50
51 #include <sys/buf2.h>
52
53 #include "quota.h"
54 #include "inode.h"
55 #include "fs.h"
56 #include "ffs_extern.h"
57
58 /*
59  * Return buffer with the contents of block "offset" from the beginning of
60  * vnode "vp".  If "res" is non-zero, fill it in with a pointer to the
61  * remaining space in the vnode.
62  */
63 int
64 ffs_blkatoff(struct vnode *vp, off_t uoffset, char **res, struct buf **bpp)
65 {
66         struct inode *ip;
67         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, uoffset);
75         bsize = blksize(fs, ip, lbn);
76
77         *bpp = NULL;
78         error = bread(vp, lblktodoff(fs, lbn), bsize, &bp);
79         if (error) {
80                 brelse(bp);
81                 return (error);
82         }
83         if (res)
84                 *res = (char *)bp->b_data + blkoff(fs, uoffset);
85         *bpp = bp;
86         return (0);
87 }
88
89 /*
90  * Return buffer with the contents of block "offset" from the beginning of
91  * vnode "vp".  If "res" is non-zero, fill it in with a pointer to the
92  * remaining space in the vnode.
93  *
94  * This version includes a read-ahead optimization.
95  */
96 int
97 ffs_blkatoff_ra(struct vnode *vp, off_t uoffset, char **res, struct buf **bpp,
98                 int seqcount)
99 {
100         struct inode *ip;
101         struct fs *fs;
102         struct buf *bp;
103         ufs_daddr_t lbn;
104         ufs_daddr_t nextlbn;
105         off_t base_loffset;
106         off_t next_loffset;
107         int bsize, error;
108         int nextbsize;
109
110         ip = VTOI(vp);
111         fs = ip->i_fs;
112         lbn = lblkno(fs, uoffset);
113         base_loffset = lblktodoff(fs, lbn);
114         bsize = blksize(fs, ip, lbn);
115
116         nextlbn = lbn + 1;
117         next_loffset = lblktodoff(fs, nextlbn);
118
119
120         *bpp = NULL;
121
122         if (next_loffset >= ip->i_size) {
123                 /*
124                  * Do not do readahead if this is the last block,
125                  * bsize might represent a fragment.
126                  */
127                 error = bread(vp, base_loffset, bsize, &bp);
128         } else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
129                 /*
130                  * Try to cluster if we allowed to.
131                  */
132                 error = cluster_read(vp, (off_t)ip->i_size,
133                                      base_loffset, bsize,
134                                      bsize, seqcount * BKVASIZE, &bp);
135         } else if (seqcount > 1) {
136                 /*
137                  * Faked read ahead
138                  */
139                 nextbsize = blksize(fs, ip, nextlbn);
140                 error = breadn(vp, base_loffset, bsize,
141                                &next_loffset, &nextbsize, 1, &bp);
142         } else {
143                 /*
144                  * Failing all of the above, just read what the
145                  * user asked for. Interestingly, the same as
146                  * the first option above.
147                  */
148                 error = bread(vp, base_loffset, bsize, &bp);
149         }
150         if (error) {
151                 brelse(bp);
152                 return (error);
153         }
154         if (res)
155                 *res = (char *)bp->b_data + (int)(uoffset - base_loffset);
156         *bpp = bp;
157         return (0);
158 }
159
160 #endif
161
162 /*
163  * Update the frsum fields to reflect addition or deletion
164  * of some frags.
165  */
166 void
167 ffs_fragacct(struct fs *fs, int fragmap, int32_t fraglist[], int cnt)
168 {
169         int inblk;
170         int field, subfield;
171         int siz, pos;
172
173         /*
174          * inblk represents a bitmap of fragment sizes which may be
175          * contained in the data 'fragmap'.  e.g. if a fragment of size
176          * 1 is available, bit 0 would be set.  inblk is shifted left
177          * by one so we do not have to calculate (1 << (siz - 1)).
178          *
179          * fragment represents the data pattern we are trying to decipher,
180          * we shift it left by one to align it with the 'around' and 'inside'
181          * masks.
182          *
183          * around represents the bits around the subfield and is a mask.
184          * inside represents what we must match within the mask, it is
185          * basically the mask with the first and last bit set to 0, allowing
186          * us to represent a whole fragment.
187          *
188          * When we find a match we bump our position by the size of the
189          * matching fragment, then bump the position again:
190          *
191          * 010101010 fragmap (shifted left by 1)
192          *       111 around mask
193          *       010 inside mask
194          *      111     (shifted by siz)
195          *      010
196          *     111      (shifted again)
197          *     010
198          */
199         inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
200         fragmap <<= 1;
201         for (siz = 1; siz < fs->fs_frag; siz++) {
202                 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
203                         continue;
204                 field = around[siz];
205                 subfield = inside[siz];
206                 for (pos = siz; pos <= fs->fs_frag; pos++) {
207                         if ((fragmap & field) == subfield) {
208                                 fraglist[siz] += cnt;
209                                 pos += siz;
210                                 field <<= siz;
211                                 subfield <<= siz;
212                         }
213                         field <<= 1;
214                         subfield <<= 1;
215                 }
216         }
217 }
218
219 /*
220  * block operations
221  *
222  * check if a block is available
223  */
224 int
225 ffs_isblock(struct fs *fs, unsigned char *cp, ufs_daddr_t h)
226 {
227         unsigned char mask;
228
229         switch ((int)fs->fs_frag) {
230         case 8:
231                 return (cp[h] == 0xff);
232         case 4:
233                 mask = 0x0f << ((h & 0x1) << 2);
234                 return ((cp[h >> 1] & mask) == mask);
235         case 2:
236                 mask = 0x03 << ((h & 0x3) << 1);
237                 return ((cp[h >> 2] & mask) == mask);
238         case 1:
239                 mask = 0x01 << (h & 0x7);
240                 return ((cp[h >> 3] & mask) == mask);
241         default:
242                 panic("ffs_isblock");
243         }
244 }
245
246 /*
247  * check if a block is free
248  */
249 int
250 ffs_isfreeblock(struct fs *fs, unsigned char *cp, ufs_daddr_t h)
251 {
252         switch ((int)fs->fs_frag) {
253         case 8:
254                 return (cp[h] == 0);
255         case 4:
256                 return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0);
257         case 2:
258                 return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0);
259         case 1:
260                 return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0);
261         default:
262                 panic("ffs_isfreeblock");
263         }
264 }
265
266 /*
267  * take a block out of the map
268  */
269 void
270 ffs_clrblock(struct fs *fs, u_char *cp, ufs_daddr_t h)
271 {
272         switch ((int)fs->fs_frag) {
273         case 8:
274                 cp[h] = 0;
275                 return;
276         case 4:
277                 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
278                 return;
279         case 2:
280                 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
281                 return;
282         case 1:
283                 cp[h >> 3] &= ~(0x01 << (h & 0x7));
284                 return;
285         default:
286                 panic("ffs_clrblock");
287         }
288 }
289
290 /*
291  * put a block into the map
292  */
293 void
294 ffs_setblock(struct fs *fs, unsigned char *cp, ufs_daddr_t h)
295 {
296         switch ((int)fs->fs_frag) {
297         case 8:
298                 cp[h] = 0xff;
299                 return;
300         case 4:
301                 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
302                 return;
303         case 2:
304                 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
305                 return;
306         case 1:
307                 cp[h >> 3] |= (0x01 << (h & 0x7));
308                 return;
309         default:
310                 panic("ffs_setblock");
311         }
312 }