1 /* $NetBSD: filecore_bmap.c,v 1.2 2003/08/07 16:31:37 agc 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.2 2003/08/07 16:31:37 agc 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 79 #include <fs/filecorefs/filecore.h> 80 #include <fs/filecorefs/filecore_extern.h> 81 #include <fs/filecorefs/filecore_node.h> 82 83 /* 84 * Bmap converts a the logical block number of a file to its physical block 85 * number on the disk. The conversion is done by using the logical block 86 * number to index into the data block (extent) for the file. 87 */ 88 int 89 filecore_bmap(v) 90 void *v; 91 { 92 struct vop_bmap_args /* { 93 struct vnode *a_vp; 94 daddr_t a_bn; 95 struct vnode **a_vpp; 96 daddr_t *a_bnp; 97 int *a_runp; 98 } */ *ap = v; 99 struct filecore_node *ip = VTOI(ap->a_vp); 100 struct filecore_mnt *fcmp = ip->i_mnt; 101 daddr_t lbn = ap->a_bn; 102 103 /* 104 * Check for underlying vnode requests and ensure that logical 105 * to physical mapping is requested. 106 */ 107 if (ap->a_vpp != NULL) 108 *ap->a_vpp = ip->i_devvp; 109 if (ap->a_bnp == NULL) 110 return (0); 111 112 /* 113 * Determine maximum number of readahead blocks following the 114 * requested block. 115 */ 116 if (ap->a_runp) { 117 int nblk; 118 int bshift=fcmp->log2bsize; 119 120 nblk = (ip->i_size >> bshift) - (lbn + 1); 121 if (nblk <= 0) 122 *ap->a_runp = 0; 123 else if (nblk >= (MAXBSIZE >> bshift)) 124 *ap->a_runp = (MAXBSIZE >> bshift) - 1; 125 else 126 *ap->a_runp = nblk; 127 } 128 /* 129 * Compute the requested block number 130 */ 131 return filecore_map(fcmp, ip->i_dirent.addr, lbn, ap->a_bnp); 132 } 133 134 int 135 filecore_map(fcmp, addr, lbn, bnp) 136 struct filecore_mnt *fcmp; 137 u_int32_t addr; 138 daddr_t lbn; 139 daddr_t *bnp; 140 { 141 struct buf *bp; 142 u_long frag, sect, zone, izone, a, b, m, n; 143 u_int64_t zaddr; 144 u_long *ptr; 145 long c; 146 int error = 0; 147 148 #ifdef FILECORE_DEBUG 149 printf("filecore_map(addr=%x, lbn=%x)\n", addr, lbn); 150 #endif 151 frag = addr >> 8; 152 sect = (addr & 0xff) + 153 ((lbn << fcmp->log2bsize) >> fcmp->drec.log2secsize); 154 if (frag != 2) 155 zone = frag / fcmp->idspz; 156 else 157 zone = fcmp->drec.nzones / 2; 158 izone = zone; 159 if (zone != 0) 160 zaddr=((8<<fcmp->drec.log2secsize)-fcmp->drec.zone_spare)*zone 161 - 8*FILECORE_DISCREC_SIZE; 162 else 163 zaddr = 0; 164 if (sect > 0) 165 sect--; 166 sect <<= fcmp->drec.share_size; 167 do { 168 error=bread(fcmp->fc_devvp, fcmp->map + zone, 169 1 << fcmp->drec.log2secsize, NOCRED, &bp); 170 #ifdef FILECORE_DEBUG_BR 171 printf("bread(%p, %lx, %d, CRED, %p)=%d\n", fcmp->fc_devvp, 172 fcmp->map+zone, 1 << fcmp->drec.log2secsize, bp, error); 173 printf("block is at %p\n", bp->b_data); 174 #endif 175 if (error != 0) { 176 #ifdef FILECORE_DEBUG_BR 177 printf("brelse(%p) bm1\n", bp); 178 #endif 179 brelse(bp); 180 return error; 181 } 182 ptr = (u_long *)(bp->b_data) + 1; /* skip map zone header */ 183 if (zone == 0) 184 ptr += FILECORE_DISCREC_SIZE >> 2; 185 b = 0; 186 while (b < (8 << (fcmp->drec.log2secsize)) 187 - fcmp->drec.zone_spare) { 188 a = ptr[b >> 5] >> (b & 31); 189 c = 32 - (b & 31) - fcmp->drec.idlen; 190 if (c <= 0) { 191 m = ptr[(b >> 5) + 1]; 192 a |= m << (fcmp->drec.idlen+c); 193 m >>= -c; 194 c += 32; 195 } else 196 m = a >> fcmp->drec.idlen; 197 n = fcmp->drec.idlen + 1; 198 while ((m & 1) == 0) { 199 m >>= 1; 200 n++; 201 if (--c == 0) { 202 c=32; 203 m = ptr[(b + n - 1) >> 5]; 204 } 205 } 206 a &= fcmp->mask; 207 if (a == frag) { 208 if (sect << fcmp->drec.log2secsize < n 209 << fcmp->drec.log2bpmb) { 210 *bnp = (((zaddr+b) 211 << fcmp->drec.log2bpmb) 212 >> fcmp->drec.log2secsize) + sect; 213 214 #ifdef FILECORE_DEBUG_BR 215 printf("brelse(%p) bm2\n", bp); 216 #endif 217 brelse(bp); 218 return 0; 219 } else 220 sect -= (n<<fcmp->drec.log2bpmb) 221 >> fcmp->drec.log2secsize; 222 } 223 b += n; 224 } 225 #ifdef FILECORE_DEBUG_BR 226 printf("brelse(%p) bm3\n", bp); 227 #endif 228 brelse(bp); 229 if (++zone == fcmp->drec.nzones) { 230 zone = 0; 231 zaddr=0; 232 } else 233 zaddr += ((8 << fcmp->drec.log2secsize) 234 - fcmp->drec.zone_spare); 235 } while (zone != izone); 236 return (E2BIG); 237 } 238 239 int 240 filecore_bread(fcmp, addr, size, cred, bp) 241 struct filecore_mnt *fcmp; 242 u_int32_t addr; 243 int size; 244 struct ucred *cred; 245 struct buf **bp; 246 { 247 int error = 0; 248 daddr_t bn; 249 250 error = filecore_map(fcmp, addr, 0, &bn); 251 if (error) { 252 253 #ifdef FILECORE_DEBUG 254 printf("filecore_bread(error=%d)\n", error); 255 #endif 256 return error; 257 } 258 error = bread(fcmp->fc_devvp, bn, size, cred, bp); 259 #ifdef FILECORE_DEBUG_BR 260 printf("bread(%p, %x, %d, CRED, %p)=%d\n", fcmp->fc_devvp, bn, size, 261 *bp, error); 262 #endif 263 return error; 264 } 265 266 int 267 filecore_dbread(ip, bp) 268 struct filecore_node *ip; 269 struct buf **bp; 270 { 271 int error = 0; 272 273 if (ip->i_block == -1) 274 error = filecore_map(ip->i_mnt, ip->i_dirent.addr, 275 0, &(ip->i_block)); 276 if (error) 277 return error; 278 error = bread(ip->i_mnt->fc_devvp, ip->i_block, FILECORE_DIR_SIZE, 279 NOCRED, bp); 280 #ifdef FILECORE_DEBUG_BR 281 printf("bread(%p, %x, %d, CRED, %p)=%d\n", ip->i_mnt->fc_devvp, 282 ip->i_block, FILECORE_DIR_SIZE, *bp, error); 283 #endif 284 return error; 285 } 286