Skip to content

Commit 150d5be

Browse files
Dave Chinnerdchinner
authored andcommitted
xfs: remove xfs_cancel_ioend
We currently have code to cancel ioends being built because we change bufferhead state as we build the ioend. On error, this needs to be unwound and so we have cancelling code that walks the buffers on the ioend chain and undoes these state changes. However, the IO submission path already handles state changes for buffers when a submission error occurs, so we don't really need a separate cancel function to do this - we can simply submit the ioend chain with the specific error and it will be cancelled rather than submitted. Hence we can remove the explicit cancel code and just rely on submission to deal with the error correctly. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <david@fromorbit.com>
1 parent 988ef92 commit 150d5be

File tree

1 file changed

+46
-47
lines changed

1 file changed

+46
-47
lines changed

fs/xfs/xfs_aops.c

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -521,38 +521,6 @@ xfs_submit_ioend(
521521
} while ((ioend = next) != NULL);
522522
}
523523

524-
/*
525-
* Cancel submission of all buffer_heads so far in this endio.
526-
* Toss the endio too. Only ever called for the initial page
527-
* in a writepage request, so only ever one page.
528-
*/
529-
STATIC void
530-
xfs_cancel_ioend(
531-
xfs_ioend_t *ioend)
532-
{
533-
xfs_ioend_t *next;
534-
struct buffer_head *bh, *next_bh;
535-
536-
do {
537-
next = ioend->io_list;
538-
bh = ioend->io_buffer_head;
539-
do {
540-
next_bh = bh->b_private;
541-
clear_buffer_async_write(bh);
542-
/*
543-
* The unwritten flag is cleared when added to the
544-
* ioend. We're not submitting for I/O so mark the
545-
* buffer unwritten again for next time around.
546-
*/
547-
if (ioend->io_type == XFS_IO_UNWRITTEN)
548-
set_buffer_unwritten(bh);
549-
unlock_buffer(bh);
550-
} while ((bh = next_bh) != NULL);
551-
552-
mempool_free(ioend, xfs_ioend_pool);
553-
} while ((ioend = next) != NULL);
554-
}
555-
556524
/*
557525
* Test to see if we've been building up a completion structure for
558526
* earlier buffers -- if so, we try to append to this ioend if we
@@ -925,6 +893,28 @@ xfs_aops_discard_page(
925893
return;
926894
}
927895

896+
static int
897+
xfs_writepage_submit(
898+
struct xfs_ioend *ioend,
899+
struct xfs_ioend *iohead,
900+
struct writeback_control *wbc,
901+
int status)
902+
{
903+
struct blk_plug plug;
904+
905+
/* Reserve log space if we might write beyond the on-disk inode size. */
906+
if (!status && ioend && ioend->io_type != XFS_IO_UNWRITTEN &&
907+
xfs_ioend_is_append(ioend))
908+
status = xfs_setfilesize_trans_alloc(ioend);
909+
910+
if (iohead) {
911+
blk_start_plug(&plug);
912+
xfs_submit_ioend(wbc, iohead, status);
913+
blk_finish_plug(&plug);
914+
}
915+
return status;
916+
}
917+
928918
/*
929919
* Write out a dirty page.
930920
*
@@ -1136,6 +1126,7 @@ xfs_vm_writepage(
11361126
return 0;
11371127

11381128
ASSERT(iohead);
1129+
ASSERT(err == 0);
11391130

11401131
/*
11411132
* Any errors from this point onwards need tobe reported through the IO
@@ -1161,25 +1152,33 @@ xfs_vm_writepage(
11611152
wbc, end_index);
11621153
}
11631154

1155+
return xfs_writepage_submit(ioend, iohead, wbc, 0);
11641156

1157+
error:
11651158
/*
1166-
* Reserve log space if we might write beyond the on-disk inode size.
1159+
* On error, we have to fail the iohead here because we buffers locked
1160+
* in the ioend chain. If we don't do this, we'll deadlock invalidating
1161+
* the page as that tries to lock the buffers on the page. Also, because
1162+
* we may have set pages under writeback, we have to run IO completion to
1163+
* mark the error state of the IO appropriately, so we can't cancel the
1164+
* ioend directly here. That means we have to mark this page as under
1165+
* writeback if we included any buffers from it in the ioend chain.
11671166
*/
1168-
err = 0;
1169-
if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend))
1170-
err = xfs_setfilesize_trans_alloc(ioend);
1171-
1172-
xfs_submit_ioend(wbc, iohead, err);
1167+
if (count)
1168+
xfs_start_page_writeback(page, 0, count);
1169+
xfs_writepage_submit(ioend, iohead, wbc, err);
11731170

1174-
return 0;
1175-
1176-
error:
1177-
if (iohead)
1178-
xfs_cancel_ioend(iohead);
1179-
1180-
xfs_aops_discard_page(page);
1181-
ClearPageUptodate(page);
1182-
unlock_page(page);
1171+
/*
1172+
* We can only discard the page we had the IO error on if we haven't
1173+
* included it in the ioend above. If it has already been errored out,
1174+
* the it is unlocked and we can't touch it here.
1175+
*/
1176+
if (!count) {
1177+
xfs_aops_discard_page(page);
1178+
ClearPageUptodate(page);
1179+
unlock_page(page);
1180+
}
1181+
mapping_set_error(page->mapping, err);
11831182
return err;
11841183

11851184
redirty:

0 commit comments

Comments
 (0)