diff options
author | Christoph Hellwig <hch@infradead.org> | 2011-12-18 15:00:12 -0500 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-01-17 16:10:19 -0500 |
commit | 2813d682e8e6a278f94817429afd46b30875bb6e (patch) | |
tree | d865b04ec89076b692a922b7f5fced9be0458f47 /fs/xfs/xfs_aops.c | |
parent | ce7ae151ddada3dbf67301464343c154903166b3 (diff) |
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>
Diffstat (limited to 'fs/xfs/xfs_aops.c')
-rw-r--r-- | fs/xfs/xfs_aops.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 4d27ea117e0e..74b9baf36ac3 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -111,8 +111,7 @@ xfs_ioend_new_eof( | |||
111 | xfs_fsize_t bsize; | 111 | xfs_fsize_t bsize; |
112 | 112 | ||
113 | bsize = ioend->io_offset + ioend->io_size; | 113 | bsize = ioend->io_offset + ioend->io_size; |
114 | isize = MAX(i_size_read(VFS_I(ip)), ip->i_new_size); | 114 | isize = MIN(i_size_read(VFS_I(ip)), bsize); |
115 | isize = MIN(isize, bsize); | ||
116 | return isize > ip->i_d.di_size ? isize : 0; | 115 | return isize > ip->i_d.di_size ? isize : 0; |
117 | } | 116 | } |
118 | 117 | ||
@@ -126,11 +125,7 @@ static inline bool xfs_ioend_is_append(struct xfs_ioend *ioend) | |||
126 | } | 125 | } |
127 | 126 | ||
128 | /* | 127 | /* |
129 | * Update on-disk file size now that data has been written to disk. The | 128 | * Update on-disk file size now that data has been written to disk. |
130 | * current in-memory file size is i_size. If a write is beyond eof i_new_size | ||
131 | * will be the intended file size until i_size is updated. If this write does | ||
132 | * not extend all the way to the valid file size then restrict this update to | ||
133 | * the end of the write. | ||
134 | * | 129 | * |
135 | * This function does not block as blocking on the inode lock in IO completion | 130 | * This function does not block as blocking on the inode lock in IO completion |
136 | * can lead to IO completion order dependency deadlocks.. If it can't get the | 131 | * can lead to IO completion order dependency deadlocks.. If it can't get the |
@@ -1279,6 +1274,15 @@ xfs_end_io_direct_write( | |||
1279 | struct xfs_ioend *ioend = iocb->private; | 1274 | struct xfs_ioend *ioend = iocb->private; |
1280 | 1275 | ||
1281 | /* | 1276 | /* |
1277 | * While the generic direct I/O code updates the inode size, it does | ||
1278 | * so only after the end_io handler is called, which means our | ||
1279 | * end_io handler thinks the on-disk size is outside the in-core | ||
1280 | * size. To prevent this just update it a little bit earlier here. | ||
1281 | */ | ||
1282 | if (offset + size > i_size_read(ioend->io_inode)) | ||
1283 | i_size_write(ioend->io_inode, offset + size); | ||
1284 | |||
1285 | /* | ||
1282 | * blockdev_direct_IO can return an error even after the I/O | 1286 | * blockdev_direct_IO can return an error even after the I/O |
1283 | * completion handler was called. Thus we need to protect | 1287 | * completion handler was called. Thus we need to protect |
1284 | * against double-freeing. | 1288 | * against double-freeing. |
@@ -1340,12 +1344,11 @@ xfs_vm_write_failed( | |||
1340 | 1344 | ||
1341 | if (to > inode->i_size) { | 1345 | if (to > inode->i_size) { |
1342 | /* | 1346 | /* |
1343 | * punch out the delalloc blocks we have already allocated. We | 1347 | * Punch out the delalloc blocks we have already allocated. |
1344 | * don't call xfs_setattr() to do this as we may be in the | 1348 | * |
1345 | * middle of a multi-iovec write and so the vfs inode->i_size | 1349 | * Don't bother with xfs_setattr given that nothing can have |
1346 | * will not match the xfs ip->i_size and so it will zero too | 1350 | * made it to disk yet as the page is still locked at this |
1347 | * much. Hence we jus truncate the page cache to zero what is | 1351 | * point. |
1348 | * necessary and punch the delalloc blocks directly. | ||
1349 | */ | 1352 | */ |
1350 | struct xfs_inode *ip = XFS_I(inode); | 1353 | struct xfs_inode *ip = XFS_I(inode); |
1351 | xfs_fileoff_t start_fsb; | 1354 | xfs_fileoff_t start_fsb; |