xfs: remove the i_new_size field in struct xfs_inode
Now that we use the VFS i_size field throughout XFS there is no need for the i_new_size field any more given that the VFS i_size field gets updated in ->write_end before unlocking the page, and thus is always uptodate when writeback could see a page. Removing i_new_size also has the advantage that we will never have to trim back di_size during a failed buffered write, given that it never gets updated past i_size. Note that currently the generic direct I/O code only updates i_size after calling our end_io handler, which requires a small workaround to make sure di_size actually makes it to disk. I hope to fix this properly in the generic code. A downside is that we lose the support for parallel non-overlapping O_DIRECT appending writes that recently was added. I don't think keeping the complex and fragile i_new_size infrastructure for this is a good tradeoff - if we really care about parallel appending writers we should investigate turning the iolock into a range lock, which would also allow for parallel non-overlapping buffered writers. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
committed by
Ben Myers
parent
ce7ae151dd
commit
2813d682e8
@@ -111,8 +111,7 @@ xfs_ioend_new_eof(
|
||||
xfs_fsize_t bsize;
|
||||
|
||||
bsize = ioend->io_offset + ioend->io_size;
|
||||
isize = MAX(i_size_read(VFS_I(ip)), ip->i_new_size);
|
||||
isize = MIN(isize, bsize);
|
||||
isize = MIN(i_size_read(VFS_I(ip)), bsize);
|
||||
return isize > ip->i_d.di_size ? isize : 0;
|
||||
}
|
||||
|
||||
@@ -126,11 +125,7 @@ static inline bool xfs_ioend_is_append(struct xfs_ioend *ioend)
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* Update on-disk file size now that data has been written to disk.
|
||||
*
|
||||
* This function does not block as blocking on the inode lock in IO completion
|
||||
* can lead to IO completion order dependency deadlocks.. If it can't get the
|
||||
@@ -1278,6 +1273,15 @@ xfs_end_io_direct_write(
|
||||
{
|
||||
struct xfs_ioend *ioend = iocb->private;
|
||||
|
||||
/*
|
||||
* While the generic direct I/O code updates the inode size, it does
|
||||
* so only after the end_io handler is called, which means our
|
||||
* end_io handler thinks the on-disk size is outside the in-core
|
||||
* size. To prevent this just update it a little bit earlier here.
|
||||
*/
|
||||
if (offset + size > i_size_read(ioend->io_inode))
|
||||
i_size_write(ioend->io_inode, offset + size);
|
||||
|
||||
/*
|
||||
* blockdev_direct_IO can return an error even after the I/O
|
||||
* completion handler was called. Thus we need to protect
|
||||
@@ -1340,12 +1344,11 @@ xfs_vm_write_failed(
|
||||
|
||||
if (to > inode->i_size) {
|
||||
/*
|
||||
* punch out the delalloc blocks we have already allocated. We
|
||||
* don't call xfs_setattr() to do this as we may be in the
|
||||
* middle of a multi-iovec write and so the vfs inode->i_size
|
||||
* will not match the xfs ip->i_size and so it will zero too
|
||||
* much. Hence we jus truncate the page cache to zero what is
|
||||
* necessary and punch the delalloc blocks directly.
|
||||
* Punch out the delalloc blocks we have already allocated.
|
||||
*
|
||||
* Don't bother with xfs_setattr given that nothing can have
|
||||
* made it to disk yet as the page is still locked at this
|
||||
* point.
|
||||
*/
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
xfs_fileoff_t start_fsb;
|
||||
|
Reference in New Issue
Block a user