Commit | Line | Data |
---|---|---|
984263bc MD |
1 | /* |
2 | * Copyright (c) 1982, 1986, 1989, 1993 | |
3 | * The Regents of the University of California. All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
dc71b7ab | 13 | * 3. Neither the name of the University nor the names of its contributors |
984263bc MD |
14 | * may be used to endorse or promote products derived from this software |
15 | * without specific prior written permission. | |
16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | |
28 | * | |
29 | * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95 | |
30 | * $FreeBSD: src/sys/ufs/ffs/ffs_balloc.c,v 1.26.2.1 2002/10/10 19:48:20 dillon Exp $ | |
31 | */ | |
32 | ||
61cb3b4b SW |
33 | #include "opt_quota.h" |
34 | ||
984263bc MD |
35 | #include <sys/param.h> |
36 | #include <sys/systm.h> | |
3020e3be | 37 | #include <sys/proc.h> |
984263bc MD |
38 | #include <sys/buf.h> |
39 | #include <sys/lock.h> | |
40 | #include <sys/mount.h> | |
41 | #include <sys/vnode.h> | |
42 | ||
54341a3b MD |
43 | #include <sys/buf2.h> |
44 | ||
1f2de5d4 MD |
45 | #include "quota.h" |
46 | #include "inode.h" | |
47 | #include "ufs_extern.h" | |
984263bc | 48 | |
1f2de5d4 MD |
49 | #include "fs.h" |
50 | #include "ffs_extern.h" | |
984263bc MD |
51 | |
52 | /* | |
0973c589 CP |
53 | * ffs_balloc(struct vnode *a_vp, ufs_daddr_t a_lbn, int a_size, |
54 | * struct ucred *a_cred, int a_flags, struct buf *a_bpp) | |
1c9602b3 MD |
55 | * |
56 | * Balloc defines the structure of filesystem storage by allocating | |
57 | * the physical blocks on a device given the inode and the logical | |
58 | * block number in a file. | |
59 | * | |
60 | * NOTE: B_CLRBUF - this flag tells balloc to clear invalid portions | |
61 | * of the buffer. However, any dirty bits will override missing | |
62 | * valid bits. This case occurs when writable mmaps are truncated | |
63 | * and then extended. | |
984263bc MD |
64 | */ |
65 | int | |
0973c589 | 66 | ffs_balloc(struct vop_balloc_args *ap) |
984263bc MD |
67 | { |
68 | struct inode *ip; | |
69 | ufs_daddr_t lbn; | |
70 | int size; | |
71 | struct ucred *cred; | |
72 | int flags; | |
73 | struct fs *fs; | |
74 | ufs_daddr_t nb; | |
481df61e | 75 | struct buf *bp, *nbp, *dbp; |
984263bc | 76 | struct vnode *vp; |
c309c6d4 | 77 | struct indir indirs[UFS_NIADDR + 2]; |
984263bc MD |
78 | ufs_daddr_t newb, *bap, pref; |
79 | int deallocated, osize, nsize, num, i, error; | |
c309c6d4 SW |
80 | ufs_daddr_t *allocib, *blkp, *allocblk, allociblk[UFS_NIADDR + 1]; |
81 | ufs_daddr_t *lbns_remfree, lbns[UFS_NIADDR + 1]; | |
481df61e MD |
82 | int unwindidx; |
83 | int seqcount; | |
984263bc MD |
84 | |
85 | vp = ap->a_vp; | |
86 | ip = VTOI(vp); | |
87 | fs = ip->i_fs; | |
88 | lbn = lblkno(fs, ap->a_startoffset); | |
89 | size = blkoff(fs, ap->a_startoffset) + ap->a_size; | |
90 | if (size > fs->fs_bsize) | |
91 | panic("ffs_balloc: blk too big"); | |
92 | *ap->a_bpp = NULL; | |
93 | if (lbn < 0) | |
94 | return (EFBIG); | |
95 | cred = ap->a_cred; | |
96 | flags = ap->a_flags; | |
97 | ||
4edc08c9 MD |
98 | /* |
99 | * The vnode must be locked for us to be able to safely mess | |
100 | * around with the inode. | |
101 | */ | |
a11aaa81 | 102 | if (vn_islocked(vp) != LK_EXCLUSIVE) { |
4edc08c9 MD |
103 | panic("ffs_balloc: vnode %p not exclusively locked!", vp); |
104 | } | |
105 | ||
984263bc MD |
106 | /* |
107 | * If the next write will extend the file into a new block, | |
108 | * and the file is currently composed of a fragment | |
109 | * this fragment has to be extended to be a full block. | |
110 | */ | |
111 | nb = lblkno(fs, ip->i_size); | |
c309c6d4 | 112 | if (nb < UFS_NDADDR && nb < lbn) { |
0f1737b3 DR |
113 | /* |
114 | * The filesize prior to this write can fit in direct | |
6d435183 | 115 | * blocks (ex. fragmentation is possibly done) |
0f1737b3 DR |
116 | * we are now extending the file write beyond |
117 | * the block which has end of the file prior to this write. | |
2dac3b8e | 118 | */ |
984263bc | 119 | osize = blksize(fs, ip, nb); |
0f1737b3 DR |
120 | /* |
121 | * osize gives disk allocated size in the last block. It is | |
122 | * either in fragments or a file system block size. | |
123 | */ | |
984263bc | 124 | if (osize < fs->fs_bsize && osize > 0) { |
0f1737b3 DR |
125 | /* A few fragments are already allocated, since the |
126 | * current extends beyond this block allocated the | |
127 | * complete block as fragments are on in last block. | |
128 | */ | |
984263bc MD |
129 | error = ffs_realloccg(ip, nb, |
130 | ffs_blkpref(ip, nb, (int)nb, &ip->i_db[0]), | |
131 | osize, (int)fs->fs_bsize, cred, &bp); | |
132 | if (error) | |
133 | return (error); | |
134 | if (DOINGSOFTDEP(vp)) | |
135 | softdep_setup_allocdirect(ip, nb, | |
54078292 | 136 | dofftofsb(fs, bp->b_bio2.bio_offset), |
81b5c339 | 137 | ip->i_db[nb], fs->fs_bsize, osize, bp); |
0f1737b3 | 138 | /* adjust the inode size, we just grew */ |
984263bc | 139 | ip->i_size = smalllblktosize(fs, nb + 1); |
54078292 | 140 | ip->i_db[nb] = dofftofsb(fs, bp->b_bio2.bio_offset); |
984263bc MD |
141 | ip->i_flag |= IN_CHANGE | IN_UPDATE; |
142 | if (flags & B_SYNC) | |
143 | bwrite(bp); | |
144 | else | |
145 | bawrite(bp); | |
0f1737b3 | 146 | /* bp is already released here */ |
984263bc MD |
147 | } |
148 | } | |
149 | /* | |
c309c6d4 | 150 | * The first UFS_NDADDR blocks are direct blocks |
984263bc | 151 | */ |
c309c6d4 | 152 | if (lbn < UFS_NDADDR) { |
984263bc MD |
153 | nb = ip->i_db[lbn]; |
154 | if (nb != 0 && ip->i_size >= smalllblktosize(fs, lbn + 1)) { | |
54078292 | 155 | error = bread(vp, lblktodoff(fs, lbn), fs->fs_bsize, &bp); |
984263bc MD |
156 | if (error) { |
157 | brelse(bp); | |
158 | return (error); | |
159 | } | |
54078292 | 160 | bp->b_bio2.bio_offset = fsbtodoff(fs, nb); |
984263bc MD |
161 | *ap->a_bpp = bp; |
162 | return (0); | |
163 | } | |
164 | if (nb != 0) { | |
165 | /* | |
166 | * Consider need to reallocate a fragment. | |
167 | */ | |
168 | osize = fragroundup(fs, blkoff(fs, ip->i_size)); | |
169 | nsize = fragroundup(fs, size); | |
170 | if (nsize <= osize) { | |
54078292 MD |
171 | error = bread(vp, lblktodoff(fs, lbn), |
172 | osize, &bp); | |
984263bc MD |
173 | if (error) { |
174 | brelse(bp); | |
175 | return (error); | |
176 | } | |
54078292 | 177 | bp->b_bio2.bio_offset = fsbtodoff(fs, nb); |
984263bc | 178 | } else { |
1c9602b3 MD |
179 | /* |
180 | * NOTE: ffs_realloccg() issues a bread(). | |
181 | */ | |
984263bc MD |
182 | error = ffs_realloccg(ip, lbn, |
183 | ffs_blkpref(ip, lbn, (int)lbn, | |
184 | &ip->i_db[0]), osize, nsize, cred, &bp); | |
185 | if (error) | |
186 | return (error); | |
187 | if (DOINGSOFTDEP(vp)) | |
188 | softdep_setup_allocdirect(ip, lbn, | |
54078292 | 189 | dofftofsb(fs, bp->b_bio2.bio_offset), |
81b5c339 | 190 | nb, nsize, osize, bp); |
984263bc MD |
191 | } |
192 | } else { | |
193 | if (ip->i_size < smalllblktosize(fs, lbn + 1)) | |
194 | nsize = fragroundup(fs, size); | |
195 | else | |
196 | nsize = fs->fs_bsize; | |
197 | error = ffs_alloc(ip, lbn, | |
198 | ffs_blkpref(ip, lbn, (int)lbn, &ip->i_db[0]), | |
199 | nsize, cred, &newb); | |
200 | if (error) | |
201 | return (error); | |
54078292 MD |
202 | bp = getblk(vp, lblktodoff(fs, lbn), nsize, 0, 0); |
203 | bp->b_bio2.bio_offset = fsbtodoff(fs, newb); | |
984263bc MD |
204 | if (flags & B_CLRBUF) |
205 | vfs_bio_clrbuf(bp); | |
206 | if (DOINGSOFTDEP(vp)) | |
207 | softdep_setup_allocdirect(ip, lbn, newb, 0, | |
208 | nsize, 0, bp); | |
209 | } | |
54078292 | 210 | ip->i_db[lbn] = dofftofsb(fs, bp->b_bio2.bio_offset); |
984263bc MD |
211 | ip->i_flag |= IN_CHANGE | IN_UPDATE; |
212 | *ap->a_bpp = bp; | |
213 | return (0); | |
214 | } | |
215 | /* | |
216 | * Determine the number of levels of indirection. | |
217 | */ | |
218 | pref = 0; | |
219 | if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0) | |
220 | return(error); | |
221 | #ifdef DIAGNOSTIC | |
222 | if (num < 1) | |
223 | panic ("ffs_balloc: ufs_bmaparray returned indirect block"); | |
224 | #endif | |
225 | /* | |
481df61e MD |
226 | * Get a handle on the data block buffer before working through |
227 | * indirect blocks to avoid a deadlock between the VM system holding | |
228 | * a locked VM page and issuing a BMAP (which tries to lock the | |
229 | * indirect blocks), and the filesystem holding a locked indirect | |
230 | * block and then trying to read a data block (which tries to lock | |
231 | * the underlying VM pages). | |
232 | */ | |
54078292 | 233 | dbp = getblk(vp, lblktodoff(fs, lbn), fs->fs_bsize, 0, 0); |
481df61e MD |
234 | |
235 | /* | |
236 | * Setup undo history | |
984263bc | 237 | */ |
984263bc MD |
238 | allocib = NULL; |
239 | allocblk = allociblk; | |
ae675022 MD |
240 | lbns_remfree = lbns; |
241 | ||
481df61e MD |
242 | unwindidx = -1; |
243 | ||
244 | /* | |
245 | * Fetch the first indirect block directly from the inode, allocating | |
246 | * one if necessary. | |
247 | */ | |
248 | --num; | |
249 | nb = ip->i_ib[indirs[0].in_off]; | |
984263bc | 250 | if (nb == 0) { |
60233e58 | 251 | pref = ffs_blkpref(ip, lbn, 0, NULL); |
481df61e MD |
252 | /* |
253 | * If the filesystem has run out of space we can skip the | |
254 | * full fsync/undo of the main [fail] case since no undo | |
255 | * history has been built yet. Hence the goto fail2. | |
256 | */ | |
984263bc MD |
257 | if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, |
258 | cred, &newb)) != 0) | |
481df61e | 259 | goto fail2; |
984263bc MD |
260 | nb = newb; |
261 | *allocblk++ = nb; | |
ae675022 | 262 | *lbns_remfree++ = indirs[1].in_lbn; |
54078292 MD |
263 | bp = getblk(vp, lblktodoff(fs, indirs[1].in_lbn), |
264 | fs->fs_bsize, 0, 0); | |
265 | bp->b_bio2.bio_offset = fsbtodoff(fs, nb); | |
984263bc MD |
266 | vfs_bio_clrbuf(bp); |
267 | if (DOINGSOFTDEP(vp)) { | |
c309c6d4 SW |
268 | softdep_setup_allocdirect(ip, |
269 | UFS_NDADDR + indirs[0].in_off, | |
984263bc MD |
270 | newb, 0, fs->fs_bsize, 0, bp); |
271 | bdwrite(bp); | |
272 | } else { | |
273 | /* | |
274 | * Write synchronously so that indirect blocks | |
275 | * never point at garbage. | |
276 | */ | |
277 | if (DOINGASYNC(vp)) | |
278 | bdwrite(bp); | |
279 | else if ((error = bwrite(bp)) != 0) | |
280 | goto fail; | |
281 | } | |
282 | allocib = &ip->i_ib[indirs[0].in_off]; | |
283 | *allocib = nb; | |
284 | ip->i_flag |= IN_CHANGE | IN_UPDATE; | |
285 | } | |
481df61e | 286 | |
984263bc MD |
287 | /* |
288 | * Fetch through the indirect blocks, allocating as necessary. | |
289 | */ | |
290 | for (i = 1;;) { | |
54078292 | 291 | error = bread(vp, lblktodoff(fs, indirs[i].in_lbn), (int)fs->fs_bsize, &bp); |
984263bc MD |
292 | if (error) { |
293 | brelse(bp); | |
294 | goto fail; | |
295 | } | |
296 | bap = (ufs_daddr_t *)bp->b_data; | |
297 | nb = bap[indirs[i].in_off]; | |
298 | if (i == num) | |
299 | break; | |
300 | i += 1; | |
301 | if (nb != 0) { | |
302 | bqrelse(bp); | |
303 | continue; | |
304 | } | |
305 | if (pref == 0) | |
60233e58 | 306 | pref = ffs_blkpref(ip, lbn, 0, NULL); |
984263bc MD |
307 | if ((error = |
308 | ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) != 0) { | |
309 | brelse(bp); | |
310 | goto fail; | |
311 | } | |
312 | nb = newb; | |
313 | *allocblk++ = nb; | |
ae675022 | 314 | *lbns_remfree++ = indirs[i].in_lbn; |
54078292 MD |
315 | nbp = getblk(vp, lblktodoff(fs, indirs[i].in_lbn), |
316 | fs->fs_bsize, 0, 0); | |
317 | nbp->b_bio2.bio_offset = fsbtodoff(fs, nb); | |
984263bc MD |
318 | vfs_bio_clrbuf(nbp); |
319 | if (DOINGSOFTDEP(vp)) { | |
320 | softdep_setup_allocindir_meta(nbp, ip, bp, | |
321 | indirs[i - 1].in_off, nb); | |
322 | bdwrite(nbp); | |
323 | } else { | |
324 | /* | |
325 | * Write synchronously so that indirect blocks | |
326 | * never point at garbage. | |
327 | */ | |
328 | if ((error = bwrite(nbp)) != 0) { | |
329 | brelse(bp); | |
330 | goto fail; | |
331 | } | |
332 | } | |
333 | bap[indirs[i - 1].in_off] = nb; | |
334 | if (allocib == NULL && unwindidx < 0) | |
335 | unwindidx = i - 1; | |
336 | /* | |
337 | * If required, write synchronously, otherwise use | |
338 | * delayed write. | |
339 | */ | |
340 | if (flags & B_SYNC) { | |
341 | bwrite(bp); | |
342 | } else { | |
343 | if (bp->b_bufsize == fs->fs_bsize) | |
344 | bp->b_flags |= B_CLUSTEROK; | |
345 | bdwrite(bp); | |
346 | } | |
347 | } | |
481df61e | 348 | |
984263bc | 349 | /* |
481df61e MD |
350 | * Get the data block, allocating if necessary. We have already |
351 | * called getblk() on the data block buffer, dbp. If we have to | |
352 | * allocate it and B_CLRBUF has been set the inference is an intention | |
353 | * to zero out the related disk blocks, so we do not have to issue | |
354 | * a read. Instead we simply call vfs_bio_clrbuf(). If B_CLRBUF is | |
355 | * not set the caller intends to overwrite the entire contents of the | |
356 | * buffer and we don't waste time trying to clean up the contents. | |
357 | * | |
358 | * bp references the current indirect block. When allocating, | |
359 | * the block must be updated. | |
984263bc MD |
360 | */ |
361 | if (nb == 0) { | |
362 | pref = ffs_blkpref(ip, lbn, indirs[i].in_off, &bap[0]); | |
363 | error = ffs_alloc(ip, | |
364 | lbn, pref, (int)fs->fs_bsize, cred, &newb); | |
365 | if (error) { | |
366 | brelse(bp); | |
367 | goto fail; | |
368 | } | |
369 | nb = newb; | |
370 | *allocblk++ = nb; | |
ae675022 | 371 | *lbns_remfree++ = lbn; |
54078292 | 372 | dbp->b_bio2.bio_offset = fsbtodoff(fs, nb); |
984263bc | 373 | if (flags & B_CLRBUF) |
481df61e | 374 | vfs_bio_clrbuf(dbp); |
984263bc MD |
375 | if (DOINGSOFTDEP(vp)) |
376 | softdep_setup_allocindir_page(ip, lbn, bp, | |
481df61e | 377 | indirs[i].in_off, nb, 0, dbp); |
984263bc MD |
378 | bap[indirs[i].in_off] = nb; |
379 | /* | |
380 | * If required, write synchronously, otherwise use | |
381 | * delayed write. | |
382 | */ | |
383 | if (flags & B_SYNC) { | |
384 | bwrite(bp); | |
385 | } else { | |
386 | if (bp->b_bufsize == fs->fs_bsize) | |
387 | bp->b_flags |= B_CLUSTEROK; | |
388 | bdwrite(bp); | |
389 | } | |
481df61e | 390 | *ap->a_bpp = dbp; |
984263bc MD |
391 | return (0); |
392 | } | |
393 | brelse(bp); | |
481df61e | 394 | |
984263bc | 395 | /* |
481df61e MD |
396 | * At this point all related indirect blocks have been allocated |
397 | * if necessary and released. bp is no longer valid. dbp holds | |
398 | * our getblk()'d data block. | |
399 | * | |
400 | * XXX we previously performed a cluster_read operation here. | |
984263bc MD |
401 | */ |
402 | if (flags & B_CLRBUF) { | |
481df61e MD |
403 | /* |
404 | * If B_CLRBUF is set we must validate the invalid portions | |
405 | * of the buffer. This typically requires a read-before- | |
54078292 | 406 | * write. The strategy call will fill in bio_offset in that |
481df61e MD |
407 | * case. |
408 | * | |
409 | * If we hit this case we do a cluster read if possible | |
410 | * since nearby data blocks are likely to be accessed soon | |
411 | * too. | |
412 | */ | |
413 | if ((dbp->b_flags & B_CACHE) == 0) { | |
414 | bqrelse(dbp); | |
415 | seqcount = (flags & B_SEQMASK) >> B_SEQSHIFT; | |
416 | if (seqcount && | |
417 | (vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { | |
54078292 MD |
418 | error = cluster_read(vp, (off_t)ip->i_size, |
419 | lblktodoff(fs, lbn), | |
481df61e | 420 | (int)fs->fs_bsize, |
364c022c | 421 | fs->fs_bsize, |
dc6a6bd2 | 422 | seqcount * MAXBSIZE, |
364c022c | 423 | &dbp); |
481df61e | 424 | } else { |
364c022c MD |
425 | error = bread(vp, lblktodoff(fs, lbn), |
426 | (int)fs->fs_bsize, &dbp); | |
481df61e MD |
427 | } |
428 | if (error) | |
429 | goto fail; | |
984263bc | 430 | } else { |
54078292 | 431 | dbp->b_bio2.bio_offset = fsbtodoff(fs, nb); |
984263bc MD |
432 | } |
433 | } else { | |
481df61e MD |
434 | /* |
435 | * If B_CLRBUF is not set the caller intends to overwrite | |
436 | * the entire contents of the buffer. We can simply set | |
54078292 | 437 | * bio_offset and we are done. |
481df61e | 438 | */ |
54078292 | 439 | dbp->b_bio2.bio_offset = fsbtodoff(fs, nb); |
984263bc | 440 | } |
481df61e | 441 | *ap->a_bpp = dbp; |
984263bc MD |
442 | return (0); |
443 | fail: | |
444 | /* | |
445 | * If we have failed part way through block allocation, we | |
446 | * have to deallocate any indirect blocks that we have allocated. | |
447 | * We have to fsync the file before we start to get rid of all | |
448 | * of its dependencies so that we do not leave them dangling. | |
449 | * We have to sync it at the end so that the soft updates code | |
450 | * does not find any untracked changes. Although this is really | |
451 | * slow, running out of disk space is not expected to be a common | |
452 | * occurence. The error return from fsync is ignored as we already | |
453 | * have an error to return to the user. | |
454 | */ | |
52174f71 | 455 | VOP_FSYNC(vp, MNT_WAIT, 0); |
ae675022 MD |
456 | for (deallocated = 0, blkp = allociblk, lbns_remfree = lbns; |
457 | blkp < allocblk; blkp++, lbns_remfree++) { | |
458 | /* | |
459 | * We shall not leave the freed blocks on the vnode | |
460 | * buffer object lists. | |
461 | */ | |
ee4e54d2 | 462 | bp = getblk(vp, lblktodoff(fs, *lbns_remfree), fs->fs_bsize, 0, 0); |
ae675022 | 463 | bp->b_flags |= (B_INVAL | B_RELBUF); |
ae675022 | 464 | brelse(bp); |
984263bc MD |
465 | deallocated += fs->fs_bsize; |
466 | } | |
ae675022 | 467 | |
984263bc MD |
468 | if (allocib != NULL) { |
469 | *allocib = 0; | |
470 | } else if (unwindidx >= 0) { | |
471 | int r; | |
472 | ||
54078292 | 473 | r = bread(vp, lblktodoff(fs, indirs[unwindidx].in_lbn), (int)fs->fs_bsize, &bp); |
984263bc MD |
474 | if (r) { |
475 | panic("Could not unwind indirect block, error %d", r); | |
476 | brelse(bp); | |
477 | } else { | |
478 | bap = (ufs_daddr_t *)bp->b_data; | |
479 | bap[indirs[unwindidx].in_off] = 0; | |
480 | if (flags & B_SYNC) { | |
481 | bwrite(bp); | |
482 | } else { | |
483 | if (bp->b_bufsize == fs->fs_bsize) | |
484 | bp->b_flags |= B_CLUSTEROK; | |
485 | bdwrite(bp); | |
486 | } | |
487 | } | |
488 | } | |
489 | if (deallocated) { | |
490 | #ifdef QUOTA | |
491 | /* | |
492 | * Restore user's disk quota because allocation failed. | |
493 | */ | |
50e58362 | 494 | (void) ufs_chkdq(ip, (long)-btodb(deallocated), cred, FORCE); |
984263bc MD |
495 | #endif |
496 | ip->i_blocks -= btodb(deallocated); | |
497 | ip->i_flag |= IN_CHANGE | IN_UPDATE; | |
498 | } | |
52174f71 | 499 | VOP_FSYNC(vp, MNT_WAIT, 0); |
481df61e | 500 | |
ae675022 MD |
501 | /* |
502 | * After the buffers are invalidated and on-disk pointers are | |
503 | * cleared, free the blocks. | |
504 | */ | |
505 | for (blkp = allociblk; blkp < allocblk; blkp++) { | |
506 | ffs_blkfree(ip, *blkp, fs->fs_bsize); | |
507 | } | |
508 | ||
481df61e MD |
509 | /* |
510 | * Cleanup the data block we getblk()'d before returning. | |
511 | */ | |
512 | fail2: | |
513 | brelse(dbp); | |
984263bc MD |
514 | return (error); |
515 | } | |
481df61e | 516 |