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