Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'xfs-6.6-fixes-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fix from Chandan Babu:

- fix for commit 68b957f64fca ("xfs: load uncached unlinked inodes into
memory on demand") which address review comments provided by Dave
Chinner

* tag 'xfs-6.6-fixes-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
xfs: fix reloading entire unlinked bucket lists

+61 -20
+12 -4
fs/xfs/xfs_export.c
··· 146 146 return ERR_PTR(error); 147 147 } 148 148 149 - error = xfs_inode_reload_unlinked(ip); 150 - if (error) { 151 - xfs_irele(ip); 152 - return ERR_PTR(error); 149 + /* 150 + * Reload the incore unlinked list to avoid failure in inodegc. 151 + * Use an unlocked check here because unrecovered unlinked inodes 152 + * should be somewhat rare. 153 + */ 154 + if (xfs_inode_unlinked_incomplete(ip)) { 155 + error = xfs_inode_reload_unlinked(ip); 156 + if (error) { 157 + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 158 + xfs_irele(ip); 159 + return ERR_PTR(error); 160 + } 153 161 } 154 162 155 163 if (VFS_I(ip)->i_generation != generation) {
+35 -13
fs/xfs/xfs_inode.c
··· 1743 1743 truncate = 1; 1744 1744 1745 1745 if (xfs_iflags_test(ip, XFS_IQUOTAUNCHECKED)) { 1746 + /* 1747 + * If this inode is being inactivated during a quotacheck and 1748 + * has not yet been scanned by quotacheck, we /must/ remove 1749 + * the dquots from the inode before inactivation changes the 1750 + * block and inode counts. Most probably this is a result of 1751 + * reloading the incore iunlinked list to purge unrecovered 1752 + * unlinked inodes. 1753 + */ 1746 1754 xfs_qm_dqdetach(ip); 1747 1755 } else { 1748 1756 error = xfs_qm_dqattach(ip); ··· 3649 3641 if (error) 3650 3642 return error; 3651 3643 3644 + /* 3645 + * We've taken ILOCK_SHARED and the AGI buffer lock to stabilize the 3646 + * incore unlinked list pointers for this inode. Check once more to 3647 + * see if we raced with anyone else to reload the unlinked list. 3648 + */ 3649 + if (!xfs_inode_unlinked_incomplete(ip)) { 3650 + foundit = true; 3651 + goto out_agibp; 3652 + } 3653 + 3652 3654 bucket = agino % XFS_AGI_UNLINKED_BUCKETS; 3653 3655 agi = agibp->b_addr; 3654 3656 ··· 3673 3655 while (next_agino != NULLAGINO) { 3674 3656 struct xfs_inode *next_ip = NULL; 3675 3657 3658 + /* Found this caller's inode, set its backlink. */ 3676 3659 if (next_agino == agino) { 3677 - /* Found this inode, set its backlink. */ 3678 3660 next_ip = ip; 3679 3661 next_ip->i_prev_unlinked = prev_agino; 3680 3662 foundit = true; 3663 + goto next_inode; 3681 3664 } 3682 - if (!next_ip) { 3683 - /* Inode already in memory. */ 3684 - next_ip = xfs_iunlink_lookup(pag, next_agino); 3685 - } 3686 - if (!next_ip) { 3687 - /* Inode not in memory, reload. */ 3688 - error = xfs_iunlink_reload_next(tp, agibp, prev_agino, 3689 - next_agino); 3690 - if (error) 3691 - break; 3692 3665 3693 - next_ip = xfs_iunlink_lookup(pag, next_agino); 3694 - } 3666 + /* Try in-memory lookup first. */ 3667 + next_ip = xfs_iunlink_lookup(pag, next_agino); 3668 + if (next_ip) 3669 + goto next_inode; 3670 + 3671 + /* Inode not in memory, try reloading it. */ 3672 + error = xfs_iunlink_reload_next(tp, agibp, prev_agino, 3673 + next_agino); 3674 + if (error) 3675 + break; 3676 + 3677 + /* Grab the reloaded inode. */ 3678 + next_ip = xfs_iunlink_lookup(pag, next_agino); 3695 3679 if (!next_ip) { 3696 3680 /* No incore inode at all? We reloaded it... */ 3697 3681 ASSERT(next_ip != NULL); ··· 3701 3681 break; 3702 3682 } 3703 3683 3684 + next_inode: 3704 3685 prev_agino = next_agino; 3705 3686 next_agino = next_ip->i_next_unlinked; 3706 3687 } 3707 3688 3689 + out_agibp: 3708 3690 xfs_trans_brelse(tp, agibp); 3709 3691 /* Should have found this inode somewhere in the iunlinked bucket. */ 3710 3692 if (!error && !foundit)
+2
fs/xfs/xfs_itable.c
··· 80 80 if (error) 81 81 goto out; 82 82 83 + /* Reload the incore unlinked list to avoid failure in inodegc. */ 83 84 if (xfs_inode_unlinked_incomplete(ip)) { 84 85 error = xfs_inode_reload_unlinked_bucket(tp, ip); 85 86 if (error) { 86 87 xfs_iunlock(ip, XFS_ILOCK_SHARED); 88 + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 87 89 xfs_irele(ip); 88 90 return error; 89 91 }
+12 -3
fs/xfs/xfs_qm.c
··· 1160 1160 if (error) 1161 1161 return error; 1162 1162 1163 - error = xfs_inode_reload_unlinked(ip); 1164 - if (error) 1165 - goto error0; 1163 + /* 1164 + * Reload the incore unlinked list to avoid failure in inodegc. 1165 + * Use an unlocked check here because unrecovered unlinked inodes 1166 + * should be somewhat rare. 1167 + */ 1168 + if (xfs_inode_unlinked_incomplete(ip)) { 1169 + error = xfs_inode_reload_unlinked(ip); 1170 + if (error) { 1171 + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 1172 + goto error0; 1173 + } 1174 + } 1166 1175 1167 1176 ASSERT(ip->i_delayed_blks == 0); 1168 1177