mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
xfs: prevent close() from hanging on frozen filesystems
When a file is closed, xfs_file_release() attempts to trim speculative post-EOF blocks. This requires allocating a transaction, which blocks indefinitely if the filesystem is frozen. Fix the hang by wrapping the preallocation cleanup block with sb_start_write_trylock() and xfs_ilock_nowait() to bypass the trim best-effort when the filesystem is frozen or locking fails. Suggested-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Aditya Prakash Srivastava <aditya.ansh182@gmail.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
parent
ddeb5fe2d8
commit
aa5dba2d21
|
|
@ -1872,17 +1872,21 @@ xfs_file_release(
|
|||
return 0;
|
||||
|
||||
/*
|
||||
* If we can't get the iolock just skip truncating the blocks past EOF
|
||||
* because we could deadlock with the mmap_lock otherwise. We'll get
|
||||
* another chance to drop them once the last reference to the inode is
|
||||
* dropped, so we'll never leak blocks permanently.
|
||||
* If we can't get the iolock or if the filesystem is frozen, just skip
|
||||
* truncating the blocks past EOF because we could deadlock with the
|
||||
* mmap_lock or hang the close() call. We'll get another chance to drop
|
||||
* them once the last reference to the inode is dropped, so we'll never
|
||||
* leak blocks permanently.
|
||||
*/
|
||||
if (!xfs_iflags_test(ip, XFS_EOFBLOCKS_RELEASED) &&
|
||||
xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
|
||||
if (xfs_can_free_eofblocks(ip) &&
|
||||
!xfs_iflags_test_and_set(ip, XFS_EOFBLOCKS_RELEASED))
|
||||
xfs_free_eofblocks(ip);
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
sb_start_write_trylock(mp->m_super)) {
|
||||
if (xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
|
||||
if (xfs_can_free_eofblocks(ip) &&
|
||||
!xfs_iflags_test_and_set(ip, XFS_EOFBLOCKS_RELEASED))
|
||||
xfs_free_eofblocks(ip);
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
}
|
||||
sb_end_write(mp->m_super);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user