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