15978408cSSascha Wildner /* $NetBSD: ufs_bmap.c,v 1.14 2004/06/20 22:20:18 jmc Exp $ */
25978408cSSascha Wildner /* From: NetBSD: ufs_bmap.c,v 1.14 2001/11/08 05:00:51 chs Exp */
35978408cSSascha Wildner
45978408cSSascha Wildner /*-
55978408cSSascha Wildner * SPDX-License-Identifier: BSD-3-Clause
65978408cSSascha Wildner *
75978408cSSascha Wildner * Copyright (c) 1989, 1991, 1993
85978408cSSascha Wildner * The Regents of the University of California. All rights reserved.
95978408cSSascha Wildner * (c) UNIX System Laboratories, Inc.
105978408cSSascha Wildner * All or some portions of this file are derived from material licensed
115978408cSSascha Wildner * to the University of California by American Telephone and Telegraph
125978408cSSascha Wildner * Co. or Unix System Laboratories, Inc. and are reproduced herein with
135978408cSSascha Wildner * the permission of UNIX System Laboratories, Inc.
145978408cSSascha Wildner *
155978408cSSascha Wildner * Redistribution and use in source and binary forms, with or without
165978408cSSascha Wildner * modification, are permitted provided that the following conditions
175978408cSSascha Wildner * are met:
185978408cSSascha Wildner * 1. Redistributions of source code must retain the above copyright
195978408cSSascha Wildner * notice, this list of conditions and the following disclaimer.
205978408cSSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
215978408cSSascha Wildner * notice, this list of conditions and the following disclaimer in the
225978408cSSascha Wildner * documentation and/or other materials provided with the distribution.
235978408cSSascha Wildner * 3. Neither the name of the University nor the names of its contributors
245978408cSSascha Wildner * may be used to endorse or promote products derived from this software
255978408cSSascha Wildner * without specific prior written permission.
265978408cSSascha Wildner *
275978408cSSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
285978408cSSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
295978408cSSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
305978408cSSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
315978408cSSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
325978408cSSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
335978408cSSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
345978408cSSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
355978408cSSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
365978408cSSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
375978408cSSascha Wildner * SUCH DAMAGE.
385978408cSSascha Wildner *
395978408cSSascha Wildner * @(#)ufs_bmap.c 8.8 (Berkeley) 8/11/95
40811c2036SSascha Wildner * $FreeBSD: head/usr.sbin/makefs/ffs/ufs_bmap.c 326025 2017-11-20 19:49:47Z pfg $
415978408cSSascha Wildner */
425978408cSSascha Wildner
435978408cSSascha Wildner #include <sys/param.h>
445978408cSSascha Wildner #include <sys/time.h>
455978408cSSascha Wildner
465978408cSSascha Wildner #include <assert.h>
475978408cSSascha Wildner #include <errno.h>
485978408cSSascha Wildner #include <strings.h>
495978408cSSascha Wildner
505978408cSSascha Wildner #include "makefs.h"
515978408cSSascha Wildner
52*346b9dadSzrj #include <vfs/ufs/dinode.h>
53*346b9dadSzrj #include <vfs/ufs/fs.h>
545978408cSSascha Wildner
555978408cSSascha Wildner #include "ffs/ufs_bswap.h"
565978408cSSascha Wildner #include "ffs/ufs_inode.h"
575978408cSSascha Wildner #include "ffs/ffs_extern.h"
585978408cSSascha Wildner
595978408cSSascha Wildner /*
605978408cSSascha Wildner * Create an array of logical block number/offset pairs which represent the
615978408cSSascha Wildner * path of indirect blocks required to access a data block. The first "pair"
625978408cSSascha Wildner * contains the logical block number of the appropriate single, double or
635978408cSSascha Wildner * triple indirect block and the offset into the inode indirect block array.
645978408cSSascha Wildner * Note, the logical block number of the inode single/double/triple indirect
655978408cSSascha Wildner * block appears twice in the array, once with the offset into the i_ffs_ib and
665978408cSSascha Wildner * once with the offset into the page itself.
675978408cSSascha Wildner */
685978408cSSascha Wildner int
ufs_getlbns(struct inode * ip,makefs_daddr_t bn,struct indir * ap,int * nump)69811c2036SSascha Wildner ufs_getlbns(struct inode *ip, makefs_daddr_t bn, struct indir *ap, int *nump)
705978408cSSascha Wildner {
71811c2036SSascha Wildner makefs_daddr_t metalbn, realbn;
725978408cSSascha Wildner int64_t blockcnt;
735978408cSSascha Wildner int lbc;
745978408cSSascha Wildner int i, numlevels, off;
755978408cSSascha Wildner u_long lognindir;
765978408cSSascha Wildner
775978408cSSascha Wildner lognindir = ffs(NINDIR(ip->i_fs)) - 1;
785978408cSSascha Wildner if (nump)
795978408cSSascha Wildner *nump = 0;
805978408cSSascha Wildner numlevels = 0;
815978408cSSascha Wildner realbn = bn;
825978408cSSascha Wildner if ((long)bn < 0)
835978408cSSascha Wildner bn = -(long)bn;
845978408cSSascha Wildner
855978408cSSascha Wildner assert (bn >= UFS_NDADDR);
865978408cSSascha Wildner
875978408cSSascha Wildner /*
885978408cSSascha Wildner * Determine the number of levels of indirection. After this loop
895978408cSSascha Wildner * is done, blockcnt indicates the number of data blocks possible
905978408cSSascha Wildner * at the given level of indirection, and UFS_NIADDR - i is the number
915978408cSSascha Wildner * of levels of indirection needed to locate the requested block.
925978408cSSascha Wildner */
935978408cSSascha Wildner
945978408cSSascha Wildner bn -= UFS_NDADDR;
955978408cSSascha Wildner for (lbc = 0, i = UFS_NIADDR;; i--, bn -= blockcnt) {
965978408cSSascha Wildner if (i == 0)
975978408cSSascha Wildner return (EFBIG);
985978408cSSascha Wildner
995978408cSSascha Wildner lbc += lognindir;
1005978408cSSascha Wildner blockcnt = (int64_t)1 << lbc;
1015978408cSSascha Wildner
1025978408cSSascha Wildner if (bn < blockcnt)
1035978408cSSascha Wildner break;
1045978408cSSascha Wildner }
1055978408cSSascha Wildner
1065978408cSSascha Wildner /* Calculate the address of the first meta-block. */
1075978408cSSascha Wildner if (realbn >= 0)
1085978408cSSascha Wildner metalbn = -(realbn - bn + UFS_NIADDR - i);
1095978408cSSascha Wildner else
1105978408cSSascha Wildner metalbn = -(-realbn - bn + UFS_NIADDR - i);
1115978408cSSascha Wildner
1125978408cSSascha Wildner /*
1135978408cSSascha Wildner * At each iteration, off is the offset into the bap array which is
1145978408cSSascha Wildner * an array of disk addresses at the current level of indirection.
1155978408cSSascha Wildner * The logical block number and the offset in that block are stored
1165978408cSSascha Wildner * into the argument array.
1175978408cSSascha Wildner */
1185978408cSSascha Wildner ap->in_lbn = metalbn;
1195978408cSSascha Wildner ap->in_off = off = UFS_NIADDR - i;
1205978408cSSascha Wildner ap++;
1215978408cSSascha Wildner for (++numlevels; i <= UFS_NIADDR; i++) {
1225978408cSSascha Wildner /* If searching for a meta-data block, quit when found. */
1235978408cSSascha Wildner if (metalbn == realbn)
1245978408cSSascha Wildner break;
1255978408cSSascha Wildner
1265978408cSSascha Wildner lbc -= lognindir;
1275978408cSSascha Wildner blockcnt = (int64_t)1 << lbc;
1285978408cSSascha Wildner off = (bn >> lbc) & (NINDIR(ip->i_fs) - 1);
1295978408cSSascha Wildner
1305978408cSSascha Wildner ++numlevels;
1315978408cSSascha Wildner ap->in_lbn = metalbn;
1325978408cSSascha Wildner ap->in_off = off;
1335978408cSSascha Wildner ++ap;
1345978408cSSascha Wildner
1355978408cSSascha Wildner metalbn -= -1 + (off << lbc);
1365978408cSSascha Wildner }
1375978408cSSascha Wildner if (nump)
1385978408cSSascha Wildner *nump = numlevels;
1395978408cSSascha Wildner return (0);
1405978408cSSascha Wildner }
141