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.
13 * 4. Neither the name of the University nor the names of its contributors
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_inode.c 8.13 (Berkeley) 4/21/95
30 */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include "opt_quota.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/bio.h>
40 #include <sys/buf.h>
41 #include <sys/malloc.h>
42 #include <sys/mount.h>
43 #include <sys/proc.h>
44 #include <sys/racct.h>
45 #include <sys/random.h>
46 #include <sys/resourcevar.h>
47 #include <sys/rwlock.h>
48 #include <sys/stat.h>
49 #include <sys/vmmeter.h>
50 #include <sys/vnode.h>
51
52 #include <vm/vm.h>
53 #include <vm/vm_extern.h>
54 #include <vm/vm_object.h>
55
56 #include <ufs/ufs/extattr.h>
57 #include <ufs/ufs/quota.h>
58 #include <ufs/ufs/ufsmount.h>
59 #include <ufs/ufs/inode.h>
60 #include <ufs/ufs/ufs_extern.h>
61
62 #include <ufs/ffs/fs.h>
63 #include <ufs/ffs/ffs_extern.h>
64
65 static int ffs_indirtrunc(struct inode *, ufs2_daddr_t, ufs2_daddr_t,
66 ufs2_daddr_t, int, ufs2_daddr_t *);
67
68 /*
69 * Update the access, modified, and inode change times as specified by the
70 * IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively. Write the inode
71 * to disk if the IN_MODIFIED flag is set (it may be set initially, or by
72 * the timestamp update). The IN_LAZYMOD flag is set to force a write
73 * later if not now. The IN_LAZYACCESS is set instead of IN_MODIFIED if the fs
74 * is currently being suspended (or is suspended) and vnode has been accessed.
75 * If we write now, then clear IN_MODIFIED, IN_LAZYACCESS and IN_LAZYMOD to
76 * reflect the presumably successful write, and if waitfor is set, then wait
77 * for the write to complete.
78 */
79 int
80 ffs_update(vp, waitfor)
81 struct vnode *vp;
82 int waitfor;
83 {
84 struct fs *fs;
85 struct buf *bp;
86 struct inode *ip;
87 int flags, error;
88
89 ASSERT_VOP_ELOCKED(vp, "ffs_update");
90 ufs_itimes(vp);
91 ip = VTOI(vp);
92 if ((ip->i_flag & IN_MODIFIED) == 0 && waitfor == 0)
93 return (0);
94 ip->i_flag &= ~(IN_LAZYACCESS | IN_LAZYMOD | IN_MODIFIED);
95 /*
96 * The IN_SIZEMOD and IN_IBLKDATA flags indicate changes to the
97 * file size and block pointer fields in the inode. When these
98 * fields have been changed, the fsync() and fsyncdata() system
99 * calls must write the inode to ensure their semantics that the
100 * file is on stable store.
101 *
102 * The IN_SIZEMOD and IN_IBLKDATA flags cannot be cleared until
103 * a synchronous write of the inode is done. If they are cleared
104 * on an asynchronous write, then the inode may not yet have been
105 * written to the disk when an fsync() or fsyncdata() call is done.
106 * Absent these flags, these calls would not know that they needed
107 * to write the inode. Thus, these flags only can be cleared on
108 * synchronous writes of the inode. Since the inode will be locked
109 * for the duration of the I/O that writes it to disk, no fsync()
110 * or fsyncdata() will be able to run before the on-disk inode
111 * is complete.
112 */
113 if (waitfor)
114 ip->i_flag &= ~(IN_SIZEMOD | IN_IBLKDATA);
115 fs = ITOFS(ip);
116 if (fs->fs_ronly && ITOUMP(ip)->um_fsckpid == 0)
117 return (0);
118 /*
119 * If we are updating a snapshot and another process is currently
120 * writing the buffer containing the inode for this snapshot then
121 * a deadlock can occur when it tries to check the snapshot to see
122 * if that block needs to be copied. Thus when updating a snapshot
123 * we check to see if the buffer is already locked, and if it is
124 * we drop the snapshot lock until the buffer has been written
125 * and is available to us. We have to grab a reference to the
126 * snapshot vnode to prevent it from being removed while we are
127 * waiting for the buffer.
128 */
129 flags = 0;
130 if (IS_SNAPSHOT(ip))
131 flags = GB_LOCK_NOWAIT;
132 loop:
133 error = breadn_flags(ITODEVVP(ip),
134 fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
135 (int) fs->fs_bsize, 0, 0, 0, NOCRED, flags, &bp);
136 if (error != 0) {
137 if (error != EBUSY)
138 return (error);
139 KASSERT((IS_SNAPSHOT(ip)), ("EBUSY from non-snapshot"));
140 /*
141 * Wait for our inode block to become available.
142 *
143 * Hold a reference to the vnode to protect against
144 * ffs_snapgone(). Since we hold a reference, it can only
145 * get reclaimed (VI_DOOMED flag) in a forcible downgrade
146 * or unmount. For an unmount, the entire filesystem will be
147 * gone, so we cannot attempt to touch anything associated
148 * with it while the vnode is unlocked; all we can do is
149 * pause briefly and try again. If when we relock the vnode
150 * we discover that it has been reclaimed, updating it is no
151 * longer necessary and we can just return an error.
152 */
153 vref(vp);
154 VOP_UNLOCK(vp, 0);
155 pause("ffsupd", 1);
156 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
157 vrele(vp);
158 if ((vp->v_iflag & VI_DOOMED) != 0)
159 return (ENOENT);
160 goto loop;
161 }
162 if (DOINGSOFTDEP(vp))
163 softdep_update_inodeblock(ip, bp, waitfor);
164 else if (ip->i_effnlink != ip->i_nlink)
165 panic("ffs_update: bad link cnt");
166 if (I_IS_UFS1(ip)) {
167 *((struct ufs1_dinode *)bp->b_data +
168 ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1;
169 /* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */
170 random_harvest_queue(&(ip->i_din1), sizeof(ip->i_din1), 1, RANDOM_FS_ATIME);
171 } else {
172 *((struct ufs2_dinode *)bp->b_data +
173 ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
174 /* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */
175 random_harvest_queue(&(ip->i_din2), sizeof(ip->i_din2), 1, RANDOM_FS_ATIME);
176 }
177 if (waitfor && !DOINGASYNC(vp))
178 error = bwrite(bp);
179 else if (vm_page_count_severe() || buf_dirty_count_severe()) {
180 bawrite(bp);
181 error = 0;
182 } else {
183 if (bp->b_bufsize == fs->fs_bsize)
184 bp->b_flags |= B_CLUSTEROK;
185 bdwrite(bp);
186 error = 0;
187 }
188 return (error);
189 }
190
191 #define SINGLE 0 /* index of single indirect block */
192 #define DOUBLE 1 /* index of double indirect block */
193 #define TRIPLE 2 /* index of triple indirect block */
194 /*
195 * Truncate the inode ip to at most length size, freeing the
196 * disk blocks.
197 */
198 int
199 ffs_truncate(vp, length, flags, cred)
200 struct vnode *vp;
201 off_t length;
202 int flags;
203 struct ucred *cred;
204 {
205 struct inode *ip;
206 ufs2_daddr_t bn, lbn, lastblock, lastiblock[NIADDR], indir_lbn[NIADDR];
207 ufs2_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
208 ufs2_daddr_t count, blocksreleased = 0, datablocks, blkno;
209 struct bufobj *bo;
210 struct fs *fs;
211 struct buf *bp;
212 struct ufsmount *ump;
213 int softdeptrunc, journaltrunc;
214 int needextclean, extblocks;
215 int offset, size, level, nblocks;
216 int i, error, allerror, indiroff;
217 off_t osize;
218
219 ip = VTOI(vp);
220 ump = VFSTOUFS(vp->v_mount);
221 fs = ump->um_fs;
222 bo = &vp->v_bufobj;
223
224 ASSERT_VOP_LOCKED(vp, "ffs_truncate");
225
226 if (length < 0)
227 return (EINVAL);
228 if (length > fs->fs_maxfilesize)
229 return (EFBIG);
230 #ifdef QUOTA
231 error = getinoquota(ip);
232 if (error)
233 return (error);
234 #endif
235 /*
236 * Historically clients did not have to specify which data
237 * they were truncating. So, if not specified, we assume
238 * traditional behavior, e.g., just the normal data.
239 */
240 if ((flags & (IO_EXT | IO_NORMAL)) == 0)
241 flags |= IO_NORMAL;
242 if (!DOINGSOFTDEP(vp) && !DOINGASYNC(vp))
243 flags |= IO_SYNC;
244 /*
245 * If we are truncating the extended-attributes, and cannot
246 * do it with soft updates, then do it slowly here. If we are
247 * truncating both the extended attributes and the file contents
248 * (e.g., the file is being unlinked), then pick it off with
249 * soft updates below.
250 */
251 allerror = 0;
252 needextclean = 0;
253 softdeptrunc = 0;
254 journaltrunc = DOINGSUJ(vp);
255 if (journaltrunc == 0 && DOINGSOFTDEP(vp) && length == 0)
256 softdeptrunc = !softdep_slowdown(vp);
257 extblocks = 0;
258 datablocks = DIP(ip, i_blocks);
259 if (fs->fs_magic == FS_UFS2_MAGIC && ip->i_din2->di_extsize > 0) {
260 extblocks = btodb(fragroundup(fs, ip->i_din2->di_extsize));
261 datablocks -= extblocks;
262 }
263 if ((flags & IO_EXT) && extblocks > 0) {
264 if (length != 0)
265 panic("ffs_truncate: partial trunc of extdata");
266 if (softdeptrunc || journaltrunc) {
267 if ((flags & IO_NORMAL) == 0)
268 goto extclean;
269 needextclean = 1;
270 } else {
271 if ((error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0)
272 return (error);
273 #ifdef QUOTA
274 (void) chkdq(ip, -extblocks, NOCRED, 0);
275 #endif
276 vinvalbuf(vp, V_ALT, 0, 0);
277 vn_pages_remove(vp,
278 OFF_TO_IDX(lblktosize(fs, -extblocks)), 0);
279 osize = ip->i_din2->di_extsize;
280 ip->i_din2->di_blocks -= extblocks;
281 ip->i_din2->di_extsize = 0;
282 for (i = 0; i < NXADDR; i++) {
283 oldblks[i] = ip->i_din2->di_extb[i];
284 ip->i_din2->di_extb[i] = 0;
285 }
286 ip->i_flag |= IN_SIZEMOD | IN_CHANGE;
287 if ((error = ffs_update(vp, !DOINGASYNC(vp))))
288 return (error);
289 for (i = 0; i < NXADDR; i++) {
290 if (oldblks[i] == 0)
291 continue;
292 ffs_blkfree(ump, fs, ITODEVVP(ip), oldblks[i],
293 sblksize(fs, osize, i), ip->i_number,
294 vp->v_type, NULL);
295 }
296 }
297 }
298 if ((flags & IO_NORMAL) == 0)
299 return (0);
300 if (vp->v_type == VLNK &&
301 (ip->i_size < vp->v_mount->mnt_maxsymlinklen ||
302 datablocks == 0)) {
303 #ifdef INVARIANTS
304 if (length != 0)
305 panic("ffs_truncate: partial truncate of symlink");
306 #endif
307 bzero(SHORTLINK(ip), (u_int)ip->i_size);
308 ip->i_size = 0;
309 DIP_SET(ip, i_size, 0);
310 ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
311 if (needextclean)
312 goto extclean;
313 return (ffs_update(vp, !DOINGASYNC(vp)));
314 }
315 if (ip->i_size == length) {
316 ip->i_flag |= IN_CHANGE | IN_UPDATE;
317 if (needextclean)
318 goto extclean;
319 return (ffs_update(vp, 0));
320 }
321 if (fs->fs_ronly)
322 panic("ffs_truncate: read-only filesystem");
323 if (IS_SNAPSHOT(ip))
324 ffs_snapremove(vp);
325 vp->v_lasta = vp->v_clen = vp->v_cstart = vp->v_lastw = 0;
326 osize = ip->i_size;
327 /*
328 * Lengthen the size of the file. We must ensure that the
329 * last byte of the file is allocated. Since the smallest
330 * value of osize is 0, length will be at least 1.
331 */
332 if (osize < length) {
333 vnode_pager_setsize(vp, length);
334 flags |= BA_CLRBUF;
335 error = UFS_BALLOC(vp, length - 1, 1, cred, flags, &bp);
336 if (error) {
337 vnode_pager_setsize(vp, osize);
338 return (error);
339 }
340 ip->i_size = length;
341 DIP_SET(ip, i_size, length);
342 if (bp->b_bufsize == fs->fs_bsize)
343 bp->b_flags |= B_CLUSTEROK;
344 if (flags & IO_SYNC)
345 bwrite(bp);
346 else if (DOINGASYNC(vp))
347 bdwrite(bp);
348 else
349 bawrite(bp);
350 ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
351 return (ffs_update(vp, !DOINGASYNC(vp)));
352 }
353 /*
354 * Lookup block number for a given offset. Zero length files
355 * have no blocks, so return a blkno of -1.
356 */
357 lbn = lblkno(fs, length - 1);
358 if (length == 0) {
359 blkno = -1;
360 } else if (lbn < NDADDR) {
361 blkno = DIP(ip, i_db[lbn]);
362 } else {
363 error = UFS_BALLOC(vp, lblktosize(fs, (off_t)lbn), fs->fs_bsize,
364 cred, BA_METAONLY, &bp);
365 if (error)
366 return (error);
367 indiroff = (lbn - NDADDR) % NINDIR(fs);
368 if (I_IS_UFS1(ip))
369 blkno = ((ufs1_daddr_t *)(bp->b_data))[indiroff];
370 else
371 blkno = ((ufs2_daddr_t *)(bp->b_data))[indiroff];
372 /*
373 * If the block number is non-zero, then the indirect block
374 * must have been previously allocated and need not be written.
375 * If the block number is zero, then we may have allocated
376 * the indirect block and hence need to write it out.
377 */
378 if (blkno != 0)
379 brelse(bp);
380 else if (DOINGSOFTDEP(vp) || DOINGASYNC(vp))
381 bdwrite(bp);
382 else
383 bwrite(bp);
384 }
385 /*
386 * If the block number at the new end of the file is zero,
387 * then we must allocate it to ensure that the last block of
388 * the file is allocated. Soft updates does not handle this
389 * case, so here we have to clean up the soft updates data
390 * structures describing the allocation past the truncation
391 * point. Finding and deallocating those structures is a lot of
392 * work. Since partial truncation with a hole at the end occurs
393 * rarely, we solve the problem by syncing the file so that it
394 * will have no soft updates data structures left.
395 */
396 if (blkno == 0 && (error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0)
397 return (error);
398 if (blkno != 0 && DOINGSOFTDEP(vp)) {
399 if (softdeptrunc == 0 && journaltrunc == 0) {
400 /*
401 * If soft updates cannot handle this truncation,
402 * clean up soft dependency data structures and
403 * fall through to the synchronous truncation.
404 */
405 if ((error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0)
406 return (error);
407 } else {
408 flags = IO_NORMAL | (needextclean ? IO_EXT: 0);
409 if (journaltrunc)
410 softdep_journal_freeblocks(ip, cred, length,
411 flags);
412 else
413 softdep_setup_freeblocks(ip, length, flags);
414 ASSERT_VOP_LOCKED(vp, "ffs_truncate1");
415 if (journaltrunc == 0) {
416 ip->i_flag |= IN_CHANGE | IN_UPDATE;
417 error = ffs_update(vp, 0);
418 }
419 return (error);
420 }
421 }
422 /*
423 * Shorten the size of the file. If the last block of the
424 * shortened file is unallocated, we must allocate it.
425 * Additionally, if the file is not being truncated to a
426 * block boundary, the contents of the partial block
427 * following the end of the file must be zero'ed in
428 * case it ever becomes accessible again because of
429 * subsequent file growth. Directories however are not
430 * zero'ed as they should grow back initialized to empty.
431 */
432 offset = blkoff(fs, length);
433 if (blkno != 0 && offset == 0) {
434 ip->i_size = length;
435 DIP_SET(ip, i_size, length);
436 ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
437 } else {
438 lbn = lblkno(fs, length);
439 flags |= BA_CLRBUF;
440 error = UFS_BALLOC(vp, length - 1, 1, cred, flags, &bp);
441 if (error)
442 return (error);
443 /*
444 * When we are doing soft updates and the UFS_BALLOC
445 * above fills in a direct block hole with a full sized
446 * block that will be truncated down to a fragment below,
447 * we must flush out the block dependency with an FSYNC
448 * so that we do not get a soft updates inconsistency
449 * when we create the fragment below.
450 */
451 if (DOINGSOFTDEP(vp) && lbn < NDADDR &&
452 fragroundup(fs, blkoff(fs, length)) < fs->fs_bsize &&
453 (error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0)
454 return (error);
455 ip->i_size = length;
456 DIP_SET(ip, i_size, length);
457 size = blksize(fs, ip, lbn);
458 if (vp->v_type != VDIR && offset != 0)
459 bzero((char *)bp->b_data + offset,
460 (u_int)(size - offset));
461 /* Kirk's code has reallocbuf(bp, size, 1) here */
462 allocbuf(bp, size);
463 if (bp->b_bufsize == fs->fs_bsize)
464 bp->b_flags |= B_CLUSTEROK;
465 if (flags & IO_SYNC)
466 bwrite(bp);
467 else if (DOINGASYNC(vp))
468 bdwrite(bp);
469 else
470 bawrite(bp);
471 ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
472 }
473 /*
474 * Calculate index into inode's block list of
475 * last direct and indirect blocks (if any)
476 * which we want to keep. Lastblock is -1 when
477 * the file is truncated to 0.
478 */
479 lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1;
480 lastiblock[SINGLE] = lastblock - NDADDR;
481 lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
482 lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
483 nblocks = btodb(fs->fs_bsize);
484 /*
485 * Update file and block pointers on disk before we start freeing
486 * blocks. If we crash before free'ing blocks below, the blocks
487 * will be returned to the free list. lastiblock values are also
488 * normalized to -1 for calls to ffs_indirtrunc below.
489 */
490 for (level = TRIPLE; level >= SINGLE; level--) {
491 oldblks[NDADDR + level] = DIP(ip, i_ib[level]);
492 if (lastiblock[level] < 0) {
493 DIP_SET(ip, i_ib[level], 0);
494 lastiblock[level] = -1;
495 }
496 }
497 for (i = 0; i < NDADDR; i++) {
498 oldblks[i] = DIP(ip, i_db[i]);
499 if (i > lastblock)
500 DIP_SET(ip, i_db[i], 0);
501 }
502 ip->i_flag |= IN_CHANGE | IN_UPDATE;
503 allerror = ffs_update(vp, !DOINGASYNC(vp));
504
505 /*
506 * Having written the new inode to disk, save its new configuration
507 * and put back the old block pointers long enough to process them.
508 * Note that we save the new block configuration so we can check it
509 * when we are done.
510 */
511 for (i = 0; i < NDADDR; i++) {
512 newblks[i] = DIP(ip, i_db[i]);
513 DIP_SET(ip, i_db[i], oldblks[i]);
514 }
515 for (i = 0; i < NIADDR; i++) {
516 newblks[NDADDR + i] = DIP(ip, i_ib[i]);
517 DIP_SET(ip, i_ib[i], oldblks[NDADDR + i]);
518 }
519 ip->i_size = osize;
520 DIP_SET(ip, i_size, osize);
521 ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
522
523 error = vtruncbuf(vp, length, fs->fs_bsize);
524 if (error && (allerror == 0))
525 allerror = error;
526
527 /*
528 * Indirect blocks first.
529 */
530 indir_lbn[SINGLE] = -NDADDR;
531 indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1;
532 indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1;
533 for (level = TRIPLE; level >= SINGLE; level--) {
534 bn = DIP(ip, i_ib[level]);
535 if (bn != 0) {
536 error = ffs_indirtrunc(ip, indir_lbn[level],
537 fsbtodb(fs, bn), lastiblock[level], level, &count);
538 if (error)
539 allerror = error;
540 blocksreleased += count;
541 if (lastiblock[level] < 0) {
542 DIP_SET(ip, i_ib[level], 0);
543 ffs_blkfree(ump, fs, ump->um_devvp, bn,
544 fs->fs_bsize, ip->i_number,
545 vp->v_type, NULL);
546 blocksreleased += nblocks;
547 }
548 }
549 if (lastiblock[level] >= 0)
550 goto done;
551 }
552
553 /*
554 * All whole direct blocks or frags.
555 */
556 for (i = NDADDR - 1; i > lastblock; i--) {
557 long bsize;
558
559 bn = DIP(ip, i_db[i]);
560 if (bn == 0)
561 continue;
562 DIP_SET(ip, i_db[i], 0);
563 bsize = blksize(fs, ip, i);
564 ffs_blkfree(ump, fs, ump->um_devvp, bn, bsize, ip->i_number,
565 vp->v_type, NULL);
566 blocksreleased += btodb(bsize);
567 }
568 if (lastblock < 0)
569 goto done;
570
571 /*
572 * Finally, look for a change in size of the
573 * last direct block; release any frags.
574 */
575 bn = DIP(ip, i_db[lastblock]);
576 if (bn != 0) {
577 long oldspace, newspace;
578
579 /*
580 * Calculate amount of space we're giving
581 * back as old block size minus new block size.
582 */
583 oldspace = blksize(fs, ip, lastblock);
584 ip->i_size = length;
585 DIP_SET(ip, i_size, length);
586 ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
587 newspace = blksize(fs, ip, lastblock);
588 if (newspace == 0)
589 panic("ffs_truncate: newspace");
590 if (oldspace - newspace > 0) {
591 /*
592 * Block number of space to be free'd is
593 * the old block # plus the number of frags
594 * required for the storage we're keeping.
595 */
596 bn += numfrags(fs, newspace);
597 ffs_blkfree(ump, fs, ump->um_devvp, bn,
598 oldspace - newspace, ip->i_number, vp->v_type, NULL);
599 blocksreleased += btodb(oldspace - newspace);
600 }
601 }
602 done:
603 #ifdef INVARIANTS
604 for (level = SINGLE; level <= TRIPLE; level++)
605 if (newblks[NDADDR + level] != DIP(ip, i_ib[level]))
606 panic("ffs_truncate1");
607 for (i = 0; i < NDADDR; i++)
608 if (newblks[i] != DIP(ip, i_db[i]))
609 panic("ffs_truncate2");
610 BO_LOCK(bo);
611 if (length == 0 &&
612 (fs->fs_magic != FS_UFS2_MAGIC || ip->i_din2->di_extsize == 0) &&
613 (bo->bo_dirty.bv_cnt > 0 || bo->bo_clean.bv_cnt > 0))
614 panic("ffs_truncate3");
615 BO_UNLOCK(bo);
616 #endif /* INVARIANTS */
617 /*
618 * Put back the real size.
619 */
620 ip->i_size = length;
621 DIP_SET(ip, i_size, length);
622 if (DIP(ip, i_blocks) >= blocksreleased)
623 DIP_SET(ip, i_blocks, DIP(ip, i_blocks) - blocksreleased);
624 else /* sanity */
625 DIP_SET(ip, i_blocks, 0);
626 ip->i_flag |= IN_SIZEMOD | IN_CHANGE;
627 #ifdef QUOTA
628 (void) chkdq(ip, -blocksreleased, NOCRED, 0);
629 #endif
630 return (allerror);
631
632 extclean:
633 if (journaltrunc)
634 softdep_journal_freeblocks(ip, cred, length, IO_EXT);
635 else
636 softdep_setup_freeblocks(ip, length, IO_EXT);
637 return (ffs_update(vp, (flags & IO_SYNC) != 0 || !DOINGASYNC(vp)));
638 }
639
640 /*
641 * Release blocks associated with the inode ip and stored in the indirect
642 * block bn. Blocks are free'd in LIFO order up to (but not including)
643 * lastbn. If level is greater than SINGLE, the block is an indirect block
644 * and recursive calls to indirtrunc must be used to cleanse other indirect
645 * blocks.
646 */
647 static int
648 ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
649 struct inode *ip;
650 ufs2_daddr_t lbn, lastbn;
651 ufs2_daddr_t dbn;
652 int level;
653 ufs2_daddr_t *countp;
654 {
655 struct buf *bp;
656 struct fs *fs;
657 struct vnode *vp;
658 caddr_t copy = NULL;
659 int i, nblocks, error = 0, allerror = 0;
660 ufs2_daddr_t nb, nlbn, last;
661 ufs2_daddr_t blkcount, factor, blocksreleased = 0;
662 ufs1_daddr_t *bap1 = NULL;
663 ufs2_daddr_t *bap2 = NULL;
664 #define BAP(ip, i) (I_IS_UFS1(ip) ? bap1[i] : bap2[i])
665
666 fs = ITOFS(ip);
667
668 /*
669 * Calculate index in current block of last
670 * block to be kept. -1 indicates the entire
671 * block so we need not calculate the index.
672 */
673 factor = lbn_offset(fs, level);
674 last = lastbn;
675 if (lastbn > 0)
676 last /= factor;
677 nblocks = btodb(fs->fs_bsize);
678 /*
679 * Get buffer of block pointers, zero those entries corresponding
680 * to blocks to be free'd, and update on disk copy first. Since
681 * double(triple) indirect before single(double) indirect, calls
682 * to bmap on these blocks will fail. However, we already have
683 * the on disk address, so we have to set the b_blkno field
684 * explicitly instead of letting bread do everything for us.
685 */
686 vp = ITOV(ip);
687 bp = getblk(vp, lbn, (int)fs->fs_bsize, 0, 0, 0);
688 if ((bp->b_flags & B_CACHE) == 0) {
689 #ifdef RACCT
690 if (racct_enable) {
691 PROC_LOCK(curproc);
692 racct_add_buf(curproc, bp, 0);
693 PROC_UNLOCK(curproc);
694 }
695 #endif /* RACCT */
696 curthread->td_ru.ru_inblock++; /* pay for read */
697 bp->b_iocmd = BIO_READ;
698 bp->b_flags &= ~B_INVAL;
699 bp->b_ioflags &= ~BIO_ERROR;
700 if (bp->b_bcount > bp->b_bufsize)
701 panic("ffs_indirtrunc: bad buffer size");
702 bp->b_blkno = dbn;
703 vfs_busy_pages(bp, 0);
704 bp->b_iooffset = dbtob(bp->b_blkno);
705 bstrategy(bp);
706 error = bufwait(bp);
707 }
708 if (error) {
709 brelse(bp);
710 *countp = 0;
711 return (error);
712 }
713
714 if (I_IS_UFS1(ip))
715 bap1 = (ufs1_daddr_t *)bp->b_data;
716 else
717 bap2 = (ufs2_daddr_t *)bp->b_data;
718 if (lastbn != -1) {
719 copy = malloc(fs->fs_bsize, M_TEMP, M_WAITOK);
720 bcopy((caddr_t)bp->b_data, copy, (u_int)fs->fs_bsize);
721 for (i = last + 1; i < NINDIR(fs); i++)
722 if (I_IS_UFS1(ip))
723 bap1[i] = 0;
724 else
725 bap2[i] = 0;
726 if (DOINGASYNC(vp)) {
727 bdwrite(bp);
728 } else {
729 error = bwrite(bp);
730 if (error)
731 allerror = error;
732 }
733 if (I_IS_UFS1(ip))
734 bap1 = (ufs1_daddr_t *)copy;
735 else
736 bap2 = (ufs2_daddr_t *)copy;
737 }
738
739 /*
740 * Recursively free totally unused blocks.
741 */
742 for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last;
743 i--, nlbn += factor) {
744 nb = BAP(ip, i);
745 if (nb == 0)
746 continue;
747 if (level > SINGLE) {
748 if ((error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
749 (ufs2_daddr_t)-1, level - 1, &blkcount)) != 0)
750 allerror = error;
751 blocksreleased += blkcount;
752 }
753 ffs_blkfree(ITOUMP(ip), fs, ITODEVVP(ip), nb, fs->fs_bsize,
754 ip->i_number, vp->v_type, NULL);
755 blocksreleased += nblocks;
756 }
757
758 /*
759 * Recursively free last partial block.
760 */
761 if (level > SINGLE && lastbn >= 0) {
762 last = lastbn % factor;
763 nb = BAP(ip, i);
764 if (nb != 0) {
765 error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
766 last, level - 1, &blkcount);
767 if (error)
768 allerror = error;
769 blocksreleased += blkcount;
770 }
771 }
772 if (copy != NULL) {
773 free(copy, M_TEMP);
774 } else {
775 bp->b_flags |= B_INVAL | B_NOCACHE;
776 brelse(bp);
777 }
778
779 *countp = blocksreleased;
780 return (allerror);
781 }
782
783 int
784 ffs_rdonly(struct inode *ip)
785 {
786
787 return (ITOFS(ip)->fs_ronly != 0);
788 }
789
Cache object: cf502861a851ca3909123723d046cd4c
|