1 /* $NetBSD: ext2fs_inode.c,v 1.82 2015/03/28 19:24:04 maxv Exp $ */
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * @(#)ffs_inode.c 8.8 (Berkeley) 10/19/94
32 * Modified for ext2fs by Manuel Bouyer.
36 * Copyright (c) 1997 Manuel Bouyer.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
51 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
52 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
53 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
54 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
56 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 * @(#)ffs_inode.c 8.8 (Berkeley) 10/19/94
59 * Modified for ext2fs by Manuel Bouyer.
62 #include <sys/cdefs.h>
63 __KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.82 2015/03/28 19:24:04 maxv Exp $");
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/mount.h>
71 #include <sys/vnode.h>
72 #include <sys/kernel.h>
74 #include <sys/trace.h>
75 #include <sys/resourcevar.h>
76 #include <sys/kauth.h>
78 #include <ufs/ufs/inode.h>
79 #include <ufs/ufs/ufsmount.h>
80 #include <ufs/ufs/ufs_extern.h>
82 #include <ufs/ext2fs/ext2fs.h>
83 #include <ufs/ext2fs/ext2fs_extern.h>
87 static int ext2fs_indirtrunc(struct inode
*, daddr_t
, daddr_t
,
88 daddr_t
, int, long *);
91 * These are fortunately the same values; it is likely that there is
92 * code that assumes they're equal. In any event, neither ought to
93 * ever change because it's a property of the on-disk formats.
95 CTASSERT(EXT2FS_NDADDR
== UFS_NDADDR
);
96 CTASSERT(EXT2FS_NIADDR
== UFS_NIADDR
);
99 * Get the size of an inode.
102 ext2fs_size(struct inode
*ip
)
104 uint64_t size
= ip
->i_e2fs_size
;
106 if ((ip
->i_e2fs_mode
& IFMT
) == IFREG
)
107 size
|= (uint64_t)ip
->i_e2fs_dacl
<< 32;
112 ext2fs_setsize(struct inode
*ip
, uint64_t size
)
114 if ((ip
->i_e2fs_mode
& IFMT
) == IFREG
||
115 ip
->i_e2fs_mode
== 0) {
116 ip
->i_e2fs_dacl
= size
>> 32;
117 if (size
>= 0x80000000U
) {
118 struct m_ext2fs
*fs
= ip
->i_e2fs
;
120 if (fs
->e2fs
.e2fs_rev
<= E2FS_REV0
) {
121 /* Linux automagically upgrades to REV1 here! */
124 if (!(fs
->e2fs
.e2fs_features_rocompat
125 & EXT2F_ROCOMPAT_LARGEFILE
)) {
126 fs
->e2fs
.e2fs_features_rocompat
|=
127 EXT2F_ROCOMPAT_LARGEFILE
;
131 } else if (size
>= 0x80000000U
)
134 ip
->i_e2fs_size
= size
;
140 ext2fs_nblock(struct inode
*ip
)
142 uint64_t nblock
= ip
->i_e2fs_nblock
;
143 struct m_ext2fs
* const fs
= ip
->i_e2fs
;
145 if (fs
->e2fs
.e2fs_features_rocompat
& EXT2F_ROCOMPAT_HUGE_FILE
) {
146 nblock
|= (uint64_t)ip
->i_e2fs_nblock_high
<< 32;
148 if ((ip
->i_e2fs_flags
& EXT2_HUGE_FILE
)) {
149 nblock
= EXT2_FSBTODB(fs
, nblock
);
157 ext2fs_setnblock(struct inode
*ip
, uint64_t nblock
)
159 struct m_ext2fs
* const fs
= ip
->i_e2fs
;
161 if (nblock
<= 0xffffffffULL
) {
162 CLR(ip
->i_e2fs_flags
, EXT2_HUGE_FILE
);
163 ip
->i_e2fs_nblock
= nblock
;
167 if (!ISSET(fs
->e2fs
.e2fs_features_rocompat
, EXT2F_ROCOMPAT_HUGE_FILE
))
170 if (nblock
<= 0xffffffffffffULL
) {
171 CLR(ip
->i_e2fs_flags
, EXT2_HUGE_FILE
);
172 ip
->i_e2fs_nblock
= nblock
& 0xffffffff;
173 ip
->i_e2fs_nblock_high
= (nblock
>> 32) & 0xffff;
177 if (EXT2_DBTOFSB(fs
, nblock
) <= 0xffffffffffffULL
) {
178 SET(ip
->i_e2fs_flags
, EXT2_HUGE_FILE
);
179 ip
->i_e2fs_nblock
= EXT2_DBTOFSB(fs
, nblock
) & 0xffffffff;
180 ip
->i_e2fs_nblock_high
= (EXT2_DBTOFSB(fs
, nblock
) >> 32) & 0xffff;
188 * Last reference to an inode. If necessary, write or delete it.
191 ext2fs_inactive(void *v
)
193 struct vop_inactive_args
/* {
197 struct vnode
*vp
= ap
->a_vp
;
198 struct inode
*ip
= VTOI(vp
);
201 if (prtactive
&& vp
->v_usecount
!= 0)
202 vprint("ext2fs_inactive: pushing active", vp
);
203 /* Get rid of inodes related to stale file handles. */
204 if (ip
->i_e2fs_mode
== 0 || ip
->i_e2fs_dtime
!= 0)
208 if (ip
->i_e2fs_nlink
== 0 && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0) {
209 /* Defer final inode free and update to reclaim.*/
210 if (ext2fs_size(ip
) != 0) {
211 error
= ext2fs_truncate(vp
, (off_t
)0, 0, NOCRED
);
213 ip
->i_e2fs_dtime
= time_second
;
214 ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
217 if (ip
->i_flag
& (IN_CHANGE
| IN_UPDATE
| IN_MODIFIED
)) {
218 ext2fs_update(vp
, NULL
, NULL
, 0);
222 * If we are done with the inode, reclaim it
223 * so that it can be reused immediately.
225 *ap
->a_recycle
= (ip
->i_e2fs_dtime
!= 0);
232 * Update the access, modified, and inode change times as specified by the
233 * IACCESS, IUPDATE, and ICHANGE flags respectively. The IMODIFIED flag is
234 * used to specify that the inode needs to be updated but that the times have
235 * already been set. The access and modified times are taken from the second
236 * and third parameters; the inode change time is always taken from the current
237 * time. If UPDATE_WAIT or UPDATE_DIROP is set, then wait for the disk
238 * write of the inode to complete.
241 ext2fs_update(struct vnode
*vp
, const struct timespec
*acc
,
242 const struct timespec
*mod
, int updflags
)
251 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
254 EXT2FS_ITIMES(ip
, acc
, mod
, NULL
);
255 if (updflags
& UPDATE_CLOSE
)
256 flags
= ip
->i_flag
& (IN_MODIFIED
| IN_ACCESSED
);
258 flags
= ip
->i_flag
& IN_MODIFIED
;
263 error
= bread(ip
->i_devvp
,
264 EXT2_FSBTODB(fs
, ino_to_fsba(fs
, ip
->i_number
)),
265 (int)fs
->e2fs_bsize
, B_MODIFY
, &bp
);
269 ip
->i_flag
&= ~(IN_MODIFIED
| IN_ACCESSED
);
270 cp
= (char *)bp
->b_data
+
271 (ino_to_fsbo(fs
, ip
->i_number
) * EXT2_DINODE_SIZE(fs
));
272 e2fs_isave(ip
->i_din
.e2fs_din
, (struct ext2fs_dinode
*)cp
);
273 if ((updflags
& (UPDATE_WAIT
|UPDATE_DIROP
)) != 0 &&
274 (flags
& IN_MODIFIED
) != 0 &&
275 (vp
->v_mount
->mnt_flag
& MNT_ASYNC
) == 0)
283 #define SINGLE 0 /* index of single indirect block */
284 #define DOUBLE 1 /* index of double indirect block */
285 #define TRIPLE 2 /* index of triple indirect block */
287 * Truncate the inode oip to at most length size, freeing the
291 ext2fs_truncate(struct vnode
*ovp
, off_t length
, int ioflag
,
295 struct inode
*oip
= VTOI(ovp
);
296 daddr_t bn
, lastiblock
[EXT2FS_NIADDR
], indir_lbn
[EXT2FS_NIADDR
];
298 int32_t oldblks
[EXT2FS_NDADDR
+ EXT2FS_NIADDR
], newblks
[EXT2FS_NDADDR
+ EXT2FS_NIADDR
];
300 int offset
, size
, level
;
301 long count
, blocksreleased
= 0;
303 int error
, allerror
= 0;
306 struct ufsmount
*ump
= oip
->i_ump
;
308 if (ovp
->v_type
== VCHR
|| ovp
->v_type
== VBLK
||
309 ovp
->v_type
== VFIFO
|| ovp
->v_type
== VSOCK
) {
316 if (ovp
->v_type
== VLNK
&&
317 (ext2fs_size(oip
) < ump
->um_maxsymlinklen
||
318 (ump
->um_maxsymlinklen
== 0 && ext2fs_nblock(oip
) == 0))) {
319 KDASSERT(length
== 0);
320 memset((char *)&oip
->i_din
.e2fs_din
->e2di_shortlink
, 0,
321 (u_int
)ext2fs_size(oip
));
322 (void)ext2fs_setsize(oip
, 0);
323 oip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
324 return (ext2fs_update(ovp
, NULL
, NULL
, 0));
326 if (ext2fs_size(oip
) == length
) {
327 /* still do a uvm_vnp_setsize() as writesize may be larger */
328 uvm_vnp_setsize(ovp
, length
);
329 oip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
330 return (ext2fs_update(ovp
, NULL
, NULL
, 0));
333 if (length
> ump
->um_maxfilesize
)
336 osize
= ext2fs_size(oip
);
339 * Lengthen the size of the file. We must ensure that the
340 * last byte of the file is allocated. Since the smallest
341 * value of osize is 0, length will be at least 1.
343 if (osize
< length
) {
344 uvm_vnp_setwritesize(ovp
, length
);
345 error
= ufs_balloc_range(ovp
, length
- 1, 1, cred
,
346 ioflag
& IO_SYNC
? B_SYNC
: 0);
348 (void) ext2fs_truncate(ovp
, osize
, ioflag
& IO_SYNC
,
352 uvm_vnp_setsize(ovp
, length
);
353 oip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
354 KASSERT(error
|| ovp
->v_size
== ext2fs_size(oip
));
355 return (ext2fs_update(ovp
, NULL
, NULL
, 0));
358 * Shorten the size of the file. If the file is not being
359 * truncated to a block boundry, the contents of the
360 * partial block following the end of the file must be
361 * zero'ed in case it ever become accessible again because
362 * of subsequent file growth.
364 offset
= ext2_blkoff(fs
, length
);
366 size
= fs
->e2fs_bsize
;
368 /* XXXUBC we should handle more than just VREG */
369 ubc_zerorange(&ovp
->v_uobj
, length
, size
- offset
,
370 UBC_UNMAP_FLAG(ovp
));
372 (void)ext2fs_setsize(oip
, length
);
373 uvm_vnp_setsize(ovp
, length
);
375 * Calculate index into inode's block list of
376 * last direct and indirect blocks (if any)
377 * which we want to keep. Lastblock is -1 when
378 * the file is truncated to 0.
380 lastblock
= ext2_lblkno(fs
, length
+ fs
->e2fs_bsize
- 1) - 1;
381 lastiblock
[SINGLE
] = lastblock
- EXT2FS_NDADDR
;
382 lastiblock
[DOUBLE
] = lastiblock
[SINGLE
] - EXT2_NINDIR(fs
);
383 lastiblock
[TRIPLE
] = lastiblock
[DOUBLE
] - EXT2_NINDIR(fs
) * EXT2_NINDIR(fs
);
384 nblocks
= btodb(fs
->e2fs_bsize
);
386 * Update file and block pointers on disk before we start freeing
387 * blocks. If we crash before free'ing blocks below, the blocks
388 * will be returned to the free list. lastiblock values are also
389 * normalized to -1 for calls to ext2fs_indirtrunc below.
391 memcpy((void *)oldblks
, (void *)&oip
->i_e2fs_blocks
[0], sizeof oldblks
);
393 for (level
= TRIPLE
; level
>= SINGLE
; level
--) {
394 if (lastiblock
[level
] < 0 && oldblks
[EXT2FS_NDADDR
+ level
] != 0) {
396 oip
->i_e2fs_blocks
[EXT2FS_NDADDR
+ level
] = 0;
397 lastiblock
[level
] = -1;
400 for (i
= 0; i
< EXT2FS_NDADDR
; i
++) {
401 if (i
> lastblock
&& oldblks
[i
] != 0) {
403 oip
->i_e2fs_blocks
[i
] = 0;
406 oip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
408 error
= ext2fs_update(ovp
, NULL
, NULL
, UPDATE_WAIT
);
409 if (error
&& !allerror
)
414 * Having written the new inode to disk, save its new configuration
415 * and put back the old block pointers long enough to process them.
416 * Note that we save the new block configuration so we can check it
419 memcpy((void *)newblks
, (void *)&oip
->i_e2fs_blocks
[0], sizeof newblks
);
420 memcpy((void *)&oip
->i_e2fs_blocks
[0], (void *)oldblks
, sizeof oldblks
);
422 (void)ext2fs_setsize(oip
, osize
);
423 error
= vtruncbuf(ovp
, lastblock
+ 1, 0, 0);
424 if (error
&& !allerror
)
428 * Indirect blocks first.
430 indir_lbn
[SINGLE
] = -EXT2FS_NDADDR
;
431 indir_lbn
[DOUBLE
] = indir_lbn
[SINGLE
] - EXT2_NINDIR(fs
) -1;
432 indir_lbn
[TRIPLE
] = indir_lbn
[DOUBLE
] - EXT2_NINDIR(fs
) * EXT2_NINDIR(fs
) - 1;
433 for (level
= TRIPLE
; level
>= SINGLE
; level
--) {
435 bn
= fs2h32(oip
->i_e2fs_blocks
[EXT2FS_NDADDR
+ level
]);
437 error
= ext2fs_indirtrunc(oip
, indir_lbn
[level
],
438 EXT2_FSBTODB(fs
, bn
), lastiblock
[level
], level
, &count
);
441 blocksreleased
+= count
;
442 if (lastiblock
[level
] < 0) {
443 oip
->i_e2fs_blocks
[EXT2FS_NDADDR
+ level
] = 0;
444 ext2fs_blkfree(oip
, bn
);
445 blocksreleased
+= nblocks
;
448 if (lastiblock
[level
] >= 0)
453 * All whole direct blocks or frags.
455 for (i
= EXT2FS_NDADDR
- 1; i
> lastblock
; i
--) {
457 bn
= fs2h32(oip
->i_e2fs_blocks
[i
]);
460 oip
->i_e2fs_blocks
[i
] = 0;
461 ext2fs_blkfree(oip
, bn
);
462 blocksreleased
+= btodb(fs
->e2fs_bsize
);
467 for (level
= SINGLE
; level
<= TRIPLE
; level
++)
468 if (newblks
[EXT2FS_NDADDR
+ level
] !=
469 oip
->i_e2fs_blocks
[EXT2FS_NDADDR
+ level
])
470 panic("ext2fs_truncate1");
471 for (i
= 0; i
< EXT2FS_NDADDR
; i
++)
472 if (newblks
[i
] != oip
->i_e2fs_blocks
[i
])
473 panic("ext2fs_truncate2");
475 (!LIST_EMPTY(&ovp
->v_cleanblkhd
) ||
476 !LIST_EMPTY(&ovp
->v_dirtyblkhd
)))
477 panic("ext2fs_truncate3");
478 #endif /* DIAGNOSTIC */
480 * Put back the real size.
482 (void)ext2fs_setsize(oip
, length
);
483 error
= ext2fs_setnblock(oip
, ext2fs_nblock(oip
) - blocksreleased
);
486 oip
->i_flag
|= IN_CHANGE
;
487 KASSERT(ovp
->v_type
!= VREG
|| ovp
->v_size
== ext2fs_size(oip
));
492 * Release blocks associated with the inode ip and stored in the indirect
493 * block bn. Blocks are free'd in LIFO order up to (but not including)
494 * lastbn. If level is greater than SINGLE, the block is an indirect block
495 * and recursive calls to indirtrunc must be used to cleanse other indirect
498 * NB: triple indirect blocks are untested.
501 ext2fs_indirtrunc(struct inode
*ip
, daddr_t lbn
, daddr_t dbn
, daddr_t lastbn
,
502 int level
, long *countp
)
506 struct m_ext2fs
*fs
= ip
->i_e2fs
;
507 int32_t *bap
; /* XXX ondisk32 */
509 daddr_t nb
, nlbn
, last
;
510 int32_t *copy
= NULL
; /* XXX ondisk32 */
511 long blkcount
, factor
;
512 int nblocks
, blocksreleased
= 0;
513 int error
= 0, allerror
= 0;
516 * Calculate index in current block of last
517 * block to be kept. -1 indicates the entire
518 * block so we need not calculate the index.
521 for (i
= SINGLE
; i
< level
; i
++)
522 factor
*= EXT2_NINDIR(fs
);
526 nblocks
= btodb(fs
->e2fs_bsize
);
528 * Get buffer of block pointers, zero those entries corresponding
529 * to blocks to be free'd, and update on disk copy first. Since
530 * double(triple) indirect before single(double) indirect, calls
531 * to bmap on these blocks will fail. However, we already have
532 * the on disk address, so we have to set the b_blkno field
533 * explicitly instead of letting bread do everything for us.
536 bp
= getblk(vp
, lbn
, (int)fs
->e2fs_bsize
, 0, 0);
537 if (bp
->b_oflags
& (BO_DONE
| BO_DELWRI
)) {
538 /* Braces must be here in case trace evaluates to nothing. */
539 trace(TR_BREADHIT
, pack(vp
, fs
->e2fs_bsize
), lbn
);
541 trace(TR_BREADMISS
, pack(vp
, fs
->e2fs_bsize
), lbn
);
542 curlwp
->l_ru
.ru_inblock
++; /* pay for read */
543 bp
->b_flags
|= B_READ
;
544 if (bp
->b_bcount
> bp
->b_bufsize
)
545 panic("ext2fs_indirtrunc: bad buffer size");
547 VOP_STRATEGY(vp
, bp
);
556 bap
= (int32_t *)bp
->b_data
; /* XXX ondisk32 */
559 copy
= kmem_alloc(fs
->e2fs_bsize
, KM_SLEEP
);
560 memcpy((void *)copy
, (void *)bap
, (u_int
)fs
->e2fs_bsize
);
561 memset((void *)&bap
[last
+ 1], 0,
562 (u_int
)(EXT2_NINDIR(fs
) - (last
+ 1)) * sizeof (uint32_t));
570 * Recursively free totally unused blocks.
572 for (i
= EXT2_NINDIR(fs
) - 1,
573 nlbn
= lbn
+ 1 - i
* factor
; i
> last
;
574 i
--, nlbn
+= factor
) {
579 if (level
> SINGLE
) {
580 error
= ext2fs_indirtrunc(ip
, nlbn
, EXT2_FSBTODB(fs
, nb
),
581 (daddr_t
)-1, level
- 1,
585 blocksreleased
+= blkcount
;
587 ext2fs_blkfree(ip
, nb
);
588 blocksreleased
+= nblocks
;
592 * Recursively free last partial block.
594 if (level
> SINGLE
&& lastbn
>= 0) {
595 last
= lastbn
% factor
;
599 error
= ext2fs_indirtrunc(ip
, nlbn
, EXT2_FSBTODB(fs
, nb
),
600 last
, level
- 1, &blkcount
);
603 blocksreleased
+= blkcount
;
608 kmem_free(copy
, fs
->e2fs_bsize
);
610 brelse(bp
, BC_INVAL
);
613 *countp
= blocksreleased
;