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