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