1 1.66 chs /* $NetBSD: ffs_balloc.c,v 1.66 2022/11/17 06:40:40 chs Exp $ */ 2 1.2 cgd 3 1.1 mycroft /* 4 1.33 fvdl * Copyright (c) 2002 Networks Associates Technology, Inc. 5 1.33 fvdl * All rights reserved. 6 1.33 fvdl * 7 1.33 fvdl * This software was developed for the FreeBSD Project by Marshall 8 1.33 fvdl * Kirk McKusick and Network Associates Laboratories, the Security 9 1.33 fvdl * Research Division of Network Associates, Inc. under DARPA/SPAWAR 10 1.33 fvdl * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS 11 1.33 fvdl * research program 12 1.33 fvdl * 13 1.1 mycroft * Copyright (c) 1982, 1986, 1989, 1993 14 1.1 mycroft * The Regents of the University of California. All rights reserved. 15 1.1 mycroft * 16 1.1 mycroft * Redistribution and use in source and binary forms, with or without 17 1.1 mycroft * modification, are permitted provided that the following conditions 18 1.1 mycroft * are met: 19 1.1 mycroft * 1. Redistributions of source code must retain the above copyright 20 1.1 mycroft * notice, this list of conditions and the following disclaimer. 21 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright 22 1.1 mycroft * notice, this list of conditions and the following disclaimer in the 23 1.1 mycroft * documentation and/or other materials provided with the distribution. 24 1.34 agc * 3. Neither the name of the University nor the names of its contributors 25 1.1 mycroft * may be used to endorse or promote products derived from this software 26 1.1 mycroft * without specific prior written permission. 27 1.1 mycroft * 28 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 1.1 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 1.1 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 1.1 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 1.1 mycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 1.1 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 1.1 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 1.1 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 1.1 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 1.1 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 1.1 mycroft * SUCH DAMAGE. 39 1.1 mycroft * 40 1.8 fvdl * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95 41 1.1 mycroft */ 42 1.28 lukem 43 1.28 lukem #include <sys/cdefs.h> 44 1.66 chs __KERNEL_RCSID(0, "$NetBSD: ffs_balloc.c,v 1.66 2022/11/17 06:40:40 chs Exp $"); 45 1.7 mrg 46 1.24 mrg #if defined(_KERNEL_OPT) 47 1.10 scottr #include "opt_quota.h" 48 1.65 riastrad #include "opt_uvmhist.h" 49 1.11 scottr #endif 50 1.1 mycroft 51 1.1 mycroft #include <sys/param.h> 52 1.1 mycroft #include <sys/systm.h> 53 1.1 mycroft #include <sys/buf.h> 54 1.1 mycroft #include <sys/file.h> 55 1.15 fvdl #include <sys/mount.h> 56 1.1 mycroft #include <sys/vnode.h> 57 1.43 elad #include <sys/kauth.h> 58 1.49 hannken #include <sys/fstrans.h> 59 1.6 mrg 60 1.1 mycroft #include <ufs/ufs/quota.h> 61 1.9 bouyer #include <ufs/ufs/ufsmount.h> 62 1.1 mycroft #include <ufs/ufs/inode.h> 63 1.1 mycroft #include <ufs/ufs/ufs_extern.h> 64 1.9 bouyer #include <ufs/ufs/ufs_bswap.h> 65 1.1 mycroft 66 1.1 mycroft #include <ufs/ffs/fs.h> 67 1.1 mycroft #include <ufs/ffs/ffs_extern.h> 68 1.1 mycroft 69 1.65 riastrad #ifdef UVMHIST 70 1.23 chs #include <uvm/uvm.h> 71 1.65 riastrad #endif 72 1.65 riastrad #include <uvm/uvm_extern.h> 73 1.65 riastrad #include <uvm/uvm_stat.h> 74 1.23 chs 75 1.43 elad static int ffs_balloc_ufs1(struct vnode *, off_t, int, kauth_cred_t, int, 76 1.39 yamt struct buf **); 77 1.43 elad static int ffs_balloc_ufs2(struct vnode *, off_t, int, kauth_cred_t, int, 78 1.39 yamt struct buf **); 79 1.33 fvdl 80 1.64 christos static daddr_t 81 1.64 christos ffs_extb(struct fs *fs, struct ufs2_dinode *dp, daddr_t nb) 82 1.64 christos { 83 1.64 christos return ufs_rw64(dp->di_extb[nb], UFS_FSNEEDSWAP(fs)); 84 1.64 christos } 85 1.64 christos 86 1.1 mycroft /* 87 1.1 mycroft * Balloc defines the structure of file system storage 88 1.1 mycroft * by allocating the physical blocks on a device given 89 1.1 mycroft * the inode and the logical block number in a file. 90 1.1 mycroft */ 91 1.33 fvdl 92 1.3 christos int 93 1.43 elad ffs_balloc(struct vnode *vp, off_t off, int size, kauth_cred_t cred, int flags, 94 1.39 yamt struct buf **bpp) 95 1.15 fvdl { 96 1.49 hannken int error; 97 1.33 fvdl 98 1.39 yamt if (VTOI(vp)->i_fs->fs_magic == FS_UFS2_MAGIC) 99 1.49 hannken error = ffs_balloc_ufs2(vp, off, size, cred, flags, bpp); 100 1.33 fvdl else 101 1.49 hannken error = ffs_balloc_ufs1(vp, off, size, cred, flags, bpp); 102 1.49 hannken 103 1.49 hannken if (error == 0 && bpp != NULL && (error = fscow_run(*bpp, false)) != 0) 104 1.49 hannken brelse(*bpp, 0); 105 1.49 hannken 106 1.49 hannken return error; 107 1.49 hannken } 108 1.49 hannken 109 1.49 hannken static int 110 1.43 elad ffs_balloc_ufs1(struct vnode *vp, off_t off, int size, kauth_cred_t cred, 111 1.39 yamt int flags, struct buf **bpp) 112 1.33 fvdl { 113 1.33 fvdl daddr_t lbn, lastlbn; 114 1.1 mycroft struct buf *bp, *nbp; 115 1.15 fvdl struct inode *ip = VTOI(vp); 116 1.15 fvdl struct fs *fs = ip->i_fs; 117 1.46 ad struct ufsmount *ump = ip->i_ump; 118 1.56 dholland struct indir indirs[UFS_NIADDR + 2]; 119 1.37 mycroft daddr_t newb, pref, nb; 120 1.31 fvdl int32_t *bap; /* XXX ondisk32 */ 121 1.8 fvdl int deallocated, osize, nsize, num, i, error; 122 1.56 dholland int32_t *blkp, *allocblk, allociblk[UFS_NIADDR + 1]; 123 1.33 fvdl int32_t *allocib; 124 1.17 fvdl int unwindidx = -1; 125 1.15 fvdl const int needswap = UFS_FSNEEDSWAP(fs); 126 1.23 chs UVMHIST_FUNC("ffs_balloc"); UVMHIST_CALLED(ubchist); 127 1.1 mycroft 128 1.59 dholland lbn = ffs_lblkno(fs, off); 129 1.57 dholland size = ffs_blkoff(fs, off) + size; 130 1.15 fvdl if (size > fs->fs_bsize) 131 1.15 fvdl panic("ffs_balloc: blk too big"); 132 1.23 chs if (bpp != NULL) { 133 1.23 chs *bpp = NULL; 134 1.23 chs } 135 1.63 pgoyette UVMHIST_LOG(ubchist, "vp %#jx lbn 0x%jx size 0x%jx", (uintptr_t)vp, 136 1.63 pgoyette lbn, size, 0); 137 1.23 chs 138 1.8 fvdl if (lbn < 0) 139 1.1 mycroft return (EFBIG); 140 1.1 mycroft 141 1.1 mycroft /* 142 1.1 mycroft * If the next write will extend the file into a new block, 143 1.1 mycroft * and the file is currently composed of a fragment 144 1.1 mycroft * this fragment has to be extended to be a full block. 145 1.1 mycroft */ 146 1.23 chs 147 1.59 dholland lastlbn = ffs_lblkno(fs, ip->i_size); 148 1.56 dholland if (lastlbn < UFS_NDADDR && lastlbn < lbn) { 149 1.33 fvdl nb = lastlbn; 150 1.57 dholland osize = ffs_blksize(fs, ip, nb); 151 1.1 mycroft if (osize < fs->fs_bsize && osize > 0) { 152 1.46 ad mutex_enter(&ump->um_lock); 153 1.64 christos error = ffs_realloccg(ip, nb, ffs_getdb(fs, ip, nb), 154 1.51 simonb ffs_blkpref_ufs1(ip, lastlbn, nb, flags, 155 1.33 fvdl &ip->i_ffs1_db[0]), 156 1.64 christos osize, (int)fs->fs_bsize, flags, cred, bpp, 157 1.64 christos &newb); 158 1.1 mycroft if (error) 159 1.1 mycroft return (error); 160 1.59 dholland ip->i_size = ffs_lblktosize(fs, nb + 1); 161 1.33 fvdl ip->i_ffs1_size = ip->i_size; 162 1.33 fvdl uvm_vnp_setsize(vp, ip->i_ffs1_size); 163 1.37 mycroft ip->i_ffs1_db[nb] = ufs_rw32((u_int32_t)newb, needswap); 164 1.1 mycroft ip->i_flag |= IN_CHANGE | IN_UPDATE; 165 1.42 christos if (bpp && *bpp) { 166 1.23 chs if (flags & B_SYNC) 167 1.23 chs bwrite(*bpp); 168 1.23 chs else 169 1.23 chs bawrite(*bpp); 170 1.23 chs } 171 1.1 mycroft } 172 1.1 mycroft } 173 1.23 chs 174 1.1 mycroft /* 175 1.56 dholland * The first UFS_NDADDR blocks are direct blocks 176 1.1 mycroft */ 177 1.23 chs 178 1.56 dholland if (lbn < UFS_NDADDR) { 179 1.33 fvdl nb = ufs_rw32(ip->i_ffs1_db[lbn], needswap); 180 1.59 dholland if (nb != 0 && ip->i_size >= ffs_lblktosize(fs, lbn + 1)) { 181 1.23 chs 182 1.23 chs /* 183 1.23 chs * The block is an already-allocated direct block 184 1.23 chs * and the file already extends past this block, 185 1.23 chs * thus this must be a whole block. 186 1.23 chs * Just read the block (if requested). 187 1.23 chs */ 188 1.23 chs 189 1.23 chs if (bpp != NULL) { 190 1.61 maxv error = bread(vp, lbn, fs->fs_bsize, 191 1.49 hannken B_MODIFY, bpp); 192 1.23 chs if (error) { 193 1.23 chs return (error); 194 1.23 chs } 195 1.1 mycroft } 196 1.1 mycroft return (0); 197 1.1 mycroft } 198 1.1 mycroft if (nb != 0) { 199 1.23 chs 200 1.1 mycroft /* 201 1.1 mycroft * Consider need to reallocate a fragment. 202 1.1 mycroft */ 203 1.23 chs 204 1.59 dholland osize = ffs_fragroundup(fs, ffs_blkoff(fs, ip->i_size)); 205 1.59 dholland nsize = ffs_fragroundup(fs, size); 206 1.1 mycroft if (nsize <= osize) { 207 1.23 chs 208 1.23 chs /* 209 1.23 chs * The existing block is already 210 1.23 chs * at least as big as we want. 211 1.23 chs * Just read the block (if requested). 212 1.23 chs */ 213 1.23 chs 214 1.23 chs if (bpp != NULL) { 215 1.61 maxv error = bread(vp, lbn, osize, 216 1.49 hannken B_MODIFY, bpp); 217 1.23 chs if (error) { 218 1.23 chs return (error); 219 1.23 chs } 220 1.1 mycroft } 221 1.23 chs return 0; 222 1.1 mycroft } else { 223 1.23 chs 224 1.23 chs /* 225 1.23 chs * The existing block is smaller than we want, 226 1.23 chs * grow it. 227 1.23 chs */ 228 1.46 ad mutex_enter(&ump->um_lock); 229 1.8 fvdl error = ffs_realloccg(ip, lbn, 230 1.64 christos ffs_getdb(fs, ip, lbn), 231 1.51 simonb ffs_blkpref_ufs1(ip, lbn, (int)lbn, flags, 232 1.51 simonb &ip->i_ffs1_db[0]), 233 1.64 christos osize, nsize, flags, cred, bpp, &newb); 234 1.1 mycroft if (error) 235 1.1 mycroft return (error); 236 1.1 mycroft } 237 1.1 mycroft } else { 238 1.23 chs 239 1.23 chs /* 240 1.23 chs * the block was not previously allocated, 241 1.23 chs * allocate a new block or fragment. 242 1.23 chs */ 243 1.23 chs 244 1.59 dholland if (ip->i_size < ffs_lblktosize(fs, lbn + 1)) 245 1.59 dholland nsize = ffs_fragroundup(fs, size); 246 1.1 mycroft else 247 1.1 mycroft nsize = fs->fs_bsize; 248 1.46 ad mutex_enter(&ump->um_lock); 249 1.8 fvdl error = ffs_alloc(ip, lbn, 250 1.51 simonb ffs_blkpref_ufs1(ip, lbn, (int)lbn, flags, 251 1.33 fvdl &ip->i_ffs1_db[0]), 252 1.51 simonb nsize, flags, cred, &newb); 253 1.1 mycroft if (error) 254 1.1 mycroft return (error); 255 1.23 chs if (bpp != NULL) { 256 1.58 dholland error = ffs_getblk(vp, lbn, FFS_FSBTODB(fs, newb), 257 1.49 hannken nsize, (flags & B_CLRBUF) != 0, bpp); 258 1.49 hannken if (error) 259 1.49 hannken return error; 260 1.23 chs } 261 1.1 mycroft } 262 1.37 mycroft ip->i_ffs1_db[lbn] = ufs_rw32((u_int32_t)newb, needswap); 263 1.1 mycroft ip->i_flag |= IN_CHANGE | IN_UPDATE; 264 1.1 mycroft return (0); 265 1.1 mycroft } 266 1.29 chs 267 1.1 mycroft /* 268 1.1 mycroft * Determine the number of levels of indirection. 269 1.1 mycroft */ 270 1.29 chs 271 1.1 mycroft pref = 0; 272 1.8 fvdl if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0) 273 1.29 chs return (error); 274 1.23 chs 275 1.1 mycroft /* 276 1.1 mycroft * Fetch the first indirect block allocating if necessary. 277 1.1 mycroft */ 278 1.29 chs 279 1.1 mycroft --num; 280 1.33 fvdl nb = ufs_rw32(ip->i_ffs1_ib[indirs[0].in_off], needswap); 281 1.8 fvdl allocib = NULL; 282 1.8 fvdl allocblk = allociblk; 283 1.1 mycroft if (nb == 0) { 284 1.46 ad mutex_enter(&ump->um_lock); 285 1.51 simonb pref = ffs_blkpref_ufs1(ip, lbn, 0, flags | B_METAONLY, NULL); 286 1.51 simonb error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, 287 1.51 simonb flags | B_METAONLY, cred, &newb); 288 1.3 christos if (error) 289 1.27 chs goto fail; 290 1.1 mycroft nb = newb; 291 1.8 fvdl *allocblk++ = nb; 292 1.58 dholland error = ffs_getblk(vp, indirs[1].in_lbn, FFS_FSBTODB(fs, nb), 293 1.49 hannken fs->fs_bsize, true, &bp); 294 1.49 hannken if (error) 295 1.49 hannken goto fail; 296 1.52 ad /* 297 1.52 ad * Write synchronously so that indirect blocks 298 1.52 ad * never point at garbage. 299 1.52 ad */ 300 1.52 ad if ((error = bwrite(bp)) != 0) 301 1.52 ad goto fail; 302 1.18 mycroft unwindidx = 0; 303 1.33 fvdl allocib = &ip->i_ffs1_ib[indirs[0].in_off]; 304 1.33 fvdl *allocib = ufs_rw32(nb, needswap); 305 1.1 mycroft ip->i_flag |= IN_CHANGE | IN_UPDATE; 306 1.1 mycroft } 307 1.29 chs 308 1.1 mycroft /* 309 1.1 mycroft * Fetch through the indirect blocks, allocating as necessary. 310 1.1 mycroft */ 311 1.29 chs 312 1.1 mycroft for (i = 1;;) { 313 1.1 mycroft error = bread(vp, 314 1.61 maxv indirs[i].in_lbn, (int)fs->fs_bsize, 0, &bp); 315 1.1 mycroft if (error) { 316 1.8 fvdl goto fail; 317 1.1 mycroft } 318 1.31 fvdl bap = (int32_t *)bp->b_data; /* XXX ondisk32 */ 319 1.15 fvdl nb = ufs_rw32(bap[indirs[i].in_off], needswap); 320 1.1 mycroft if (i == num) 321 1.1 mycroft break; 322 1.18 mycroft i++; 323 1.1 mycroft if (nb != 0) { 324 1.46 ad brelse(bp, 0); 325 1.1 mycroft continue; 326 1.1 mycroft } 327 1.49 hannken if (fscow_run(bp, true) != 0) { 328 1.49 hannken brelse(bp, 0); 329 1.49 hannken goto fail; 330 1.49 hannken } 331 1.46 ad mutex_enter(&ump->um_lock); 332 1.54 hannken /* Try to keep snapshot indirect blocks contiguous. */ 333 1.54 hannken if (i == num && (ip->i_flags & SF_SNAPSHOT) != 0) 334 1.54 hannken pref = ffs_blkpref_ufs1(ip, lbn, indirs[i-1].in_off, 335 1.54 hannken flags | B_METAONLY, &bap[0]); 336 1.1 mycroft if (pref == 0) 337 1.51 simonb pref = ffs_blkpref_ufs1(ip, lbn, 0, flags | B_METAONLY, 338 1.51 simonb NULL); 339 1.51 simonb error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, 340 1.51 simonb flags | B_METAONLY, cred, &newb); 341 1.3 christos if (error) { 342 1.46 ad brelse(bp, 0); 343 1.8 fvdl goto fail; 344 1.1 mycroft } 345 1.1 mycroft nb = newb; 346 1.8 fvdl *allocblk++ = nb; 347 1.58 dholland error = ffs_getblk(vp, indirs[i].in_lbn, FFS_FSBTODB(fs, nb), 348 1.49 hannken fs->fs_bsize, true, &nbp); 349 1.49 hannken if (error) { 350 1.49 hannken brelse(bp, 0); 351 1.49 hannken goto fail; 352 1.49 hannken } 353 1.52 ad /* 354 1.52 ad * Write synchronously so that indirect blocks 355 1.52 ad * never point at garbage. 356 1.52 ad */ 357 1.52 ad if ((error = bwrite(nbp)) != 0) { 358 1.52 ad brelse(bp, 0); 359 1.52 ad goto fail; 360 1.1 mycroft } 361 1.18 mycroft if (unwindidx < 0) 362 1.18 mycroft unwindidx = i - 1; 363 1.33 fvdl bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap); 364 1.29 chs 365 1.1 mycroft /* 366 1.1 mycroft * If required, write synchronously, otherwise use 367 1.1 mycroft * delayed write. 368 1.1 mycroft */ 369 1.29 chs 370 1.1 mycroft if (flags & B_SYNC) { 371 1.1 mycroft bwrite(bp); 372 1.1 mycroft } else { 373 1.1 mycroft bdwrite(bp); 374 1.1 mycroft } 375 1.1 mycroft } 376 1.29 chs 377 1.35 hannken if (flags & B_METAONLY) { 378 1.41 hannken KASSERT(bpp != NULL); 379 1.35 hannken *bpp = bp; 380 1.35 hannken return (0); 381 1.35 hannken } 382 1.35 hannken 383 1.1 mycroft /* 384 1.1 mycroft * Get the data block, allocating if necessary. 385 1.1 mycroft */ 386 1.29 chs 387 1.1 mycroft if (nb == 0) { 388 1.49 hannken if (fscow_run(bp, true) != 0) { 389 1.49 hannken brelse(bp, 0); 390 1.49 hannken goto fail; 391 1.49 hannken } 392 1.46 ad mutex_enter(&ump->um_lock); 393 1.51 simonb pref = ffs_blkpref_ufs1(ip, lbn, indirs[num].in_off, flags, 394 1.51 simonb &bap[0]); 395 1.51 simonb error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, flags, cred, 396 1.18 mycroft &newb); 397 1.3 christos if (error) { 398 1.46 ad brelse(bp, 0); 399 1.8 fvdl goto fail; 400 1.1 mycroft } 401 1.1 mycroft nb = newb; 402 1.8 fvdl *allocblk++ = nb; 403 1.23 chs if (bpp != NULL) { 404 1.58 dholland error = ffs_getblk(vp, lbn, FFS_FSBTODB(fs, nb), 405 1.49 hannken fs->fs_bsize, (flags & B_CLRBUF) != 0, bpp); 406 1.49 hannken if (error) { 407 1.49 hannken brelse(bp, 0); 408 1.49 hannken goto fail; 409 1.49 hannken } 410 1.23 chs } 411 1.33 fvdl bap[indirs[num].in_off] = ufs_rw32(nb, needswap); 412 1.23 chs if (allocib == NULL && unwindidx < 0) { 413 1.23 chs unwindidx = i - 1; 414 1.23 chs } 415 1.29 chs 416 1.1 mycroft /* 417 1.1 mycroft * If required, write synchronously, otherwise use 418 1.1 mycroft * delayed write. 419 1.1 mycroft */ 420 1.29 chs 421 1.1 mycroft if (flags & B_SYNC) { 422 1.1 mycroft bwrite(bp); 423 1.1 mycroft } else { 424 1.1 mycroft bdwrite(bp); 425 1.1 mycroft } 426 1.1 mycroft return (0); 427 1.1 mycroft } 428 1.46 ad brelse(bp, 0); 429 1.23 chs if (bpp != NULL) { 430 1.23 chs if (flags & B_CLRBUF) { 431 1.49 hannken error = bread(vp, lbn, (int)fs->fs_bsize, 432 1.61 maxv B_MODIFY, &nbp); 433 1.23 chs if (error) { 434 1.23 chs goto fail; 435 1.23 chs } 436 1.23 chs } else { 437 1.58 dholland error = ffs_getblk(vp, lbn, FFS_FSBTODB(fs, nb), 438 1.49 hannken fs->fs_bsize, true, &nbp); 439 1.49 hannken if (error) 440 1.49 hannken goto fail; 441 1.1 mycroft } 442 1.23 chs *bpp = nbp; 443 1.1 mycroft } 444 1.1 mycroft return (0); 445 1.27 chs 446 1.8 fvdl fail: 447 1.27 chs /* 448 1.29 chs * If we have failed part way through block allocation, we 449 1.29 chs * have to deallocate any indirect blocks that we have allocated. 450 1.27 chs */ 451 1.27 chs 452 1.29 chs if (unwindidx >= 0) { 453 1.27 chs 454 1.29 chs /* 455 1.29 chs * First write out any buffers we've created to resolve their 456 1.29 chs * softdeps. This must be done in reverse order of creation 457 1.29 chs * so that we resolve the dependencies in one pass. 458 1.29 chs * Write the cylinder group buffers for these buffers too. 459 1.29 chs */ 460 1.29 chs 461 1.29 chs for (i = num; i >= unwindidx; i--) { 462 1.29 chs if (i == 0) { 463 1.29 chs break; 464 1.29 chs } 465 1.50 hannken if (ffs_getblk(vp, indirs[i].in_lbn, FFS_NOBLK, 466 1.50 hannken fs->fs_bsize, false, &bp) != 0) 467 1.50 hannken continue; 468 1.48 ad if (bp->b_oflags & BO_DELWRI) { 469 1.58 dholland nb = FFS_FSBTODB(fs, cgtod(fs, dtog(fs, 470 1.58 dholland FFS_DBTOFSB(fs, bp->b_blkno)))); 471 1.29 chs bwrite(bp); 472 1.50 hannken if (ffs_getblk(ip->i_devvp, nb, FFS_NOBLK, 473 1.50 hannken fs->fs_cgsize, false, &bp) != 0) 474 1.50 hannken continue; 475 1.48 ad if (bp->b_oflags & BO_DELWRI) { 476 1.29 chs bwrite(bp); 477 1.29 chs } else { 478 1.46 ad brelse(bp, BC_INVAL); 479 1.29 chs } 480 1.29 chs } else { 481 1.46 ad brelse(bp, BC_INVAL); 482 1.29 chs } 483 1.29 chs } 484 1.47 ad 485 1.29 chs /* 486 1.52 ad * Undo the partial allocation. 487 1.29 chs */ 488 1.18 mycroft if (unwindidx == 0) { 489 1.18 mycroft *allocib = 0; 490 1.36 mycroft ip->i_flag |= IN_CHANGE | IN_UPDATE; 491 1.17 fvdl } else { 492 1.18 mycroft int r; 493 1.29 chs 494 1.29 chs r = bread(vp, indirs[unwindidx].in_lbn, 495 1.61 maxv (int)fs->fs_bsize, 0, &bp); 496 1.18 mycroft if (r) { 497 1.18 mycroft panic("Could not unwind indirect block, error %d", r); 498 1.18 mycroft } else { 499 1.31 fvdl bap = (int32_t *)bp->b_data; /* XXX ondisk32 */ 500 1.18 mycroft bap[indirs[unwindidx].in_off] = 0; 501 1.29 chs bwrite(bp); 502 1.18 mycroft } 503 1.17 fvdl } 504 1.19 mycroft for (i = unwindidx + 1; i <= num; i++) { 505 1.50 hannken if (ffs_getblk(vp, indirs[i].in_lbn, FFS_NOBLK, 506 1.50 hannken fs->fs_bsize, false, &bp) == 0) 507 1.50 hannken brelse(bp, BC_INVAL); 508 1.19 mycroft } 509 1.17 fvdl } 510 1.29 chs for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) { 511 1.35 hannken ffs_blkfree(fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number); 512 1.29 chs deallocated += fs->fs_bsize; 513 1.29 chs } 514 1.8 fvdl if (deallocated) { 515 1.53 bouyer #if defined(QUOTA) || defined(QUOTA2) 516 1.8 fvdl /* 517 1.8 fvdl * Restore user's disk quota because allocation failed. 518 1.8 fvdl */ 519 1.33 fvdl (void)chkdq(ip, -btodb(deallocated), cred, FORCE); 520 1.33 fvdl #endif 521 1.33 fvdl ip->i_ffs1_blocks -= btodb(deallocated); 522 1.33 fvdl ip->i_flag |= IN_CHANGE | IN_UPDATE; 523 1.33 fvdl } 524 1.33 fvdl return (error); 525 1.33 fvdl } 526 1.33 fvdl 527 1.33 fvdl static int 528 1.43 elad ffs_balloc_ufs2(struct vnode *vp, off_t off, int size, kauth_cred_t cred, 529 1.39 yamt int flags, struct buf **bpp) 530 1.33 fvdl { 531 1.33 fvdl daddr_t lbn, lastlbn; 532 1.33 fvdl struct buf *bp, *nbp; 533 1.33 fvdl struct inode *ip = VTOI(vp); 534 1.33 fvdl struct fs *fs = ip->i_fs; 535 1.46 ad struct ufsmount *ump = ip->i_ump; 536 1.56 dholland struct indir indirs[UFS_NIADDR + 2]; 537 1.33 fvdl daddr_t newb, pref, nb; 538 1.33 fvdl int64_t *bap; 539 1.33 fvdl int deallocated, osize, nsize, num, i, error; 540 1.56 dholland daddr_t *blkp, *allocblk, allociblk[UFS_NIADDR + 1]; 541 1.33 fvdl int64_t *allocib; 542 1.33 fvdl int unwindidx = -1; 543 1.33 fvdl const int needswap = UFS_FSNEEDSWAP(fs); 544 1.33 fvdl UVMHIST_FUNC("ffs_balloc"); UVMHIST_CALLED(ubchist); 545 1.33 fvdl 546 1.66 chs KASSERT((ump->um_flags & UFS_EA) != 0 || (flags & IO_EXT) == 0); 547 1.66 chs 548 1.59 dholland lbn = ffs_lblkno(fs, off); 549 1.57 dholland size = ffs_blkoff(fs, off) + size; 550 1.33 fvdl if (size > fs->fs_bsize) 551 1.33 fvdl panic("ffs_balloc: blk too big"); 552 1.33 fvdl if (bpp != NULL) { 553 1.33 fvdl *bpp = NULL; 554 1.33 fvdl } 555 1.63 pgoyette UVMHIST_LOG(ubchist, "vp %#jx lbn 0x%jx size 0x%jx", (uintptr_t)vp, 556 1.63 pgoyette lbn, size, 0); 557 1.33 fvdl 558 1.33 fvdl if (lbn < 0) 559 1.33 fvdl return (EFBIG); 560 1.33 fvdl 561 1.33 fvdl /* 562 1.33 fvdl * Check for allocating external data. 563 1.33 fvdl */ 564 1.33 fvdl if (flags & IO_EXT) { 565 1.64 christos struct ufs2_dinode *dp = ip->i_din.ffs2_din; 566 1.56 dholland if (lbn >= UFS_NXADDR) 567 1.33 fvdl return (EFBIG); 568 1.33 fvdl /* 569 1.33 fvdl * If the next write will extend the data into a new block, 570 1.33 fvdl * and the data is currently composed of a fragment 571 1.33 fvdl * this fragment has to be extended to be a full block. 572 1.33 fvdl */ 573 1.59 dholland lastlbn = ffs_lblkno(fs, dp->di_extsize); 574 1.33 fvdl if (lastlbn < lbn) { 575 1.33 fvdl nb = lastlbn; 576 1.57 dholland osize = ffs_sblksize(fs, dp->di_extsize, nb); 577 1.33 fvdl if (osize < fs->fs_bsize && osize > 0) { 578 1.46 ad mutex_enter(&ump->um_lock); 579 1.33 fvdl error = ffs_realloccg(ip, -1 - nb, 580 1.64 christos ffs_extb(fs, dp, nb), 581 1.33 fvdl ffs_blkpref_ufs2(ip, lastlbn, (int)nb, 582 1.51 simonb flags, &dp->di_extb[0]), 583 1.64 christos osize, (int)fs->fs_bsize, flags, cred, 584 1.64 christos &bp, &newb); 585 1.33 fvdl if (error) 586 1.33 fvdl return (error); 587 1.64 christos dp->di_extsize = ffs_lblktosize(fs, nb + 1); 588 1.58 dholland dp->di_extb[nb] = FFS_DBTOFSB(fs, bp->b_blkno); 589 1.33 fvdl ip->i_flag |= IN_CHANGE | IN_UPDATE; 590 1.33 fvdl if (flags & IO_SYNC) 591 1.33 fvdl bwrite(bp); 592 1.33 fvdl else 593 1.33 fvdl bawrite(bp); 594 1.33 fvdl } 595 1.33 fvdl } 596 1.33 fvdl /* 597 1.33 fvdl * All blocks are direct blocks 598 1.33 fvdl */ 599 1.33 fvdl nb = dp->di_extb[lbn]; 600 1.64 christos if (nb != 0 && dp->di_extsize >= ffs_lblktosize(fs, lbn + 1)) { 601 1.49 hannken error = bread(vp, -1 - lbn, fs->fs_bsize, 602 1.61 maxv 0, &bp); 603 1.33 fvdl if (error) { 604 1.33 fvdl return (error); 605 1.33 fvdl } 606 1.64 christos mutex_enter(bp->b_objlock); 607 1.58 dholland bp->b_blkno = FFS_FSBTODB(fs, nb); 608 1.64 christos mutex_exit(bp->b_objlock); 609 1.33 fvdl *bpp = bp; 610 1.33 fvdl return (0); 611 1.33 fvdl } 612 1.33 fvdl if (nb != 0) { 613 1.33 fvdl /* 614 1.33 fvdl * Consider need to reallocate a fragment. 615 1.33 fvdl */ 616 1.59 dholland osize = ffs_fragroundup(fs, ffs_blkoff(fs, dp->di_extsize)); 617 1.59 dholland nsize = ffs_fragroundup(fs, size); 618 1.33 fvdl if (nsize <= osize) { 619 1.49 hannken error = bread(vp, -1 - lbn, osize, 620 1.61 maxv 0, &bp); 621 1.33 fvdl if (error) { 622 1.33 fvdl return (error); 623 1.33 fvdl } 624 1.64 christos mutex_enter(bp->b_objlock); 625 1.58 dholland bp->b_blkno = FFS_FSBTODB(fs, nb); 626 1.64 christos mutex_exit(bp->b_objlock); 627 1.33 fvdl } else { 628 1.46 ad mutex_enter(&ump->um_lock); 629 1.33 fvdl error = ffs_realloccg(ip, -1 - lbn, 630 1.64 christos ffs_extb(fs, dp, lbn), 631 1.51 simonb ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags, 632 1.51 simonb &dp->di_extb[0]), 633 1.64 christos osize, nsize, flags, cred, &bp, &newb); 634 1.33 fvdl if (error) 635 1.33 fvdl return (error); 636 1.33 fvdl } 637 1.33 fvdl } else { 638 1.64 christos if (dp->di_extsize < ffs_lblktosize(fs, lbn + 1)) 639 1.59 dholland nsize = ffs_fragroundup(fs, size); 640 1.33 fvdl else 641 1.33 fvdl nsize = fs->fs_bsize; 642 1.46 ad mutex_enter(&ump->um_lock); 643 1.33 fvdl error = ffs_alloc(ip, lbn, 644 1.51 simonb ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags, 645 1.51 simonb &dp->di_extb[0]), 646 1.51 simonb nsize, flags, cred, &newb); 647 1.33 fvdl if (error) 648 1.33 fvdl return (error); 649 1.58 dholland error = ffs_getblk(vp, -1 - lbn, FFS_FSBTODB(fs, newb), 650 1.62 jdolecek nsize, (flags & B_CLRBUF) != 0, &bp); 651 1.50 hannken if (error) 652 1.50 hannken return error; 653 1.33 fvdl } 654 1.58 dholland dp->di_extb[lbn] = FFS_DBTOFSB(fs, bp->b_blkno); 655 1.33 fvdl ip->i_flag |= IN_CHANGE | IN_UPDATE; 656 1.33 fvdl *bpp = bp; 657 1.33 fvdl return (0); 658 1.33 fvdl } 659 1.33 fvdl /* 660 1.33 fvdl * If the next write will extend the file into a new block, 661 1.33 fvdl * and the file is currently composed of a fragment 662 1.33 fvdl * this fragment has to be extended to be a full block. 663 1.33 fvdl */ 664 1.33 fvdl 665 1.59 dholland lastlbn = ffs_lblkno(fs, ip->i_size); 666 1.56 dholland if (lastlbn < UFS_NDADDR && lastlbn < lbn) { 667 1.33 fvdl nb = lastlbn; 668 1.57 dholland osize = ffs_blksize(fs, ip, nb); 669 1.33 fvdl if (osize < fs->fs_bsize && osize > 0) { 670 1.46 ad mutex_enter(&ump->um_lock); 671 1.64 christos error = ffs_realloccg(ip, nb, ffs_getdb(fs, ip, lbn), 672 1.51 simonb ffs_blkpref_ufs2(ip, lastlbn, nb, flags, 673 1.33 fvdl &ip->i_ffs2_db[0]), 674 1.64 christos osize, (int)fs->fs_bsize, flags, cred, bpp, 675 1.64 christos &newb); 676 1.33 fvdl if (error) 677 1.33 fvdl return (error); 678 1.59 dholland ip->i_size = ffs_lblktosize(fs, nb + 1); 679 1.33 fvdl ip->i_ffs2_size = ip->i_size; 680 1.33 fvdl uvm_vnp_setsize(vp, ip->i_size); 681 1.33 fvdl ip->i_ffs2_db[nb] = ufs_rw64(newb, needswap); 682 1.33 fvdl ip->i_flag |= IN_CHANGE | IN_UPDATE; 683 1.33 fvdl if (bpp) { 684 1.33 fvdl if (flags & B_SYNC) 685 1.33 fvdl bwrite(*bpp); 686 1.33 fvdl else 687 1.33 fvdl bawrite(*bpp); 688 1.33 fvdl } 689 1.33 fvdl } 690 1.33 fvdl } 691 1.33 fvdl 692 1.33 fvdl /* 693 1.56 dholland * The first UFS_NDADDR blocks are direct blocks 694 1.33 fvdl */ 695 1.33 fvdl 696 1.56 dholland if (lbn < UFS_NDADDR) { 697 1.33 fvdl nb = ufs_rw64(ip->i_ffs2_db[lbn], needswap); 698 1.59 dholland if (nb != 0 && ip->i_size >= ffs_lblktosize(fs, lbn + 1)) { 699 1.33 fvdl 700 1.33 fvdl /* 701 1.33 fvdl * The block is an already-allocated direct block 702 1.33 fvdl * and the file already extends past this block, 703 1.33 fvdl * thus this must be a whole block. 704 1.33 fvdl * Just read the block (if requested). 705 1.33 fvdl */ 706 1.33 fvdl 707 1.33 fvdl if (bpp != NULL) { 708 1.61 maxv error = bread(vp, lbn, fs->fs_bsize, 709 1.49 hannken B_MODIFY, bpp); 710 1.33 fvdl if (error) { 711 1.33 fvdl return (error); 712 1.33 fvdl } 713 1.33 fvdl } 714 1.33 fvdl return (0); 715 1.33 fvdl } 716 1.33 fvdl if (nb != 0) { 717 1.33 fvdl 718 1.33 fvdl /* 719 1.33 fvdl * Consider need to reallocate a fragment. 720 1.33 fvdl */ 721 1.33 fvdl 722 1.59 dholland osize = ffs_fragroundup(fs, ffs_blkoff(fs, ip->i_size)); 723 1.59 dholland nsize = ffs_fragroundup(fs, size); 724 1.33 fvdl if (nsize <= osize) { 725 1.33 fvdl 726 1.33 fvdl /* 727 1.33 fvdl * The existing block is already 728 1.33 fvdl * at least as big as we want. 729 1.33 fvdl * Just read the block (if requested). 730 1.33 fvdl */ 731 1.33 fvdl 732 1.33 fvdl if (bpp != NULL) { 733 1.61 maxv error = bread(vp, lbn, osize, 734 1.49 hannken B_MODIFY, bpp); 735 1.33 fvdl if (error) { 736 1.33 fvdl return (error); 737 1.33 fvdl } 738 1.33 fvdl } 739 1.33 fvdl return 0; 740 1.33 fvdl } else { 741 1.33 fvdl 742 1.33 fvdl /* 743 1.33 fvdl * The existing block is smaller than we want, 744 1.33 fvdl * grow it. 745 1.33 fvdl */ 746 1.46 ad mutex_enter(&ump->um_lock); 747 1.33 fvdl error = ffs_realloccg(ip, lbn, 748 1.64 christos ffs_getdb(fs, ip, lbn), 749 1.51 simonb ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags, 750 1.51 simonb &ip->i_ffs2_db[0]), 751 1.64 christos osize, nsize, flags, cred, bpp, &newb); 752 1.33 fvdl if (error) 753 1.33 fvdl return (error); 754 1.33 fvdl } 755 1.33 fvdl } else { 756 1.33 fvdl 757 1.33 fvdl /* 758 1.33 fvdl * the block was not previously allocated, 759 1.33 fvdl * allocate a new block or fragment. 760 1.33 fvdl */ 761 1.33 fvdl 762 1.59 dholland if (ip->i_size < ffs_lblktosize(fs, lbn + 1)) 763 1.59 dholland nsize = ffs_fragroundup(fs, size); 764 1.33 fvdl else 765 1.33 fvdl nsize = fs->fs_bsize; 766 1.46 ad mutex_enter(&ump->um_lock); 767 1.33 fvdl error = ffs_alloc(ip, lbn, 768 1.51 simonb ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags, 769 1.51 simonb &ip->i_ffs2_db[0]), 770 1.51 simonb nsize, flags, cred, &newb); 771 1.33 fvdl if (error) 772 1.33 fvdl return (error); 773 1.33 fvdl if (bpp != NULL) { 774 1.58 dholland error = ffs_getblk(vp, lbn, FFS_FSBTODB(fs, newb), 775 1.49 hannken nsize, (flags & B_CLRBUF) != 0, bpp); 776 1.49 hannken if (error) 777 1.49 hannken return error; 778 1.33 fvdl } 779 1.33 fvdl } 780 1.33 fvdl ip->i_ffs2_db[lbn] = ufs_rw64(newb, needswap); 781 1.33 fvdl ip->i_flag |= IN_CHANGE | IN_UPDATE; 782 1.33 fvdl return (0); 783 1.33 fvdl } 784 1.33 fvdl 785 1.33 fvdl /* 786 1.33 fvdl * Determine the number of levels of indirection. 787 1.33 fvdl */ 788 1.33 fvdl 789 1.33 fvdl pref = 0; 790 1.33 fvdl if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0) 791 1.33 fvdl return (error); 792 1.33 fvdl 793 1.33 fvdl /* 794 1.33 fvdl * Fetch the first indirect block allocating if necessary. 795 1.33 fvdl */ 796 1.33 fvdl 797 1.33 fvdl --num; 798 1.33 fvdl nb = ufs_rw64(ip->i_ffs2_ib[indirs[0].in_off], needswap); 799 1.33 fvdl allocib = NULL; 800 1.33 fvdl allocblk = allociblk; 801 1.33 fvdl if (nb == 0) { 802 1.46 ad mutex_enter(&ump->um_lock); 803 1.51 simonb pref = ffs_blkpref_ufs2(ip, lbn, 0, flags | B_METAONLY, NULL); 804 1.51 simonb error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, 805 1.51 simonb flags | B_METAONLY, cred, &newb); 806 1.33 fvdl if (error) 807 1.33 fvdl goto fail; 808 1.33 fvdl nb = newb; 809 1.33 fvdl *allocblk++ = nb; 810 1.58 dholland error = ffs_getblk(vp, indirs[1].in_lbn, FFS_FSBTODB(fs, nb), 811 1.49 hannken fs->fs_bsize, true, &bp); 812 1.49 hannken if (error) 813 1.49 hannken goto fail; 814 1.52 ad /* 815 1.52 ad * Write synchronously so that indirect blocks 816 1.52 ad * never point at garbage. 817 1.52 ad */ 818 1.52 ad if ((error = bwrite(bp)) != 0) 819 1.52 ad goto fail; 820 1.33 fvdl unwindidx = 0; 821 1.33 fvdl allocib = &ip->i_ffs2_ib[indirs[0].in_off]; 822 1.33 fvdl *allocib = ufs_rw64(nb, needswap); 823 1.33 fvdl ip->i_flag |= IN_CHANGE | IN_UPDATE; 824 1.33 fvdl } 825 1.33 fvdl 826 1.33 fvdl /* 827 1.33 fvdl * Fetch through the indirect blocks, allocating as necessary. 828 1.33 fvdl */ 829 1.33 fvdl 830 1.33 fvdl for (i = 1;;) { 831 1.33 fvdl error = bread(vp, 832 1.61 maxv indirs[i].in_lbn, (int)fs->fs_bsize, 0, &bp); 833 1.33 fvdl if (error) { 834 1.33 fvdl goto fail; 835 1.33 fvdl } 836 1.33 fvdl bap = (int64_t *)bp->b_data; 837 1.33 fvdl nb = ufs_rw64(bap[indirs[i].in_off], needswap); 838 1.33 fvdl if (i == num) 839 1.33 fvdl break; 840 1.33 fvdl i++; 841 1.33 fvdl if (nb != 0) { 842 1.46 ad brelse(bp, 0); 843 1.33 fvdl continue; 844 1.33 fvdl } 845 1.49 hannken if (fscow_run(bp, true) != 0) { 846 1.49 hannken brelse(bp, 0); 847 1.49 hannken goto fail; 848 1.49 hannken } 849 1.46 ad mutex_enter(&ump->um_lock); 850 1.54 hannken /* Try to keep snapshot indirect blocks contiguous. */ 851 1.54 hannken if (i == num && (ip->i_flags & SF_SNAPSHOT) != 0) 852 1.54 hannken pref = ffs_blkpref_ufs2(ip, lbn, indirs[i-1].in_off, 853 1.54 hannken flags | B_METAONLY, &bap[0]); 854 1.33 fvdl if (pref == 0) 855 1.51 simonb pref = ffs_blkpref_ufs2(ip, lbn, 0, flags | B_METAONLY, 856 1.51 simonb NULL); 857 1.51 simonb error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, 858 1.51 simonb flags | B_METAONLY, cred, &newb); 859 1.33 fvdl if (error) { 860 1.46 ad brelse(bp, 0); 861 1.33 fvdl goto fail; 862 1.33 fvdl } 863 1.33 fvdl nb = newb; 864 1.33 fvdl *allocblk++ = nb; 865 1.58 dholland error = ffs_getblk(vp, indirs[i].in_lbn, FFS_FSBTODB(fs, nb), 866 1.49 hannken fs->fs_bsize, true, &nbp); 867 1.49 hannken if (error) { 868 1.49 hannken brelse(bp, 0); 869 1.49 hannken goto fail; 870 1.49 hannken } 871 1.52 ad /* 872 1.52 ad * Write synchronously so that indirect blocks 873 1.52 ad * never point at garbage. 874 1.52 ad */ 875 1.52 ad if ((error = bwrite(nbp)) != 0) { 876 1.52 ad brelse(bp, 0); 877 1.52 ad goto fail; 878 1.33 fvdl } 879 1.33 fvdl if (unwindidx < 0) 880 1.33 fvdl unwindidx = i - 1; 881 1.33 fvdl bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap); 882 1.33 fvdl 883 1.33 fvdl /* 884 1.33 fvdl * If required, write synchronously, otherwise use 885 1.33 fvdl * delayed write. 886 1.33 fvdl */ 887 1.33 fvdl 888 1.33 fvdl if (flags & B_SYNC) { 889 1.33 fvdl bwrite(bp); 890 1.33 fvdl } else { 891 1.33 fvdl bdwrite(bp); 892 1.33 fvdl } 893 1.33 fvdl } 894 1.33 fvdl 895 1.35 hannken if (flags & B_METAONLY) { 896 1.41 hannken KASSERT(bpp != NULL); 897 1.35 hannken *bpp = bp; 898 1.35 hannken return (0); 899 1.35 hannken } 900 1.35 hannken 901 1.33 fvdl /* 902 1.33 fvdl * Get the data block, allocating if necessary. 903 1.33 fvdl */ 904 1.33 fvdl 905 1.33 fvdl if (nb == 0) { 906 1.49 hannken if (fscow_run(bp, true) != 0) { 907 1.49 hannken brelse(bp, 0); 908 1.49 hannken goto fail; 909 1.49 hannken } 910 1.46 ad mutex_enter(&ump->um_lock); 911 1.51 simonb pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, flags, 912 1.51 simonb &bap[0]); 913 1.51 simonb error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, flags, cred, 914 1.33 fvdl &newb); 915 1.33 fvdl if (error) { 916 1.46 ad brelse(bp, 0); 917 1.33 fvdl goto fail; 918 1.33 fvdl } 919 1.33 fvdl nb = newb; 920 1.33 fvdl *allocblk++ = nb; 921 1.33 fvdl if (bpp != NULL) { 922 1.58 dholland error = ffs_getblk(vp, lbn, FFS_FSBTODB(fs, nb), 923 1.49 hannken fs->fs_bsize, (flags & B_CLRBUF) != 0, bpp); 924 1.49 hannken if (error) { 925 1.49 hannken brelse(bp, 0); 926 1.49 hannken goto fail; 927 1.49 hannken } 928 1.33 fvdl } 929 1.33 fvdl bap[indirs[num].in_off] = ufs_rw64(nb, needswap); 930 1.33 fvdl if (allocib == NULL && unwindidx < 0) { 931 1.33 fvdl unwindidx = i - 1; 932 1.33 fvdl } 933 1.33 fvdl 934 1.33 fvdl /* 935 1.33 fvdl * If required, write synchronously, otherwise use 936 1.33 fvdl * delayed write. 937 1.33 fvdl */ 938 1.33 fvdl 939 1.33 fvdl if (flags & B_SYNC) { 940 1.33 fvdl bwrite(bp); 941 1.33 fvdl } else { 942 1.33 fvdl bdwrite(bp); 943 1.33 fvdl } 944 1.33 fvdl return (0); 945 1.33 fvdl } 946 1.46 ad brelse(bp, 0); 947 1.33 fvdl if (bpp != NULL) { 948 1.33 fvdl if (flags & B_CLRBUF) { 949 1.49 hannken error = bread(vp, lbn, (int)fs->fs_bsize, 950 1.61 maxv B_MODIFY, &nbp); 951 1.33 fvdl if (error) { 952 1.33 fvdl goto fail; 953 1.33 fvdl } 954 1.33 fvdl } else { 955 1.58 dholland error = ffs_getblk(vp, lbn, FFS_FSBTODB(fs, nb), 956 1.49 hannken fs->fs_bsize, true, &nbp); 957 1.49 hannken if (error) 958 1.49 hannken goto fail; 959 1.33 fvdl } 960 1.33 fvdl *bpp = nbp; 961 1.33 fvdl } 962 1.33 fvdl return (0); 963 1.33 fvdl 964 1.33 fvdl fail: 965 1.33 fvdl /* 966 1.33 fvdl * If we have failed part way through block allocation, we 967 1.33 fvdl * have to deallocate any indirect blocks that we have allocated. 968 1.33 fvdl */ 969 1.33 fvdl 970 1.33 fvdl if (unwindidx >= 0) { 971 1.33 fvdl 972 1.33 fvdl /* 973 1.33 fvdl * First write out any buffers we've created to resolve their 974 1.33 fvdl * softdeps. This must be done in reverse order of creation 975 1.33 fvdl * so that we resolve the dependencies in one pass. 976 1.33 fvdl * Write the cylinder group buffers for these buffers too. 977 1.33 fvdl */ 978 1.33 fvdl 979 1.33 fvdl for (i = num; i >= unwindidx; i--) { 980 1.33 fvdl if (i == 0) { 981 1.33 fvdl break; 982 1.33 fvdl } 983 1.50 hannken if (ffs_getblk(vp, indirs[i].in_lbn, FFS_NOBLK, 984 1.50 hannken fs->fs_bsize, false, &bp) != 0) 985 1.50 hannken continue; 986 1.48 ad if (bp->b_oflags & BO_DELWRI) { 987 1.58 dholland nb = FFS_FSBTODB(fs, cgtod(fs, dtog(fs, 988 1.58 dholland FFS_DBTOFSB(fs, bp->b_blkno)))); 989 1.33 fvdl bwrite(bp); 990 1.50 hannken if (ffs_getblk(ip->i_devvp, nb, FFS_NOBLK, 991 1.50 hannken fs->fs_cgsize, false, &bp) != 0) 992 1.50 hannken continue; 993 1.48 ad if (bp->b_oflags & BO_DELWRI) { 994 1.33 fvdl bwrite(bp); 995 1.33 fvdl } else { 996 1.46 ad brelse(bp, BC_INVAL); 997 1.33 fvdl } 998 1.33 fvdl } else { 999 1.46 ad brelse(bp, BC_INVAL); 1000 1.33 fvdl } 1001 1.33 fvdl } 1002 1.47 ad 1003 1.33 fvdl /* 1004 1.33 fvdl * Now that any dependencies that we created have been 1005 1.33 fvdl * resolved, we can undo the partial allocation. 1006 1.33 fvdl */ 1007 1.33 fvdl 1008 1.33 fvdl if (unwindidx == 0) { 1009 1.33 fvdl *allocib = 0; 1010 1.36 mycroft ip->i_flag |= IN_CHANGE | IN_UPDATE; 1011 1.33 fvdl } else { 1012 1.33 fvdl int r; 1013 1.33 fvdl 1014 1.33 fvdl r = bread(vp, indirs[unwindidx].in_lbn, 1015 1.61 maxv (int)fs->fs_bsize, 0, &bp); 1016 1.33 fvdl if (r) { 1017 1.33 fvdl panic("Could not unwind indirect block, error %d", r); 1018 1.33 fvdl } else { 1019 1.33 fvdl bap = (int64_t *)bp->b_data; 1020 1.33 fvdl bap[indirs[unwindidx].in_off] = 0; 1021 1.33 fvdl bwrite(bp); 1022 1.33 fvdl } 1023 1.33 fvdl } 1024 1.33 fvdl for (i = unwindidx + 1; i <= num; i++) { 1025 1.50 hannken if (ffs_getblk(vp, indirs[i].in_lbn, FFS_NOBLK, 1026 1.50 hannken fs->fs_bsize, false, &bp) == 0) 1027 1.50 hannken brelse(bp, BC_INVAL); 1028 1.33 fvdl } 1029 1.33 fvdl } 1030 1.33 fvdl for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) { 1031 1.35 hannken ffs_blkfree(fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number); 1032 1.33 fvdl deallocated += fs->fs_bsize; 1033 1.33 fvdl } 1034 1.33 fvdl if (deallocated) { 1035 1.53 bouyer #if defined(QUOTA) || defined(QUOTA2) 1036 1.33 fvdl /* 1037 1.33 fvdl * Restore user's disk quota because allocation failed. 1038 1.33 fvdl */ 1039 1.33 fvdl (void)chkdq(ip, -btodb(deallocated), cred, FORCE); 1040 1.8 fvdl #endif 1041 1.33 fvdl ip->i_ffs2_blocks -= btodb(deallocated); 1042 1.13 mycroft ip->i_flag |= IN_CHANGE | IN_UPDATE; 1043 1.8 fvdl } 1044 1.47 ad 1045 1.8 fvdl return (error); 1046 1.1 mycroft } 1047