xfs: fix locking in xfs_iget_cache_hit
The locking in xfs_iget_cache_hit currently has numerous problems: - we clear the reclaim tag without i_flags_lock which protects modifications to it - we call inode_init_always which can sleep with pag_ici_lock held (this is oss.sgi.com BZ #819) - we acquire and drop i_flags_lock a lot and thus provide no consistency between the various flags we set/clear under it This patch fixes all that with a major revamp of the locking in the function. The new version acquires i_flags_lock early and only drops it once we need to call into inode_init_always or before calling xfs_ilock. This patch fixes a bug seen in the wild where we race modifying the reclaim tag. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Felix Blyakher <felixb@sgi.com> Reviewed-by: Eric Sandeen <sandeen@sandeen.net> Signed-off-by: Felix Blyakher <felixb@sgi.com>
This commit is contained in:
committed by
Felix Blyakher
parent
894ef820b1
commit
bc990f5cb4
@ -708,6 +708,16 @@ xfs_reclaim_inode(
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
__xfs_inode_set_reclaim_tag(
|
||||
struct xfs_perag *pag,
|
||||
struct xfs_inode *ip)
|
||||
{
|
||||
radix_tree_tag_set(&pag->pag_ici_root,
|
||||
XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
|
||||
XFS_ICI_RECLAIM_TAG);
|
||||
}
|
||||
|
||||
/*
|
||||
* We set the inode flag atomically with the radix tree tag.
|
||||
* Once we get tag lookups on the radix tree, this inode flag
|
||||
@ -722,8 +732,7 @@ xfs_inode_set_reclaim_tag(
|
||||
|
||||
read_lock(&pag->pag_ici_lock);
|
||||
spin_lock(&ip->i_flags_lock);
|
||||
radix_tree_tag_set(&pag->pag_ici_root,
|
||||
XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
|
||||
__xfs_inode_set_reclaim_tag(pag, ip);
|
||||
__xfs_iflags_set(ip, XFS_IRECLAIMABLE);
|
||||
spin_unlock(&ip->i_flags_lock);
|
||||
read_unlock(&pag->pag_ici_lock);
|
||||
|
Reference in New Issue
Block a user