aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 40d2226060d1..6a2910ee8a28 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -186,19 +186,37 @@ xfs_destroy_ioend(
186} 186}
187 187
188/* 188/*
189 * If the end of the current ioend is beyond the current EOF,
190 * return the new EOF value, otherwise zero.
191 */
192STATIC xfs_fsize_t
193xfs_ioend_new_eof(
194 xfs_ioend_t *ioend)
195{
196 xfs_inode_t *ip = XFS_I(ioend->io_inode);
197 xfs_fsize_t isize;
198 xfs_fsize_t bsize;
199
200 bsize = ioend->io_offset + ioend->io_size;
201 isize = MAX(ip->i_size, ip->i_new_size);
202 isize = MIN(isize, bsize);
203 return isize > ip->i_d.di_size ? isize : 0;
204}
205
206/*
189 * Update on-disk file size now that data has been written to disk. 207 * Update on-disk file size now that data has been written to disk.
190 * The current in-memory file size is i_size. If a write is beyond 208 * The current in-memory file size is i_size. If a write is beyond
191 * eof i_new_size will be the intended file size until i_size is 209 * eof i_new_size will be the intended file size until i_size is
192 * updated. If this write does not extend all the way to the valid 210 * updated. If this write does not extend all the way to the valid
193 * file size then restrict this update to the end of the write. 211 * file size then restrict this update to the end of the write.
194 */ 212 */
213
195STATIC void 214STATIC void
196xfs_setfilesize( 215xfs_setfilesize(
197 xfs_ioend_t *ioend) 216 xfs_ioend_t *ioend)
198{ 217{
199 xfs_inode_t *ip = XFS_I(ioend->io_inode); 218 xfs_inode_t *ip = XFS_I(ioend->io_inode);
200 xfs_fsize_t isize; 219 xfs_fsize_t isize;
201 xfs_fsize_t bsize;
202 220
203 ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG); 221 ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
204 ASSERT(ioend->io_type != IOMAP_READ); 222 ASSERT(ioend->io_type != IOMAP_READ);
@@ -206,14 +224,9 @@ xfs_setfilesize(
206 if (unlikely(ioend->io_error)) 224 if (unlikely(ioend->io_error))
207 return; 225 return;
208 226
209 bsize = ioend->io_offset + ioend->io_size;
210
211 xfs_ilock(ip, XFS_ILOCK_EXCL); 227 xfs_ilock(ip, XFS_ILOCK_EXCL);
212 228 isize = xfs_ioend_new_eof(ioend);
213 isize = MAX(ip->i_size, ip->i_new_size); 229 if (isize) {
214 isize = MIN(isize, bsize);
215
216 if (ip->i_d.di_size < isize) {
217 ip->i_d.di_size = isize; 230 ip->i_d.di_size = isize;
218 xfs_mark_inode_dirty_sync(ip); 231 xfs_mark_inode_dirty_sync(ip);
219 } 232 }
@@ -403,10 +416,16 @@ xfs_submit_ioend_bio(
403 struct bio *bio) 416 struct bio *bio)
404{ 417{
405 atomic_inc(&ioend->io_remaining); 418 atomic_inc(&ioend->io_remaining);
406
407 bio->bi_private = ioend; 419 bio->bi_private = ioend;
408 bio->bi_end_io = xfs_end_bio; 420 bio->bi_end_io = xfs_end_bio;
409 421
422 /*
423 * If the I/O is beyond EOF we mark the inode dirty immediately
424 * but don't update the inode size until I/O completion.
425 */
426 if (xfs_ioend_new_eof(ioend))
427 xfs_mark_inode_dirty_sync(XFS_I(ioend->io_inode));
428
410 submit_bio(WRITE, bio); 429 submit_bio(WRITE, bio);
411 ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP)); 430 ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP));
412 bio_put(bio); 431 bio_put(bio);