diff options
author | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-12-22 01:56:49 -0500 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-12-22 01:56:49 -0500 |
commit | 9f6c92b9cc2fd41d6c7b493be5637cc5b5659880 (patch) | |
tree | 64ea95c3305d2bba4191f7dec831e623bff8a911 /fs/xfs/xfs_iomap.c | |
parent | 4fdc7781799926dca6c3a3bb6e9533a9718c4dea (diff) |
[XFS] Fix speculative allocation beyond eof
Speculative allocation beyond eof doesn't work properly. It was
broken some time ago after a code cleanup that moved what is now
xfs_iomap_eof_align_last_fsb() and xfs_iomap_eof_want_preallocate()
out of xfs_iomap_write_delay() into separate functions. The code
used to use the current file size in various checks but got changed
to be max(file_size, i_new_size). Since i_new_size is the result
of 'offset + count' then in xfs_iomap_eof_want_preallocate() the
check for '(offset + count) <= isize' will always be true.
ie if 'offset + count' is > ip->i_size then isize will be i_new_size
and equal to 'offset + count'.
This change fixes all the places that used to use the current file
size.
Reviewed-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_iomap.c')
-rw-r--r-- | fs/xfs/xfs_iomap.c | 28 |
1 files changed, 7 insertions, 21 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 67f22b2b44b3..911062cf73a6 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -290,7 +290,6 @@ STATIC int | |||
290 | xfs_iomap_eof_align_last_fsb( | 290 | xfs_iomap_eof_align_last_fsb( |
291 | xfs_mount_t *mp, | 291 | xfs_mount_t *mp, |
292 | xfs_inode_t *ip, | 292 | xfs_inode_t *ip, |
293 | xfs_fsize_t isize, | ||
294 | xfs_extlen_t extsize, | 293 | xfs_extlen_t extsize, |
295 | xfs_fileoff_t *last_fsb) | 294 | xfs_fileoff_t *last_fsb) |
296 | { | 295 | { |
@@ -306,14 +305,14 @@ xfs_iomap_eof_align_last_fsb( | |||
306 | * stripe width and we are allocating past the allocation eof. | 305 | * stripe width and we are allocating past the allocation eof. |
307 | */ | 306 | */ |
308 | else if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC) && | 307 | else if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC) && |
309 | (isize >= XFS_FSB_TO_B(mp, mp->m_swidth))) | 308 | (ip->i_size >= XFS_FSB_TO_B(mp, mp->m_swidth))) |
310 | new_last_fsb = roundup_64(*last_fsb, mp->m_swidth); | 309 | new_last_fsb = roundup_64(*last_fsb, mp->m_swidth); |
311 | /* | 310 | /* |
312 | * Roundup the allocation request to a stripe unit (m_dalign) boundary | 311 | * Roundup the allocation request to a stripe unit (m_dalign) boundary |
313 | * if the file size is >= stripe unit size, and we are allocating past | 312 | * if the file size is >= stripe unit size, and we are allocating past |
314 | * the allocation eof. | 313 | * the allocation eof. |
315 | */ | 314 | */ |
316 | else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign))) | 315 | else if (mp->m_dalign && (ip->i_size >= XFS_FSB_TO_B(mp, mp->m_dalign))) |
317 | new_last_fsb = roundup_64(*last_fsb, mp->m_dalign); | 316 | new_last_fsb = roundup_64(*last_fsb, mp->m_dalign); |
318 | 317 | ||
319 | /* | 318 | /* |
@@ -403,7 +402,6 @@ xfs_iomap_write_direct( | |||
403 | xfs_filblks_t count_fsb, resaligned; | 402 | xfs_filblks_t count_fsb, resaligned; |
404 | xfs_fsblock_t firstfsb; | 403 | xfs_fsblock_t firstfsb; |
405 | xfs_extlen_t extsz, temp; | 404 | xfs_extlen_t extsz, temp; |
406 | xfs_fsize_t isize; | ||
407 | int nimaps; | 405 | int nimaps; |
408 | int bmapi_flag; | 406 | int bmapi_flag; |
409 | int quota_flag; | 407 | int quota_flag; |
@@ -426,15 +424,10 @@ xfs_iomap_write_direct( | |||
426 | rt = XFS_IS_REALTIME_INODE(ip); | 424 | rt = XFS_IS_REALTIME_INODE(ip); |
427 | extsz = xfs_get_extsz_hint(ip); | 425 | extsz = xfs_get_extsz_hint(ip); |
428 | 426 | ||
429 | isize = ip->i_size; | ||
430 | if (ip->i_new_size > isize) | ||
431 | isize = ip->i_new_size; | ||
432 | |||
433 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 427 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
434 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); | 428 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); |
435 | if ((offset + count) > isize) { | 429 | if ((offset + count) > ip->i_size) { |
436 | error = xfs_iomap_eof_align_last_fsb(mp, ip, isize, extsz, | 430 | error = xfs_iomap_eof_align_last_fsb(mp, ip, extsz, &last_fsb); |
437 | &last_fsb); | ||
438 | if (error) | 431 | if (error) |
439 | goto error_out; | 432 | goto error_out; |
440 | } else { | 433 | } else { |
@@ -559,7 +552,6 @@ STATIC int | |||
559 | xfs_iomap_eof_want_preallocate( | 552 | xfs_iomap_eof_want_preallocate( |
560 | xfs_mount_t *mp, | 553 | xfs_mount_t *mp, |
561 | xfs_inode_t *ip, | 554 | xfs_inode_t *ip, |
562 | xfs_fsize_t isize, | ||
563 | xfs_off_t offset, | 555 | xfs_off_t offset, |
564 | size_t count, | 556 | size_t count, |
565 | int ioflag, | 557 | int ioflag, |
@@ -573,7 +565,7 @@ xfs_iomap_eof_want_preallocate( | |||
573 | int n, error, imaps; | 565 | int n, error, imaps; |
574 | 566 | ||
575 | *prealloc = 0; | 567 | *prealloc = 0; |
576 | if ((ioflag & BMAPI_SYNC) || (offset + count) <= isize) | 568 | if ((ioflag & BMAPI_SYNC) || (offset + count) <= ip->i_size) |
577 | return 0; | 569 | return 0; |
578 | 570 | ||
579 | /* | 571 | /* |
@@ -617,7 +609,6 @@ xfs_iomap_write_delay( | |||
617 | xfs_fileoff_t ioalign; | 609 | xfs_fileoff_t ioalign; |
618 | xfs_fsblock_t firstblock; | 610 | xfs_fsblock_t firstblock; |
619 | xfs_extlen_t extsz; | 611 | xfs_extlen_t extsz; |
620 | xfs_fsize_t isize; | ||
621 | int nimaps; | 612 | int nimaps; |
622 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; | 613 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; |
623 | int prealloc, fsynced = 0; | 614 | int prealloc, fsynced = 0; |
@@ -637,11 +628,7 @@ xfs_iomap_write_delay( | |||
637 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 628 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
638 | 629 | ||
639 | retry: | 630 | retry: |
640 | isize = ip->i_size; | 631 | error = xfs_iomap_eof_want_preallocate(mp, ip, offset, count, |
641 | if (ip->i_new_size > isize) | ||
642 | isize = ip->i_new_size; | ||
643 | |||
644 | error = xfs_iomap_eof_want_preallocate(mp, ip, isize, offset, count, | ||
645 | ioflag, imap, XFS_WRITE_IMAPS, &prealloc); | 632 | ioflag, imap, XFS_WRITE_IMAPS, &prealloc); |
646 | if (error) | 633 | if (error) |
647 | return error; | 634 | return error; |
@@ -655,8 +642,7 @@ retry: | |||
655 | } | 642 | } |
656 | 643 | ||
657 | if (prealloc || extsz) { | 644 | if (prealloc || extsz) { |
658 | error = xfs_iomap_eof_align_last_fsb(mp, ip, isize, extsz, | 645 | error = xfs_iomap_eof_align_last_fsb(mp, ip, extsz, &last_fsb); |
659 | &last_fsb); | ||
660 | if (error) | 646 | if (error) |
661 | return error; | 647 | return error; |
662 | } | 648 | } |