aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLachlan McIlroy <lachlan@sgi.com>2007-02-10 02:36:47 -0500
committerTim Shimmin <tes@sgi.com>2007-02-10 02:36:47 -0500
commit681601613759accffd8e8ddbc6f942eba7ecbfe5 (patch)
tree8495ec3a648ca6ea2dce55ed7baf0127fb2ea486
parent2823945fda94e0636be573a037c45cb7b6495af2 (diff)
[XFS] Fix callers of xfs_iozero() to zero the correct range.
The problem is the two callers of xfs_iozero() are rounding out the range to be zeroed to the end of a fsb and in some cases this extends past the new eof. The call to commit_write() in xfs_iozero() will cause the Linux inode's file size to be set too high. SGI-PV: 960788 SGI-Modid: xfs-linux-melb:xfs-kern:28013a Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Tim Shimmin <tes@sgi.com>
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c36
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h2
-rw-r--r--fs/xfs/xfs_inode.c2
3 files changed, 20 insertions, 20 deletions
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 65e79b471d49..50ba4794f19f 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -134,8 +134,7 @@ STATIC int
134xfs_iozero( 134xfs_iozero(
135 struct inode *ip, /* inode */ 135 struct inode *ip, /* inode */
136 loff_t pos, /* offset in file */ 136 loff_t pos, /* offset in file */
137 size_t count, /* size of data to zero */ 137 size_t count) /* size of data to zero */
138 loff_t end_size) /* max file size to set */
139{ 138{
140 unsigned bytes; 139 unsigned bytes;
141 struct page *page; 140 struct page *page;
@@ -172,8 +171,6 @@ xfs_iozero(
172 if (!status) { 171 if (!status) {
173 pos += bytes; 172 pos += bytes;
174 count -= bytes; 173 count -= bytes;
175 if (pos > i_size_read(ip))
176 i_size_write(ip, pos < end_size ? pos : end_size);
177 } 174 }
178 175
179unlock: 176unlock:
@@ -449,8 +446,8 @@ STATIC int /* error (positive) */
449xfs_zero_last_block( 446xfs_zero_last_block(
450 struct inode *ip, 447 struct inode *ip,
451 xfs_iocore_t *io, 448 xfs_iocore_t *io,
452 xfs_fsize_t isize, 449 xfs_fsize_t offset,
453 xfs_fsize_t end_size) 450 xfs_fsize_t isize)
454{ 451{
455 xfs_fileoff_t last_fsb; 452 xfs_fileoff_t last_fsb;
456 xfs_mount_t *mp = io->io_mount; 453 xfs_mount_t *mp = io->io_mount;
@@ -459,7 +456,6 @@ xfs_zero_last_block(
459 int zero_len; 456 int zero_len;
460 int error = 0; 457 int error = 0;
461 xfs_bmbt_irec_t imap; 458 xfs_bmbt_irec_t imap;
462 loff_t loff;
463 459
464 ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); 460 ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
465 461
@@ -494,9 +490,10 @@ xfs_zero_last_block(
494 */ 490 */
495 XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD); 491 XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
496 492
497 loff = XFS_FSB_TO_B(mp, last_fsb);
498 zero_len = mp->m_sb.sb_blocksize - zero_offset; 493 zero_len = mp->m_sb.sb_blocksize - zero_offset;
499 error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size); 494 if (isize + zero_len > offset)
495 zero_len = offset - isize;
496 error = xfs_iozero(ip, isize, zero_len);
500 497
501 XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); 498 XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
502 ASSERT(error >= 0); 499 ASSERT(error >= 0);
@@ -519,14 +516,15 @@ xfs_zero_eof(
519 bhv_vnode_t *vp, 516 bhv_vnode_t *vp,
520 xfs_iocore_t *io, 517 xfs_iocore_t *io,
521 xfs_off_t offset, /* starting I/O offset */ 518 xfs_off_t offset, /* starting I/O offset */
522 xfs_fsize_t isize, /* current inode size */ 519 xfs_fsize_t isize) /* current inode size */
523 xfs_fsize_t end_size) /* terminal inode size */
524{ 520{
525 struct inode *ip = vn_to_inode(vp); 521 struct inode *ip = vn_to_inode(vp);
526 xfs_fileoff_t start_zero_fsb; 522 xfs_fileoff_t start_zero_fsb;
527 xfs_fileoff_t end_zero_fsb; 523 xfs_fileoff_t end_zero_fsb;
528 xfs_fileoff_t zero_count_fsb; 524 xfs_fileoff_t zero_count_fsb;
529 xfs_fileoff_t last_fsb; 525 xfs_fileoff_t last_fsb;
526 xfs_fileoff_t zero_off;
527 xfs_fsize_t zero_len;
530 xfs_mount_t *mp = io->io_mount; 528 xfs_mount_t *mp = io->io_mount;
531 int nimaps; 529 int nimaps;
532 int error = 0; 530 int error = 0;
@@ -540,7 +538,7 @@ xfs_zero_eof(
540 * First handle zeroing the block on which isize resides. 538 * First handle zeroing the block on which isize resides.
541 * We only zero a part of that block so it is handled specially. 539 * We only zero a part of that block so it is handled specially.
542 */ 540 */
543 error = xfs_zero_last_block(ip, io, isize, end_size); 541 error = xfs_zero_last_block(ip, io, offset, isize);
544 if (error) { 542 if (error) {
545 ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); 543 ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
546 ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); 544 ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
@@ -601,10 +599,13 @@ xfs_zero_eof(
601 */ 599 */
602 XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); 600 XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
603 601
604 error = xfs_iozero(ip, 602 zero_off = XFS_FSB_TO_B(mp, start_zero_fsb);
605 XFS_FSB_TO_B(mp, start_zero_fsb), 603 zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount);
606 XFS_FSB_TO_B(mp, imap.br_blockcount), 604
607 end_size); 605 if ((zero_off + zero_len) > offset)
606 zero_len = offset - zero_off;
607
608 error = xfs_iozero(ip, zero_off, zero_len);
608 if (error) { 609 if (error) {
609 goto out_lock; 610 goto out_lock;
610 } 611 }
@@ -783,8 +784,7 @@ start:
783 */ 784 */
784 785
785 if (pos > isize) { 786 if (pos > isize) {
786 error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, 787 error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, isize);
787 isize, pos + count);
788 if (error) { 788 if (error) {
789 xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock); 789 xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
790 goto out_unlock_mutex; 790 goto out_unlock_mutex;
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index c77e62efb742..7ac51b1d2161 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -83,7 +83,7 @@ extern int xfs_bdstrat_cb(struct xfs_buf *);
83extern int xfs_dev_is_read_only(struct xfs_mount *, char *); 83extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
84 84
85extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t, 85extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t,
86 xfs_fsize_t, xfs_fsize_t); 86 xfs_fsize_t);
87extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *, 87extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
88 const struct iovec *, unsigned int, 88 const struct iovec *, unsigned int,
89 loff_t *, int, struct cred *); 89 loff_t *, int, struct cred *);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index e42418f92215..295577d67ea0 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1810,7 +1810,7 @@ xfs_igrow_start(
1810 * and any blocks between the old and new file sizes. 1810 * and any blocks between the old and new file sizes.
1811 */ 1811 */
1812 error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size, 1812 error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size,
1813 ip->i_d.di_size, new_size); 1813 ip->i_d.di_size);
1814 return error; 1814 return error;
1815} 1815}
1816 1816