Skip to content

Commit e21fea4

Browse files
Darrick J. WongChandan Babu R
authored andcommitted
xfs: fix di_onlink checking for V1/V2 inodes
"KjellR" complained on IRC that an old V4 filesystem suddenly stopped mounting after upgrading from 6.9.11 to 6.10.3, with the following splat when trying to read the rt bitmap inode: 00000000: 49 4e 80 00 01 02 00 01 00 00 00 00 00 00 00 00 IN.............. 00000010: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000020: 00 00 00 00 00 00 00 00 43 d2 a9 da 21 0f d6 30 ........C...!..0 00000030: 43 d2 a9 da 21 0f d6 30 00 00 00 00 00 00 00 00 C...!..0........ 00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000050: 00 00 00 02 00 00 00 00 00 00 00 04 00 00 00 00 ................ 00000060: ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ As Dave Chinner points out, this is a V1 inode with both di_onlink and di_nlink set to 1 and di_flushiter == 0. In other words, this inode was formatted this way by mkfs and hasn't been touched since then. Back in the old days of xfsprogs 3.2.3, I observed that libxfs_ialloc would set di_nlink, but if the filesystem didn't have NLINK, it would then set di_version = 1. libxfs_iflush_int later sees the V1 inode and copies the value of di_nlink to di_onlink without zeroing di_onlink. Eventually this filesystem must have been upgraded to support NLINK because 6.10 doesn't support !NLINK filesystems, which is how we tripped over this old behavior. The filesystem doesn't have a realtime section, so that's why the rtbitmap inode has never been touched. Fix this by removing the di_onlink/di_nlink checking for all V1/V2 inodes because this is a muddy mess. The V3 inode handling code has always supported NLINK and written di_onlink==0 so keep that check. The removal of the V1 inode handling code when we dropped support for !NLINK obscured this old behavior. Reported-by: [email protected] Fixes: 40cb861 ("xfs: check unused nlink fields in the ondisk inode") Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Chandan Babu R <[email protected]>
1 parent 5be63fc commit e21fea4

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

fs/xfs/libxfs/xfs_inode_buf.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -514,12 +514,18 @@ xfs_dinode_verify(
514514
return __this_address;
515515
}
516516

517-
if (dip->di_version > 1) {
517+
/*
518+
* Historical note: xfsprogs in the 3.2 era set up its incore inodes to
519+
* have di_nlink track the link count, even if the actual filesystem
520+
* only supported V1 inodes (i.e. di_onlink). When writing out the
521+
* ondisk inode, it would set both the ondisk di_nlink and di_onlink to
522+
* the the incore di_nlink value, which is why we cannot check for
523+
* di_nlink==0 on a V1 inode. V2/3 inodes would get written out with
524+
* di_onlink==0, so we can check that.
525+
*/
526+
if (dip->di_version >= 2) {
518527
if (dip->di_onlink)
519528
return __this_address;
520-
} else {
521-
if (dip->di_nlink)
522-
return __this_address;
523529
}
524530

525531
/* don't allow invalid i_size */

0 commit comments

Comments
 (0)