Skip to content

Commit b784951

Browse files
Christoph Hellwigcmaiolino
authored andcommitted
iomap: move locking out of iomap_write_delalloc_release
XFS (which currently is the only user of iomap_write_delalloc_release) already holds invalidate_lock for most zeroing operations. To be able to avoid a deadlock it needs to stop taking the lock, but doing so in iomap would leak XFS locking details into iomap. To avoid this require the caller to hold invalidate_lock when calling iomap_write_delalloc_release instead of taking it there. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Carlos Maiolino <[email protected]>
1 parent caf0ea4 commit b784951

File tree

2 files changed

+10
-9
lines changed

2 files changed

+10
-9
lines changed

fs/iomap/buffered-io.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,12 +1211,13 @@ void iomap_write_delalloc_release(struct inode *inode, loff_t start_byte,
12111211
loff_t scan_end_byte = min(i_size_read(inode), end_byte);
12121212

12131213
/*
1214-
* Lock the mapping to avoid races with page faults re-instantiating
1215-
* folios and dirtying them via ->page_mkwrite whilst we walk the
1216-
* cache and perform delalloc extent removal. Failing to do this can
1217-
* leave dirty pages with no space reservation in the cache.
1214+
* The caller must hold invalidate_lock to avoid races with page faults
1215+
* re-instantiating folios and dirtying them via ->page_mkwrite whilst
1216+
* we walk the cache and perform delalloc extent removal. Failing to do
1217+
* this can leave dirty pages with no space reservation in the cache.
12181218
*/
1219-
filemap_invalidate_lock(inode->i_mapping);
1219+
lockdep_assert_held_write(&inode->i_mapping->invalidate_lock);
1220+
12201221
while (start_byte < scan_end_byte) {
12211222
loff_t data_end;
12221223

@@ -1233,7 +1234,7 @@ void iomap_write_delalloc_release(struct inode *inode, loff_t start_byte,
12331234
if (start_byte == -ENXIO || start_byte == scan_end_byte)
12341235
break;
12351236
if (WARN_ON_ONCE(start_byte < 0))
1236-
goto out_unlock;
1237+
return;
12371238
WARN_ON_ONCE(start_byte < punch_start_byte);
12381239
WARN_ON_ONCE(start_byte > scan_end_byte);
12391240

@@ -1244,7 +1245,7 @@ void iomap_write_delalloc_release(struct inode *inode, loff_t start_byte,
12441245
data_end = mapping_seek_hole_data(inode->i_mapping, start_byte,
12451246
scan_end_byte, SEEK_HOLE);
12461247
if (WARN_ON_ONCE(data_end < 0))
1247-
goto out_unlock;
1248+
return;
12481249

12491250
/*
12501251
* If we race with post-direct I/O invalidation of the page cache,
@@ -1266,8 +1267,6 @@ void iomap_write_delalloc_release(struct inode *inode, loff_t start_byte,
12661267
if (punch_start_byte < end_byte)
12671268
punch(inode, punch_start_byte, end_byte - punch_start_byte,
12681269
iomap);
1269-
out_unlock:
1270-
filemap_invalidate_unlock(inode->i_mapping);
12711270
}
12721271
EXPORT_SYMBOL_GPL(iomap_write_delalloc_release);
12731272

fs/xfs/xfs_iomap.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,8 +1239,10 @@ xfs_buffered_write_iomap_end(
12391239
if (start_byte >= end_byte)
12401240
return 0;
12411241

1242+
filemap_invalidate_lock(inode->i_mapping);
12421243
iomap_write_delalloc_release(inode, start_byte, end_byte, flags, iomap,
12431244
xfs_buffered_write_delalloc_punch);
1245+
filemap_invalidate_unlock(inode->i_mapping);
12441246
return 0;
12451247
}
12461248

0 commit comments

Comments
 (0)