|
@@ -185,6 +185,24 @@ xfs_destroy_ioend(
|
|
|
mempool_free(ioend, xfs_ioend_pool);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * If the end of the current ioend is beyond the current EOF,
|
|
|
+ * return the new EOF value, otherwise zero.
|
|
|
+ */
|
|
|
+STATIC xfs_fsize_t
|
|
|
+xfs_ioend_new_eof(
|
|
|
+ xfs_ioend_t *ioend)
|
|
|
+{
|
|
|
+ xfs_inode_t *ip = XFS_I(ioend->io_inode);
|
|
|
+ xfs_fsize_t isize;
|
|
|
+ xfs_fsize_t bsize;
|
|
|
+
|
|
|
+ bsize = ioend->io_offset + ioend->io_size;
|
|
|
+ isize = MAX(ip->i_size, ip->i_new_size);
|
|
|
+ isize = MIN(isize, bsize);
|
|
|
+ return isize > ip->i_d.di_size ? isize : 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* 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
|
|
@@ -192,13 +210,13 @@ xfs_destroy_ioend(
|
|
|
* 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_fsize_t bsize;
|
|
|
|
|
|
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
|
|
|
ASSERT(ioend->io_type != IOMAP_READ);
|
|
@@ -206,14 +224,9 @@ xfs_setfilesize(
|
|
|
if (unlikely(ioend->io_error))
|
|
|
return;
|
|
|
|
|
|
- bsize = ioend->io_offset + ioend->io_size;
|
|
|
-
|
|
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
|
|
-
|
|
|
- isize = MAX(ip->i_size, ip->i_new_size);
|
|
|
- isize = MIN(isize, bsize);
|
|
|
-
|
|
|
- if (ip->i_d.di_size < isize) {
|
|
|
+ isize = xfs_ioend_new_eof(ioend);
|
|
|
+ if (isize) {
|
|
|
ip->i_d.di_size = isize;
|
|
|
xfs_mark_inode_dirty_sync(ip);
|
|
|
}
|
|
@@ -403,10 +416,16 @@ xfs_submit_ioend_bio(
|
|
|
struct bio *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_sync(XFS_I(ioend->io_inode));
|
|
|
+
|
|
|
submit_bio(WRITE, bio);
|
|
|
ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP));
|
|
|
bio_put(bio);
|