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