From: Wengang Wang Date: Tue, 29 Jan 2019 03:19:09 +0000 (-0800) Subject: Revert "xfs: remove xfs_cancel_ioend" X-Git-Tag: v4.1.12-124.31.3~309 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=a60668522bb8963c65dfe1ca808c4f6a09488a64;p=users%2Fjedix%2Flinux-maple.git Revert "xfs: remove xfs_cancel_ioend" This reverts commit c680537035066177fa845053354974f7245c02d8. These commits are very possibly to cause SIGBUS issue. (We can't verify that in customer's environment). Revert them. Orabug: 29279692 Signed-off-by: Wengang Wang Reviewed-by: Shan Hai Signed-off-by: Brian Maly --- diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 0a0f5c9294f1..75edf5846f32 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -527,6 +527,38 @@ xfs_submit_ioend( } while ((ioend = next) != NULL); } +/* + * Cancel submission of all buffer_heads so far in this endio. + * Toss the endio too. Only ever called for the initial page + * in a writepage request, so only ever one page. + */ +STATIC void +xfs_cancel_ioend( + xfs_ioend_t *ioend) +{ + xfs_ioend_t *next; + struct buffer_head *bh, *next_bh; + + do { + next = ioend->io_list; + bh = ioend->io_buffer_head; + do { + next_bh = bh->b_private; + clear_buffer_async_write(bh); + /* + * The unwritten flag is cleared when added to the + * ioend. We're not submitting for I/O so mark the + * buffer unwritten again for next time around. + */ + if (ioend->io_type == XFS_IO_UNWRITTEN) + set_buffer_unwritten(bh); + unlock_buffer(bh); + } while ((bh = next_bh) != NULL); + + mempool_free(ioend, xfs_ioend_pool); + } while ((ioend = next) != NULL); +} + /* * Test to see if we've been building up a completion structure for * earlier buffers -- if so, we try to append to this ioend if we @@ -899,28 +931,6 @@ out_invalidate: return; } -static int -xfs_writepage_submit( - struct xfs_ioend *ioend, - struct xfs_ioend *iohead, - struct writeback_control *wbc, - int status) -{ - struct blk_plug plug; - - /* Reserve log space if we might write beyond the on-disk inode size. */ - if (!status && ioend && ioend->io_type != XFS_IO_UNWRITTEN && - xfs_ioend_is_append(ioend)) - status = xfs_setfilesize_trans_alloc(ioend); - - if (iohead) { - blk_start_plug(&plug); - xfs_submit_ioend(wbc, iohead, status); - blk_finish_plug(&plug); - } - return status; -} - /* * Write out a dirty page. * @@ -1132,7 +1142,6 @@ xfs_vm_writepage( return 0; ASSERT(iohead); - ASSERT(err == 0); /* * Any errors from this point onwards need tobe reported through the IO @@ -1158,33 +1167,25 @@ xfs_vm_writepage( wbc, end_index); } - return xfs_writepage_submit(ioend, iohead, wbc, 0); -error: /* - * On error, we have to fail the iohead here because we buffers locked - * in the ioend chain. If we don't do this, we'll deadlock invalidating - * the page as that tries to lock the buffers on the page. Also, because - * we may have set pages under writeback, we have to run IO completion to - * mark the error state of the IO appropriately, so we can't cancel the - * ioend directly here. That means we have to mark this page as under - * writeback if we included any buffers from it in the ioend chain. + * Reserve log space if we might write beyond the on-disk inode size. */ - if (count) - xfs_start_page_writeback(page, 0, count); - xfs_writepage_submit(ioend, iohead, wbc, err); + err = 0; + if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend)) + err = xfs_setfilesize_trans_alloc(ioend); - /* - * We can only discard the page we had the IO error on if we haven't - * included it in the ioend above. If it has already been errored out, - * the it is unlocked and we can't touch it here. - */ - if (!count) { - xfs_aops_discard_page(page); - ClearPageUptodate(page); - unlock_page(page); - } - mapping_set_error(page->mapping, err); + xfs_submit_ioend(wbc, iohead, err); + + return 0; + +error: + if (iohead) + xfs_cancel_ioend(iohead); + + xfs_aops_discard_page(page); + ClearPageUptodate(page); + unlock_page(page); return err; redirty: