2 * modified for Lites 1.1
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
8 * Copyright (c) 1982, 1986, 1989, 1993
9 * The Regents of the University of California. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * @(#)ext2_inode.c 8.5 (Berkeley) 12/30/93
40 * $FreeBSD: src/sys/gnu/ext2fs/ext2_inode.c,v 1.24.2.1 2000/08/03 00:52:57 peter Exp $
41 * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_inode.c,v 1.21 2007/05/06 19:23:33 dillon Exp $
44 #include "opt_quota.h"
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/mount.h>
50 #include <sys/vnode.h>
51 #include <sys/malloc.h>
54 #include <vm/vm_extern.h>
58 #include "ext2mount.h"
61 #include "ext2_fs_sb.h"
63 #include "ext2_extern.h"
65 static int ext2_indirtrunc (struct inode
*, daddr_t
, off_t
, daddr_t
,
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. If we write now, then clear both IN_MODIFIED and
74 * IN_LAZYMOD to reflect the presumably successful write, and if waitfor is
75 * set, then wait for the write to complete.
78 ext2_update(struct vnode
*vp
, int waitfor
)
80 struct ext2_sb_info
*fs
;
87 if ((ip
->i_flag
& IN_MODIFIED
) == 0)
89 ip
->i_flag
&= ~(IN_LAZYMOD
| IN_MODIFIED
);
90 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
93 error
= bread(ip
->i_devvp
,
94 fsbtodoff(fs
, ino_to_fsba(fs
, ip
->i_number
)),
95 (int)fs
->s_blocksize
, &bp
);
100 ext2_di2ei( &ip
->i_din
, (struct ext2_inode
*) ((char *)bp
->b_data
+ EXT2_INODE_SIZE
*
101 ino_to_fsbo(fs
, ip
->i_number
)));
103 if (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
114 #define SINGLE 0 /* index of single indirect block */
115 #define DOUBLE 1 /* index of double indirect block */
116 #define TRIPLE 2 /* index of triple indirect block */
118 * Truncate the inode oip to at most length size, freeing the
122 ext2_truncate(struct vnode
*vp
, off_t length
, int flags
, struct ucred
*cred
)
124 struct vnode
*ovp
= vp
;
127 daddr_t bn
, lbn
, lastiblock
[NIADDR
], indir_lbn
[NIADDR
];
128 daddr_t oldblks
[NDADDR
+ NIADDR
], newblks
[NDADDR
+ NIADDR
];
129 struct ext2_sb_info
*fs
;
131 int offset
, size
, level
;
132 long count
, nblocks
, blocksreleased
= 0;
134 int aflags
, error
, allerror
;
137 kprintf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length);
139 * negative file sizes will totally break the code below and
140 * are not meaningful anyways.
146 if (ovp
->v_type
== VLNK
&&
147 oip
->i_size
< ovp
->v_mount
->mnt_maxsymlinklen
) {
150 panic("ext2_truncate: partial truncate of symlink");
152 bzero((char *)&oip
->i_shortlink
, (u_int
)oip
->i_size
);
154 oip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
155 return (EXT2_UPDATE(ovp
, 1));
157 if (oip
->i_size
== length
) {
158 oip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
159 return (EXT2_UPDATE(ovp
, 0));
162 if ((error
= ext2_getinoquota(oip
)) != 0)
167 ext2_discard_prealloc(oip
);
169 * Lengthen the size of the file. We must ensure that the
170 * last byte of the file is allocated. Since the smallest
171 * value of oszie is 0, length will be at least 1.
173 if (osize
< length
) {
174 offset
= blkoff(fs
, length
- 1);
175 lbn
= lblkno(fs
, length
- 1);
179 vnode_pager_setsize(ovp
, length
);
180 if ((error
= ext2_balloc(oip
, lbn
, offset
+ 1, cred
, &bp
,
183 oip
->i_size
= length
;
184 if (aflags
& IO_SYNC
)
188 oip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
189 return (EXT2_UPDATE(ovp
, 1));
192 * Shorten the size of the file. If the file is not being
193 * truncated to a block boundry, the contents of the
194 * partial block following the end of the file must be
195 * zero'ed in case it ever become accessable again because
196 * of subsequent file growth.
198 /* I don't understand the comment above */
199 offset
= blkoff(fs
, length
);
201 oip
->i_size
= length
;
203 lbn
= lblkno(fs
, length
);
207 if ((error
= ext2_balloc(oip
, lbn
, offset
, cred
, &bp
,
210 oip
->i_size
= length
;
211 size
= blksize(fs
, oip
, lbn
);
212 bzero((char *)bp
->b_data
+ offset
, (u_int
)(size
- offset
));
214 if (aflags
& IO_SYNC
)
220 * Calculate index into inode's block list of
221 * last direct and indirect blocks (if any)
222 * which we want to keep. Lastblock is -1 when
223 * the file is truncated to 0.
225 lastblock
= lblkno(fs
, length
+ fs
->s_blocksize
- 1) - 1;
226 lastiblock
[SINGLE
] = lastblock
- NDADDR
;
227 lastiblock
[DOUBLE
] = lastiblock
[SINGLE
] - NINDIR(fs
);
228 lastiblock
[TRIPLE
] = lastiblock
[DOUBLE
] - NINDIR(fs
) * NINDIR(fs
);
229 nblocks
= btodb(fs
->s_blocksize
);
231 * Update file and block pointers on disk before we start freeing
232 * blocks. If we crash before free'ing blocks below, the blocks
233 * will be returned to the free list. lastiblock values are also
234 * normalized to -1 for calls to ext2_indirtrunc below.
236 bcopy((caddr_t
)&oip
->i_db
[0], (caddr_t
)oldblks
, sizeof oldblks
);
237 for (level
= TRIPLE
; level
>= SINGLE
; level
--)
238 if (lastiblock
[level
] < 0) {
239 oip
->i_ib
[level
] = 0;
240 lastiblock
[level
] = -1;
242 for (i
= NDADDR
- 1; i
> lastblock
; i
--)
244 oip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
245 allerror
= EXT2_UPDATE(ovp
, 1);
248 * Having written the new inode to disk, save its new configuration
249 * and put back the old block pointers long enough to process them.
250 * Note that we save the new block configuration so we can check it
253 bcopy((caddr_t
)&oip
->i_db
[0], (caddr_t
)newblks
, sizeof newblks
);
254 bcopy((caddr_t
)oldblks
, (caddr_t
)&oip
->i_db
[0], sizeof oldblks
);
256 error
= vtruncbuf(ovp
, length
, (int)fs
->s_blocksize
);
257 if (error
&& (allerror
== 0))
261 * Indirect blocks first.
263 indir_lbn
[SINGLE
] = -NDADDR
;
264 indir_lbn
[DOUBLE
] = indir_lbn
[SINGLE
] - NINDIR(fs
) - 1;
265 indir_lbn
[TRIPLE
] = indir_lbn
[DOUBLE
] - NINDIR(fs
) * NINDIR(fs
) - 1;
266 for (level
= TRIPLE
; level
>= SINGLE
; level
--) {
267 bn
= oip
->i_ib
[level
];
269 error
= ext2_indirtrunc(oip
, indir_lbn
[level
],
270 fsbtodoff(fs
, bn
), lastiblock
[level
], level
, &count
);
273 blocksreleased
+= count
;
274 if (lastiblock
[level
] < 0) {
275 oip
->i_ib
[level
] = 0;
276 ext2_blkfree(oip
, bn
, fs
->s_frag_size
);
277 blocksreleased
+= nblocks
;
280 if (lastiblock
[level
] >= 0)
285 * All whole direct blocks or frags.
287 for (i
= NDADDR
- 1; i
> lastblock
; i
--) {
294 bsize
= blksize(fs
, oip
, i
);
295 ext2_blkfree(oip
, bn
, bsize
);
296 blocksreleased
+= btodb(bsize
);
302 * Finally, look for a change in size of the
303 * last direct block; release any frags.
305 bn
= oip
->i_db
[lastblock
];
307 long oldspace
, newspace
;
310 * Calculate amount of space we're giving
311 * back as old block size minus new block size.
313 oldspace
= blksize(fs
, oip
, lastblock
);
314 oip
->i_size
= length
;
315 newspace
= blksize(fs
, oip
, lastblock
);
317 panic("itrunc: newspace");
318 if (oldspace
- newspace
> 0) {
320 * Block number of space to be free'd is
321 * the old block # plus the number of frags
322 * required for the storage we're keeping.
324 bn
+= numfrags(fs
, newspace
);
325 ext2_blkfree(oip
, bn
, oldspace
- newspace
);
326 blocksreleased
+= btodb(oldspace
- newspace
);
331 for (level
= SINGLE
; level
<= TRIPLE
; level
++)
332 if (newblks
[NDADDR
+ level
] != oip
->i_ib
[level
])
334 for (i
= 0; i
< NDADDR
; i
++)
335 if (newblks
[i
] != oip
->i_db
[i
])
337 if (length
== 0 && (!RB_EMPTY(&ovp
->v_rbdirty_tree
) ||
338 !RB_EMPTY(&ovp
->v_rbclean_tree
)))
340 #endif /* DIAGNOSTIC */
342 * Put back the real size.
344 oip
->i_size
= length
;
345 oip
->i_blocks
-= blocksreleased
;
346 if (oip
->i_blocks
< 0) /* sanity */
348 oip
->i_flag
|= IN_CHANGE
;
349 vnode_pager_setsize(ovp
, length
);
351 ext2_chkdq(oip
, -blocksreleased
, NOCRED
, 0);
357 * Release blocks associated with the inode ip and stored in the indirect
358 * block bn. Blocks are free'd in LIFO order up to (but not including)
359 * lastbn. If level is greater than SINGLE, the block is an indirect block
360 * and recursive calls to indirtrunc must be used to cleanse other indirect
363 * NB: triple indirect blocks are untested.
367 ext2_indirtrunc(struct inode
*ip
, daddr_t lbn
, off_t doffset
, daddr_t lastbn
,
368 int level
, long *countp
)
372 struct ext2_sb_info
*fs
= ip
->i_e2fs
;
375 daddr_t
*copy
, nb
, nlbn
, last
;
376 long blkcount
, factor
;
377 int nblocks
, blocksreleased
= 0;
378 int error
= 0, allerror
= 0;
381 * Calculate index in current block of last
382 * block to be kept. -1 indicates the entire
383 * block so we need not calculate the index.
386 for (i
= SINGLE
; i
< level
; i
++)
387 factor
*= NINDIR(fs
);
391 nblocks
= btodb(fs
->s_blocksize
);
393 * Get buffer of block pointers, zero those entries corresponding
394 * to blocks to be free'd, and update on disk copy first. Since
395 * double(triple) indirect before single(double) indirect, calls
396 * to bmap on these blocks will fail. However, we already have
397 * the on disk address, so we have to set the bio_offset field
398 * explicitly instead of letting bread do everything for us.
401 bp
= getblk(vp
, lblktodoff(fs
, lbn
), (int)fs
->s_blocksize
, 0, 0);
402 if ((bp
->b_flags
& B_CACHE
) == 0) {
403 bp
->b_flags
&= ~(B_ERROR
| B_INVAL
);
404 bp
->b_cmd
= BUF_CMD_READ
;
405 if (bp
->b_bcount
> bp
->b_bufsize
)
406 panic("ext2_indirtrunc: bad buffer size");
407 bp
->b_bio2
.bio_offset
= doffset
;
408 vfs_busy_pages(bp
->b_vp
, bp
);
409 vn_strategy(vp
, &bp
->b_bio1
);
418 bap
= (daddr_t
*)bp
->b_data
;
419 MALLOC(copy
, daddr_t
*, fs
->s_blocksize
, M_TEMP
, M_WAITOK
);
420 bcopy((caddr_t
)bap
, (caddr_t
)copy
, (u_int
)fs
->s_blocksize
);
421 bzero((caddr_t
)&bap
[last
+ 1],
422 (u_int
)(NINDIR(fs
) - (last
+ 1)) * sizeof (daddr_t
));
424 bp
->b_flags
|= B_INVAL
;
431 * Recursively free totally unused blocks.
433 for (i
= NINDIR(fs
) - 1, nlbn
= lbn
+ 1 - i
* factor
; i
> last
;
434 i
--, nlbn
+= factor
) {
438 if (level
> SINGLE
) {
439 if ((error
= ext2_indirtrunc(ip
, nlbn
,
440 fsbtodoff(fs
, nb
), (daddr_t
)-1, level
- 1, &blkcount
)) != 0)
442 blocksreleased
+= blkcount
;
444 ext2_blkfree(ip
, nb
, fs
->s_blocksize
);
445 blocksreleased
+= nblocks
;
449 * Recursively free last partial block.
451 if (level
> SINGLE
&& lastbn
>= 0) {
452 last
= lastbn
% factor
;
455 error
= ext2_indirtrunc(ip
, nlbn
, fsbtodoff(fs
, nb
),
456 last
, level
- 1, &blkcount
);
459 blocksreleased
+= blkcount
;
463 *countp
= blocksreleased
;
468 * Last reference to an inode. If necessary, write or delete it.
470 * ext2_inactive(struct vnode *a_vp)
473 ext2_inactive(struct vop_inactive_args
*ap
)
475 struct vnode
*vp
= ap
->a_vp
;
476 struct inode
*ip
= VTOI(vp
);
479 ext2_discard_prealloc(ip
);
480 if (prtactive
&& vp
->v_sysref
.refcnt
> 1)
481 vprint("ext2_inactive: pushing active", vp
);
484 * Ignore inodes related to stale file handles.
486 if (ip
== NULL
|| ip
->i_mode
== 0)
488 if (ip
->i_nlink
<= 0 && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0) {
490 if (!ext2_getinoquota(ip
))
491 (void)ext2_chkiq(ip
, -1, NOCRED
, FORCE
);
493 error
= EXT2_TRUNCATE(vp
, (off_t
)0, 0, NOCRED
);
497 ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
498 EXT2_VFREE(vp
, ip
->i_number
, mode
);
500 if (ip
->i_flag
& (IN_ACCESS
| IN_CHANGE
| IN_MODIFIED
| IN_UPDATE
))
504 * If we are done with the inode, reclaim it
505 * so that it can be reused immediately.
507 if (ip
== NULL
|| ip
->i_mode
== 0)
513 * Reclaim an inode so that it can be used for other purposes.
515 * ext2_reclaim(struct vnode *a_vp)
518 ext2_reclaim(struct vop_reclaim_args
*ap
)
521 struct vnode
*vp
= ap
->a_vp
;
526 if (prtactive
&& vp
->v_sysref
.refcnt
> 1)
527 vprint("ext2_reclaim: pushing active", vp
);
534 if (ip
->i_flag
& IN_LAZYMOD
) {
535 ip
->i_flag
|= IN_MODIFIED
;
540 if (ip
&& (ip
->i_flag
& (IN_ACCESS
| IN_CHANGE
| IN_MODIFIED
| IN_UPDATE
))) {
541 kprintf("WARNING: INODE %ld flags %08x: modified inode being released!\n", (long)ip
->i_number
, (int)ip
->i_flag
);
542 ip
->i_flag
|= IN_MODIFIED
;
547 * Remove the inode from its hash chain and purge namecache
548 * data associated with the vnode.
558 for (i
= 0; i
< MAXQUOTAS
; i
++) {
559 if (ip
->i_dquot
[i
] != NODQUOT
) {
560 ext2_dqrele(vp
, ip
->i_dquot
[i
]);
561 ip
->i_dquot
[i
] = NODQUOT
;
566 if (ip
->i_dirhash
!= NULL
)
567 ext2dirhash_free(ip
);
569 kfree(ip
, VFSTOEXT2(vp
->v_mount
)->um_malloctype
);