Bug Summary

File:ufs/ffs/ffs_balloc.c
Warning:line 750, column 4
Value stored to 'unwindidx' is never read

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 ffs_balloc.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/ffs/ffs_balloc.c
1/* $OpenBSD: ffs_balloc.c,v 1.45 2019/07/19 00:24:31 cheloha Exp $ */
2/* $NetBSD: ffs_balloc.c,v 1.3 1996/02/09 22:22:21 christos Exp $ */
3
4/*
5 * Copyright (c) 2002 Networks Associates Technology, Inc.
6 * All rights reserved.
7 *
8 * This software was developed for the FreeBSD Project by Marshall
9 * Kirk McKusick and Network Associates Laboratories, the Security
10 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
11 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
12 * research program.
13 *
14 * Copyright (c) 1982, 1986, 1989, 1993
15 * The Regents of the University of California. All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 * @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93
42 */
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/buf.h>
47#include <sys/proc.h>
48#include <sys/mount.h>
49#include <sys/vnode.h>
50
51#include <ufs/ufs/quota.h>
52#include <ufs/ufs/inode.h>
53#include <ufs/ufs/ufsmount.h>
54#include <ufs/ufs/ufs_extern.h>
55
56#include <ufs/ffs/fs.h>
57#include <ufs/ffs/ffs_extern.h>
58
59int ffs1_balloc(struct inode *, off_t, int, struct ucred *, int, struct buf **);
60#ifdef FFS21
61int ffs2_balloc(struct inode *, off_t, int, struct ucred *, int, struct buf **);
62#endif
63
64/*
65 * Balloc defines the structure of file system storage
66 * by allocating the physical blocks on a device given
67 * the inode and the logical block number in a file.
68 */
69int
70ffs1_balloc(struct inode *ip, off_t startoffset, int size, struct ucred *cred,
71 int flags, struct buf **bpp)
72{
73 daddr_t lbn, nb, newb, pref;
74 struct fs *fs;
75 struct buf *bp, *nbp;
76 struct vnode *vp;
77 struct proc *p;
78 struct indir indirs[NIADDR3 + 2];
79 int32_t *bap;
80 int deallocated, osize, nsize, num, i, error;
81 int32_t *allocib, *blkp, *allocblk, allociblk[NIADDR3+1];
82 int unwindidx = -1;
83
84 vp = ITOV(ip)((ip)->i_vnode);
85 fs = ip->i_fsinode_u.fs;
86 p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
87 lbn = lblkno(fs, startoffset)((startoffset) >> (fs)->fs_bshift);
88 size = blkoff(fs, startoffset)((startoffset) & (fs)->fs_qbmask) + size;
89 if (size > fs->fs_bsize)
90 panic("ffs1_balloc: blk too big");
91 if (bpp != NULL((void *)0))
92 *bpp = NULL((void *)0);
93 if (lbn < 0)
94 return (EFBIG27);
95
96 /*
97 * If the next write will extend the file into a new block,
98 * and the file is currently composed of a fragment
99 * this fragment has to be extended to be a full block.
100 */
101 nb = lblkno(fs, ip->i_ffs1_size)((ip->dinode_u.ffs1_din->di_size) >> (fs)->fs_bshift
)
;
102 if (nb < NDADDR12 && nb < lbn) {
103 osize = blksize(fs, ip, nb)(((nb) >= 12 || ((((ip))->i_ump->um_fstype == 1) ? (
(ip))->dinode_u.ffs1_din->di_size : ((ip))->dinode_u
.ffs2_din->di_size) >= ((nb) + 1) << (fs)->fs_bshift
) ? (u_int64_t)(fs)->fs_bsize : ((((((((((ip))->i_ump->
um_fstype == 1) ? ((ip))->dinode_u.ffs1_din->di_size : (
(ip))->dinode_u.ffs2_din->di_size)) & (fs)->fs_qbmask
)) + (fs)->fs_qfmask) & (fs)->fs_fmask)))
;
104 if (osize < fs->fs_bsize && osize > 0) {
105 error = ffs_realloccg(ip, nb,
106 ffs1_blkpref(ip, nb, (int)nb, &ip->i_ffs1_dbdinode_u.ffs1_din->di_db[0]),
107 osize, (int)fs->fs_bsize, cred, bpp, &newb);
108 if (error)
109 return (error);
110 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000))
111 softdep_setup_allocdirect(ip, nb, newb,
112 ip->i_ffs1_dbdinode_u.ffs1_din->di_db[nb], fs->fs_bsize, osize,
113 bpp ? *bpp : NULL((void *)0));
114
115 ip->i_ffs1_sizedinode_u.ffs1_din->di_size = lblktosize(fs, nb + 1)((off_t)(nb + 1) << (fs)->fs_bshift);
116 uvm_vnp_setsize(vp, ip->i_ffs1_sizedinode_u.ffs1_din->di_size);
117 ip->i_ffs1_dbdinode_u.ffs1_din->di_db[nb] = newb;
118 ip->i_flag |= IN_CHANGE0x0002 | IN_UPDATE0x0004;
119 if (bpp != NULL((void *)0)) {
120 if (flags & B_SYNC0x02)
121 bwrite(*bpp);
122 else
123 bawrite(*bpp);
124 }
125 }
126 }
127 /*
128 * The first NDADDR blocks are direct blocks
129 */
130 if (lbn < NDADDR12) {
131 nb = ip->i_ffs1_dbdinode_u.ffs1_din->di_db[lbn];
132 if (nb != 0 && ip->i_ffs1_sizedinode_u.ffs1_din->di_size >= lblktosize(fs, lbn + 1)((off_t)(lbn + 1) << (fs)->fs_bshift)) {
133 /*
134 * The block is an already-allocated direct block
135 * and the file already extends past this block,
136 * thus this must be a whole block.
137 * Just read the block (if requested).
138 */
139
140 if (bpp != NULL((void *)0)) {
141 error = bread(vp, lbn, fs->fs_bsize, bpp);
142 if (error) {
143 brelse(*bpp);
144 return (error);
145 }
146 }
147 return (0);
148 }
149 if (nb != 0) {
150 /*
151 * Consider need to reallocate a fragment.
152 */
153 osize = fragroundup(fs, blkoff(fs, ip->i_ffs1_size))(((((ip->dinode_u.ffs1_din->di_size) & (fs)->fs_qbmask
)) + (fs)->fs_qfmask) & (fs)->fs_fmask)
;
154 nsize = fragroundup(fs, size)(((size) + (fs)->fs_qfmask) & (fs)->fs_fmask);
155 if (nsize <= osize) {
156 /*
157 * The existing block is already
158 * at least as big as we want.
159 * Just read the block (if requested).
160 */
161 if (bpp != NULL((void *)0)) {
162 error = bread(vp, lbn, fs->fs_bsize,
163 bpp);
164 if (error) {
165 brelse(*bpp);
166 return (error);
167 }
168 buf_adjcnt((*bpp), osize);
169 }
170 return (0);
171 } else {
172 /*
173 * The existing block is smaller than we
174 * want, grow it.
175 */
176 error = ffs_realloccg(ip, lbn,
177 ffs1_blkpref(ip, lbn, (int)lbn,
178 &ip->i_ffs1_dbdinode_u.ffs1_din->di_db[0]),
179 osize, nsize, cred, bpp, &newb);
180 if (error)
181 return (error);
182 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000))
183 softdep_setup_allocdirect(ip, lbn,
184 newb, nb, nsize, osize,
185 bpp ? *bpp : NULL((void *)0));
186 }
187 } else {
188 /*
189 * The block was not previously allocated,
190 * allocate a new block or fragment.
191 */
192
193 if (ip->i_ffs1_sizedinode_u.ffs1_din->di_size < lblktosize(fs, lbn + 1)((off_t)(lbn + 1) << (fs)->fs_bshift))
194 nsize = fragroundup(fs, size)(((size) + (fs)->fs_qfmask) & (fs)->fs_fmask);
195 else
196 nsize = fs->fs_bsize;
197 error = ffs_alloc(ip, lbn,
198 ffs1_blkpref(ip, lbn, (int)lbn, &ip->i_ffs1_dbdinode_u.ffs1_din->di_db[0]),
199 nsize, cred, &newb);
200 if (error)
201 return (error);
202 if (bpp != NULL((void *)0)) {
203 *bpp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP0xffffffffffffffffULL);
204 if (nsize < fs->fs_bsize)
205 (*bpp)->b_bcount = nsize;
206 (*bpp)->b_blkno = fsbtodb(fs, newb)((newb) << (fs)->fs_fsbtodb);
207 if (flags & B_CLRBUF0x01)
208 clrbuf(*bpp){ __builtin_bzero(((*bpp)->b_data), ((*bpp)->b_bcount))
; (*bpp)->b_resid = 0; }
;
209 }
210 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000))
211 softdep_setup_allocdirect(ip, lbn, newb, 0,
212 nsize, 0, bpp ? *bpp : NULL((void *)0));
213 }
214 ip->i_ffs1_dbdinode_u.ffs1_din->di_db[lbn] = newb;
215 ip->i_flag |= IN_CHANGE0x0002 | IN_UPDATE0x0004;
216 return (0);
217 }
218
219 /*
220 * Determine the number of levels of indirection.
221 */
222 pref = 0;
223 if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0)
224 return(error);
225#ifdef DIAGNOSTIC1
226 if (num < 1)
227 panic ("ffs1_balloc: ufs_bmaparray returned indirect block");
228#endif
229 /*
230 * Fetch the first indirect block allocating if necessary.
231 */
232 --num;
233 nb = ip->i_ffs1_ibdinode_u.ffs1_din->di_ib[indirs[0].in_off];
234
235 allocib = NULL((void *)0);
236 allocblk = allociblk;
237 if (nb == 0) {
238 pref = ffs1_blkpref(ip, lbn, -indirs[0].in_off - 1, NULL((void *)0));
239 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
240 cred, &newb);
241 if (error)
242 goto fail;
243 nb = newb;
244
245 *allocblk++ = nb;
246 bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, INFSLP0xffffffffffffffffULL);
247 bp->b_blkno = fsbtodb(fs, nb)((nb) << (fs)->fs_fsbtodb);
248 clrbuf(bp){ __builtin_bzero(((bp)->b_data), ((bp)->b_bcount)); (bp
)->b_resid = 0; }
;
249
250 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000)) {
251 softdep_setup_allocdirect(ip, NDADDR12 + indirs[0].in_off,
252 newb, 0, fs->fs_bsize, 0, bp);
253 bdwrite(bp);
254 } else {
255 /*
256 * Write synchronously so that indirect blocks
257 * never point at garbage.
258 */
259 if ((error = bwrite(bp)) != 0)
260 goto fail;
261 }
262 allocib = &ip->i_ffs1_ibdinode_u.ffs1_din->di_ib[indirs[0].in_off];
263 *allocib = nb;
264 ip->i_flag |= IN_CHANGE0x0002 | IN_UPDATE0x0004;
265 }
266
267 /*
268 * Fetch through the indirect blocks, allocating as necessary.
269 */
270 for (i = 1;;) {
271 error = bread(vp, indirs[i].in_lbn, (int)fs->fs_bsize, &bp);
272 if (error) {
273 brelse(bp);
274 goto fail;
275 }
276 bap = (int32_t *)bp->b_data;
277 nb = bap[indirs[i].in_off];
278 if (i == num)
279 break;
280 i++;
281 if (nb != 0) {
282 brelse(bp);
283 continue;
284 }
285 if (pref == 0)
286 pref = ffs1_blkpref(ip, lbn, i - num - 1, NULL((void *)0));
287 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
288 &newb);
289 if (error) {
290 brelse(bp);
291 goto fail;
292 }
293 nb = newb;
294 *allocblk++ = nb;
295 nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, INFSLP0xffffffffffffffffULL);
296 nbp->b_blkno = fsbtodb(fs, nb)((nb) << (fs)->fs_fsbtodb);
297 clrbuf(nbp){ __builtin_bzero(((nbp)->b_data), ((nbp)->b_bcount)); (
nbp)->b_resid = 0; }
;
298
299 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000)) {
300 softdep_setup_allocindir_meta(nbp, ip, bp,
301 indirs[i - 1].in_off, nb);
302 bdwrite(nbp);
303 } else {
304 /*
305 * Write synchronously so that indirect blocks
306 * never point at garbage.
307 */
308 if ((error = bwrite(nbp)) != 0) {
309 brelse(bp);
310 goto fail;
311 }
312 }
313 bap[indirs[i - 1].in_off] = nb;
314 if (allocib == NULL((void *)0) && unwindidx < 0)
315 unwindidx = i - 1;
316 /*
317 * If required, write synchronously, otherwise use
318 * delayed write.
319 */
320 if (flags & B_SYNC0x02) {
321 bwrite(bp);
322 } else {
323 bdwrite(bp);
324 }
325 }
326 /*
327 * Get the data block, allocating if necessary.
328 */
329 if (nb == 0) {
330 pref = ffs1_blkpref(ip, lbn, indirs[i].in_off, &bap[0]);
331 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
332 &newb);
333 if (error) {
334 brelse(bp);
335 goto fail;
336 }
337 nb = newb;
338 *allocblk++ = nb;
339 if (bpp != NULL((void *)0)) {
340 nbp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP0xffffffffffffffffULL);
341 nbp->b_blkno = fsbtodb(fs, nb)((nb) << (fs)->fs_fsbtodb);
342 if (flags & B_CLRBUF0x01)
343 clrbuf(nbp){ __builtin_bzero(((nbp)->b_data), ((nbp)->b_bcount)); (
nbp)->b_resid = 0; }
;
344 *bpp = nbp;
345 }
346 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000))
347 softdep_setup_allocindir_page(ip, lbn, bp,
348 indirs[i].in_off, nb, 0, bpp ? *bpp : NULL((void *)0));
349 bap[indirs[i].in_off] = nb;
350 /*
351 * If required, write synchronously, otherwise use
352 * delayed write.
353 */
354 if (flags & B_SYNC0x02) {
355 bwrite(bp);
356 } else {
357 bdwrite(bp);
358 }
359 return (0);
360 }
361 brelse(bp);
362 if (bpp != NULL((void *)0)) {
363 if (flags & B_CLRBUF0x01) {
364 error = bread(vp, lbn, (int)fs->fs_bsize, &nbp);
365 if (error) {
366 brelse(nbp);
367 goto fail;
368 }
369 } else {
370 nbp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP0xffffffffffffffffULL);
371 nbp->b_blkno = fsbtodb(fs, nb)((nb) << (fs)->fs_fsbtodb);
372 }
373 *bpp = nbp;
374 }
375 return (0);
376
377fail:
378 /*
379 * If we have failed to allocate any blocks, simply return the error.
380 * This is the usual case and avoids the need to fsync the file.
381 */
382 if (allocblk == allociblk && allocib == NULL((void *)0) && unwindidx == -1)
383 return (error);
384 /*
385 * If we have failed part way through block allocation, we have to
386 * deallocate any indirect blocks that we have allocated. We have to
387 * fsync the file before we start to get rid of all of its
388 * dependencies so that we do not leave them dangling. We have to sync
389 * it at the end so that the softdep code does not find any untracked
390 * changes. Although this is really slow, running out of disk space is
391 * not expected to be a common occurrence. The error return from fsync
392 * is ignored as we already have an error to return to the user.
393 */
394 VOP_FSYNC(vp, p->p_ucred, MNT_WAIT1, p);
395 for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
396 ffs_blkfree(ip, *blkp, fs->fs_bsize);
397 deallocated += fs->fs_bsize;
398 }
399 if (allocib != NULL((void *)0)) {
400 *allocib = 0;
401 } else if (unwindidx >= 0) {
402 int r;
403
404 r = bread(vp, indirs[unwindidx].in_lbn, (int)fs->fs_bsize, &bp);
405 if (r)
406 panic("Could not unwind indirect block, error %d", r);
407 bap = (int32_t *)bp->b_data;
408 bap[indirs[unwindidx].in_off] = 0;
409 if (flags & B_SYNC0x02) {
410 bwrite(bp);
411 } else {
412 bdwrite(bp);
413 }
414 }
415 if (deallocated) {
416 /*
417 * Restore user's disk quota because allocation failed.
418 */
419 (void)ufs_quota_free_blocks(ip, btodb(deallocated), cred)ufs_quota_free_blocks2(ip, ((deallocated) >> 9), cred, 0
)
;
420
421 ip->i_ffs1_blocksdinode_u.ffs1_din->di_blocks -= btodb(deallocated)((deallocated) >> 9);
422 ip->i_flag |= IN_CHANGE0x0002 | IN_UPDATE0x0004;
423 }
424 VOP_FSYNC(vp, p->p_ucred, MNT_WAIT1, p);
425 return (error);
426}
427
428#ifdef FFS21
429int
430ffs2_balloc(struct inode *ip, off_t off, int size, struct ucred *cred,
431 int flags, struct buf **bpp)
432{
433 daddr_t lbn, lastlbn, nb, newb, *blkp;
434 daddr_t pref, *allocblk, allociblk[NIADDR3 + 1];
435 daddr_t *bap, *allocib;
436 int deallocated, osize, nsize, num, i, error, unwindidx, r;
437 struct buf *bp, *nbp;
438 struct indir indirs[NIADDR3 + 2];
439 struct fs *fs;
440 struct vnode *vp;
441 struct proc *p;
442
443 vp = ITOV(ip)((ip)->i_vnode);
444 fs = ip->i_fsinode_u.fs;
445 p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
446 unwindidx = -1;
447
448 lbn = lblkno(fs, off)((off) >> (fs)->fs_bshift);
449 size = blkoff(fs, off)((off) & (fs)->fs_qbmask) + size;
450
451 if (size > fs->fs_bsize)
452 panic("ffs2_balloc: block too big");
453
454 if (bpp != NULL((void *)0))
455 *bpp = NULL((void *)0);
456
457 if (lbn < 0)
458 return (EFBIG27);
459
460 /*
461 * If the next write will extend the file into a new block, and the
462 * file is currently composed of a fragment, this fragment has to be
463 * extended to be a full block.
464 */
465 lastlbn = lblkno(fs, ip->i_ffs2_size)((ip->dinode_u.ffs2_din->di_size) >> (fs)->fs_bshift
)
;
466 if (lastlbn < NDADDR12 && lastlbn < lbn) {
467 nb = lastlbn;
468 osize = blksize(fs, ip, nb)(((nb) >= 12 || ((((ip))->i_ump->um_fstype == 1) ? (
(ip))->dinode_u.ffs1_din->di_size : ((ip))->dinode_u
.ffs2_din->di_size) >= ((nb) + 1) << (fs)->fs_bshift
) ? (u_int64_t)(fs)->fs_bsize : ((((((((((ip))->i_ump->
um_fstype == 1) ? ((ip))->dinode_u.ffs1_din->di_size : (
(ip))->dinode_u.ffs2_din->di_size)) & (fs)->fs_qbmask
)) + (fs)->fs_qfmask) & (fs)->fs_fmask)))
;
469 if (osize < fs->fs_bsize && osize > 0) {
470 error = ffs_realloccg(ip, nb, ffs2_blkpref(ip,
471 lastlbn, nb, &ip->i_ffs2_dbdinode_u.ffs2_din->di_db[0]), osize,
472 (int) fs->fs_bsize, cred, bpp, &newb);
473 if (error)
474 return (error);
475
476 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000))
477 softdep_setup_allocdirect(ip, nb, newb,
478 ip->i_ffs2_dbdinode_u.ffs2_din->di_db[nb], fs->fs_bsize, osize,
479 bpp ? *bpp : NULL((void *)0));
480
481 ip->i_ffs2_sizedinode_u.ffs2_din->di_size = lblktosize(fs, nb + 1)((off_t)(nb + 1) << (fs)->fs_bshift);
482 uvm_vnp_setsize(vp, ip->i_ffs2_sizedinode_u.ffs2_din->di_size);
483 ip->i_ffs2_dbdinode_u.ffs2_din->di_db[nb] = newb;
484 ip->i_flag |= IN_CHANGE0x0002 | IN_UPDATE0x0004;
485
486 if (bpp) {
487 if (flags & B_SYNC0x02)
488 bwrite(*bpp);
489 else
490 bawrite(*bpp);
491 }
492 }
493 }
494
495 /*
496 * The first NDADDR blocks are direct.
497 */
498 if (lbn < NDADDR12) {
499
500 nb = ip->i_ffs2_dbdinode_u.ffs2_din->di_db[lbn];
501
502 if (nb != 0 && ip->i_ffs2_sizedinode_u.ffs2_din->di_size >= lblktosize(fs, lbn + 1)((off_t)(lbn + 1) << (fs)->fs_bshift)) {
503 /*
504 * The direct block is already allocated and the file
505 * extends past this block, thus this must be a whole
506 * block. Just read it, if requested.
507 */
508 if (bpp != NULL((void *)0)) {
509 error = bread(vp, lbn, fs->fs_bsize, bpp);
510 if (error) {
511 brelse(*bpp);
512 return (error);
513 }
514 }
515
516 return (0);
517 }
518
519 if (nb != 0) {
520 /*
521 * Consider the need to allocate a fragment.
522 */
523 osize = fragroundup(fs, blkoff(fs, ip->i_ffs2_size))(((((ip->dinode_u.ffs2_din->di_size) & (fs)->fs_qbmask
)) + (fs)->fs_qfmask) & (fs)->fs_fmask)
;
524 nsize = fragroundup(fs, size)(((size) + (fs)->fs_qfmask) & (fs)->fs_fmask);
525
526 if (nsize <= osize) {
527 /*
528 * The existing block is already at least as
529 * big as we want. Just read it, if requested.
530 */
531 if (bpp != NULL((void *)0)) {
532 error = bread(vp, lbn, fs->fs_bsize,
533 bpp);
534 if (error) {
535 brelse(*bpp);
536 return (error);
537 }
538 buf_adjcnt((*bpp), osize);
539 }
540
541 return (0);
542 } else {
543 /*
544 * The existing block is smaller than we want,
545 * grow it.
546 */
547 error = ffs_realloccg(ip, lbn,
548 ffs2_blkpref(ip, lbn, (int) lbn,
549 &ip->i_ffs2_dbdinode_u.ffs2_din->di_db[0]), osize, nsize, cred,
550 bpp, &newb);
551 if (error)
552 return (error);
553
554 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000))
555 softdep_setup_allocdirect(ip, lbn,
556 newb, nb, nsize, osize,
557 bpp ? *bpp : NULL((void *)0));
558 }
559 } else {
560 /*
561 * The block was not previously allocated, allocate a
562 * new block or fragment.
563 */
564 if (ip->i_ffs2_sizedinode_u.ffs2_din->di_size < lblktosize(fs, lbn + 1)((off_t)(lbn + 1) << (fs)->fs_bshift))
565 nsize = fragroundup(fs, size)(((size) + (fs)->fs_qfmask) & (fs)->fs_fmask);
566 else
567 nsize = fs->fs_bsize;
568
569 error = ffs_alloc(ip, lbn, ffs2_blkpref(ip, lbn,
570 (int) lbn, &ip->i_ffs2_dbdinode_u.ffs2_din->di_db[0]), nsize, cred, &newb);
571 if (error)
572 return (error);
573
574 if (bpp != NULL((void *)0)) {
575 bp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP0xffffffffffffffffULL);
576 if (nsize < fs->fs_bsize)
577 bp->b_bcount = nsize;
578 bp->b_blkno = fsbtodb(fs, newb)((newb) << (fs)->fs_fsbtodb);
579 if (flags & B_CLRBUF0x01)
580 clrbuf(bp){ __builtin_bzero(((bp)->b_data), ((bp)->b_bcount)); (bp
)->b_resid = 0; }
;
581 *bpp = bp;
582 }
583
584 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000))
585 softdep_setup_allocdirect(ip, lbn, newb, 0,
586 nsize, 0, bpp ? *bpp : NULL((void *)0));
587 }
588
589 ip->i_ffs2_dbdinode_u.ffs2_din->di_db[lbn] = newb;
590 ip->i_flag |= IN_CHANGE0x0002 | IN_UPDATE0x0004;
591
592 return (0);
593 }
594
595 /*
596 * Determine the number of levels of indirection.
597 */
598 pref = 0;
599 error = ufs_getlbns(vp, lbn, indirs, &num);
600 if (error)
601 return (error);
602
603#ifdef DIAGNOSTIC1
604 if (num < 1)
605 panic("ffs2_balloc: ufs_bmaparray returned indirect block");
606#endif
607
608 /*
609 * Fetch the first indirect block allocating it necessary.
610 */
611 --num;
612 nb = ip->i_ffs2_ibdinode_u.ffs2_din->di_ib[indirs[0].in_off];
613 allocib = NULL((void *)0);
614 allocblk = allociblk;
615
616 if (nb == 0) {
617 pref = ffs2_blkpref(ip, lbn, -indirs[0].in_off - 1, NULL((void *)0));
618 error = ffs_alloc(ip, lbn, pref, (int) fs->fs_bsize, cred,
619 &newb);
620 if (error)
621 goto fail;
622
623 nb = newb;
624 *allocblk++ = nb;
625 bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, INFSLP0xffffffffffffffffULL);
626 bp->b_blkno = fsbtodb(fs, nb)((nb) << (fs)->fs_fsbtodb);
627 clrbuf(bp){ __builtin_bzero(((bp)->b_data), ((bp)->b_bcount)); (bp
)->b_resid = 0; }
;
628
629 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000)) {
630 softdep_setup_allocdirect(ip, NDADDR12 + indirs[0].in_off,
631 newb, 0, fs->fs_bsize, 0, bp);
632 bdwrite(bp);
633 } else {
634 /*
635 * Write synchronously so that indirect blocks never
636 * point at garbage.
637 */
638 error = bwrite(bp);
639 if (error)
640 goto fail;
641 }
642
643 unwindidx = 0;
644 allocib = &ip->i_ffs2_ibdinode_u.ffs2_din->di_ib[indirs[0].in_off];
645 *allocib = nb;
646 ip->i_flag |= IN_CHANGE0x0002 | IN_UPDATE0x0004;
647 }
648
649 /*
650 * Fetch through the indirect blocks, allocating as necessary.
651 */
652 for (i = 1;;) {
653 error = bread(vp, indirs[i].in_lbn, (int)fs->fs_bsize, &bp);
654 if (error) {
655 brelse(bp);
656 goto fail;
657 }
658
659 bap = (int64_t *) bp->b_data;
660 nb = bap[indirs[i].in_off];
661
662 if (i == num)
663 break;
664
665 i++;
666
667 if (nb != 0) {
668 brelse(bp);
669 continue;
670 }
671
672 if (pref == 0)
673 pref = ffs2_blkpref(ip, lbn, i - num - 1, NULL((void *)0));
674
675 error = ffs_alloc(ip, lbn, pref, (int) fs->fs_bsize, cred,
676 &newb);
677 if (error) {
678 brelse(bp);
679 goto fail;
680 }
681
682 nb = newb;
683 *allocblk++ = nb;
684 nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, INFSLP0xffffffffffffffffULL);
685 nbp->b_blkno = fsbtodb(fs, nb)((nb) << (fs)->fs_fsbtodb);
686 clrbuf(nbp){ __builtin_bzero(((nbp)->b_data), ((nbp)->b_bcount)); (
nbp)->b_resid = 0; }
;
687
688 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000)) {
689 softdep_setup_allocindir_meta(nbp, ip, bp,
690 indirs[i - 1].in_off, nb);
691 bdwrite(nbp);
692 } else {
693 /*
694 * Write synchronously so that indirect blocks never
695 * point at garbage.
696 */
697 error = bwrite(nbp);
698 if (error) {
699 brelse(bp);
700 goto fail;
701 }
702 }
703
704 if (unwindidx < 0)
705 unwindidx = i - 1;
706
707 bap[indirs[i - 1].in_off] = nb;
708
709 /*
710 * If required, write synchronously, otherwise use delayed
711 * write.
712 */
713 if (flags & B_SYNC0x02)
714 bwrite(bp);
715 else
716 bdwrite(bp);
717 }
718
719 /*
720 * Get the data block, allocating if necessary.
721 */
722 if (nb == 0) {
723 pref = ffs2_blkpref(ip, lbn, indirs[num].in_off, &bap[0]);
724
725 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
726 &newb);
727 if (error) {
728 brelse(bp);
729 goto fail;
730 }
731
732 nb = newb;
733 *allocblk++ = nb;
734
735 if (bpp != NULL((void *)0)) {
736 nbp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP0xffffffffffffffffULL);
737 nbp->b_blkno = fsbtodb(fs, nb)((nb) << (fs)->fs_fsbtodb);
738 if (flags & B_CLRBUF0x01)
739 clrbuf(nbp){ __builtin_bzero(((nbp)->b_data), ((nbp)->b_bcount)); (
nbp)->b_resid = 0; }
;
740 *bpp = nbp;
741 }
742
743 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000))
744 softdep_setup_allocindir_page(ip, lbn, bp,
745 indirs[num].in_off, nb, 0, bpp ? *bpp : NULL((void *)0));
746
747 bap[indirs[num].in_off] = nb;
748
749 if (allocib == NULL((void *)0) && unwindidx < 0)
750 unwindidx = i - 1;
Value stored to 'unwindidx' is never read
751
752 /*
753 * If required, write synchronously, otherwise use delayed
754 * write.
755 */
756 if (flags & B_SYNC0x02)
757 bwrite(bp);
758 else
759 bdwrite(bp);
760
761 return (0);
762 }
763
764 brelse(bp);
765
766 if (bpp != NULL((void *)0)) {
767 if (flags & B_CLRBUF0x01) {
768 error = bread(vp, lbn, (int)fs->fs_bsize, &nbp);
769 if (error) {
770 brelse(nbp);
771 goto fail;
772 }
773 } else {
774 nbp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP0xffffffffffffffffULL);
775 nbp->b_blkno = fsbtodb(fs, nb)((nb) << (fs)->fs_fsbtodb);
776 clrbuf(nbp){ __builtin_bzero(((nbp)->b_data), ((nbp)->b_bcount)); (
nbp)->b_resid = 0; }
;
777 }
778
779 *bpp = nbp;
780 }
781
782 return (0);
783
784fail:
785 /*
786 * If we have failed to allocate any blocks, simply return the error.
787 * This is the usual case and avoids the need to fsync the file.
788 */
789 if (allocblk == allociblk && allocib == NULL((void *)0) && unwindidx == -1)
790 return (error);
791 /*
792 * If we have failed part way through block allocation, we have to
793 * deallocate any indirect blocks that we have allocated. We have to
794 * fsync the file before we start to get rid of all of its
795 * dependencies so that we do not leave them dangling. We have to sync
796 * it at the end so that the softdep code does not find any untracked
797 * changes. Although this is really slow, running out of disk space is
798 * not expected to be a common occurrence. The error return from fsync
799 * is ignored as we already have an error to return to the user.
800 */
801 VOP_FSYNC(vp, p->p_ucred, MNT_WAIT1, p);
802 if (unwindidx >= 0) {
803 /*
804 * First write out any buffers we've created to resolve their
805 * softdeps. This must be done in reverse order of creation so
806 * that we resolve the dependencies in one pass.
807 * Write the cylinder group buffers for these buffers too.
808 */
809 for (i = num; i >= unwindidx; i--) {
810 if (i == 0)
811 break;
812
813 bp = getblk(vp, indirs[i].in_lbn, (int) fs->fs_bsize,
814 0, INFSLP0xffffffffffffffffULL);
815 if (bp->b_flags & B_DELWRI0x00000080) {
816 nb = fsbtodb(fs, cgtod(fs, dtog(fs,((((((daddr_t)(fs)->fs_fpg * (((((bp->b_blkno) >>
(fs)->fs_fsbtodb)) / (fs)->fs_fpg))) + (fs)->fs_cgoffset
* ((((((bp->b_blkno) >> (fs)->fs_fsbtodb)) / (fs
)->fs_fpg)) & ~((fs)->fs_cgmask))) + (fs)->fs_cblkno
)) << (fs)->fs_fsbtodb)
817 dbtofsb(fs, bp->b_blkno))))((((((daddr_t)(fs)->fs_fpg * (((((bp->b_blkno) >>
(fs)->fs_fsbtodb)) / (fs)->fs_fpg))) + (fs)->fs_cgoffset
* ((((((bp->b_blkno) >> (fs)->fs_fsbtodb)) / (fs
)->fs_fpg)) & ~((fs)->fs_cgmask))) + (fs)->fs_cblkno
)) << (fs)->fs_fsbtodb)
;
818 bwrite(bp);
819 bp = getblk(ip->i_devvpi_ump->um_devvp, nb,
820 (int) fs->fs_cgsize, 0, INFSLP0xffffffffffffffffULL);
821 if (bp->b_flags & B_DELWRI0x00000080)
822 bwrite(bp);
823 else {
824 bp->b_flags |= B_INVAL0x00000800;
825 brelse(bp);
826 }
827 } else {
828 bp->b_flags |= B_INVAL0x00000800;
829 brelse(bp);
830 }
831 }
832
833 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000) && unwindidx == 0) {
834 ip->i_flag |= IN_CHANGE0x0002 | IN_UPDATE0x0004;
835 ffs_update(ip, 1);
836 }
837
838 /*
839 * Now that any dependencies that we created have been
840 * resolved, we can undo the partial allocation.
841 */
842 if (unwindidx == 0) {
843 *allocib = 0;
844 ip->i_flag |= IN_CHANGE0x0002 | IN_UPDATE0x0004;
845 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000))
846 ffs_update(ip, 1);
847 } else {
848 r = bread(vp, indirs[unwindidx].in_lbn,
849 (int)fs->fs_bsize, &bp);
850 if (r)
851 panic("ffs2_balloc: unwind failed");
852
853 bap = (int64_t *) bp->b_data;
854 bap[indirs[unwindidx].in_off] = 0;
855 bwrite(bp);
856 }
857
858 for (i = unwindidx + 1; i <= num; i++) {
859 bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0,
860 INFSLP0xffffffffffffffffULL);
861 bp->b_flags |= B_INVAL0x00000800;
862 brelse(bp);
863 }
864 }
865
866 for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
867 ffs_blkfree(ip, *blkp, fs->fs_bsize);
868 deallocated += fs->fs_bsize;
869 }
870
871 if (deallocated) {
872 /*
873 * Restore user's disk quota because allocation failed.
874 */
875 (void) ufs_quota_free_blocks(ip, btodb(deallocated), cred)ufs_quota_free_blocks2(ip, ((deallocated) >> 9), cred, 0
)
;
876
877 ip->i_ffs2_blocksdinode_u.ffs2_din->di_blocks -= btodb(deallocated)((deallocated) >> 9);
878 ip->i_flag |= IN_CHANGE0x0002 | IN_UPDATE0x0004;
879 }
880 VOP_FSYNC(vp, p->p_ucred, MNT_WAIT1, p);
881 return (error);
882}
883#endif /* FFS2 */
884
885/*
886 * Balloc defines the structure of file system storage by allocating the
887 * physical blocks given the inode and the logical block number in a file.
888 */
889int
890ffs_balloc(struct inode *ip, off_t off, int size, struct ucred *cred,
891 int flags, struct buf **bpp)
892{
893#ifdef FFS21
894 if (ip->i_fsinode_u.fs->fs_magic == FS_UFS2_MAGIC0x19540119)
895 return (ffs2_balloc(ip, off, size, cred, flags, bpp));
896 else
897#endif
898 return (ffs1_balloc(ip, off, size, cred, flags, bpp));
899}