1*6e392401Smaxv /* $NetBSD: filecore_bmap.c,v 1.11 2015/03/28 19:24:05 maxv Exp $ */
2aad01611Sagc
3aad01611Sagc /*-
4aad01611Sagc * Copyright (c) 1994 The Regents of the University of California.
5aad01611Sagc * All rights reserved.
6aad01611Sagc *
7aad01611Sagc * Redistribution and use in source and binary forms, with or without
8aad01611Sagc * modification, are permitted provided that the following conditions
9aad01611Sagc * are met:
10aad01611Sagc * 1. Redistributions of source code must retain the above copyright
11aad01611Sagc * notice, this list of conditions and the following disclaimer.
12aad01611Sagc * 2. Redistributions in binary form must reproduce the above copyright
13aad01611Sagc * notice, this list of conditions and the following disclaimer in the
14aad01611Sagc * documentation and/or other materials provided with the distribution.
15aad01611Sagc * 3. Neither the name of the University nor the names of its contributors
16aad01611Sagc * may be used to endorse or promote products derived from this software
17aad01611Sagc * without specific prior written permission.
18aad01611Sagc *
19aad01611Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20aad01611Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21aad01611Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22aad01611Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23aad01611Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24aad01611Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25aad01611Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26aad01611Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27aad01611Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28aad01611Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29aad01611Sagc * SUCH DAMAGE.
30aad01611Sagc *
31aad01611Sagc * filecore_bmap.c 1.1 1998/6/26
32aad01611Sagc */
335356de15Sjdolecek
345356de15Sjdolecek /*-
355356de15Sjdolecek * Copyright (c) 1998 Andrew McMurry
365356de15Sjdolecek *
375356de15Sjdolecek * Redistribution and use in source and binary forms, with or without
385356de15Sjdolecek * modification, are permitted provided that the following conditions
395356de15Sjdolecek * are met:
405356de15Sjdolecek * 1. Redistributions of source code must retain the above copyright
415356de15Sjdolecek * notice, this list of conditions and the following disclaimer.
425356de15Sjdolecek * 2. Redistributions in binary form must reproduce the above copyright
435356de15Sjdolecek * notice, this list of conditions and the following disclaimer in the
445356de15Sjdolecek * documentation and/or other materials provided with the distribution.
455356de15Sjdolecek * 3. All advertising materials mentioning features or use of this software
465356de15Sjdolecek * must display the following acknowledgement:
475356de15Sjdolecek * This product includes software developed by the University of
485356de15Sjdolecek * California, Berkeley and its contributors.
495356de15Sjdolecek * 4. Neither the name of the University nor the names of its contributors
505356de15Sjdolecek * may be used to endorse or promote products derived from this software
515356de15Sjdolecek * without specific prior written permission.
525356de15Sjdolecek *
535356de15Sjdolecek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
545356de15Sjdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
555356de15Sjdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
565356de15Sjdolecek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
575356de15Sjdolecek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
585356de15Sjdolecek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
595356de15Sjdolecek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
605356de15Sjdolecek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
615356de15Sjdolecek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
625356de15Sjdolecek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
635356de15Sjdolecek * SUCH DAMAGE.
645356de15Sjdolecek *
655356de15Sjdolecek * filecore_bmap.c 1.1 1998/6/26
665356de15Sjdolecek */
675356de15Sjdolecek
685356de15Sjdolecek #include <sys/cdefs.h>
69*6e392401Smaxv __KERNEL_RCSID(0, "$NetBSD: filecore_bmap.c,v 1.11 2015/03/28 19:24:05 maxv Exp $");
705356de15Sjdolecek
715356de15Sjdolecek #include <sys/param.h>
725356de15Sjdolecek #include <sys/systm.h>
735356de15Sjdolecek #include <sys/namei.h>
745356de15Sjdolecek #include <sys/buf.h>
755356de15Sjdolecek #include <sys/file.h>
765356de15Sjdolecek #include <sys/vnode.h>
775356de15Sjdolecek #include <sys/mount.h>
78641b7ad8Schristos #include <sys/kauth.h>
795356de15Sjdolecek
805356de15Sjdolecek #include <fs/filecorefs/filecore.h>
815356de15Sjdolecek #include <fs/filecorefs/filecore_extern.h>
825356de15Sjdolecek #include <fs/filecorefs/filecore_node.h>
835356de15Sjdolecek
845356de15Sjdolecek /*
855356de15Sjdolecek * Bmap converts a the logical block number of a file to its physical block
865356de15Sjdolecek * number on the disk. The conversion is done by using the logical block
875356de15Sjdolecek * number to index into the data block (extent) for the file.
885356de15Sjdolecek */
895356de15Sjdolecek int
filecore_bmap(void * v)90454af1c0Sdsl filecore_bmap(void *v)
915356de15Sjdolecek {
925356de15Sjdolecek struct vop_bmap_args /* {
935356de15Sjdolecek struct vnode *a_vp;
945356de15Sjdolecek daddr_t a_bn;
955356de15Sjdolecek struct vnode **a_vpp;
965356de15Sjdolecek daddr_t *a_bnp;
975356de15Sjdolecek int *a_runp;
985356de15Sjdolecek } */ *ap = v;
995356de15Sjdolecek struct filecore_node *ip = VTOI(ap->a_vp);
1005356de15Sjdolecek struct filecore_mnt *fcmp = ip->i_mnt;
1015356de15Sjdolecek daddr_t lbn = ap->a_bn;
1025356de15Sjdolecek
1035356de15Sjdolecek /*
1045356de15Sjdolecek * Check for underlying vnode requests and ensure that logical
1055356de15Sjdolecek * to physical mapping is requested.
1065356de15Sjdolecek */
1075356de15Sjdolecek if (ap->a_vpp != NULL)
1085356de15Sjdolecek *ap->a_vpp = ip->i_devvp;
1095356de15Sjdolecek if (ap->a_bnp == NULL)
1105356de15Sjdolecek return (0);
1115356de15Sjdolecek
1125356de15Sjdolecek /*
1135356de15Sjdolecek * Determine maximum number of readahead blocks following the
1145356de15Sjdolecek * requested block.
1155356de15Sjdolecek */
1165356de15Sjdolecek if (ap->a_runp) {
1175356de15Sjdolecek int nblk;
1185356de15Sjdolecek int bshift=fcmp->log2bsize;
1195356de15Sjdolecek
1205356de15Sjdolecek nblk = (ip->i_size >> bshift) - (lbn + 1);
1215356de15Sjdolecek if (nblk <= 0)
1225356de15Sjdolecek *ap->a_runp = 0;
1235356de15Sjdolecek else if (nblk >= (MAXBSIZE >> bshift))
1245356de15Sjdolecek *ap->a_runp = (MAXBSIZE >> bshift) - 1;
1255356de15Sjdolecek else
1265356de15Sjdolecek *ap->a_runp = nblk;
1275356de15Sjdolecek }
1285356de15Sjdolecek /*
1295356de15Sjdolecek * Compute the requested block number
1305356de15Sjdolecek */
1315356de15Sjdolecek return filecore_map(fcmp, ip->i_dirent.addr, lbn, ap->a_bnp);
1325356de15Sjdolecek }
1335356de15Sjdolecek
1345356de15Sjdolecek int
filecore_map(struct filecore_mnt * fcmp,u_int32_t addr,daddr_t lbn,daddr_t * bnp)135454af1c0Sdsl filecore_map(struct filecore_mnt *fcmp, u_int32_t addr, daddr_t lbn, daddr_t *bnp)
1365356de15Sjdolecek {
1375356de15Sjdolecek struct buf *bp;
1385356de15Sjdolecek u_long frag, sect, zone, izone, a, b, m, n;
1395356de15Sjdolecek u_int64_t zaddr;
1405356de15Sjdolecek u_long *ptr;
1415356de15Sjdolecek long c;
1425356de15Sjdolecek int error = 0;
1435356de15Sjdolecek
1445356de15Sjdolecek #ifdef FILECORE_DEBUG
1451498ad22Sad printf("filecore_map(addr=%x, lbn=%llx)\n", addr, (long long)lbn);
1465356de15Sjdolecek #endif
1475356de15Sjdolecek frag = addr >> 8;
1485356de15Sjdolecek sect = (addr & 0xff) +
1495356de15Sjdolecek ((lbn << fcmp->log2bsize) >> fcmp->drec.log2secsize);
1505356de15Sjdolecek if (frag != 2)
1515356de15Sjdolecek zone = frag / fcmp->idspz;
1525356de15Sjdolecek else
1535356de15Sjdolecek zone = fcmp->drec.nzones / 2;
1545356de15Sjdolecek izone = zone;
1555356de15Sjdolecek if (zone != 0)
1565356de15Sjdolecek zaddr=((8<<fcmp->drec.log2secsize)-fcmp->drec.zone_spare)*zone
1575356de15Sjdolecek - 8*FILECORE_DISCREC_SIZE;
1585356de15Sjdolecek else
1595356de15Sjdolecek zaddr = 0;
1605356de15Sjdolecek if (sect > 0)
1615356de15Sjdolecek sect--;
1625356de15Sjdolecek sect <<= fcmp->drec.share_size;
1635356de15Sjdolecek do {
1645356de15Sjdolecek error=bread(fcmp->fc_devvp, fcmp->map + zone,
165*6e392401Smaxv 1 << fcmp->drec.log2secsize, 0, &bp);
1665356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
1675356de15Sjdolecek printf("bread(%p, %lx, %d, CRED, %p)=%d\n", fcmp->fc_devvp,
1685356de15Sjdolecek fcmp->map+zone, 1 << fcmp->drec.log2secsize, bp, error);
1695356de15Sjdolecek printf("block is at %p\n", bp->b_data);
1705356de15Sjdolecek #endif
1715356de15Sjdolecek if (error != 0) {
1725356de15Sjdolecek return error;
1735356de15Sjdolecek }
1745356de15Sjdolecek ptr = (u_long *)(bp->b_data) + 1; /* skip map zone header */
1755356de15Sjdolecek if (zone == 0)
1765356de15Sjdolecek ptr += FILECORE_DISCREC_SIZE >> 2;
1775356de15Sjdolecek b = 0;
1785356de15Sjdolecek while (b < (8 << (fcmp->drec.log2secsize))
1795356de15Sjdolecek - fcmp->drec.zone_spare) {
1805356de15Sjdolecek a = ptr[b >> 5] >> (b & 31);
1815356de15Sjdolecek c = 32 - (b & 31) - fcmp->drec.idlen;
1825356de15Sjdolecek if (c <= 0) {
1835356de15Sjdolecek m = ptr[(b >> 5) + 1];
1845356de15Sjdolecek a |= m << (fcmp->drec.idlen+c);
1855356de15Sjdolecek m >>= -c;
1865356de15Sjdolecek c += 32;
1875356de15Sjdolecek } else
1885356de15Sjdolecek m = a >> fcmp->drec.idlen;
1895356de15Sjdolecek n = fcmp->drec.idlen + 1;
1905356de15Sjdolecek while ((m & 1) == 0) {
1915356de15Sjdolecek m >>= 1;
1925356de15Sjdolecek n++;
1935356de15Sjdolecek if (--c == 0) {
1945356de15Sjdolecek c=32;
1955356de15Sjdolecek m = ptr[(b + n - 1) >> 5];
1965356de15Sjdolecek }
1975356de15Sjdolecek }
1985356de15Sjdolecek a &= fcmp->mask;
1995356de15Sjdolecek if (a == frag) {
2005356de15Sjdolecek if (sect << fcmp->drec.log2secsize < n
2015356de15Sjdolecek << fcmp->drec.log2bpmb) {
2025356de15Sjdolecek *bnp = (((zaddr+b)
2035356de15Sjdolecek << fcmp->drec.log2bpmb)
2045356de15Sjdolecek >> fcmp->drec.log2secsize) + sect;
2055356de15Sjdolecek
2065356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
2075356de15Sjdolecek printf("brelse(%p) bm2\n", bp);
2085356de15Sjdolecek #endif
2099f56dfa5Sad brelse(bp, 0);
2105356de15Sjdolecek return 0;
2115356de15Sjdolecek } else
2125356de15Sjdolecek sect -= (n<<fcmp->drec.log2bpmb)
2135356de15Sjdolecek >> fcmp->drec.log2secsize;
2145356de15Sjdolecek }
2155356de15Sjdolecek b += n;
2165356de15Sjdolecek }
2175356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
2185356de15Sjdolecek printf("brelse(%p) bm3\n", bp);
2195356de15Sjdolecek #endif
2209f56dfa5Sad brelse(bp, 0);
2215356de15Sjdolecek if (++zone == fcmp->drec.nzones) {
2225356de15Sjdolecek zone = 0;
2235356de15Sjdolecek zaddr=0;
2245356de15Sjdolecek } else
2255356de15Sjdolecek zaddr += ((8 << fcmp->drec.log2secsize)
2265356de15Sjdolecek - fcmp->drec.zone_spare);
2275356de15Sjdolecek } while (zone != izone);
2285356de15Sjdolecek return (E2BIG);
2295356de15Sjdolecek }
2305356de15Sjdolecek
2315356de15Sjdolecek int
filecore_bread(struct filecore_mnt * fcmp,u_int32_t addr,int size,kauth_cred_t cred,struct buf ** bp)232454af1c0Sdsl filecore_bread(struct filecore_mnt *fcmp, u_int32_t addr, int size, kauth_cred_t cred, struct buf **bp)
2335356de15Sjdolecek {
2345356de15Sjdolecek int error = 0;
2355356de15Sjdolecek daddr_t bn;
2365356de15Sjdolecek
2375356de15Sjdolecek error = filecore_map(fcmp, addr, 0, &bn);
2385356de15Sjdolecek if (error) {
2395356de15Sjdolecek
2405356de15Sjdolecek #ifdef FILECORE_DEBUG
2415356de15Sjdolecek printf("filecore_bread(error=%d)\n", error);
2425356de15Sjdolecek #endif
2435356de15Sjdolecek return error;
2445356de15Sjdolecek }
245*6e392401Smaxv error = bread(fcmp->fc_devvp, bn, size, 0, bp);
2465356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
2471498ad22Sad printf("bread(%p, %llx, %d, CRED, %p)=%d\n", fcmp->fc_devvp,
2481498ad22Sad (long long)bn, size, *bp, error);
2495356de15Sjdolecek #endif
2505356de15Sjdolecek return error;
2515356de15Sjdolecek }
2525356de15Sjdolecek
2535356de15Sjdolecek int
filecore_dbread(struct filecore_node * ip,struct buf ** bp)254454af1c0Sdsl filecore_dbread(struct filecore_node *ip, struct buf **bp)
2555356de15Sjdolecek {
2565356de15Sjdolecek int error = 0;
2575356de15Sjdolecek
2585356de15Sjdolecek if (ip->i_block == -1)
2595356de15Sjdolecek error = filecore_map(ip->i_mnt, ip->i_dirent.addr,
2605356de15Sjdolecek 0, &(ip->i_block));
2615356de15Sjdolecek if (error)
2625356de15Sjdolecek return error;
2635356de15Sjdolecek error = bread(ip->i_mnt->fc_devvp, ip->i_block, FILECORE_DIR_SIZE,
264*6e392401Smaxv 0, bp);
2655356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
2661498ad22Sad printf("bread(%p, %llx, %d, CRED, %p)=%d\n", ip->i_mnt->fc_devvp,
2671498ad22Sad (long long)ip->i_block, FILECORE_DIR_SIZE, *bp, error);
2685356de15Sjdolecek #endif
2695356de15Sjdolecek return error;
2705356de15Sjdolecek }
271