1 /* $NetBSD: filecore_bmap.c,v 1.11 2015/03/28 19:24:05 maxv 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.11 2015/03/28 19:24:05 maxv 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(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(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, 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 return error; 173 } 174 ptr = (u_long *)(bp->b_data) + 1; /* skip map zone header */ 175 if (zone == 0) 176 ptr += FILECORE_DISCREC_SIZE >> 2; 177 b = 0; 178 while (b < (8 << (fcmp->drec.log2secsize)) 179 - fcmp->drec.zone_spare) { 180 a = ptr[b >> 5] >> (b & 31); 181 c = 32 - (b & 31) - fcmp->drec.idlen; 182 if (c <= 0) { 183 m = ptr[(b >> 5) + 1]; 184 a |= m << (fcmp->drec.idlen+c); 185 m >>= -c; 186 c += 32; 187 } else 188 m = a >> fcmp->drec.idlen; 189 n = fcmp->drec.idlen + 1; 190 while ((m & 1) == 0) { 191 m >>= 1; 192 n++; 193 if (--c == 0) { 194 c=32; 195 m = ptr[(b + n - 1) >> 5]; 196 } 197 } 198 a &= fcmp->mask; 199 if (a == frag) { 200 if (sect << fcmp->drec.log2secsize < n 201 << fcmp->drec.log2bpmb) { 202 *bnp = (((zaddr+b) 203 << fcmp->drec.log2bpmb) 204 >> fcmp->drec.log2secsize) + sect; 205 206 #ifdef FILECORE_DEBUG_BR 207 printf("brelse(%p) bm2\n", bp); 208 #endif 209 brelse(bp, 0); 210 return 0; 211 } else 212 sect -= (n<<fcmp->drec.log2bpmb) 213 >> fcmp->drec.log2secsize; 214 } 215 b += n; 216 } 217 #ifdef FILECORE_DEBUG_BR 218 printf("brelse(%p) bm3\n", bp); 219 #endif 220 brelse(bp, 0); 221 if (++zone == fcmp->drec.nzones) { 222 zone = 0; 223 zaddr=0; 224 } else 225 zaddr += ((8 << fcmp->drec.log2secsize) 226 - fcmp->drec.zone_spare); 227 } while (zone != izone); 228 return (E2BIG); 229 } 230 231 int 232 filecore_bread(struct filecore_mnt *fcmp, u_int32_t addr, int size, kauth_cred_t cred, struct buf **bp) 233 { 234 int error = 0; 235 daddr_t bn; 236 237 error = filecore_map(fcmp, addr, 0, &bn); 238 if (error) { 239 240 #ifdef FILECORE_DEBUG 241 printf("filecore_bread(error=%d)\n", error); 242 #endif 243 return error; 244 } 245 error = bread(fcmp->fc_devvp, bn, size, 0, bp); 246 #ifdef FILECORE_DEBUG_BR 247 printf("bread(%p, %llx, %d, CRED, %p)=%d\n", fcmp->fc_devvp, 248 (long long)bn, size, *bp, error); 249 #endif 250 return error; 251 } 252 253 int 254 filecore_dbread(struct filecore_node *ip, struct buf **bp) 255 { 256 int error = 0; 257 258 if (ip->i_block == -1) 259 error = filecore_map(ip->i_mnt, ip->i_dirent.addr, 260 0, &(ip->i_block)); 261 if (error) 262 return error; 263 error = bread(ip->i_mnt->fc_devvp, ip->i_block, FILECORE_DIR_SIZE, 264 0, bp); 265 #ifdef FILECORE_DEBUG_BR 266 printf("bread(%p, %llx, %d, CRED, %p)=%d\n", ip->i_mnt->fc_devvp, 267 (long long)ip->i_block, FILECORE_DIR_SIZE, *bp, error); 268 #endif 269 return error; 270 } 271