Instead of updating the inode size through the VFS dirty mechanism and ->write_inode just log it directly. This may cause a few additional transactions for inode core updates, but with the delaylog code those are cheap enough to not bother. Signed-off-by: Christoph Hellwig <hch@xxxxxx> Index: xfs/fs/xfs/linux-2.6/xfs_aops.c =================================================================== --- xfs.orig/fs/xfs/linux-2.6/xfs_aops.c 2011-06-22 10:58:30.344461631 +0200 +++ xfs/fs/xfs/linux-2.6/xfs_aops.c 2011-06-22 10:58:55.877793671 +0200 @@ -156,29 +156,6 @@ xfs_ioend_new_eof( } /* - * Update on-disk file size now that data has been written to disk. The - * current in-memory file size is i_size. If a write is beyond eof i_new_size - * will be the intended file size until i_size is updated. If this write does - * not extend all the way to the valid file size then restrict this update to - * the end of the write. - */ -STATIC void -xfs_setfilesize( - xfs_ioend_t *ioend) -{ - xfs_inode_t *ip = XFS_I(ioend->io_inode); - xfs_fsize_t isize; - - xfs_ilock(ip, XFS_ILOCK_EXCL); - isize = xfs_ioend_new_eof(ioend); - if (isize) { - ip->i_d.di_size = isize; - xfs_mark_inode_dirty(ip); - } - xfs_iunlock(ip, XFS_ILOCK_EXCL); -} - -/* * Schedule IO completion handling on the final put of an ioend. */ STATIC void @@ -223,10 +200,25 @@ xfs_end_io( } /* - * We might have to update the on-disk file size after extending - * writes. + * Update on-disk file size now that data has been written to disk. + * + * The current in-memory file size is i_size. If a write is beyond + * eof i_new_size will be the intended file size until i_size is + * updated. If this write does not extend all the way to the valid + * file size then restrict this update to the end of the write. */ - xfs_setfilesize(ioend); + if (likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) { + xfs_fsize_t isize; + + xfs_ilock(ip, XFS_ILOCK_EXCL); + isize = xfs_ioend_new_eof(ioend); + if (isize) + error = xfs_setfilesize(ip, isize); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + + if (error) + ioend->io_error = error; + } if (ioend->io_iocb) aio_complete(ioend->io_iocb, ioend->io_result, 0); @@ -386,14 +378,6 @@ xfs_submit_ioend_bio( atomic_inc(&ioend->io_remaining); bio->bi_private = ioend; bio->bi_end_io = xfs_end_bio; - - /* - * If the I/O is beyond EOF we mark the inode dirty immediately - * but don't update the inode size until I/O completion. - */ - if (xfs_ioend_new_eof(ioend)) - xfs_mark_inode_dirty(XFS_I(ioend->io_inode)); - submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, bio); } Index: xfs/fs/xfs/linux-2.6/xfs_file.c =================================================================== --- xfs.orig/fs/xfs/linux-2.6/xfs_file.c 2011-06-22 10:58:30.361128296 +0200 +++ xfs/fs/xfs/linux-2.6/xfs_file.c 2011-06-22 11:16:25.057740552 +0200 @@ -405,7 +405,7 @@ xfs_aio_write_newsize_update( xfs_rw_ilock(ip, XFS_ILOCK_EXCL); ip->i_new_size = 0; if (ip->i_d.di_size > ip->i_size) - ip->i_d.di_size = ip->i_size; + xfs_setfilesize(ip, ip->i_size); xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); } } Index: xfs/fs/xfs/xfs_inode.c =================================================================== --- xfs.orig/fs/xfs/xfs_inode.c 2011-06-22 10:58:30.371128295 +0200 +++ xfs/fs/xfs/xfs_inode.c 2011-06-22 11:17:51.944402819 +0200 @@ -1515,6 +1515,34 @@ xfs_itruncate_finish( } /* + * Update the inode size during I/O completions or error handling. + */ +int +xfs_setfilesize( + struct xfs_inode *ip, + xfs_fsize_t isize) +{ + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + int error = 0; + + ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); + + tp = _xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS, KM_NOFS, true); + error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); + if (error) { + xfs_trans_cancel(tp, 0); + return error; + } + + ip->i_d.di_size = isize; + xfs_trans_ijoin(tp, ip); + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + + return xfs_trans_commit(tp, 0); +} + +/* * This is called when the inode's link count goes to 0. * We place the on-disk inode on a list in the AGI. It * will be pulled from this list when the inode is freed. Index: xfs/fs/xfs/xfs_inode.h =================================================================== --- xfs.orig/fs/xfs/xfs_inode.h 2011-06-22 10:58:30.387794963 +0200 +++ xfs/fs/xfs/xfs_inode.h 2011-06-22 11:16:25.141073882 +0200 @@ -482,6 +482,7 @@ int xfs_ifree(struct xfs_trans *, xfs_i struct xfs_bmap_free *); int xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *, xfs_fsize_t, int, int); +int xfs_setfilesize(struct xfs_inode *, xfs_fsize_t); int xfs_iunlink(struct xfs_trans *, xfs_inode_t *); void xfs_iext_realloc(xfs_inode_t *, int, int); _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs