xref: /netbsd-src/usr.sbin/makefs/ffs/ufs_bmap.c (revision bf2ad7248906fbda5c0a68bac7ee290dcd2d2b38)
1*bf2ad724Sriastradh /*	$NetBSD: ufs_bmap.c,v 1.19 2022/04/09 10:05:35 riastradh Exp $	*/
268b8babdSlukem /* From: NetBSD: ufs_bmap.c,v 1.14 2001/11/08 05:00:51 chs Exp */
36325773eSlukem 
46325773eSlukem /*
56325773eSlukem  * Copyright (c) 1989, 1991, 1993
66325773eSlukem  *	The Regents of the University of California.  All rights reserved.
76325773eSlukem  * (c) UNIX System Laboratories, Inc.
86325773eSlukem  * All or some portions of this file are derived from material licensed
96325773eSlukem  * to the University of California by American Telephone and Telegraph
106325773eSlukem  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
116325773eSlukem  * the permission of UNIX System Laboratories, Inc.
126325773eSlukem  *
136325773eSlukem  * Redistribution and use in source and binary forms, with or without
146325773eSlukem  * modification, are permitted provided that the following conditions
156325773eSlukem  * are met:
166325773eSlukem  * 1. Redistributions of source code must retain the above copyright
176325773eSlukem  *    notice, this list of conditions and the following disclaimer.
186325773eSlukem  * 2. Redistributions in binary form must reproduce the above copyright
196325773eSlukem  *    notice, this list of conditions and the following disclaimer in the
206325773eSlukem  *    documentation and/or other materials provided with the distribution.
21326b2259Sagc  * 3. Neither the name of the University nor the names of its contributors
226325773eSlukem  *    may be used to endorse or promote products derived from this software
236325773eSlukem  *    without specific prior written permission.
246325773eSlukem  *
256325773eSlukem  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
266325773eSlukem  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
276325773eSlukem  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
286325773eSlukem  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
296325773eSlukem  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
306325773eSlukem  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
316325773eSlukem  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
326325773eSlukem  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
336325773eSlukem  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
346325773eSlukem  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
356325773eSlukem  * SUCH DAMAGE.
366325773eSlukem  *
376325773eSlukem  *	@(#)ufs_bmap.c	8.8 (Berkeley) 8/11/95
386325773eSlukem  */
396325773eSlukem 
40b2f78261Sjmc #if HAVE_NBTOOL_CONFIG_H
41b2f78261Sjmc #include "nbtool_config.h"
42b2f78261Sjmc #endif
43b2f78261Sjmc 
44cafb53fcSlukem #include <sys/cdefs.h>
4576834aefStv #if defined(__RCSID) && !defined(__lint)
46*bf2ad724Sriastradh __RCSID("$NetBSD: ufs_bmap.c,v 1.19 2022/04/09 10:05:35 riastradh Exp $");
47cafb53fcSlukem #endif	/* !__lint */
48cafb53fcSlukem 
496325773eSlukem #include <sys/param.h>
506325773eSlukem #include <sys/time.h>
516325773eSlukem 
5268b8babdSlukem #include <assert.h>
536325773eSlukem #include <errno.h>
541b1d20a8Sthorpej #include <strings.h>
556325773eSlukem 
56d74b2fc0Slukem #include "makefs.h"
57d74b2fc0Slukem 
583d765797Slukem #include <ufs/ufs/dinode.h>
59557afc60Slukem #include <ufs/ufs/ufs_bswap.h>
60557afc60Slukem #include <ufs/ffs/fs.h>
616325773eSlukem 
62944794a5Slukem #include "ffs/ufs_inode.h"
636325773eSlukem #include "ffs/ffs_extern.h"
646325773eSlukem 
656325773eSlukem /*
666325773eSlukem  * Create an array of logical block number/offset pairs which represent the
676325773eSlukem  * path of indirect blocks required to access a data block.  The first "pair"
686325773eSlukem  * contains the logical block number of the appropriate single, double or
696325773eSlukem  * triple indirect block and the offset into the inode indirect block array.
706325773eSlukem  * Note, the logical block number of the inode single/double/triple indirect
716325773eSlukem  * block appears twice in the array, once with the offset into the i_ffs_ib and
726325773eSlukem  * once with the offset into the page itself.
736325773eSlukem  */
746325773eSlukem int
ufs_getlbns(struct inode * ip,daddr_t bn,struct indir * ap,int * nump)75a3ff3a30Sfvdl ufs_getlbns(struct inode *ip, daddr_t bn, struct indir *ap, int *nump)
766325773eSlukem {
77a3ff3a30Sfvdl 	daddr_t metalbn, realbn;
786325773eSlukem 	int64_t blockcnt;
796325773eSlukem 	int lbc;
806325773eSlukem 	int i, numlevels, off;
816325773eSlukem 	u_long lognindir;
826325773eSlukem 
83f1333577Sdholland 	lognindir = ffs(FFS_NINDIR(ip->i_fs)) - 1;
846325773eSlukem 	if (nump)
856325773eSlukem 		*nump = 0;
866325773eSlukem 	numlevels = 0;
876325773eSlukem 	realbn = bn;
886325773eSlukem 	if ((long)bn < 0)
896325773eSlukem 		bn = -(long)bn;
906325773eSlukem 
91dcd34a91Sdholland 	assert (bn >= UFS_NDADDR);
926325773eSlukem 
936325773eSlukem 	/*
946325773eSlukem 	 * Determine the number of levels of indirection.  After this loop
956325773eSlukem 	 * is done, blockcnt indicates the number of data blocks possible
96dcd34a91Sdholland 	 * at the given level of indirection, and UFS_NIADDR - i is the number
976325773eSlukem 	 * of levels of indirection needed to locate the requested block.
986325773eSlukem 	 */
996325773eSlukem 
100dcd34a91Sdholland 	bn -= UFS_NDADDR;
101dcd34a91Sdholland 	for (lbc = 0, i = UFS_NIADDR;; i--, bn -= blockcnt) {
1026325773eSlukem 		if (i == 0)
1036325773eSlukem 			return (EFBIG);
1046325773eSlukem 
1056325773eSlukem 		lbc += lognindir;
1066325773eSlukem 		blockcnt = (int64_t)1 << lbc;
1076325773eSlukem 
1086325773eSlukem 		if (bn < blockcnt)
1096325773eSlukem 			break;
1106325773eSlukem 	}
1116325773eSlukem 
1126325773eSlukem 	/* Calculate the address of the first meta-block. */
113dcd34a91Sdholland 	metalbn = -((realbn >= 0 ? realbn : -realbn) - bn + UFS_NIADDR - i);
1146325773eSlukem 
1156325773eSlukem 	/*
1166325773eSlukem 	 * At each iteration, off is the offset into the bap array which is
1176325773eSlukem 	 * an array of disk addresses at the current level of indirection.
1186325773eSlukem 	 * The logical block number and the offset in that block are stored
1196325773eSlukem 	 * into the argument array.
1206325773eSlukem 	 */
1216325773eSlukem 	ap->in_lbn = metalbn;
122dcd34a91Sdholland 	ap->in_off = off = UFS_NIADDR - i;
1236325773eSlukem 	ap->in_exists = 0;
1246325773eSlukem 	ap++;
125dcd34a91Sdholland 	for (++numlevels; i <= UFS_NIADDR; i++) {
1266325773eSlukem 		/* If searching for a meta-data block, quit when found. */
1276325773eSlukem 		if (metalbn == realbn)
1286325773eSlukem 			break;
1296325773eSlukem 
1306325773eSlukem 		lbc -= lognindir;
1316325773eSlukem 		blockcnt = (int64_t)1 << lbc;
132f1333577Sdholland 		off = (bn >> lbc) & (FFS_NINDIR(ip->i_fs) - 1);
1336325773eSlukem 
1346325773eSlukem 		++numlevels;
1356325773eSlukem 		ap->in_lbn = metalbn;
1366325773eSlukem 		ap->in_off = off;
1376325773eSlukem 		ap->in_exists = 0;
1386325773eSlukem 		++ap;
1396325773eSlukem 
14068b8babdSlukem 		metalbn -= -1 + (off << lbc);
1416325773eSlukem 	}
1426325773eSlukem 	if (nump)
1436325773eSlukem 		*nump = numlevels;
1446325773eSlukem 	return (0);
1456325773eSlukem }
146