1/* $NetBSD: filecore_bmap.c,v 1.8 2008/05/16 09:21:59 hannken 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.8 2008/05/16 09:21:59 hannken 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 */ 89int 90filecore_bmap(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 134int 135filecore_map(struct filecore_mnt *fcmp, u_int32_t addr, daddr_t lbn, daddr_t *bnp) 136{ 137 struct buf *bp; 138 u_long frag, sect, zone, izone, a, b, m, n; 139 u_int64_t zaddr; 140 u_long *ptr; 141 long c; 142 int error = 0; 143 144#ifdef FILECORE_DEBUG 145 printf("filecore_map(addr=%x, lbn=%llx)\n", addr, (long long)lbn); 146#endif 147 frag = addr >> 8; 148 sect = (addr & 0xff) + 149 ((lbn << fcmp->log2bsize) >> fcmp->drec.log2secsize); 150 if (frag != 2) 151 zone = frag / fcmp->idspz; 152 else 153 zone = fcmp->drec.nzones / 2; 154 izone = zone; 155 if (zone != 0) 156 zaddr=((8<<fcmp->drec.log2secsize)-fcmp->drec.zone_spare)*zone 157 - 8*FILECORE_DISCREC_SIZE; 158 else 159 zaddr = 0; 160 if (sect > 0) 161 sect--; 162 sect <<= fcmp->drec.share_size; 163 do { 164 error=bread(fcmp->fc_devvp, fcmp->map + zone, 165 1 << fcmp->drec.log2secsize, NOCRED, 0, &bp); 166#ifdef FILECORE_DEBUG_BR 167 printf("bread(%p, %lx, %d, CRED, %p)=%d\n", fcmp->fc_devvp, 168 fcmp->map+zone, 1 << fcmp->drec.log2secsize, bp, error); 169 printf("block is at %p\n", bp->b_data); 170#endif 171 if (error != 0) { 172#ifdef FILECORE_DEBUG_BR 173 printf("brelse(%p) bm1\n", bp); 174#endif 175 brelse(bp, 0); 176 return error; 177 } 178 ptr = (u_long *)(bp->b_data) + 1; /* skip map zone header */ 179 if (zone == 0) 180 ptr += FILECORE_DISCREC_SIZE >> 2; 181 b = 0; 182 while (b < (8 << (fcmp->drec.log2secsize)) 183 - fcmp->drec.zone_spare) { 184 a = ptr[b >> 5] >> (b & 31); 185 c = 32 - (b & 31) - fcmp->drec.idlen; 186 if (c <= 0) { 187 m = ptr[(b >> 5) + 1]; 188 a |= m << (fcmp->drec.idlen+c); 189 m >>= -c; 190 c += 32; 191 } else 192 m = a >> fcmp->drec.idlen; 193 n = fcmp->drec.idlen + 1; 194 while ((m & 1) == 0) { 195 m >>= 1; 196 n++; 197 if (--c == 0) { 198 c=32; 199 m = ptr[(b + n - 1) >> 5]; 200 } 201 } 202 a &= fcmp->mask; 203 if (a == frag) { 204 if (sect << fcmp->drec.log2secsize < n 205 << fcmp->drec.log2bpmb) { 206 *bnp = (((zaddr+b) 207 << fcmp->drec.log2bpmb) 208 >> fcmp->drec.log2secsize) + sect; 209 210#ifdef FILECORE_DEBUG_BR 211 printf("brelse(%p) bm2\n", bp); 212#endif 213 brelse(bp, 0); 214 return 0; 215 } else 216 sect -= (n<<fcmp->drec.log2bpmb) 217 >> fcmp->drec.log2secsize; 218 } 219 b += n; 220 } 221#ifdef FILECORE_DEBUG_BR 222 printf("brelse(%p) bm3\n", bp); 223#endif 224 brelse(bp, 0); 225 if (++zone == fcmp->drec.nzones) { 226 zone = 0; 227 zaddr=0; 228 } else 229 zaddr += ((8 << fcmp->drec.log2secsize) 230 - fcmp->drec.zone_spare); 231 } while (zone != izone); 232 return (E2BIG); 233} 234 235int 236filecore_bread(struct filecore_mnt *fcmp, u_int32_t addr, int size, kauth_cred_t cred, struct buf **bp) 237{ 238 int error = 0; 239 daddr_t bn; 240 241 error = filecore_map(fcmp, addr, 0, &bn); 242 if (error) { 243 244#ifdef FILECORE_DEBUG 245 printf("filecore_bread(error=%d)\n", error); 246#endif 247 return error; 248 } 249 error = bread(fcmp->fc_devvp, bn, size, cred, 0, bp); 250#ifdef FILECORE_DEBUG_BR 251 printf("bread(%p, %llx, %d, CRED, %p)=%d\n", fcmp->fc_devvp, 252 (long long)bn, size, *bp, error); 253#endif 254 return error; 255} 256 257int 258filecore_dbread(struct filecore_node *ip, struct buf **bp) 259{ 260 int error = 0; 261 262 if (ip->i_block == -1) 263 error = filecore_map(ip->i_mnt, ip->i_dirent.addr, 264 0, &(ip->i_block)); 265 if (error) 266 return error; 267 error = bread(ip->i_mnt->fc_devvp, ip->i_block, FILECORE_DIR_SIZE, 268 NOCRED, 0, bp); 269#ifdef FILECORE_DEBUG_BR 270 printf("bread(%p, %llx, %d, CRED, %p)=%d\n", ip->i_mnt->fc_devvp, 271 (long long)ip->i_block, FILECORE_DIR_SIZE, *bp, error); 272#endif 273 return error; 274} 275