File: | ufs/ufs/ufs_bmap.c |
Warning: | line 144, column 2 Value stored to 'devvp' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ufs_bmap.c,v 1.37 2021/12/12 09:14:59 visa Exp $ */ |
2 | /* $NetBSD: ufs_bmap.c,v 1.3 1996/02/09 22:36:00 christos Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 1989, 1991, 1993 |
6 | * The Regents of the University of California. All rights reserved. |
7 | * (c) UNIX System Laboratories, Inc. |
8 | * All or some portions of this file are derived from material licensed |
9 | * to the University of California by American Telephone and Telegraph |
10 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with |
11 | * the permission of UNIX System Laboratories, Inc. |
12 | * |
13 | * Redistribution and use in source and binary forms, with or without |
14 | * modification, are permitted provided that the following conditions |
15 | * are met: |
16 | * 1. Redistributions of source code must retain the above copyright |
17 | * notice, this list of conditions and the following disclaimer. |
18 | * 2. Redistributions in binary form must reproduce the above copyright |
19 | * notice, this list of conditions and the following disclaimer in the |
20 | * documentation and/or other materials provided with the distribution. |
21 | * 3. Neither the name of the University nor the names of its contributors |
22 | * may be used to endorse or promote products derived from this software |
23 | * without specific prior written permission. |
24 | * |
25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
35 | * SUCH DAMAGE. |
36 | * |
37 | * @(#)ufs_bmap.c 8.6 (Berkeley) 1/21/94 |
38 | */ |
39 | |
40 | #include <sys/param.h> |
41 | #include <sys/systm.h> |
42 | #include <sys/buf.h> |
43 | #include <sys/proc.h> |
44 | #include <sys/vnode.h> |
45 | #include <sys/mount.h> |
46 | #include <sys/specdev.h> |
47 | |
48 | #include <ufs/ufs/quota.h> |
49 | #include <ufs/ufs/inode.h> |
50 | #include <ufs/ufs/ufsmount.h> |
51 | #include <ufs/ufs/ufs_extern.h> |
52 | |
53 | /* |
54 | * Bmap converts a the logical block number of a file to its physical block |
55 | * number on the disk. The conversion is done by using the logical block |
56 | * number to index into the array of block pointers described by the dinode. |
57 | */ |
58 | int |
59 | ufs_bmap(void *v) |
60 | { |
61 | struct vop_bmap_args *ap = v; |
62 | |
63 | /* |
64 | * Check for underlying vnode requests and ensure that logical |
65 | * to physical mapping is requested. |
66 | */ |
67 | if (ap->a_vpp != NULL((void *)0)) |
68 | *ap->a_vpp = VTOI(ap->a_vp)((struct inode *)(ap->a_vp)->v_data)->i_devvpi_ump->um_devvp; |
69 | if (ap->a_bnp == NULL((void *)0)) |
70 | return (0); |
71 | |
72 | return (ufs_bmaparray(ap->a_vp, ap->a_bn, ap->a_bnp, NULL((void *)0), NULL((void *)0), |
73 | ap->a_runp)); |
74 | } |
75 | |
76 | /* |
77 | * Indirect blocks are now on the vnode for the file. They are given negative |
78 | * logical block numbers. Indirect blocks are addressed by the negative |
79 | * address of the first data block to which they point. Double indirect blocks |
80 | * are addressed by one less than the address of the first indirect block to |
81 | * which they point. Triple indirect blocks are addressed by one less than |
82 | * the address of the first double indirect block to which they point. |
83 | * |
84 | * ufs_bmaparray does the bmap conversion, and if requested returns the |
85 | * array of logical blocks which must be traversed to get to a block. |
86 | * Each entry contains the offset into that block that gets you to the |
87 | * next block and the disk address of the block (if it is assigned). |
88 | */ |
89 | int |
90 | ufs_bmaparray(struct vnode *vp, daddr_t bn, daddr_t *bnp, struct indir *ap, |
91 | int *nump, int *runp) |
92 | { |
93 | struct inode *ip; |
94 | struct buf *bp; |
95 | struct ufsmount *ump; |
96 | struct mount *mp; |
97 | struct vnode *devvp; |
98 | struct indir a[NIADDR3+1], *xap; |
99 | daddr_t daddr, metalbn; |
100 | int error, maxrun = 0, num; |
101 | |
102 | ip = VTOI(vp)((struct inode *)(vp)->v_data); |
103 | mp = vp->v_mount; |
104 | ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data)); |
105 | #ifdef DIAGNOSTIC1 |
106 | if ((ap != NULL((void *)0) && nump == NULL((void *)0)) || (ap == NULL((void *)0) && nump != NULL((void *)0))) |
107 | panic("ufs_bmaparray: invalid arguments"); |
108 | #endif |
109 | |
110 | if (runp) { |
111 | /* |
112 | * XXX |
113 | * If MAXBSIZE is the largest transfer the disks can handle, |
114 | * we probably want maxrun to be 1 block less so that we |
115 | * don't create a block larger than the device can handle. |
116 | */ |
117 | *runp = 0; |
118 | maxrun = MAXBSIZE(64 * 1024) / mp->mnt_stat.f_iosize - 1; |
119 | } |
120 | |
121 | xap = ap == NULL((void *)0) ? a : ap; |
122 | if (!nump) |
123 | nump = # |
124 | if ((error = ufs_getlbns(vp, bn, xap, nump)) != 0) |
125 | return (error); |
126 | |
127 | num = *nump; |
128 | if (num == 0) { |
129 | *bnp = blkptrtodb(ump, DIP(ip, db[bn]))(((((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_db[bn] : (ip)->dinode_u.ffs2_din->di_db[bn])) << (ump)->um_bptrtodb); |
130 | if (*bnp == 0) |
131 | *bnp = -1; |
132 | else if (runp) |
133 | for (++bn; bn < NDADDR12 && *runp < maxrun && |
134 | is_sequential(ump, DIP(ip, db[bn - 1]),(((((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_db[bn] : (ip)->dinode_u.ffs2_din->di_db[bn])) == ((((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_db[bn - 1] : (ip)->dinode_u.ffs2_din->di_db[bn - 1])) + ump->um_seqinc) |
135 | DIP(ip, db[bn]))(((((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_db[bn] : (ip)->dinode_u.ffs2_din->di_db[bn])) == ((((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_db[bn - 1] : (ip)->dinode_u.ffs2_din->di_db[bn - 1])) + ump->um_seqinc); |
136 | ++bn, ++*runp); |
137 | return (0); |
138 | } |
139 | |
140 | |
141 | /* Get disk address out of indirect block array */ |
142 | daddr = DIP(ip, ib[xap->in_off])(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_ib[xap->in_off] : (ip)->dinode_u.ffs2_din->di_ib [xap->in_off]); |
143 | |
144 | devvp = VFSTOUFS(vp->v_mount)((struct ufsmount *)((vp->v_mount)->mnt_data))->um_devvp; |
Value stored to 'devvp' is never read | |
145 | for (bp = NULL((void *)0), ++xap; --num; ++xap) { |
146 | /* |
147 | * Exit the loop if there is no disk address assigned yet and |
148 | * the indirect block isn't in the cache, or if we were |
149 | * looking for an indirect block and we've found it. |
150 | */ |
151 | |
152 | metalbn = xap->in_lbn; |
153 | if ((daddr == 0 && !incore(vp, metalbn)) || metalbn == bn) |
154 | break; |
155 | /* |
156 | * If we get here, we've either got the block in the cache |
157 | * or we have a disk address for it, go fetch it. |
158 | */ |
159 | if (bp) |
160 | brelse(bp); |
161 | |
162 | xap->in_exists = 1; |
163 | bp = getblk(vp, metalbn, mp->mnt_stat.f_iosize, 0, INFSLP0xffffffffffffffffULL); |
164 | if (bp->b_flags & (B_DONE0x00000100 | B_DELWRI0x00000080)) { |
165 | ; |
166 | } |
167 | #ifdef DIAGNOSTIC1 |
168 | else if (!daddr) |
169 | panic("ufs_bmaparray: indirect block not in cache"); |
170 | #endif |
171 | else { |
172 | bp->b_blkno = blkptrtodb(ump, daddr)((daddr) << (ump)->um_bptrtodb); |
173 | bp->b_flags |= B_READ0x00008000; |
174 | bcstats.pendingreads++; |
175 | bcstats.numreads++; |
176 | VOP_STRATEGY(bp->b_vp, bp); |
177 | curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_ru.ru_inblock++; /* XXX */ |
178 | if ((error = biowait(bp)) != 0) { |
179 | brelse(bp); |
180 | return (error); |
181 | } |
182 | } |
183 | |
184 | #ifdef FFS21 |
185 | if (ip->i_ump->um_fstype == UM_UFS22) { |
186 | daddr = ((int64_t *)bp->b_data)[xap->in_off]; |
187 | if (num == 1 && daddr && runp) |
188 | for (bn = xap->in_off + 1; |
189 | bn < MNINDIR(ump)((ump)->um_nindir) && *runp < maxrun && |
190 | is_sequential(ump,((((int64_t *)bp->b_data)[bn]) == (((int64_t *)bp->b_data )[bn - 1]) + ump->um_seqinc) |
191 | ((int64_t *)bp->b_data)[bn - 1],((((int64_t *)bp->b_data)[bn]) == (((int64_t *)bp->b_data )[bn - 1]) + ump->um_seqinc) |
192 | ((int64_t *)bp->b_data)[bn])((((int64_t *)bp->b_data)[bn]) == (((int64_t *)bp->b_data )[bn - 1]) + ump->um_seqinc); |
193 | ++bn, ++*runp); |
194 | |
195 | continue; |
196 | } |
197 | |
198 | #endif /* FFS2 */ |
199 | |
200 | daddr = ((int32_t *)bp->b_data)[xap->in_off]; |
201 | if (num == 1 && daddr && runp) |
202 | for (bn = xap->in_off + 1; |
203 | bn < MNINDIR(ump)((ump)->um_nindir) && *runp < maxrun && |
204 | is_sequential(ump,((((int32_t *)bp->b_data)[bn]) == (((int32_t *)bp->b_data )[bn - 1]) + ump->um_seqinc) |
205 | ((int32_t *)bp->b_data)[bn - 1],((((int32_t *)bp->b_data)[bn]) == (((int32_t *)bp->b_data )[bn - 1]) + ump->um_seqinc) |
206 | ((int32_t *)bp->b_data)[bn])((((int32_t *)bp->b_data)[bn]) == (((int32_t *)bp->b_data )[bn - 1]) + ump->um_seqinc); |
207 | ++bn, ++*runp); |
208 | } |
209 | if (bp) |
210 | brelse(bp); |
211 | |
212 | daddr = blkptrtodb(ump, daddr)((daddr) << (ump)->um_bptrtodb); |
213 | *bnp = daddr == 0 ? -1 : daddr; |
214 | return (0); |
215 | } |
216 | |
217 | /* |
218 | * Create an array of logical block number/offset pairs which represent the |
219 | * path of indirect blocks required to access a data block. The first "pair" |
220 | * contains the logical block number of the appropriate single, double or |
221 | * triple indirect block and the offset into the inode indirect block array. |
222 | * Note, the logical block number of the inode single/double/triple indirect |
223 | * block appears twice in the array, once with the offset into the i_ffs_ib and |
224 | * once with the offset into the page itself. |
225 | */ |
226 | int |
227 | ufs_getlbns(struct vnode *vp, daddr_t bn, struct indir *ap, int *nump) |
228 | { |
229 | daddr_t metalbn, realbn; |
230 | struct ufsmount *ump; |
231 | int64_t blockcnt; |
232 | int i, numlevels, off; |
233 | |
234 | ump = VFSTOUFS(vp->v_mount)((struct ufsmount *)((vp->v_mount)->mnt_data)); |
235 | if (nump) |
236 | *nump = 0; |
237 | numlevels = 0; |
238 | realbn = bn; |
239 | if (bn < 0) |
240 | bn = -bn; |
241 | |
242 | #ifdef DIAGNOSTIC1 |
243 | if (realbn < 0 && realbn > -NDADDR12) { |
244 | panic ("ufs_getlbns: Invalid indirect block %lld specified", |
245 | (long long)realbn); |
246 | } |
247 | #endif |
248 | |
249 | /* The first NDADDR blocks are direct blocks. */ |
250 | if (bn < NDADDR12) |
251 | return (0); |
252 | |
253 | /* |
254 | * Determine the number of levels of indirection. After this loop |
255 | * is done, blockcnt indicates the number of data blocks possible |
256 | * at the given level of indirection, and NIADDR - i is the number |
257 | * of levels of indirection needed to locate the requested block. |
258 | */ |
259 | for (blockcnt = 1, i = NIADDR3, bn -= NDADDR12;; i--, bn -= blockcnt) { |
260 | if (i == 0) |
261 | return (EFBIG27); |
262 | blockcnt *= MNINDIR(ump)((ump)->um_nindir); |
263 | if (bn < blockcnt) |
264 | break; |
265 | } |
266 | |
267 | /* Calculate the address of the first meta-block. */ |
268 | if (realbn >= 0) |
269 | metalbn = -(realbn - bn + NIADDR3 - i); |
270 | else |
271 | metalbn = -(-realbn - bn + NIADDR3 - i); |
272 | |
273 | /* |
274 | * At each iteration, off is the offset into the bap array which is |
275 | * an array of disk addresses at the current level of indirection. |
276 | * The logical block number and the offset in that block are stored |
277 | * into the argument array. |
278 | */ |
279 | ap->in_lbn = metalbn; |
280 | ap->in_off = off = NIADDR3 - i; |
281 | ap->in_exists = 0; |
282 | ap++; |
283 | for (++numlevels; i <= NIADDR3; i++) { |
284 | /* If searching for a meta-data block, quit when found. */ |
285 | if (metalbn == realbn) |
286 | break; |
287 | |
288 | blockcnt /= MNINDIR(ump)((ump)->um_nindir); |
289 | off = (bn / blockcnt) % MNINDIR(ump)((ump)->um_nindir); |
290 | |
291 | ++numlevels; |
292 | ap->in_lbn = metalbn; |
293 | ap->in_off = off; |
294 | ap->in_exists = 0; |
295 | ++ap; |
296 | |
297 | metalbn -= -1 + off * blockcnt; |
298 | } |
299 | #ifdef DIAGNOSTIC1 |
300 | if (realbn < 0 && metalbn != realbn) { |
301 | panic("ufs_getlbns: indirect block %lld not found", |
302 | (long long)realbn); |
303 | } |
304 | #endif |
305 | if (nump) |
306 | *nump = numlevels; |
307 | return (0); |
308 | } |