Ensure that files with no allocated blocks are trimmed to zero length.
UFS does not allow files to end with a hole; it requires that the last block of a file be allocated. As fsck_ffs(8) initially scans each allocated inode, it tracks the last allocated block in the inode. It then checks that the inode's size falls in the last allocated block. If the last allocated block falls before the size, a `file size beyond end of allocated file' warning is issued and the file is shortened to reference the last allocated block (to avoid having it reference a hole at its end). If the last allocated block falls after the size, a `partially truncated file' warning is issued and all blocks following the block referenced by the size are freed. Because of an incorrect unsigned comparison, this test was failing to handle files with no allocated blocks but non-zero size (which should have had their size reset to zero). Once that was fixed the test started incorrectly complaining about short symbolic links that place the link path in the inode rather than in a disk block. Because these symbolic links have a non-zero size, but no allocated blocks, fsck_ffs wanted to zero out their size. This patch has to detect and avoid changing the size of such symbolic links. Reported by: Chuck Silvers Tested by: Chuck Silvers MFC after: 1 week Sponsored by: Netflix
This commit is contained in:
parent
1a04f0156c
commit
a3628327e7
@ -248,7 +248,7 @@ checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
|
||||
off_t kernmaxfilesize;
|
||||
ufs2_daddr_t ndb;
|
||||
mode_t mode;
|
||||
uintmax_t fixsize;
|
||||
intmax_t size, fixsize;
|
||||
int j, ret, offset;
|
||||
|
||||
if ((dp = getnextinode(inumber, rebuildcg)) == NULL)
|
||||
@ -429,25 +429,37 @@ checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
|
||||
}
|
||||
}
|
||||
/*
|
||||
* UFS does not allow files to end with a hole; it requires that
|
||||
* the last block of a file be allocated. The last allocated block
|
||||
* in a file is tracked in id_lballoc. Here, we check for a size
|
||||
* past the last allocated block of the file and if that is found,
|
||||
* shorten the file to reference the last allocated block to avoid
|
||||
* having it reference a hole at its end.
|
||||
*
|
||||
* Soft updates will always ensure that the file size is correct
|
||||
* for files that contain only direct block pointers. However
|
||||
* soft updates does not roll back sizes for files with indirect
|
||||
* blocks that it has set to unallocated because their contents
|
||||
* have not yet been written to disk. Hence, the file can appear
|
||||
* to have a hole at its end because the block pointer has been
|
||||
* rolled back to zero. Thus, id_lballoc tracks the last allocated
|
||||
* block in the file. Here, for files that extend into indirect
|
||||
* blocks, we check for a size past the last allocated block of
|
||||
* the file and if that is found, shorten the file to reference
|
||||
* the last allocated block to avoid having it reference a hole
|
||||
* at its end.
|
||||
* rolled back to zero. Thus finding a hole at the end of a file
|
||||
* that is located in an indirect block receives only a warning
|
||||
* while finding a hole at the end of a file in a direct block
|
||||
* receives a fatal error message.
|
||||
*/
|
||||
if (DIP(dp, di_size) > UFS_NDADDR * sblock.fs_bsize &&
|
||||
idesc->id_lballoc < lblkno(&sblock, DIP(dp, di_size) - 1)) {
|
||||
fixsize = lblktosize(&sblock, idesc->id_lballoc + 1);
|
||||
pwarn("INODE %lu: FILE SIZE %ju BEYOND END OF ALLOCATED FILE, "
|
||||
"SIZE SHOULD BE %ju", (u_long)inumber,
|
||||
(uintmax_t)DIP(dp, di_size), fixsize);
|
||||
size = DIP(dp, di_size);
|
||||
if (idesc->id_lballoc < lblkno(&sblock, size - 1) &&
|
||||
/* exclude embedded symbolic links */
|
||||
((mode != IFLNK) || size >= sblock.fs_maxsymlinklen)) {
|
||||
fixsize = lblktosize(&sblock, idesc->id_lballoc + 1);
|
||||
if (size > UFS_NDADDR * sblock.fs_bsize)
|
||||
pwarn("INODE %lu: FILE SIZE %ju BEYOND END OF "
|
||||
"ALLOCATED FILE, SIZE SHOULD BE %ju",
|
||||
(u_long)inumber, size, fixsize);
|
||||
else
|
||||
pfatal("INODE %lu: FILE SIZE %ju BEYOND END OF "
|
||||
"ALLOCATED FILE, SIZE SHOULD BE %ju",
|
||||
(u_long)inumber, size, fixsize);
|
||||
if (preen)
|
||||
printf(" (ADJUSTED)\n");
|
||||
else if (reply("ADJUST") == 0)
|
||||
|
Loading…
Reference in New Issue
Block a user