1 1.11 maxv /* $NetBSD: filecore_bmap.c,v 1.11 2015/03/28 19:24:05 maxv Exp $ */ 2 1.1 jdolecek 3 1.1 jdolecek /*- 4 1.1 jdolecek * Copyright (c) 1994 The Regents of the University of California. 5 1.1 jdolecek * All rights reserved. 6 1.1 jdolecek * 7 1.1 jdolecek * Redistribution and use in source and binary forms, with or without 8 1.1 jdolecek * modification, are permitted provided that the following conditions 9 1.1 jdolecek * are met: 10 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright 11 1.1 jdolecek * notice, this list of conditions and the following disclaimer. 12 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the 14 1.1 jdolecek * documentation and/or other materials provided with the distribution. 15 1.2 agc * 3. Neither the name of the University nor the names of its contributors 16 1.2 agc * may be used to endorse or promote products derived from this software 17 1.2 agc * without specific prior written permission. 18 1.2 agc * 19 1.2 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.2 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.2 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.2 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.2 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.2 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.2 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.2 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.2 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.2 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.2 agc * SUCH DAMAGE. 30 1.2 agc * 31 1.2 agc * filecore_bmap.c 1.1 1998/6/26 32 1.2 agc */ 33 1.2 agc 34 1.2 agc /*- 35 1.2 agc * Copyright (c) 1998 Andrew McMurry 36 1.2 agc * 37 1.2 agc * Redistribution and use in source and binary forms, with or without 38 1.2 agc * modification, are permitted provided that the following conditions 39 1.2 agc * are met: 40 1.2 agc * 1. Redistributions of source code must retain the above copyright 41 1.2 agc * notice, this list of conditions and the following disclaimer. 42 1.2 agc * 2. Redistributions in binary form must reproduce the above copyright 43 1.2 agc * notice, this list of conditions and the following disclaimer in the 44 1.2 agc * documentation and/or other materials provided with the distribution. 45 1.1 jdolecek * 3. All advertising materials mentioning features or use of this software 46 1.1 jdolecek * must display the following acknowledgement: 47 1.1 jdolecek * This product includes software developed by the University of 48 1.1 jdolecek * California, Berkeley and its contributors. 49 1.1 jdolecek * 4. Neither the name of the University nor the names of its contributors 50 1.1 jdolecek * may be used to endorse or promote products derived from this software 51 1.1 jdolecek * without specific prior written permission. 52 1.1 jdolecek * 53 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 1.1 jdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 1.1 jdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 1.1 jdolecek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 1.1 jdolecek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 1.1 jdolecek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 1.1 jdolecek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 1.1 jdolecek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 1.1 jdolecek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 1.1 jdolecek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 1.1 jdolecek * SUCH DAMAGE. 64 1.1 jdolecek * 65 1.1 jdolecek * filecore_bmap.c 1.1 1998/6/26 66 1.1 jdolecek */ 67 1.1 jdolecek 68 1.1 jdolecek #include <sys/cdefs.h> 69 1.11 maxv __KERNEL_RCSID(0, "$NetBSD: filecore_bmap.c,v 1.11 2015/03/28 19:24:05 maxv Exp $"); 70 1.1 jdolecek 71 1.1 jdolecek #include <sys/param.h> 72 1.1 jdolecek #include <sys/systm.h> 73 1.1 jdolecek #include <sys/namei.h> 74 1.1 jdolecek #include <sys/buf.h> 75 1.1 jdolecek #include <sys/file.h> 76 1.1 jdolecek #include <sys/vnode.h> 77 1.1 jdolecek #include <sys/mount.h> 78 1.5 christos #include <sys/kauth.h> 79 1.1 jdolecek 80 1.1 jdolecek #include <fs/filecorefs/filecore.h> 81 1.1 jdolecek #include <fs/filecorefs/filecore_extern.h> 82 1.1 jdolecek #include <fs/filecorefs/filecore_node.h> 83 1.1 jdolecek 84 1.1 jdolecek /* 85 1.1 jdolecek * Bmap converts a the logical block number of a file to its physical block 86 1.1 jdolecek * number on the disk. The conversion is done by using the logical block 87 1.1 jdolecek * number to index into the data block (extent) for the file. 88 1.1 jdolecek */ 89 1.1 jdolecek int 90 1.9 dsl filecore_bmap(void *v) 91 1.1 jdolecek { 92 1.1 jdolecek struct vop_bmap_args /* { 93 1.1 jdolecek struct vnode *a_vp; 94 1.1 jdolecek daddr_t a_bn; 95 1.1 jdolecek struct vnode **a_vpp; 96 1.1 jdolecek daddr_t *a_bnp; 97 1.1 jdolecek int *a_runp; 98 1.1 jdolecek } */ *ap = v; 99 1.1 jdolecek struct filecore_node *ip = VTOI(ap->a_vp); 100 1.1 jdolecek struct filecore_mnt *fcmp = ip->i_mnt; 101 1.1 jdolecek daddr_t lbn = ap->a_bn; 102 1.1 jdolecek 103 1.1 jdolecek /* 104 1.1 jdolecek * Check for underlying vnode requests and ensure that logical 105 1.1 jdolecek * to physical mapping is requested. 106 1.1 jdolecek */ 107 1.1 jdolecek if (ap->a_vpp != NULL) 108 1.1 jdolecek *ap->a_vpp = ip->i_devvp; 109 1.1 jdolecek if (ap->a_bnp == NULL) 110 1.1 jdolecek return (0); 111 1.1 jdolecek 112 1.1 jdolecek /* 113 1.1 jdolecek * Determine maximum number of readahead blocks following the 114 1.1 jdolecek * requested block. 115 1.1 jdolecek */ 116 1.1 jdolecek if (ap->a_runp) { 117 1.1 jdolecek int nblk; 118 1.1 jdolecek int bshift=fcmp->log2bsize; 119 1.1 jdolecek 120 1.1 jdolecek nblk = (ip->i_size >> bshift) - (lbn + 1); 121 1.1 jdolecek if (nblk <= 0) 122 1.1 jdolecek *ap->a_runp = 0; 123 1.1 jdolecek else if (nblk >= (MAXBSIZE >> bshift)) 124 1.1 jdolecek *ap->a_runp = (MAXBSIZE >> bshift) - 1; 125 1.1 jdolecek else 126 1.1 jdolecek *ap->a_runp = nblk; 127 1.1 jdolecek } 128 1.1 jdolecek /* 129 1.1 jdolecek * Compute the requested block number 130 1.1 jdolecek */ 131 1.1 jdolecek return filecore_map(fcmp, ip->i_dirent.addr, lbn, ap->a_bnp); 132 1.1 jdolecek } 133 1.1 jdolecek 134 1.1 jdolecek int 135 1.9 dsl filecore_map(struct filecore_mnt *fcmp, u_int32_t addr, daddr_t lbn, daddr_t *bnp) 136 1.1 jdolecek { 137 1.1 jdolecek struct buf *bp; 138 1.1 jdolecek u_long frag, sect, zone, izone, a, b, m, n; 139 1.1 jdolecek u_int64_t zaddr; 140 1.1 jdolecek u_long *ptr; 141 1.1 jdolecek long c; 142 1.1 jdolecek int error = 0; 143 1.1 jdolecek 144 1.1 jdolecek #ifdef FILECORE_DEBUG 145 1.7 ad printf("filecore_map(addr=%x, lbn=%llx)\n", addr, (long long)lbn); 146 1.1 jdolecek #endif 147 1.1 jdolecek frag = addr >> 8; 148 1.1 jdolecek sect = (addr & 0xff) + 149 1.1 jdolecek ((lbn << fcmp->log2bsize) >> fcmp->drec.log2secsize); 150 1.1 jdolecek if (frag != 2) 151 1.1 jdolecek zone = frag / fcmp->idspz; 152 1.1 jdolecek else 153 1.1 jdolecek zone = fcmp->drec.nzones / 2; 154 1.1 jdolecek izone = zone; 155 1.1 jdolecek if (zone != 0) 156 1.1 jdolecek zaddr=((8<<fcmp->drec.log2secsize)-fcmp->drec.zone_spare)*zone 157 1.1 jdolecek - 8*FILECORE_DISCREC_SIZE; 158 1.1 jdolecek else 159 1.1 jdolecek zaddr = 0; 160 1.1 jdolecek if (sect > 0) 161 1.1 jdolecek sect--; 162 1.1 jdolecek sect <<= fcmp->drec.share_size; 163 1.1 jdolecek do { 164 1.1 jdolecek error=bread(fcmp->fc_devvp, fcmp->map + zone, 165 1.11 maxv 1 << fcmp->drec.log2secsize, 0, &bp); 166 1.1 jdolecek #ifdef FILECORE_DEBUG_BR 167 1.1 jdolecek printf("bread(%p, %lx, %d, CRED, %p)=%d\n", fcmp->fc_devvp, 168 1.1 jdolecek fcmp->map+zone, 1 << fcmp->drec.log2secsize, bp, error); 169 1.1 jdolecek printf("block is at %p\n", bp->b_data); 170 1.1 jdolecek #endif 171 1.1 jdolecek if (error != 0) { 172 1.1 jdolecek return error; 173 1.1 jdolecek } 174 1.1 jdolecek ptr = (u_long *)(bp->b_data) + 1; /* skip map zone header */ 175 1.1 jdolecek if (zone == 0) 176 1.1 jdolecek ptr += FILECORE_DISCREC_SIZE >> 2; 177 1.1 jdolecek b = 0; 178 1.1 jdolecek while (b < (8 << (fcmp->drec.log2secsize)) 179 1.1 jdolecek - fcmp->drec.zone_spare) { 180 1.1 jdolecek a = ptr[b >> 5] >> (b & 31); 181 1.1 jdolecek c = 32 - (b & 31) - fcmp->drec.idlen; 182 1.1 jdolecek if (c <= 0) { 183 1.1 jdolecek m = ptr[(b >> 5) + 1]; 184 1.1 jdolecek a |= m << (fcmp->drec.idlen+c); 185 1.1 jdolecek m >>= -c; 186 1.1 jdolecek c += 32; 187 1.1 jdolecek } else 188 1.1 jdolecek m = a >> fcmp->drec.idlen; 189 1.1 jdolecek n = fcmp->drec.idlen + 1; 190 1.1 jdolecek while ((m & 1) == 0) { 191 1.1 jdolecek m >>= 1; 192 1.1 jdolecek n++; 193 1.1 jdolecek if (--c == 0) { 194 1.1 jdolecek c=32; 195 1.1 jdolecek m = ptr[(b + n - 1) >> 5]; 196 1.1 jdolecek } 197 1.1 jdolecek } 198 1.1 jdolecek a &= fcmp->mask; 199 1.1 jdolecek if (a == frag) { 200 1.1 jdolecek if (sect << fcmp->drec.log2secsize < n 201 1.1 jdolecek << fcmp->drec.log2bpmb) { 202 1.1 jdolecek *bnp = (((zaddr+b) 203 1.1 jdolecek << fcmp->drec.log2bpmb) 204 1.1 jdolecek >> fcmp->drec.log2secsize) + sect; 205 1.1 jdolecek 206 1.1 jdolecek #ifdef FILECORE_DEBUG_BR 207 1.1 jdolecek printf("brelse(%p) bm2\n", bp); 208 1.1 jdolecek #endif 209 1.6 ad brelse(bp, 0); 210 1.1 jdolecek return 0; 211 1.1 jdolecek } else 212 1.1 jdolecek sect -= (n<<fcmp->drec.log2bpmb) 213 1.1 jdolecek >> fcmp->drec.log2secsize; 214 1.1 jdolecek } 215 1.1 jdolecek b += n; 216 1.1 jdolecek } 217 1.1 jdolecek #ifdef FILECORE_DEBUG_BR 218 1.1 jdolecek printf("brelse(%p) bm3\n", bp); 219 1.1 jdolecek #endif 220 1.6 ad brelse(bp, 0); 221 1.1 jdolecek if (++zone == fcmp->drec.nzones) { 222 1.1 jdolecek zone = 0; 223 1.1 jdolecek zaddr=0; 224 1.1 jdolecek } else 225 1.1 jdolecek zaddr += ((8 << fcmp->drec.log2secsize) 226 1.1 jdolecek - fcmp->drec.zone_spare); 227 1.1 jdolecek } while (zone != izone); 228 1.1 jdolecek return (E2BIG); 229 1.1 jdolecek } 230 1.1 jdolecek 231 1.1 jdolecek int 232 1.9 dsl filecore_bread(struct filecore_mnt *fcmp, u_int32_t addr, int size, kauth_cred_t cred, struct buf **bp) 233 1.1 jdolecek { 234 1.1 jdolecek int error = 0; 235 1.1 jdolecek daddr_t bn; 236 1.1 jdolecek 237 1.1 jdolecek error = filecore_map(fcmp, addr, 0, &bn); 238 1.1 jdolecek if (error) { 239 1.1 jdolecek 240 1.1 jdolecek #ifdef FILECORE_DEBUG 241 1.1 jdolecek printf("filecore_bread(error=%d)\n", error); 242 1.1 jdolecek #endif 243 1.1 jdolecek return error; 244 1.1 jdolecek } 245 1.11 maxv error = bread(fcmp->fc_devvp, bn, size, 0, bp); 246 1.1 jdolecek #ifdef FILECORE_DEBUG_BR 247 1.7 ad printf("bread(%p, %llx, %d, CRED, %p)=%d\n", fcmp->fc_devvp, 248 1.7 ad (long long)bn, size, *bp, error); 249 1.1 jdolecek #endif 250 1.1 jdolecek return error; 251 1.1 jdolecek } 252 1.1 jdolecek 253 1.1 jdolecek int 254 1.9 dsl filecore_dbread(struct filecore_node *ip, struct buf **bp) 255 1.1 jdolecek { 256 1.1 jdolecek int error = 0; 257 1.1 jdolecek 258 1.1 jdolecek if (ip->i_block == -1) 259 1.1 jdolecek error = filecore_map(ip->i_mnt, ip->i_dirent.addr, 260 1.1 jdolecek 0, &(ip->i_block)); 261 1.1 jdolecek if (error) 262 1.1 jdolecek return error; 263 1.1 jdolecek error = bread(ip->i_mnt->fc_devvp, ip->i_block, FILECORE_DIR_SIZE, 264 1.11 maxv 0, bp); 265 1.1 jdolecek #ifdef FILECORE_DEBUG_BR 266 1.7 ad printf("bread(%p, %llx, %d, CRED, %p)=%d\n", ip->i_mnt->fc_devvp, 267 1.7 ad (long long)ip->i_block, FILECORE_DIR_SIZE, *bp, error); 268 1.1 jdolecek #endif 269 1.1 jdolecek return error; 270 1.1 jdolecek } 271