Bug Summary

File:ufs/ufs/ufs_bmap.c
Warning:line 280, column 15
Although the value stored to 'off' is used in the enclosing expression, the value is never actually read from 'off'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ufs_bmap.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/ufs/ufs/ufs_bmap.c
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 */
58int
59ufs_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 */
89int
90ufs_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 = &num;
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;
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 */
226int
227ufs_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;
Although the value stored to 'off' is used in the enclosing expression, the value is never actually read from 'off'
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}