2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-21 19:53:59 +08:00

xfs: remove the io_type field from the writeback context and ioend

The io_type field contains what is basically a summary of information
from the inode fork and the imap.  But we can just as easily use that
information directly, simplifying a few bits here and there and
improving the trace points.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
Christoph Hellwig 2019-02-15 08:02:46 -08:00 committed by Darrick J. Wong
parent c4a6bf7f6c
commit be225fec72
5 changed files with 63 additions and 98 deletions

View File

@ -28,7 +28,7 @@
*/ */
struct xfs_writepage_ctx { struct xfs_writepage_ctx {
struct xfs_bmbt_irec imap; struct xfs_bmbt_irec imap;
unsigned int io_type; int fork;
unsigned int data_seq; unsigned int data_seq;
unsigned int cow_seq; unsigned int cow_seq;
struct xfs_ioend *ioend; struct xfs_ioend *ioend;
@ -256,30 +256,20 @@ xfs_end_io(
*/ */
error = blk_status_to_errno(ioend->io_bio->bi_status); error = blk_status_to_errno(ioend->io_bio->bi_status);
if (unlikely(error)) { if (unlikely(error)) {
switch (ioend->io_type) { if (ioend->io_fork == XFS_COW_FORK)
case XFS_IO_COW:
xfs_reflink_cancel_cow_range(ip, offset, size, true); xfs_reflink_cancel_cow_range(ip, offset, size, true);
break;
}
goto done; goto done;
} }
/* /*
* Success: commit the COW or unwritten blocks if needed. * Success: commit the COW or unwritten blocks if needed.
*/ */
switch (ioend->io_type) { if (ioend->io_fork == XFS_COW_FORK)
case XFS_IO_COW:
error = xfs_reflink_end_cow(ip, offset, size); error = xfs_reflink_end_cow(ip, offset, size);
break; else if (ioend->io_state == XFS_EXT_UNWRITTEN)
case XFS_IO_UNWRITTEN:
/* writeback should never update isize */
error = xfs_iomap_write_unwritten(ip, offset, size, false); error = xfs_iomap_write_unwritten(ip, offset, size, false);
break; else
default:
ASSERT(!xfs_ioend_is_append(ioend) || ioend->io_append_trans); ASSERT(!xfs_ioend_is_append(ioend) || ioend->io_append_trans);
break;
}
done: done:
if (ioend->io_append_trans) if (ioend->io_append_trans)
@ -294,7 +284,8 @@ xfs_end_bio(
struct xfs_ioend *ioend = bio->bi_private; struct xfs_ioend *ioend = bio->bi_private;
struct xfs_mount *mp = XFS_I(ioend->io_inode)->i_mount; struct xfs_mount *mp = XFS_I(ioend->io_inode)->i_mount;
if (ioend->io_type == XFS_IO_UNWRITTEN || ioend->io_type == XFS_IO_COW) if (ioend->io_fork == XFS_COW_FORK ||
ioend->io_state == XFS_EXT_UNWRITTEN)
queue_work(mp->m_unwritten_workqueue, &ioend->io_work); queue_work(mp->m_unwritten_workqueue, &ioend->io_work);
else if (ioend->io_append_trans) else if (ioend->io_append_trans)
queue_work(mp->m_data_workqueue, &ioend->io_work); queue_work(mp->m_data_workqueue, &ioend->io_work);
@ -320,7 +311,7 @@ xfs_imap_valid(
* covers the offset. Be careful to check this first because the caller * covers the offset. Be careful to check this first because the caller
* can revalidate a COW mapping without updating the data seqno. * can revalidate a COW mapping without updating the data seqno.
*/ */
if (wpc->io_type == XFS_IO_COW) if (wpc->fork == XFS_COW_FORK)
return true; return true;
/* /*
@ -350,7 +341,6 @@ xfs_map_blocks(
xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset), end_fsb; xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset), end_fsb;
xfs_fileoff_t cow_fsb = NULLFILEOFF; xfs_fileoff_t cow_fsb = NULLFILEOFF;
struct xfs_bmbt_irec imap; struct xfs_bmbt_irec imap;
int whichfork = XFS_DATA_FORK;
struct xfs_iext_cursor icur; struct xfs_iext_cursor icur;
int error = 0; int error = 0;
@ -400,6 +390,9 @@ xfs_map_blocks(
if (cow_fsb != NULLFILEOFF && cow_fsb <= offset_fsb) { if (cow_fsb != NULLFILEOFF && cow_fsb <= offset_fsb) {
wpc->cow_seq = READ_ONCE(ip->i_cowfp->if_seq); wpc->cow_seq = READ_ONCE(ip->i_cowfp->if_seq);
xfs_iunlock(ip, XFS_ILOCK_SHARED); xfs_iunlock(ip, XFS_ILOCK_SHARED);
wpc->fork = XFS_COW_FORK;
/* /*
* Truncate can race with writeback since writeback doesn't * Truncate can race with writeback since writeback doesn't
* take the iolock and truncate decreases the file size before * take the iolock and truncate decreases the file size before
@ -412,11 +405,13 @@ xfs_map_blocks(
* will kill the contents anyway. * will kill the contents anyway.
*/ */
if (offset > i_size_read(inode)) { if (offset > i_size_read(inode)) {
wpc->io_type = XFS_IO_HOLE; wpc->imap.br_blockcount = end_fsb - offset_fsb;
wpc->imap.br_startoff = offset_fsb;
wpc->imap.br_startblock = HOLESTARTBLOCK;
wpc->imap.br_state = XFS_EXT_NORM;
return 0; return 0;
} }
whichfork = XFS_COW_FORK;
wpc->io_type = XFS_IO_COW;
goto allocate_blocks; goto allocate_blocks;
} }
@ -439,12 +434,14 @@ xfs_map_blocks(
wpc->data_seq = READ_ONCE(ip->i_df.if_seq); wpc->data_seq = READ_ONCE(ip->i_df.if_seq);
xfs_iunlock(ip, XFS_ILOCK_SHARED); xfs_iunlock(ip, XFS_ILOCK_SHARED);
wpc->fork = XFS_DATA_FORK;
if (imap.br_startoff > offset_fsb) { if (imap.br_startoff > offset_fsb) {
/* landed in a hole or beyond EOF */ /* landed in a hole or beyond EOF */
imap.br_blockcount = imap.br_startoff - offset_fsb; imap.br_blockcount = imap.br_startoff - offset_fsb;
imap.br_startoff = offset_fsb; imap.br_startoff = offset_fsb;
imap.br_startblock = HOLESTARTBLOCK; imap.br_startblock = HOLESTARTBLOCK;
wpc->io_type = XFS_IO_HOLE; imap.br_state = XFS_EXT_NORM;
} else { } else {
/* /*
* Truncate to the next COW extent if there is one. This is the * Truncate to the next COW extent if there is one. This is the
@ -456,31 +453,24 @@ xfs_map_blocks(
cow_fsb < imap.br_startoff + imap.br_blockcount) cow_fsb < imap.br_startoff + imap.br_blockcount)
imap.br_blockcount = cow_fsb - imap.br_startoff; imap.br_blockcount = cow_fsb - imap.br_startoff;
if (isnullstartblock(imap.br_startblock)) { /* got a delalloc extent? */
/* got a delalloc extent */ if (isnullstartblock(imap.br_startblock))
wpc->io_type = XFS_IO_DELALLOC;
goto allocate_blocks; goto allocate_blocks;
}
if (imap.br_state == XFS_EXT_UNWRITTEN)
wpc->io_type = XFS_IO_UNWRITTEN;
else
wpc->io_type = XFS_IO_OVERWRITE;
} }
wpc->imap = imap; wpc->imap = imap;
trace_xfs_map_blocks_found(ip, offset, count, wpc->io_type, &imap); trace_xfs_map_blocks_found(ip, offset, count, wpc->fork, &imap);
return 0; return 0;
allocate_blocks: allocate_blocks:
error = xfs_iomap_write_allocate(ip, whichfork, offset, &imap, error = xfs_iomap_write_allocate(ip, wpc->fork, offset, &imap,
whichfork == XFS_COW_FORK ? wpc->fork == XFS_COW_FORK ?
&wpc->cow_seq : &wpc->data_seq); &wpc->cow_seq : &wpc->data_seq);
if (error) if (error)
return error; return error;
ASSERT(whichfork == XFS_COW_FORK || cow_fsb == NULLFILEOFF || ASSERT(wpc->fork == XFS_COW_FORK || cow_fsb == NULLFILEOFF ||
imap.br_startoff + imap.br_blockcount <= cow_fsb); imap.br_startoff + imap.br_blockcount <= cow_fsb);
wpc->imap = imap; wpc->imap = imap;
trace_xfs_map_blocks_alloc(ip, offset, count, wpc->io_type, &imap); trace_xfs_map_blocks_alloc(ip, offset, count, wpc->fork, &imap);
return 0; return 0;
} }
@ -505,7 +495,7 @@ xfs_submit_ioend(
int status) int status)
{ {
/* Convert CoW extents to regular */ /* Convert CoW extents to regular */
if (!status && ioend->io_type == XFS_IO_COW) { if (!status && ioend->io_fork == XFS_COW_FORK) {
/* /*
* Yuk. This can do memory allocation, but is not a * Yuk. This can do memory allocation, but is not a
* transactional operation so everything is done in GFP_KERNEL * transactional operation so everything is done in GFP_KERNEL
@ -523,7 +513,8 @@ xfs_submit_ioend(
/* Reserve log space if we might write beyond the on-disk inode size. */ /* Reserve log space if we might write beyond the on-disk inode size. */
if (!status && if (!status &&
ioend->io_type != XFS_IO_UNWRITTEN && (ioend->io_fork == XFS_COW_FORK ||
ioend->io_state != XFS_EXT_UNWRITTEN) &&
xfs_ioend_is_append(ioend) && xfs_ioend_is_append(ioend) &&
!ioend->io_append_trans) !ioend->io_append_trans)
status = xfs_setfilesize_trans_alloc(ioend); status = xfs_setfilesize_trans_alloc(ioend);
@ -552,7 +543,8 @@ xfs_submit_ioend(
static struct xfs_ioend * static struct xfs_ioend *
xfs_alloc_ioend( xfs_alloc_ioend(
struct inode *inode, struct inode *inode,
unsigned int type, int fork,
xfs_exntst_t state,
xfs_off_t offset, xfs_off_t offset,
struct block_device *bdev, struct block_device *bdev,
sector_t sector) sector_t sector)
@ -566,7 +558,8 @@ xfs_alloc_ioend(
ioend = container_of(bio, struct xfs_ioend, io_inline_bio); ioend = container_of(bio, struct xfs_ioend, io_inline_bio);
INIT_LIST_HEAD(&ioend->io_list); INIT_LIST_HEAD(&ioend->io_list);
ioend->io_type = type; ioend->io_fork = fork;
ioend->io_state = state;
ioend->io_inode = inode; ioend->io_inode = inode;
ioend->io_size = 0; ioend->io_size = 0;
ioend->io_offset = offset; ioend->io_offset = offset;
@ -627,13 +620,15 @@ xfs_add_to_ioend(
sector = xfs_fsb_to_db(ip, wpc->imap.br_startblock) + sector = xfs_fsb_to_db(ip, wpc->imap.br_startblock) +
((offset - XFS_FSB_TO_B(mp, wpc->imap.br_startoff)) >> 9); ((offset - XFS_FSB_TO_B(mp, wpc->imap.br_startoff)) >> 9);
if (!wpc->ioend || wpc->io_type != wpc->ioend->io_type || if (!wpc->ioend ||
wpc->fork != wpc->ioend->io_fork ||
wpc->imap.br_state != wpc->ioend->io_state ||
sector != bio_end_sector(wpc->ioend->io_bio) || sector != bio_end_sector(wpc->ioend->io_bio) ||
offset != wpc->ioend->io_offset + wpc->ioend->io_size) { offset != wpc->ioend->io_offset + wpc->ioend->io_size) {
if (wpc->ioend) if (wpc->ioend)
list_add(&wpc->ioend->io_list, iolist); list_add(&wpc->ioend->io_list, iolist);
wpc->ioend = xfs_alloc_ioend(inode, wpc->io_type, offset, wpc->ioend = xfs_alloc_ioend(inode, wpc->fork,
bdev, sector); wpc->imap.br_state, offset, bdev, sector);
} }
if (!__bio_try_merge_page(wpc->ioend->io_bio, page, len, poff)) { if (!__bio_try_merge_page(wpc->ioend->io_bio, page, len, poff)) {
@ -742,7 +737,7 @@ xfs_writepage_map(
error = xfs_map_blocks(wpc, inode, file_offset); error = xfs_map_blocks(wpc, inode, file_offset);
if (error) if (error)
break; break;
if (wpc->io_type == XFS_IO_HOLE) if (wpc->imap.br_startblock == HOLESTARTBLOCK)
continue; continue;
xfs_add_to_ioend(inode, file_offset, page, iop, wpc, wbc, xfs_add_to_ioend(inode, file_offset, page, iop, wpc, wbc,
&submit_list); &submit_list);
@ -937,9 +932,7 @@ xfs_vm_writepage(
struct page *page, struct page *page,
struct writeback_control *wbc) struct writeback_control *wbc)
{ {
struct xfs_writepage_ctx wpc = { struct xfs_writepage_ctx wpc = { };
.io_type = XFS_IO_HOLE,
};
int ret; int ret;
ret = xfs_do_writepage(page, wbc, &wpc); ret = xfs_do_writepage(page, wbc, &wpc);
@ -953,9 +946,7 @@ xfs_vm_writepages(
struct address_space *mapping, struct address_space *mapping,
struct writeback_control *wbc) struct writeback_control *wbc)
{ {
struct xfs_writepage_ctx wpc = { struct xfs_writepage_ctx wpc = { };
.io_type = XFS_IO_HOLE,
};
int ret; int ret;
xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED); xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);

View File

@ -8,33 +8,13 @@
extern struct bio_set xfs_ioend_bioset; extern struct bio_set xfs_ioend_bioset;
/*
* Types of I/O for bmap clustering and I/O completion tracking.
*
* This enum is used in string mapping in xfs_trace.h; please keep the
* TRACE_DEFINE_ENUMs for it up to date.
*/
enum {
XFS_IO_HOLE, /* covers region without any block allocation */
XFS_IO_DELALLOC, /* covers delalloc region */
XFS_IO_UNWRITTEN, /* covers allocated but uninitialized data */
XFS_IO_OVERWRITE, /* covers already allocated extent */
XFS_IO_COW, /* covers copy-on-write extent */
};
#define XFS_IO_TYPES \
{ XFS_IO_HOLE, "hole" }, \
{ XFS_IO_DELALLOC, "delalloc" }, \
{ XFS_IO_UNWRITTEN, "unwritten" }, \
{ XFS_IO_OVERWRITE, "overwrite" }, \
{ XFS_IO_COW, "CoW" }
/* /*
* Structure for buffered I/O completions. * Structure for buffered I/O completions.
*/ */
struct xfs_ioend { struct xfs_ioend {
struct list_head io_list; /* next ioend in chain */ struct list_head io_list; /* next ioend in chain */
unsigned int io_type; /* delalloc / unwritten */ int io_fork; /* inode fork written back */
xfs_exntst_t io_state; /* extent state */
struct inode *io_inode; /* file being written to */ struct inode *io_inode; /* file being written to */
size_t io_size; /* size of the extent */ size_t io_size; /* size of the extent */
xfs_off_t io_offset; /* offset in the file */ xfs_off_t io_offset; /* offset in the file */

View File

@ -575,7 +575,7 @@ xfs_file_iomap_begin_delay(
goto out_unlock; goto out_unlock;
} }
trace_xfs_iomap_found(ip, offset, count, 0, &got); trace_xfs_iomap_found(ip, offset, count, XFS_DATA_FORK, &got);
goto done; goto done;
} }
@ -647,7 +647,7 @@ retry:
* them out if the write happens to fail. * them out if the write happens to fail.
*/ */
iomap->flags |= IOMAP_F_NEW; iomap->flags |= IOMAP_F_NEW;
trace_xfs_iomap_alloc(ip, offset, count, 0, &got); trace_xfs_iomap_alloc(ip, offset, count, XFS_DATA_FORK, &got);
done: done:
if (isnullstartblock(got.br_startblock)) if (isnullstartblock(got.br_startblock))
got.br_startblock = DELAYSTARTBLOCK; got.br_startblock = DELAYSTARTBLOCK;
@ -1082,7 +1082,7 @@ xfs_file_iomap_begin(
return error; return error;
iomap->flags |= IOMAP_F_NEW; iomap->flags |= IOMAP_F_NEW;
trace_xfs_iomap_alloc(ip, offset, length, 0, &imap); trace_xfs_iomap_alloc(ip, offset, length, XFS_DATA_FORK, &imap);
out_finish: out_finish:
if (xfs_ipincount(ip) && (ip->i_itemp->ili_fsync_fields if (xfs_ipincount(ip) && (ip->i_itemp->ili_fsync_fields
@ -1098,7 +1098,7 @@ out_finish:
out_found: out_found:
ASSERT(nimaps); ASSERT(nimaps);
xfs_iunlock(ip, lockmode); xfs_iunlock(ip, lockmode);
trace_xfs_iomap_found(ip, offset, length, 0, &imap); trace_xfs_iomap_found(ip, offset, length, XFS_DATA_FORK, &imap);
goto out_finish; goto out_finish;
out_unlock: out_unlock:

View File

@ -1192,7 +1192,7 @@ xfs_reflink_remap_blocks(
break; break;
ASSERT(nimaps == 1); ASSERT(nimaps == 1);
trace_xfs_reflink_remap_imap(src, srcoff, len, XFS_IO_OVERWRITE, trace_xfs_reflink_remap_imap(src, srcoff, len, XFS_DATA_FORK,
&imap); &imap);
/* Translate imap into the destination file. */ /* Translate imap into the destination file. */

View File

@ -1218,23 +1218,17 @@ DEFINE_EVENT(xfs_readpage_class, name, \
DEFINE_READPAGE_EVENT(xfs_vm_readpage); DEFINE_READPAGE_EVENT(xfs_vm_readpage);
DEFINE_READPAGE_EVENT(xfs_vm_readpages); DEFINE_READPAGE_EVENT(xfs_vm_readpages);
TRACE_DEFINE_ENUM(XFS_IO_HOLE);
TRACE_DEFINE_ENUM(XFS_IO_DELALLOC);
TRACE_DEFINE_ENUM(XFS_IO_UNWRITTEN);
TRACE_DEFINE_ENUM(XFS_IO_OVERWRITE);
TRACE_DEFINE_ENUM(XFS_IO_COW);
DECLARE_EVENT_CLASS(xfs_imap_class, DECLARE_EVENT_CLASS(xfs_imap_class,
TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count, TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count,
int type, struct xfs_bmbt_irec *irec), int whichfork, struct xfs_bmbt_irec *irec),
TP_ARGS(ip, offset, count, type, irec), TP_ARGS(ip, offset, count, whichfork, irec),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(dev_t, dev) __field(dev_t, dev)
__field(xfs_ino_t, ino) __field(xfs_ino_t, ino)
__field(loff_t, size) __field(loff_t, size)
__field(loff_t, offset) __field(loff_t, offset)
__field(size_t, count) __field(size_t, count)
__field(int, type) __field(int, whichfork)
__field(xfs_fileoff_t, startoff) __field(xfs_fileoff_t, startoff)
__field(xfs_fsblock_t, startblock) __field(xfs_fsblock_t, startblock)
__field(xfs_filblks_t, blockcount) __field(xfs_filblks_t, blockcount)
@ -1245,33 +1239,33 @@ DECLARE_EVENT_CLASS(xfs_imap_class,
__entry->size = ip->i_d.di_size; __entry->size = ip->i_d.di_size;
__entry->offset = offset; __entry->offset = offset;
__entry->count = count; __entry->count = count;
__entry->type = type; __entry->whichfork = whichfork;
__entry->startoff = irec ? irec->br_startoff : 0; __entry->startoff = irec ? irec->br_startoff : 0;
__entry->startblock = irec ? irec->br_startblock : 0; __entry->startblock = irec ? irec->br_startblock : 0;
__entry->blockcount = irec ? irec->br_blockcount : 0; __entry->blockcount = irec ? irec->br_blockcount : 0;
), ),
TP_printk("dev %d:%d ino 0x%llx size 0x%llx offset 0x%llx count %zd " TP_printk("dev %d:%d ino 0x%llx size 0x%llx offset 0x%llx count %zd "
"type %s startoff 0x%llx startblock %lld blockcount 0x%llx", "fork %s startoff 0x%llx startblock %lld blockcount 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino, __entry->ino,
__entry->size, __entry->size,
__entry->offset, __entry->offset,
__entry->count, __entry->count,
__print_symbolic(__entry->type, XFS_IO_TYPES), __entry->whichfork == XFS_COW_FORK ? "cow" : "data",
__entry->startoff, __entry->startoff,
(int64_t)__entry->startblock, (int64_t)__entry->startblock,
__entry->blockcount) __entry->blockcount)
) )
#define DEFINE_IOMAP_EVENT(name) \ #define DEFINE_IMAP_EVENT(name) \
DEFINE_EVENT(xfs_imap_class, name, \ DEFINE_EVENT(xfs_imap_class, name, \
TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count, \ TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count, \
int type, struct xfs_bmbt_irec *irec), \ int whichfork, struct xfs_bmbt_irec *irec), \
TP_ARGS(ip, offset, count, type, irec)) TP_ARGS(ip, offset, count, whichfork, irec))
DEFINE_IOMAP_EVENT(xfs_map_blocks_found); DEFINE_IMAP_EVENT(xfs_map_blocks_found);
DEFINE_IOMAP_EVENT(xfs_map_blocks_alloc); DEFINE_IMAP_EVENT(xfs_map_blocks_alloc);
DEFINE_IOMAP_EVENT(xfs_iomap_alloc); DEFINE_IMAP_EVENT(xfs_iomap_alloc);
DEFINE_IOMAP_EVENT(xfs_iomap_found); DEFINE_IMAP_EVENT(xfs_iomap_found);
DECLARE_EVENT_CLASS(xfs_simple_io_class, DECLARE_EVENT_CLASS(xfs_simple_io_class,
TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count), TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count),
@ -3078,7 +3072,7 @@ DEFINE_EVENT(xfs_inode_irec_class, name, \
DEFINE_INODE_EVENT(xfs_reflink_set_inode_flag); DEFINE_INODE_EVENT(xfs_reflink_set_inode_flag);
DEFINE_INODE_EVENT(xfs_reflink_unset_inode_flag); DEFINE_INODE_EVENT(xfs_reflink_unset_inode_flag);
DEFINE_ITRUNC_EVENT(xfs_reflink_update_inode_size); DEFINE_ITRUNC_EVENT(xfs_reflink_update_inode_size);
DEFINE_IOMAP_EVENT(xfs_reflink_remap_imap); DEFINE_IMAP_EVENT(xfs_reflink_remap_imap);
TRACE_EVENT(xfs_reflink_remap_blocks_loop, TRACE_EVENT(xfs_reflink_remap_blocks_loop,
TP_PROTO(struct xfs_inode *src, xfs_fileoff_t soffset, TP_PROTO(struct xfs_inode *src, xfs_fileoff_t soffset,
xfs_filblks_t len, struct xfs_inode *dest, xfs_filblks_t len, struct xfs_inode *dest,