Skip to content

Commit 7cd3099

Browse files
Brian FosterDarrick J. Wong
authored andcommitted
xfs: drop submit side trans alloc for append ioends
Per-inode ioend completion batching has a log reservation deadlock vector between preallocated append transactions and transactions that are acquired at completion time for other purposes (i.e., unwritten extent conversion or COW fork remaps). For example, if the ioend completion workqueue task executes on a batch of ioends that are sorted such that an append ioend sits at the tail, it's possible for the outstanding append transaction reservation to block allocation of transactions required to process preceding ioends in the list. Append ioend completion is historically the common path for on-disk inode size updates. While file extending writes may have completed sometime earlier, the on-disk inode size is only updated after successful writeback completion. These transactions are preallocated serially from writeback context to mitigate concurrency and associated log reservation pressure across completions processed by multi-threaded workqueue tasks. However, now that delalloc blocks unconditionally map to unwritten extents at physical block allocation time, size updates via append ioends are relatively rare. This means that inode size updates most commonly occur as part of the preexisting completion time transaction to convert unwritten extents. As a result, there is no longer a strong need to preallocate size update transactions. Remove the preallocation of inode size update transactions to avoid the ioend completion processing log reservation deadlock. Instead, continue to send all potential size extending ioends to workqueue context for completion and allocate the transaction from that context. This ensures that no outstanding log reservation is owned by the ioend completion worker task when it begins to process ioends. Signed-off-by: Brian Foster <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Darrick J. Wong <[email protected]>
1 parent 3b6dd9a commit 7cd3099

File tree

1 file changed

+3
-42
lines changed

1 file changed

+3
-42
lines changed

fs/xfs/xfs_aops.c

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -39,33 +39,6 @@ static inline bool xfs_ioend_is_append(struct iomap_ioend *ioend)
3939
XFS_I(ioend->io_inode)->i_disk_size;
4040
}
4141

42-
STATIC int
43-
xfs_setfilesize_trans_alloc(
44-
struct iomap_ioend *ioend)
45-
{
46-
struct xfs_mount *mp = XFS_I(ioend->io_inode)->i_mount;
47-
struct xfs_trans *tp;
48-
int error;
49-
50-
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp);
51-
if (error)
52-
return error;
53-
54-
ioend->io_private = tp;
55-
56-
/*
57-
* We may pass freeze protection with a transaction. So tell lockdep
58-
* we released it.
59-
*/
60-
__sb_writers_release(ioend->io_inode->i_sb, SB_FREEZE_FS);
61-
/*
62-
* We hand off the transaction to the completion thread now, so
63-
* clear the flag here.
64-
*/
65-
xfs_trans_clear_context(tp);
66-
return 0;
67-
}
68-
6942
/*
7043
* Update on-disk file size now that data has been written to disk.
7144
*/
@@ -182,12 +155,10 @@ xfs_end_ioend(
182155
error = xfs_reflink_end_cow(ip, offset, size);
183156
else if (ioend->io_type == IOMAP_UNWRITTEN)
184157
error = xfs_iomap_write_unwritten(ip, offset, size, false);
185-
else
186-
ASSERT(!xfs_ioend_is_append(ioend) || ioend->io_private);
187158

159+
if (!error && xfs_ioend_is_append(ioend))
160+
error = xfs_setfilesize(ip, ioend->io_offset, ioend->io_size);
188161
done:
189-
if (ioend->io_private)
190-
error = xfs_setfilesize_ioend(ioend, error);
191162
iomap_finish_ioends(ioend, error);
192163
memalloc_nofs_restore(nofs_flag);
193164
}
@@ -237,7 +208,7 @@ xfs_end_io(
237208

238209
static inline bool xfs_ioend_needs_workqueue(struct iomap_ioend *ioend)
239210
{
240-
return ioend->io_private ||
211+
return xfs_ioend_is_append(ioend) ||
241212
ioend->io_type == IOMAP_UNWRITTEN ||
242213
(ioend->io_flags & IOMAP_F_SHARED);
243214
}
@@ -250,8 +221,6 @@ xfs_end_bio(
250221
struct xfs_inode *ip = XFS_I(ioend->io_inode);
251222
unsigned long flags;
252223

253-
ASSERT(xfs_ioend_needs_workqueue(ioend));
254-
255224
spin_lock_irqsave(&ip->i_ioend_lock, flags);
256225
if (list_empty(&ip->i_ioend_list))
257226
WARN_ON_ONCE(!queue_work(ip->i_mount->m_unwritten_workqueue,
@@ -501,14 +470,6 @@ xfs_prepare_ioend(
501470
ioend->io_offset, ioend->io_size);
502471
}
503472

504-
/* Reserve log space if we might write beyond the on-disk inode size. */
505-
if (!status &&
506-
((ioend->io_flags & IOMAP_F_SHARED) ||
507-
ioend->io_type != IOMAP_UNWRITTEN) &&
508-
xfs_ioend_is_append(ioend) &&
509-
!ioend->io_private)
510-
status = xfs_setfilesize_trans_alloc(ioend);
511-
512473
memalloc_nofs_restore(nofs_flag);
513474

514475
if (xfs_ioend_needs_workqueue(ioend))

0 commit comments

Comments
 (0)