filecore_bmap.c revision 1.1 1 /* $NetBSD: filecore_bmap.c,v 1.1 2002/12/23 17:30:40 jdolecek Exp $ */
2
3 /*-
4 * Copyright (c) 1998 Andrew McMurry
5 * Copyright (c) 1994 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * filecore_bmap.c 1.1 1998/6/26
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: filecore_bmap.c,v 1.1 2002/12/23 17:30:40 jdolecek Exp $");
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/namei.h>
45 #include <sys/buf.h>
46 #include <sys/file.h>
47 #include <sys/vnode.h>
48 #include <sys/mount.h>
49
50 #include <fs/filecorefs/filecore.h>
51 #include <fs/filecorefs/filecore_extern.h>
52 #include <fs/filecorefs/filecore_node.h>
53
54 /*
55 * Bmap converts a the logical block number of a file to its physical block
56 * number on the disk. The conversion is done by using the logical block
57 * number to index into the data block (extent) for the file.
58 */
59 int
60 filecore_bmap(v)
61 void *v;
62 {
63 struct vop_bmap_args /* {
64 struct vnode *a_vp;
65 daddr_t a_bn;
66 struct vnode **a_vpp;
67 daddr_t *a_bnp;
68 int *a_runp;
69 } */ *ap = v;
70 struct filecore_node *ip = VTOI(ap->a_vp);
71 struct filecore_mnt *fcmp = ip->i_mnt;
72 daddr_t lbn = ap->a_bn;
73
74 /*
75 * Check for underlying vnode requests and ensure that logical
76 * to physical mapping is requested.
77 */
78 if (ap->a_vpp != NULL)
79 *ap->a_vpp = ip->i_devvp;
80 if (ap->a_bnp == NULL)
81 return (0);
82
83 /*
84 * Determine maximum number of readahead blocks following the
85 * requested block.
86 */
87 if (ap->a_runp) {
88 int nblk;
89 int bshift=fcmp->log2bsize;
90
91 nblk = (ip->i_size >> bshift) - (lbn + 1);
92 if (nblk <= 0)
93 *ap->a_runp = 0;
94 else if (nblk >= (MAXBSIZE >> bshift))
95 *ap->a_runp = (MAXBSIZE >> bshift) - 1;
96 else
97 *ap->a_runp = nblk;
98 }
99 /*
100 * Compute the requested block number
101 */
102 return filecore_map(fcmp, ip->i_dirent.addr, lbn, ap->a_bnp);
103 }
104
105 int
106 filecore_map(fcmp, addr, lbn, bnp)
107 struct filecore_mnt *fcmp;
108 u_int32_t addr;
109 daddr_t lbn;
110 daddr_t *bnp;
111 {
112 struct buf *bp;
113 u_long frag, sect, zone, izone, a, b, m, n;
114 u_int64_t zaddr;
115 u_long *ptr;
116 long c;
117 int error = 0;
118
119 #ifdef FILECORE_DEBUG
120 printf("filecore_map(addr=%x, lbn=%x)\n", addr, lbn);
121 #endif
122 frag = addr >> 8;
123 sect = (addr & 0xff) +
124 ((lbn << fcmp->log2bsize) >> fcmp->drec.log2secsize);
125 if (frag != 2)
126 zone = frag / fcmp->idspz;
127 else
128 zone = fcmp->drec.nzones / 2;
129 izone = zone;
130 if (zone != 0)
131 zaddr=((8<<fcmp->drec.log2secsize)-fcmp->drec.zone_spare)*zone
132 - 8*FILECORE_DISCREC_SIZE;
133 else
134 zaddr = 0;
135 if (sect > 0)
136 sect--;
137 sect <<= fcmp->drec.share_size;
138 do {
139 error=bread(fcmp->fc_devvp, fcmp->map + zone,
140 1 << fcmp->drec.log2secsize, NOCRED, &bp);
141 #ifdef FILECORE_DEBUG_BR
142 printf("bread(%p, %lx, %d, CRED, %p)=%d\n", fcmp->fc_devvp,
143 fcmp->map+zone, 1 << fcmp->drec.log2secsize, bp, error);
144 printf("block is at %p\n", bp->b_data);
145 #endif
146 if (error != 0) {
147 #ifdef FILECORE_DEBUG_BR
148 printf("brelse(%p) bm1\n", bp);
149 #endif
150 brelse(bp);
151 return error;
152 }
153 ptr = (u_long *)(bp->b_data) + 1; /* skip map zone header */
154 if (zone == 0)
155 ptr += FILECORE_DISCREC_SIZE >> 2;
156 b = 0;
157 while (b < (8 << (fcmp->drec.log2secsize))
158 - fcmp->drec.zone_spare) {
159 a = ptr[b >> 5] >> (b & 31);
160 c = 32 - (b & 31) - fcmp->drec.idlen;
161 if (c <= 0) {
162 m = ptr[(b >> 5) + 1];
163 a |= m << (fcmp->drec.idlen+c);
164 m >>= -c;
165 c += 32;
166 } else
167 m = a >> fcmp->drec.idlen;
168 n = fcmp->drec.idlen + 1;
169 while ((m & 1) == 0) {
170 m >>= 1;
171 n++;
172 if (--c == 0) {
173 c=32;
174 m = ptr[(b + n - 1) >> 5];
175 }
176 }
177 a &= fcmp->mask;
178 if (a == frag) {
179 if (sect << fcmp->drec.log2secsize < n
180 << fcmp->drec.log2bpmb) {
181 *bnp = (((zaddr+b)
182 << fcmp->drec.log2bpmb)
183 >> fcmp->drec.log2secsize) + sect;
184
185 #ifdef FILECORE_DEBUG_BR
186 printf("brelse(%p) bm2\n", bp);
187 #endif
188 brelse(bp);
189 return 0;
190 } else
191 sect -= (n<<fcmp->drec.log2bpmb)
192 >> fcmp->drec.log2secsize;
193 }
194 b += n;
195 }
196 #ifdef FILECORE_DEBUG_BR
197 printf("brelse(%p) bm3\n", bp);
198 #endif
199 brelse(bp);
200 if (++zone == fcmp->drec.nzones) {
201 zone = 0;
202 zaddr=0;
203 } else
204 zaddr += ((8 << fcmp->drec.log2secsize)
205 - fcmp->drec.zone_spare);
206 } while (zone != izone);
207 return (E2BIG);
208 }
209
210 int
211 filecore_bread(fcmp, addr, size, cred, bp)
212 struct filecore_mnt *fcmp;
213 u_int32_t addr;
214 int size;
215 struct ucred *cred;
216 struct buf **bp;
217 {
218 int error = 0;
219 daddr_t bn;
220
221 error = filecore_map(fcmp, addr, 0, &bn);
222 if (error) {
223
224 #ifdef FILECORE_DEBUG
225 printf("filecore_bread(error=%d)\n", error);
226 #endif
227 return error;
228 }
229 error = bread(fcmp->fc_devvp, bn, size, cred, bp);
230 #ifdef FILECORE_DEBUG_BR
231 printf("bread(%p, %x, %d, CRED, %p)=%d\n", fcmp->fc_devvp, bn, size,
232 *bp, error);
233 #endif
234 return error;
235 }
236
237 int
238 filecore_dbread(ip, bp)
239 struct filecore_node *ip;
240 struct buf **bp;
241 {
242 int error = 0;
243
244 if (ip->i_block == -1)
245 error = filecore_map(ip->i_mnt, ip->i_dirent.addr,
246 0, &(ip->i_block));
247 if (error)
248 return error;
249 error = bread(ip->i_mnt->fc_devvp, ip->i_block, FILECORE_DIR_SIZE,
250 NOCRED, bp);
251 #ifdef FILECORE_DEBUG_BR
252 printf("bread(%p, %x, %d, CRED, %p)=%d\n", ip->i_mnt->fc_devvp,
253 ip->i_block, FILECORE_DIR_SIZE, *bp, error);
254 #endif
255 return error;
256 }
257