tree 0121a8f6fe10e62bbd943defafe6a92c03e633b6 parent f09738638d3bae6501e8e160c66233832d8c280f author Christoph Hellwig <[EMAIL PROTECTED]> Mon, 05 Sep 2005 08:23:35 +1000 committer Nathan Scott <[EMAIL PROTECTED]> Mon, 05 Sep 2005 08:23:35 +1000
[XFS] Delay I/O completion for unwritten extents after conversion SGI-PV: 936584 SGI-Modid: xfs-linux:xfs-kern:196886a Signed-off-by: Christoph Hellwig <[EMAIL PROTECTED]> Signed-off-by: Nathan Scott <[EMAIL PROTECTED]> fs/xfs/linux-2.6/xfs_aops.c | 27 +++++++++++++++++++++++++-- fs/xfs/linux-2.6/xfs_aops.h | 1 + 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -136,10 +136,21 @@ xfs_end_bio_unwritten( vnode_t *vp = ioend->io_vnode; xfs_off_t offset = ioend->io_offset; size_t size = ioend->io_size; + struct buffer_head *bh, *next; int error; if (ioend->io_uptodate) VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error); + + /* ioend->io_buffer_head is only non-NULL for buffered I/O */ + for (bh = ioend->io_buffer_head; bh; bh = next) { + next = bh->b_private; + + bh->b_end_io = NULL; + clear_buffer_unwritten(bh); + end_buffer_async_write(bh, ioend->io_uptodate); + } + xfs_destroy_ioend(ioend); } @@ -165,6 +176,7 @@ xfs_alloc_ioend( atomic_set(&ioend->io_remaining, 1); ioend->io_uptodate = 1; /* cleared if any I/O fails */ ioend->io_vnode = LINVFS_GET_VP(inode); + ioend->io_buffer_head = NULL; atomic_inc(&ioend->io_vnode->v_iocount); ioend->io_offset = 0; ioend->io_size = 0; @@ -180,15 +192,26 @@ linvfs_unwritten_done( int uptodate) { xfs_ioend_t *ioend = bh->b_private; + static spinlock_t unwritten_done_lock = SPIN_LOCK_UNLOCKED; + unsigned long flags; ASSERT(buffer_unwritten(bh)); bh->b_end_io = NULL; - clear_buffer_unwritten(bh); + if (!uptodate) ioend->io_uptodate = 0; + /* + * Deep magic here. We reuse b_private in the buffer_heads to build + * a chain for completing the I/O from user context after we've issued + * a transaction to convert the unwritten extent. + */ + spin_lock_irqsave(&unwritten_done_lock, flags); + bh->b_private = ioend->io_buffer_head; + ioend->io_buffer_head = bh; + spin_unlock_irqrestore(&unwritten_done_lock, flags); + xfs_finish_ioend(ioend); - end_buffer_async_write(bh, uptodate); } STATIC int diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h @@ -41,6 +41,7 @@ typedef struct xfs_ioend { unsigned int io_uptodate; /* I/O status register */ atomic_t io_remaining; /* hold count */ struct vnode *io_vnode; /* file being written to */ + struct buffer_head *io_buffer_head;/* buffer linked list head */ size_t io_size; /* size of the extent */ xfs_off_t io_offset; /* offset in the file */ struct work_struct io_work; /* xfsdatad work queue */ - To unsubscribe from this list: send the line "unsubscribe git-commits-head" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html