xref: /netbsd-src/sys/fs/filecorefs/filecore_bmap.c (revision 6e39240181c12b316c197f88bf6b67704ef60e82)
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