ufs_bmap.c revision 1.2 1 1.2 lukem /* $NetBSD: ufs_bmap.c,v 1.2 2001/10/28 13:14:06 lukem Exp $ */
2 1.1 lukem /* From: NetBSD: ufs_bmap.c,v 1.10 2000/11/27 08:39:57 chs Exp */
3 1.1 lukem
4 1.1 lukem /*
5 1.1 lukem * Copyright (c) 1989, 1991, 1993
6 1.1 lukem * The Regents of the University of California. All rights reserved.
7 1.1 lukem * (c) UNIX System Laboratories, Inc.
8 1.1 lukem * All or some portions of this file are derived from material licensed
9 1.1 lukem * to the University of California by American Telephone and Telegraph
10 1.1 lukem * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11 1.1 lukem * the permission of UNIX System Laboratories, Inc.
12 1.1 lukem *
13 1.1 lukem * Redistribution and use in source and binary forms, with or without
14 1.1 lukem * modification, are permitted provided that the following conditions
15 1.1 lukem * are met:
16 1.1 lukem * 1. Redistributions of source code must retain the above copyright
17 1.1 lukem * notice, this list of conditions and the following disclaimer.
18 1.1 lukem * 2. Redistributions in binary form must reproduce the above copyright
19 1.1 lukem * notice, this list of conditions and the following disclaimer in the
20 1.1 lukem * documentation and/or other materials provided with the distribution.
21 1.1 lukem * 3. All advertising materials mentioning features or use of this software
22 1.1 lukem * must display the following acknowledgement:
23 1.1 lukem * This product includes software developed by the University of
24 1.1 lukem * California, Berkeley and its contributors.
25 1.1 lukem * 4. Neither the name of the University nor the names of its contributors
26 1.1 lukem * may be used to endorse or promote products derived from this software
27 1.1 lukem * without specific prior written permission.
28 1.1 lukem *
29 1.1 lukem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 1.1 lukem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 1.1 lukem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 1.1 lukem * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 1.1 lukem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 1.1 lukem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 1.1 lukem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 1.1 lukem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 1.1 lukem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 1.1 lukem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 1.1 lukem * SUCH DAMAGE.
40 1.1 lukem *
41 1.1 lukem * @(#)ufs_bmap.c 8.8 (Berkeley) 8/11/95
42 1.1 lukem */
43 1.2 lukem
44 1.2 lukem #include <sys/cdefs.h>
45 1.2 lukem #ifndef __lint
46 1.2 lukem __RCSID("$NetBSD: ufs_bmap.c,v 1.2 2001/10/28 13:14:06 lukem Exp $");
47 1.2 lukem #endif /* !__lint */
48 1.1 lukem
49 1.1 lukem #include <sys/param.h>
50 1.1 lukem #include <sys/time.h>
51 1.1 lukem
52 1.1 lukem #include <errno.h>
53 1.1 lukem
54 1.1 lukem #include <ufs/ufs/ufs_bswap.h>
55 1.1 lukem #include <ufs/ufs/inode.h>
56 1.1 lukem #include <ufs/ffs/fs.h>
57 1.1 lukem
58 1.1 lukem #include "ffs/buf.h"
59 1.1 lukem #include "ffs/ffs_extern.h"
60 1.1 lukem
61 1.1 lukem /*
62 1.1 lukem * Create an array of logical block number/offset pairs which represent the
63 1.1 lukem * path of indirect blocks required to access a data block. The first "pair"
64 1.1 lukem * contains the logical block number of the appropriate single, double or
65 1.1 lukem * triple indirect block and the offset into the inode indirect block array.
66 1.1 lukem * Note, the logical block number of the inode single/double/triple indirect
67 1.1 lukem * block appears twice in the array, once with the offset into the i_ffs_ib and
68 1.1 lukem * once with the offset into the page itself.
69 1.1 lukem */
70 1.1 lukem int
71 1.1 lukem ufs_getlbns(struct inode *ip, ufs_daddr_t bn, struct indir *ap, int *nump)
72 1.1 lukem {
73 1.1 lukem long metalbn, realbn;
74 1.1 lukem int64_t blockcnt;
75 1.1 lukem int lbc;
76 1.1 lukem int i, numlevels, off;
77 1.1 lukem u_long lognindir;
78 1.1 lukem
79 1.1 lukem lognindir = ffs(NINDIR(ip->i_fs)) - 1;
80 1.1 lukem if (nump)
81 1.1 lukem *nump = 0;
82 1.1 lukem numlevels = 0;
83 1.1 lukem realbn = bn;
84 1.1 lukem if ((long)bn < 0)
85 1.1 lukem bn = -(long)bn;
86 1.1 lukem
87 1.1 lukem /* The first NDADDR blocks are direct blocks. */
88 1.1 lukem if (bn < NDADDR)
89 1.1 lukem return (0);
90 1.1 lukem
91 1.1 lukem /*
92 1.1 lukem * Determine the number of levels of indirection. After this loop
93 1.1 lukem * is done, blockcnt indicates the number of data blocks possible
94 1.1 lukem * at the given level of indirection, and NIADDR - i is the number
95 1.1 lukem * of levels of indirection needed to locate the requested block.
96 1.1 lukem */
97 1.1 lukem
98 1.1 lukem bn -= NDADDR;
99 1.1 lukem for (lbc = 0, i = NIADDR;; i--, bn -= blockcnt) {
100 1.1 lukem if (i == 0)
101 1.1 lukem return (EFBIG);
102 1.1 lukem
103 1.1 lukem lbc += lognindir;
104 1.1 lukem blockcnt = (int64_t)1 << lbc;
105 1.1 lukem
106 1.1 lukem if (bn < blockcnt)
107 1.1 lukem break;
108 1.1 lukem }
109 1.1 lukem
110 1.1 lukem /* Calculate the address of the first meta-block. */
111 1.1 lukem if (realbn >= 0)
112 1.1 lukem metalbn = -(realbn - bn + NIADDR - i);
113 1.1 lukem else
114 1.1 lukem metalbn = -(-realbn - bn + NIADDR - i);
115 1.1 lukem
116 1.1 lukem /*
117 1.1 lukem * At each iteration, off is the offset into the bap array which is
118 1.1 lukem * an array of disk addresses at the current level of indirection.
119 1.1 lukem * The logical block number and the offset in that block are stored
120 1.1 lukem * into the argument array.
121 1.1 lukem */
122 1.1 lukem ap->in_lbn = metalbn;
123 1.1 lukem ap->in_off = off = NIADDR - i;
124 1.1 lukem ap->in_exists = 0;
125 1.1 lukem ap++;
126 1.1 lukem for (++numlevels; i <= NIADDR; i++) {
127 1.1 lukem /* If searching for a meta-data block, quit when found. */
128 1.1 lukem if (metalbn == realbn)
129 1.1 lukem break;
130 1.1 lukem
131 1.1 lukem lbc -= lognindir;
132 1.1 lukem blockcnt = (int64_t)1 << lbc;
133 1.1 lukem off = (bn >> lbc) & (NINDIR(ip->i_fs) - 1);
134 1.1 lukem
135 1.1 lukem ++numlevels;
136 1.1 lukem ap->in_lbn = metalbn;
137 1.1 lukem ap->in_off = off;
138 1.1 lukem ap->in_exists = 0;
139 1.1 lukem ++ap;
140 1.1 lukem
141 1.1 lukem metalbn -= -1 + off * blockcnt;
142 1.1 lukem }
143 1.1 lukem if (nump)
144 1.1 lukem *nump = numlevels;
145 1.1 lukem return (0);
146 1.1 lukem }
147