ffs_balloc.c revision 1.31 1 1.31 fvdl /* $NetBSD: ffs_balloc.c,v 1.31 2003/01/24 21:55:21 fvdl Exp $ */
2 1.2 cgd
3 1.1 mycroft /*
4 1.1 mycroft * Copyright (c) 1982, 1986, 1989, 1993
5 1.1 mycroft * The Regents of the University of California. All rights reserved.
6 1.1 mycroft *
7 1.1 mycroft * Redistribution and use in source and binary forms, with or without
8 1.1 mycroft * modification, are permitted provided that the following conditions
9 1.1 mycroft * are met:
10 1.1 mycroft * 1. Redistributions of source code must retain the above copyright
11 1.1 mycroft * notice, this list of conditions and the following disclaimer.
12 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 mycroft * notice, this list of conditions and the following disclaimer in the
14 1.1 mycroft * documentation and/or other materials provided with the distribution.
15 1.1 mycroft * 3. All advertising materials mentioning features or use of this software
16 1.1 mycroft * must display the following acknowledgement:
17 1.1 mycroft * This product includes software developed by the University of
18 1.1 mycroft * California, Berkeley and its contributors.
19 1.1 mycroft * 4. Neither the name of the University nor the names of its contributors
20 1.1 mycroft * may be used to endorse or promote products derived from this software
21 1.1 mycroft * without specific prior written permission.
22 1.1 mycroft *
23 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.1 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.1 mycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 mycroft * SUCH DAMAGE.
34 1.1 mycroft *
35 1.8 fvdl * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
36 1.1 mycroft */
37 1.28 lukem
38 1.28 lukem #include <sys/cdefs.h>
39 1.31 fvdl __KERNEL_RCSID(0, "$NetBSD: ffs_balloc.c,v 1.31 2003/01/24 21:55:21 fvdl Exp $");
40 1.7 mrg
41 1.24 mrg #if defined(_KERNEL_OPT)
42 1.10 scottr #include "opt_quota.h"
43 1.11 scottr #endif
44 1.1 mycroft
45 1.1 mycroft #include <sys/param.h>
46 1.1 mycroft #include <sys/systm.h>
47 1.1 mycroft #include <sys/buf.h>
48 1.1 mycroft #include <sys/file.h>
49 1.15 fvdl #include <sys/mount.h>
50 1.1 mycroft #include <sys/vnode.h>
51 1.9 bouyer #include <sys/mount.h>
52 1.6 mrg
53 1.1 mycroft #include <ufs/ufs/quota.h>
54 1.9 bouyer #include <ufs/ufs/ufsmount.h>
55 1.1 mycroft #include <ufs/ufs/inode.h>
56 1.1 mycroft #include <ufs/ufs/ufs_extern.h>
57 1.9 bouyer #include <ufs/ufs/ufs_bswap.h>
58 1.1 mycroft
59 1.1 mycroft #include <ufs/ffs/fs.h>
60 1.1 mycroft #include <ufs/ffs/ffs_extern.h>
61 1.1 mycroft
62 1.23 chs #include <uvm/uvm.h>
63 1.23 chs
64 1.1 mycroft /*
65 1.1 mycroft * Balloc defines the structure of file system storage
66 1.1 mycroft * by allocating the physical blocks on a device given
67 1.1 mycroft * the inode and the logical block number in a file.
68 1.1 mycroft */
69 1.3 christos int
70 1.15 fvdl ffs_balloc(v)
71 1.15 fvdl void *v;
72 1.15 fvdl {
73 1.15 fvdl struct vop_balloc_args /* {
74 1.15 fvdl struct vnode *a_vp;
75 1.25 lukem off_t a_startoffset;
76 1.15 fvdl int a_size;
77 1.15 fvdl struct ucred *a_cred;
78 1.15 fvdl int a_flags;
79 1.23 chs struct buf **a_bpp;
80 1.15 fvdl } */ *ap = v;
81 1.31 fvdl daddr_t lbn;
82 1.1 mycroft int size;
83 1.1 mycroft struct ucred *cred;
84 1.1 mycroft int flags;
85 1.31 fvdl daddr_t nb;
86 1.1 mycroft struct buf *bp, *nbp;
87 1.15 fvdl struct vnode *vp = ap->a_vp;
88 1.15 fvdl struct inode *ip = VTOI(vp);
89 1.15 fvdl struct fs *fs = ip->i_fs;
90 1.1 mycroft struct indir indirs[NIADDR + 2];
91 1.31 fvdl daddr_t newb, pref;
92 1.31 fvdl int32_t *bap; /* XXX ondisk32 */
93 1.8 fvdl int deallocated, osize, nsize, num, i, error;
94 1.31 fvdl daddr_t *blkp, *allocblk, allociblk[NIADDR + 1];
95 1.31 fvdl int32_t *allocib; /* XXX ondisk32 */
96 1.17 fvdl int unwindidx = -1;
97 1.23 chs struct buf **bpp = ap->a_bpp;
98 1.15 fvdl #ifdef FFS_EI
99 1.15 fvdl const int needswap = UFS_FSNEEDSWAP(fs);
100 1.15 fvdl #endif
101 1.23 chs UVMHIST_FUNC("ffs_balloc"); UVMHIST_CALLED(ubchist);
102 1.1 mycroft
103 1.15 fvdl lbn = lblkno(fs, ap->a_startoffset);
104 1.15 fvdl size = blkoff(fs, ap->a_startoffset) + ap->a_size;
105 1.15 fvdl if (size > fs->fs_bsize)
106 1.15 fvdl panic("ffs_balloc: blk too big");
107 1.23 chs if (bpp != NULL) {
108 1.23 chs *bpp = NULL;
109 1.23 chs }
110 1.23 chs UVMHIST_LOG(ubchist, "vp %p lbn 0x%x size 0x%x", vp, lbn, size,0);
111 1.23 chs
112 1.23 chs KASSERT(size <= fs->fs_bsize);
113 1.8 fvdl if (lbn < 0)
114 1.1 mycroft return (EFBIG);
115 1.15 fvdl cred = ap->a_cred;
116 1.15 fvdl flags = ap->a_flags;
117 1.1 mycroft
118 1.1 mycroft /*
119 1.1 mycroft * If the next write will extend the file into a new block,
120 1.1 mycroft * and the file is currently composed of a fragment
121 1.1 mycroft * this fragment has to be extended to be a full block.
122 1.1 mycroft */
123 1.23 chs
124 1.4 bouyer nb = lblkno(fs, ip->i_ffs_size);
125 1.8 fvdl if (nb < NDADDR && nb < lbn) {
126 1.1 mycroft osize = blksize(fs, ip, nb);
127 1.1 mycroft if (osize < fs->fs_bsize && osize > 0) {
128 1.1 mycroft error = ffs_realloccg(ip, nb,
129 1.4 bouyer ffs_blkpref(ip, nb, (int)nb, &ip->i_ffs_db[0]),
130 1.23 chs osize, (int)fs->fs_bsize, cred, bpp, &newb);
131 1.1 mycroft if (error)
132 1.1 mycroft return (error);
133 1.15 fvdl if (DOINGSOFTDEP(vp))
134 1.23 chs softdep_setup_allocdirect(ip, nb, newb,
135 1.15 fvdl ufs_rw32(ip->i_ffs_db[nb], needswap),
136 1.23 chs fs->fs_bsize, osize, bpp ? *bpp : NULL);
137 1.23 chs ip->i_ffs_size = lblktosize(fs, nb + 1);
138 1.6 mrg uvm_vnp_setsize(vp, ip->i_ffs_size);
139 1.31 fvdl /* XXX ondisk32 */
140 1.31 fvdl ip->i_ffs_db[nb] = ufs_rw32((int32_t)newb, needswap);
141 1.1 mycroft ip->i_flag |= IN_CHANGE | IN_UPDATE;
142 1.23 chs if (bpp) {
143 1.23 chs if (flags & B_SYNC)
144 1.23 chs bwrite(*bpp);
145 1.23 chs else
146 1.23 chs bawrite(*bpp);
147 1.23 chs }
148 1.1 mycroft }
149 1.1 mycroft }
150 1.23 chs
151 1.1 mycroft /*
152 1.1 mycroft * The first NDADDR blocks are direct blocks
153 1.1 mycroft */
154 1.23 chs
155 1.8 fvdl if (lbn < NDADDR) {
156 1.31 fvdl /* XXX ondisk32 */
157 1.15 fvdl nb = ufs_rw32(ip->i_ffs_db[lbn], needswap);
158 1.23 chs if (nb != 0 && ip->i_ffs_size >= lblktosize(fs, lbn + 1)) {
159 1.23 chs
160 1.23 chs /*
161 1.23 chs * The block is an already-allocated direct block
162 1.23 chs * and the file already extends past this block,
163 1.23 chs * thus this must be a whole block.
164 1.23 chs * Just read the block (if requested).
165 1.23 chs */
166 1.23 chs
167 1.23 chs if (bpp != NULL) {
168 1.23 chs error = bread(vp, lbn, fs->fs_bsize, NOCRED,
169 1.23 chs bpp);
170 1.23 chs if (error) {
171 1.23 chs brelse(*bpp);
172 1.23 chs return (error);
173 1.23 chs }
174 1.1 mycroft }
175 1.1 mycroft return (0);
176 1.1 mycroft }
177 1.1 mycroft if (nb != 0) {
178 1.23 chs
179 1.1 mycroft /*
180 1.1 mycroft * Consider need to reallocate a fragment.
181 1.1 mycroft */
182 1.23 chs
183 1.4 bouyer osize = fragroundup(fs, blkoff(fs, ip->i_ffs_size));
184 1.1 mycroft nsize = fragroundup(fs, size);
185 1.1 mycroft if (nsize <= osize) {
186 1.23 chs
187 1.23 chs /*
188 1.23 chs * The existing block is already
189 1.23 chs * at least as big as we want.
190 1.23 chs * Just read the block (if requested).
191 1.23 chs */
192 1.23 chs
193 1.23 chs if (bpp != NULL) {
194 1.23 chs error = bread(vp, lbn, osize, NOCRED,
195 1.23 chs bpp);
196 1.23 chs if (error) {
197 1.23 chs brelse(*bpp);
198 1.23 chs return (error);
199 1.23 chs }
200 1.1 mycroft }
201 1.23 chs return 0;
202 1.1 mycroft } else {
203 1.23 chs
204 1.23 chs /*
205 1.23 chs * The existing block is smaller than we want,
206 1.23 chs * grow it.
207 1.23 chs */
208 1.23 chs
209 1.8 fvdl error = ffs_realloccg(ip, lbn,
210 1.8 fvdl ffs_blkpref(ip, lbn, (int)lbn,
211 1.8 fvdl &ip->i_ffs_db[0]), osize, nsize, cred,
212 1.23 chs bpp, &newb);
213 1.1 mycroft if (error)
214 1.1 mycroft return (error);
215 1.15 fvdl if (DOINGSOFTDEP(vp))
216 1.15 fvdl softdep_setup_allocdirect(ip, lbn,
217 1.23 chs newb, nb, nsize, osize,
218 1.23 chs bpp ? *bpp : NULL);
219 1.1 mycroft }
220 1.1 mycroft } else {
221 1.23 chs
222 1.23 chs /*
223 1.23 chs * the block was not previously allocated,
224 1.23 chs * allocate a new block or fragment.
225 1.23 chs */
226 1.23 chs
227 1.23 chs if (ip->i_ffs_size < lblktosize(fs, lbn + 1))
228 1.1 mycroft nsize = fragroundup(fs, size);
229 1.1 mycroft else
230 1.1 mycroft nsize = fs->fs_bsize;
231 1.8 fvdl error = ffs_alloc(ip, lbn,
232 1.8 fvdl ffs_blkpref(ip, lbn, (int)lbn, &ip->i_ffs_db[0]),
233 1.8 fvdl nsize, cred, &newb);
234 1.1 mycroft if (error)
235 1.1 mycroft return (error);
236 1.23 chs if (bpp != NULL) {
237 1.23 chs bp = getblk(vp, lbn, nsize, 0, 0);
238 1.23 chs bp->b_blkno = fsbtodb(fs, newb);
239 1.23 chs if (flags & B_CLRBUF)
240 1.23 chs clrbuf(bp);
241 1.23 chs *bpp = bp;
242 1.23 chs }
243 1.23 chs if (DOINGSOFTDEP(vp)) {
244 1.15 fvdl softdep_setup_allocdirect(ip, lbn, newb, 0,
245 1.23 chs nsize, 0, bpp ? *bpp : NULL);
246 1.23 chs }
247 1.1 mycroft }
248 1.31 fvdl /* XXX ondisk32 */
249 1.31 fvdl ip->i_ffs_db[lbn] = ufs_rw32((int32_t)newb, needswap);
250 1.1 mycroft ip->i_flag |= IN_CHANGE | IN_UPDATE;
251 1.1 mycroft return (0);
252 1.1 mycroft }
253 1.29 chs
254 1.1 mycroft /*
255 1.1 mycroft * Determine the number of levels of indirection.
256 1.1 mycroft */
257 1.29 chs
258 1.1 mycroft pref = 0;
259 1.8 fvdl if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0)
260 1.29 chs return (error);
261 1.23 chs
262 1.1 mycroft /*
263 1.1 mycroft * Fetch the first indirect block allocating if necessary.
264 1.1 mycroft */
265 1.29 chs
266 1.1 mycroft --num;
267 1.15 fvdl nb = ufs_rw32(ip->i_ffs_ib[indirs[0].in_off], needswap);
268 1.8 fvdl allocib = NULL;
269 1.8 fvdl allocblk = allociblk;
270 1.1 mycroft if (nb == 0) {
271 1.31 fvdl pref = ffs_blkpref(ip, lbn, 0, (int32_t *)0);
272 1.18 mycroft error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
273 1.18 mycroft &newb);
274 1.3 christos if (error)
275 1.27 chs goto fail;
276 1.1 mycroft nb = newb;
277 1.8 fvdl *allocblk++ = nb;
278 1.1 mycroft bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
279 1.8 fvdl bp->b_blkno = fsbtodb(fs, nb);
280 1.1 mycroft clrbuf(bp);
281 1.15 fvdl if (DOINGSOFTDEP(vp)) {
282 1.15 fvdl softdep_setup_allocdirect(ip, NDADDR + indirs[0].in_off,
283 1.15 fvdl newb, 0, fs->fs_bsize, 0, bp);
284 1.15 fvdl bdwrite(bp);
285 1.15 fvdl } else {
286 1.29 chs
287 1.15 fvdl /*
288 1.15 fvdl * Write synchronously so that indirect blocks
289 1.15 fvdl * never point at garbage.
290 1.15 fvdl */
291 1.29 chs
292 1.15 fvdl if ((error = bwrite(bp)) != 0)
293 1.15 fvdl goto fail;
294 1.15 fvdl }
295 1.18 mycroft unwindidx = 0;
296 1.8 fvdl allocib = &ip->i_ffs_ib[indirs[0].in_off];
297 1.31 fvdl /* XXX ondisk32 */
298 1.31 fvdl *allocib = ufs_rw32((int32_t)nb, needswap);
299 1.1 mycroft ip->i_flag |= IN_CHANGE | IN_UPDATE;
300 1.1 mycroft }
301 1.29 chs
302 1.1 mycroft /*
303 1.1 mycroft * Fetch through the indirect blocks, allocating as necessary.
304 1.1 mycroft */
305 1.29 chs
306 1.1 mycroft for (i = 1;;) {
307 1.1 mycroft error = bread(vp,
308 1.1 mycroft indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
309 1.1 mycroft if (error) {
310 1.1 mycroft brelse(bp);
311 1.8 fvdl goto fail;
312 1.1 mycroft }
313 1.31 fvdl bap = (int32_t *)bp->b_data; /* XXX ondisk32 */
314 1.15 fvdl nb = ufs_rw32(bap[indirs[i].in_off], needswap);
315 1.1 mycroft if (i == num)
316 1.1 mycroft break;
317 1.18 mycroft i++;
318 1.1 mycroft if (nb != 0) {
319 1.1 mycroft brelse(bp);
320 1.1 mycroft continue;
321 1.1 mycroft }
322 1.1 mycroft if (pref == 0)
323 1.31 fvdl pref = ffs_blkpref(ip, lbn, 0, (int32_t *)0);
324 1.3 christos error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
325 1.18 mycroft &newb);
326 1.3 christos if (error) {
327 1.1 mycroft brelse(bp);
328 1.8 fvdl goto fail;
329 1.1 mycroft }
330 1.1 mycroft nb = newb;
331 1.8 fvdl *allocblk++ = nb;
332 1.1 mycroft nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
333 1.1 mycroft nbp->b_blkno = fsbtodb(fs, nb);
334 1.1 mycroft clrbuf(nbp);
335 1.15 fvdl if (DOINGSOFTDEP(vp)) {
336 1.15 fvdl softdep_setup_allocindir_meta(nbp, ip, bp,
337 1.15 fvdl indirs[i - 1].in_off, nb);
338 1.15 fvdl bdwrite(nbp);
339 1.15 fvdl } else {
340 1.29 chs
341 1.15 fvdl /*
342 1.15 fvdl * Write synchronously so that indirect blocks
343 1.15 fvdl * never point at garbage.
344 1.15 fvdl */
345 1.29 chs
346 1.15 fvdl if ((error = bwrite(nbp)) != 0) {
347 1.15 fvdl brelse(bp);
348 1.15 fvdl goto fail;
349 1.15 fvdl }
350 1.1 mycroft }
351 1.18 mycroft if (unwindidx < 0)
352 1.18 mycroft unwindidx = i - 1;
353 1.31 fvdl /* XXX ondisk32 */
354 1.31 fvdl bap[indirs[i - 1].in_off] = ufs_rw32((int32_t)nb, needswap);
355 1.29 chs
356 1.1 mycroft /*
357 1.1 mycroft * If required, write synchronously, otherwise use
358 1.1 mycroft * delayed write.
359 1.1 mycroft */
360 1.29 chs
361 1.1 mycroft if (flags & B_SYNC) {
362 1.1 mycroft bwrite(bp);
363 1.1 mycroft } else {
364 1.1 mycroft bdwrite(bp);
365 1.1 mycroft }
366 1.1 mycroft }
367 1.29 chs
368 1.1 mycroft /*
369 1.1 mycroft * Get the data block, allocating if necessary.
370 1.1 mycroft */
371 1.29 chs
372 1.1 mycroft if (nb == 0) {
373 1.19 mycroft pref = ffs_blkpref(ip, lbn, indirs[num].in_off, &bap[0]);
374 1.3 christos error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
375 1.18 mycroft &newb);
376 1.3 christos if (error) {
377 1.1 mycroft brelse(bp);
378 1.8 fvdl goto fail;
379 1.1 mycroft }
380 1.1 mycroft nb = newb;
381 1.8 fvdl *allocblk++ = nb;
382 1.23 chs if (bpp != NULL) {
383 1.23 chs nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
384 1.23 chs nbp->b_blkno = fsbtodb(fs, nb);
385 1.23 chs if (flags & B_CLRBUF)
386 1.23 chs clrbuf(nbp);
387 1.23 chs *bpp = nbp;
388 1.23 chs }
389 1.15 fvdl if (DOINGSOFTDEP(vp))
390 1.15 fvdl softdep_setup_allocindir_page(ip, lbn, bp,
391 1.23 chs indirs[num].in_off, nb, 0, bpp ? *bpp : NULL);
392 1.31 fvdl /* XXX ondisk32 */
393 1.31 fvdl bap[indirs[num].in_off] = ufs_rw32((int32_t)nb, needswap);
394 1.23 chs if (allocib == NULL && unwindidx < 0) {
395 1.23 chs unwindidx = i - 1;
396 1.23 chs }
397 1.29 chs
398 1.1 mycroft /*
399 1.1 mycroft * If required, write synchronously, otherwise use
400 1.1 mycroft * delayed write.
401 1.1 mycroft */
402 1.29 chs
403 1.1 mycroft if (flags & B_SYNC) {
404 1.1 mycroft bwrite(bp);
405 1.1 mycroft } else {
406 1.1 mycroft bdwrite(bp);
407 1.1 mycroft }
408 1.1 mycroft return (0);
409 1.1 mycroft }
410 1.1 mycroft brelse(bp);
411 1.23 chs if (bpp != NULL) {
412 1.23 chs if (flags & B_CLRBUF) {
413 1.23 chs error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
414 1.23 chs if (error) {
415 1.23 chs brelse(nbp);
416 1.23 chs goto fail;
417 1.23 chs }
418 1.23 chs } else {
419 1.23 chs nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
420 1.23 chs nbp->b_blkno = fsbtodb(fs, nb);
421 1.23 chs clrbuf(nbp);
422 1.1 mycroft }
423 1.23 chs *bpp = nbp;
424 1.1 mycroft }
425 1.1 mycroft return (0);
426 1.27 chs
427 1.8 fvdl fail:
428 1.27 chs /*
429 1.29 chs * If we have failed part way through block allocation, we
430 1.29 chs * have to deallocate any indirect blocks that we have allocated.
431 1.27 chs */
432 1.27 chs
433 1.29 chs if (unwindidx >= 0) {
434 1.27 chs
435 1.29 chs /*
436 1.29 chs * First write out any buffers we've created to resolve their
437 1.29 chs * softdeps. This must be done in reverse order of creation
438 1.29 chs * so that we resolve the dependencies in one pass.
439 1.29 chs * Write the cylinder group buffers for these buffers too.
440 1.29 chs */
441 1.29 chs
442 1.29 chs for (i = num; i >= unwindidx; i--) {
443 1.29 chs if (i == 0) {
444 1.29 chs break;
445 1.29 chs }
446 1.29 chs bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0,
447 1.29 chs 0);
448 1.29 chs if (bp->b_flags & B_DELWRI) {
449 1.29 chs nb = fsbtodb(fs, cgtod(fs, dtog(fs,
450 1.30 chs dbtofsb(fs, bp->b_blkno))));
451 1.29 chs bwrite(bp);
452 1.29 chs bp = getblk(ip->i_devvp, nb, (int)fs->fs_cgsize,
453 1.29 chs 0, 0);
454 1.29 chs if (bp->b_flags & B_DELWRI) {
455 1.29 chs bwrite(bp);
456 1.29 chs } else {
457 1.29 chs bp->b_flags |= B_INVAL;
458 1.29 chs brelse(bp);
459 1.29 chs }
460 1.29 chs } else {
461 1.29 chs bp->b_flags |= B_INVAL;
462 1.29 chs brelse(bp);
463 1.29 chs }
464 1.29 chs }
465 1.29 chs if (unwindidx == 0) {
466 1.29 chs ip->i_flag |= IN_MODIFIED | IN_CHANGE | IN_UPDATE;
467 1.29 chs VOP_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
468 1.27 chs }
469 1.27 chs
470 1.29 chs /*
471 1.29 chs * Now that any dependencies that we created have been
472 1.29 chs * resolved, we can undo the partial allocation.
473 1.29 chs */
474 1.27 chs
475 1.18 mycroft if (unwindidx == 0) {
476 1.18 mycroft *allocib = 0;
477 1.29 chs ip->i_flag |= IN_MODIFIED | IN_CHANGE | IN_UPDATE;
478 1.29 chs VOP_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
479 1.17 fvdl } else {
480 1.18 mycroft int r;
481 1.29 chs
482 1.29 chs r = bread(vp, indirs[unwindidx].in_lbn,
483 1.18 mycroft (int)fs->fs_bsize, NOCRED, &bp);
484 1.18 mycroft if (r) {
485 1.18 mycroft panic("Could not unwind indirect block, error %d", r);
486 1.18 mycroft brelse(bp);
487 1.18 mycroft } else {
488 1.31 fvdl bap = (int32_t *)bp->b_data; /* XXX ondisk32 */
489 1.18 mycroft bap[indirs[unwindidx].in_off] = 0;
490 1.29 chs bwrite(bp);
491 1.18 mycroft }
492 1.17 fvdl }
493 1.19 mycroft for (i = unwindidx + 1; i <= num; i++) {
494 1.19 mycroft bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0,
495 1.19 mycroft 0);
496 1.19 mycroft bp->b_flags |= B_INVAL;
497 1.19 mycroft brelse(bp);
498 1.19 mycroft }
499 1.17 fvdl }
500 1.29 chs for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
501 1.29 chs ffs_blkfree(ip, *blkp, fs->fs_bsize);
502 1.29 chs deallocated += fs->fs_bsize;
503 1.29 chs }
504 1.8 fvdl if (deallocated) {
505 1.8 fvdl #ifdef QUOTA
506 1.8 fvdl /*
507 1.8 fvdl * Restore user's disk quota because allocation failed.
508 1.8 fvdl */
509 1.8 fvdl (void)chkdq(ip, (long)-btodb(deallocated), cred, FORCE);
510 1.8 fvdl #endif
511 1.8 fvdl ip->i_ffs_blocks -= btodb(deallocated);
512 1.13 mycroft ip->i_flag |= IN_CHANGE | IN_UPDATE;
513 1.8 fvdl }
514 1.8 fvdl return (error);
515 1.23 chs }
516 1.23 chs
517 1.23 chs
518 1.23 chs int
519 1.26 chs ffs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
520 1.26 chs struct ucred *cred)
521 1.23 chs {
522 1.23 chs struct inode *ip = VTOI(vp);
523 1.23 chs struct fs *fs = ip->i_fs;
524 1.23 chs int error, delta, bshift, bsize;
525 1.26 chs UVMHIST_FUNC("ffs_gop_alloc"); UVMHIST_CALLED(ubchist);
526 1.23 chs
527 1.23 chs error = 0;
528 1.23 chs bshift = fs->fs_bshift;
529 1.23 chs bsize = 1 << bshift;
530 1.23 chs
531 1.23 chs delta = off & (bsize - 1);
532 1.23 chs off -= delta;
533 1.23 chs len += delta;
534 1.23 chs
535 1.23 chs while (len > 0) {
536 1.26 chs bsize = MIN(bsize, len);
537 1.23 chs
538 1.26 chs error = VOP_BALLOC(vp, off, bsize, cred, flags, NULL);
539 1.23 chs if (error) {
540 1.23 chs goto out;
541 1.23 chs }
542 1.23 chs
543 1.23 chs /*
544 1.23 chs * increase file size now, VOP_BALLOC() requires that
545 1.23 chs * EOF be up-to-date before each call.
546 1.23 chs */
547 1.23 chs
548 1.23 chs if (ip->i_ffs_size < off + bsize) {
549 1.26 chs UVMHIST_LOG(ubchist, "vp %p old 0x%x new 0x%x",
550 1.26 chs vp, ip->i_ffs_size, off + bsize, 0);
551 1.23 chs ip->i_ffs_size = off + bsize;
552 1.23 chs }
553 1.23 chs
554 1.23 chs off += bsize;
555 1.23 chs len -= bsize;
556 1.23 chs }
557 1.23 chs
558 1.23 chs out:
559 1.23 chs return error;
560 1.1 mycroft }
561