diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-03-27 10:34:47 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-05-14 17:20:17 -0400 |
commit | 467f78992a0743e0e71729e4faa20b67b0f25289 (patch) | |
tree | 2757c82c33b643105a8c0b42a12f61b96d6e2a19 /fs/xfs/xfs_file.c | |
parent | b4d05e3019692fc5a8c573fbce60de2d48c5b7a1 (diff) |
xfs: reduce ilock hold times in xfs_file_aio_write_checks
We do not need the ilock for generic_write_checks and the i_size_read,
which are protected by i_mutex and/or iolock, so reduce the ilock
critical section to just the call to xfs_zero_eof.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_file.c')
-rw-r--r-- | fs/xfs/xfs_file.c | 23 |
1 files changed, 9 insertions, 14 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 54a67dd9ac0..3537c8d0af4 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -593,35 +593,31 @@ xfs_file_aio_write_checks( | |||
593 | struct xfs_inode *ip = XFS_I(inode); | 593 | struct xfs_inode *ip = XFS_I(inode); |
594 | int error = 0; | 594 | int error = 0; |
595 | 595 | ||
596 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL); | ||
597 | restart: | 596 | restart: |
598 | error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode)); | 597 | error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode)); |
599 | if (error) { | 598 | if (error) |
600 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); | ||
601 | return error; | 599 | return error; |
602 | } | ||
603 | 600 | ||
604 | /* | 601 | /* |
605 | * If the offset is beyond the size of the file, we need to zero any | 602 | * If the offset is beyond the size of the file, we need to zero any |
606 | * blocks that fall between the existing EOF and the start of this | 603 | * blocks that fall between the existing EOF and the start of this |
607 | * write. If zeroing is needed and we are currently holding the | 604 | * write. If zeroing is needed and we are currently holding the |
608 | * iolock shared, we need to update it to exclusive which involves | 605 | * iolock shared, we need to update it to exclusive which implies |
609 | * dropping all locks and relocking to maintain correct locking order. | 606 | * having to redo all checks before. |
610 | * If we do this, restart the function to ensure all checks and values | ||
611 | * are still valid. | ||
612 | */ | 607 | */ |
613 | if (*pos > i_size_read(inode)) { | 608 | if (*pos > i_size_read(inode)) { |
614 | if (*iolock == XFS_IOLOCK_SHARED) { | 609 | if (*iolock == XFS_IOLOCK_SHARED) { |
615 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock); | 610 | xfs_rw_iunlock(ip, *iolock); |
616 | *iolock = XFS_IOLOCK_EXCL; | 611 | *iolock = XFS_IOLOCK_EXCL; |
617 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); | 612 | xfs_rw_ilock(ip, *iolock); |
618 | goto restart; | 613 | goto restart; |
619 | } | 614 | } |
615 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL); | ||
620 | error = -xfs_zero_eof(ip, *pos, i_size_read(inode)); | 616 | error = -xfs_zero_eof(ip, *pos, i_size_read(inode)); |
617 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); | ||
618 | if (error) | ||
619 | return error; | ||
621 | } | 620 | } |
622 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); | ||
623 | if (error) | ||
624 | return error; | ||
625 | 621 | ||
626 | /* | 622 | /* |
627 | * Updating the timestamps will grab the ilock again from | 623 | * Updating the timestamps will grab the ilock again from |
@@ -638,7 +634,6 @@ restart: | |||
638 | * people from modifying setuid and setgid binaries. | 634 | * people from modifying setuid and setgid binaries. |
639 | */ | 635 | */ |
640 | return file_remove_suid(file); | 636 | return file_remove_suid(file); |
641 | |||
642 | } | 637 | } |
643 | 638 | ||
644 | /* | 639 | /* |