ufs_bmap.c revision 1.3 1 1.3 lukem /* $NetBSD: ufs_bmap.c,v 1.3 2001/11/08 06:10:13 lukem Exp $ */
2 1.3 lukem /* From: NetBSD: ufs_bmap.c,v 1.14 2001/11/08 05:00:51 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.3 lukem __RCSID("$NetBSD: ufs_bmap.c,v 1.3 2001/11/08 06:10:13 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.3 lukem #include <assert.h>
53 1.1 lukem #include <errno.h>
54 1.1 lukem
55 1.1 lukem #include <ufs/ufs/ufs_bswap.h>
56 1.1 lukem #include <ufs/ufs/inode.h>
57 1.1 lukem #include <ufs/ffs/fs.h>
58 1.1 lukem
59 1.1 lukem #include "ffs/buf.h"
60 1.1 lukem #include "ffs/ffs_extern.h"
61 1.1 lukem
62 1.1 lukem /*
63 1.1 lukem * Create an array of logical block number/offset pairs which represent the
64 1.1 lukem * path of indirect blocks required to access a data block. The first "pair"
65 1.1 lukem * contains the logical block number of the appropriate single, double or
66 1.1 lukem * triple indirect block and the offset into the inode indirect block array.
67 1.1 lukem * Note, the logical block number of the inode single/double/triple indirect
68 1.1 lukem * block appears twice in the array, once with the offset into the i_ffs_ib and
69 1.1 lukem * once with the offset into the page itself.
70 1.1 lukem */
71 1.1 lukem int
72 1.1 lukem ufs_getlbns(struct inode *ip, ufs_daddr_t bn, struct indir *ap, int *nump)
73 1.1 lukem {
74 1.1 lukem long metalbn, realbn;
75 1.1 lukem int64_t blockcnt;
76 1.1 lukem int lbc;
77 1.1 lukem int i, numlevels, off;
78 1.1 lukem u_long lognindir;
79 1.1 lukem
80 1.1 lukem lognindir = ffs(NINDIR(ip->i_fs)) - 1;
81 1.1 lukem if (nump)
82 1.1 lukem *nump = 0;
83 1.1 lukem numlevels = 0;
84 1.1 lukem realbn = bn;
85 1.1 lukem if ((long)bn < 0)
86 1.1 lukem bn = -(long)bn;
87 1.1 lukem
88 1.3 lukem assert (bn >= NDADDR);
89 1.1 lukem
90 1.1 lukem /*
91 1.1 lukem * Determine the number of levels of indirection. After this loop
92 1.1 lukem * is done, blockcnt indicates the number of data blocks possible
93 1.1 lukem * at the given level of indirection, and NIADDR - i is the number
94 1.1 lukem * of levels of indirection needed to locate the requested block.
95 1.1 lukem */
96 1.1 lukem
97 1.1 lukem bn -= NDADDR;
98 1.1 lukem for (lbc = 0, i = NIADDR;; i--, bn -= blockcnt) {
99 1.1 lukem if (i == 0)
100 1.1 lukem return (EFBIG);
101 1.1 lukem
102 1.1 lukem lbc += lognindir;
103 1.1 lukem blockcnt = (int64_t)1 << lbc;
104 1.1 lukem
105 1.1 lukem if (bn < blockcnt)
106 1.1 lukem break;
107 1.1 lukem }
108 1.1 lukem
109 1.1 lukem /* Calculate the address of the first meta-block. */
110 1.1 lukem if (realbn >= 0)
111 1.1 lukem metalbn = -(realbn - bn + NIADDR - i);
112 1.1 lukem else
113 1.1 lukem metalbn = -(-realbn - bn + NIADDR - i);
114 1.1 lukem
115 1.1 lukem /*
116 1.1 lukem * At each iteration, off is the offset into the bap array which is
117 1.1 lukem * an array of disk addresses at the current level of indirection.
118 1.1 lukem * The logical block number and the offset in that block are stored
119 1.1 lukem * into the argument array.
120 1.1 lukem */
121 1.1 lukem ap->in_lbn = metalbn;
122 1.1 lukem ap->in_off = off = NIADDR - i;
123 1.1 lukem ap->in_exists = 0;
124 1.1 lukem ap++;
125 1.1 lukem for (++numlevels; i <= NIADDR; i++) {
126 1.1 lukem /* If searching for a meta-data block, quit when found. */
127 1.1 lukem if (metalbn == realbn)
128 1.1 lukem break;
129 1.1 lukem
130 1.1 lukem lbc -= lognindir;
131 1.1 lukem blockcnt = (int64_t)1 << lbc;
132 1.1 lukem off = (bn >> lbc) & (NINDIR(ip->i_fs) - 1);
133 1.1 lukem
134 1.1 lukem ++numlevels;
135 1.1 lukem ap->in_lbn = metalbn;
136 1.1 lukem ap->in_off = off;
137 1.1 lukem ap->in_exists = 0;
138 1.1 lukem ++ap;
139 1.1 lukem
140 1.3 lukem metalbn -= -1 + (off << lbc);
141 1.1 lukem }
142 1.1 lukem if (nump)
143 1.1 lukem *nump = numlevels;
144 1.1 lukem return (0);
145 1.1 lukem }
146