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 | |
| 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>
| -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 | } |
