diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_lrw.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_lrw.c | 48 |
1 files changed, 21 insertions, 27 deletions
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 65e79b471d49..ff8d64eba9f8 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #include "xfs_itable.h" | 43 | #include "xfs_itable.h" |
44 | #include "xfs_rw.h" | 44 | #include "xfs_rw.h" |
45 | #include "xfs_acl.h" | 45 | #include "xfs_acl.h" |
46 | #include "xfs_cap.h" | ||
47 | #include "xfs_mac.h" | ||
48 | #include "xfs_attr.h" | 46 | #include "xfs_attr.h" |
49 | #include "xfs_inode_item.h" | 47 | #include "xfs_inode_item.h" |
50 | #include "xfs_buf_item.h" | 48 | #include "xfs_buf_item.h" |
@@ -134,13 +132,11 @@ STATIC int | |||
134 | xfs_iozero( | 132 | xfs_iozero( |
135 | struct inode *ip, /* inode */ | 133 | struct inode *ip, /* inode */ |
136 | loff_t pos, /* offset in file */ | 134 | loff_t pos, /* offset in file */ |
137 | size_t count, /* size of data to zero */ | 135 | size_t count) /* size of data to zero */ |
138 | loff_t end_size) /* max file size to set */ | ||
139 | { | 136 | { |
140 | unsigned bytes; | 137 | unsigned bytes; |
141 | struct page *page; | 138 | struct page *page; |
142 | struct address_space *mapping; | 139 | struct address_space *mapping; |
143 | char *kaddr; | ||
144 | int status; | 140 | int status; |
145 | 141 | ||
146 | mapping = ip->i_mapping; | 142 | mapping = ip->i_mapping; |
@@ -158,26 +154,21 @@ xfs_iozero( | |||
158 | if (!page) | 154 | if (!page) |
159 | break; | 155 | break; |
160 | 156 | ||
161 | kaddr = kmap(page); | ||
162 | status = mapping->a_ops->prepare_write(NULL, page, offset, | 157 | status = mapping->a_ops->prepare_write(NULL, page, offset, |
163 | offset + bytes); | 158 | offset + bytes); |
164 | if (status) { | 159 | if (status) |
165 | goto unlock; | 160 | goto unlock; |
166 | } | ||
167 | 161 | ||
168 | memset((void *) (kaddr + offset), 0, bytes); | 162 | memclear_highpage_flush(page, offset, bytes); |
169 | flush_dcache_page(page); | 163 | |
170 | status = mapping->a_ops->commit_write(NULL, page, offset, | 164 | status = mapping->a_ops->commit_write(NULL, page, offset, |
171 | offset + bytes); | 165 | offset + bytes); |
172 | if (!status) { | 166 | if (!status) { |
173 | pos += bytes; | 167 | pos += bytes; |
174 | count -= bytes; | 168 | count -= bytes; |
175 | if (pos > i_size_read(ip)) | ||
176 | i_size_write(ip, pos < end_size ? pos : end_size); | ||
177 | } | 169 | } |
178 | 170 | ||
179 | unlock: | 171 | unlock: |
180 | kunmap(page); | ||
181 | unlock_page(page); | 172 | unlock_page(page); |
182 | page_cache_release(page); | 173 | page_cache_release(page); |
183 | if (status) | 174 | if (status) |
@@ -449,8 +440,8 @@ STATIC int /* error (positive) */ | |||
449 | xfs_zero_last_block( | 440 | xfs_zero_last_block( |
450 | struct inode *ip, | 441 | struct inode *ip, |
451 | xfs_iocore_t *io, | 442 | xfs_iocore_t *io, |
452 | xfs_fsize_t isize, | 443 | xfs_fsize_t offset, |
453 | xfs_fsize_t end_size) | 444 | xfs_fsize_t isize) |
454 | { | 445 | { |
455 | xfs_fileoff_t last_fsb; | 446 | xfs_fileoff_t last_fsb; |
456 | xfs_mount_t *mp = io->io_mount; | 447 | xfs_mount_t *mp = io->io_mount; |
@@ -459,7 +450,6 @@ xfs_zero_last_block( | |||
459 | int zero_len; | 450 | int zero_len; |
460 | int error = 0; | 451 | int error = 0; |
461 | xfs_bmbt_irec_t imap; | 452 | xfs_bmbt_irec_t imap; |
462 | loff_t loff; | ||
463 | 453 | ||
464 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); | 454 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); |
465 | 455 | ||
@@ -494,9 +484,10 @@ xfs_zero_last_block( | |||
494 | */ | 484 | */ |
495 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD); | 485 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD); |
496 | 486 | ||
497 | loff = XFS_FSB_TO_B(mp, last_fsb); | ||
498 | zero_len = mp->m_sb.sb_blocksize - zero_offset; | 487 | zero_len = mp->m_sb.sb_blocksize - zero_offset; |
499 | error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size); | 488 | if (isize + zero_len > offset) |
489 | zero_len = offset - isize; | ||
490 | error = xfs_iozero(ip, isize, zero_len); | ||
500 | 491 | ||
501 | XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); | 492 | XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); |
502 | ASSERT(error >= 0); | 493 | ASSERT(error >= 0); |
@@ -519,14 +510,15 @@ xfs_zero_eof( | |||
519 | bhv_vnode_t *vp, | 510 | bhv_vnode_t *vp, |
520 | xfs_iocore_t *io, | 511 | xfs_iocore_t *io, |
521 | xfs_off_t offset, /* starting I/O offset */ | 512 | xfs_off_t offset, /* starting I/O offset */ |
522 | xfs_fsize_t isize, /* current inode size */ | 513 | xfs_fsize_t isize) /* current inode size */ |
523 | xfs_fsize_t end_size) /* terminal inode size */ | ||
524 | { | 514 | { |
525 | struct inode *ip = vn_to_inode(vp); | 515 | struct inode *ip = vn_to_inode(vp); |
526 | xfs_fileoff_t start_zero_fsb; | 516 | xfs_fileoff_t start_zero_fsb; |
527 | xfs_fileoff_t end_zero_fsb; | 517 | xfs_fileoff_t end_zero_fsb; |
528 | xfs_fileoff_t zero_count_fsb; | 518 | xfs_fileoff_t zero_count_fsb; |
529 | xfs_fileoff_t last_fsb; | 519 | xfs_fileoff_t last_fsb; |
520 | xfs_fileoff_t zero_off; | ||
521 | xfs_fsize_t zero_len; | ||
530 | xfs_mount_t *mp = io->io_mount; | 522 | xfs_mount_t *mp = io->io_mount; |
531 | int nimaps; | 523 | int nimaps; |
532 | int error = 0; | 524 | int error = 0; |
@@ -540,7 +532,7 @@ xfs_zero_eof( | |||
540 | * First handle zeroing the block on which isize resides. | 532 | * First handle zeroing the block on which isize resides. |
541 | * We only zero a part of that block so it is handled specially. | 533 | * We only zero a part of that block so it is handled specially. |
542 | */ | 534 | */ |
543 | error = xfs_zero_last_block(ip, io, isize, end_size); | 535 | error = xfs_zero_last_block(ip, io, offset, isize); |
544 | if (error) { | 536 | if (error) { |
545 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); | 537 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); |
546 | ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); | 538 | ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); |
@@ -601,10 +593,13 @@ xfs_zero_eof( | |||
601 | */ | 593 | */ |
602 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); | 594 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); |
603 | 595 | ||
604 | error = xfs_iozero(ip, | 596 | zero_off = XFS_FSB_TO_B(mp, start_zero_fsb); |
605 | XFS_FSB_TO_B(mp, start_zero_fsb), | 597 | zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount); |
606 | XFS_FSB_TO_B(mp, imap.br_blockcount), | 598 | |
607 | end_size); | 599 | if ((zero_off + zero_len) > offset) |
600 | zero_len = offset - zero_off; | ||
601 | |||
602 | error = xfs_iozero(ip, zero_off, zero_len); | ||
608 | if (error) { | 603 | if (error) { |
609 | goto out_lock; | 604 | goto out_lock; |
610 | } | 605 | } |
@@ -783,8 +778,7 @@ start: | |||
783 | */ | 778 | */ |
784 | 779 | ||
785 | if (pos > isize) { | 780 | if (pos > isize) { |
786 | error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, | 781 | error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, isize); |
787 | isize, pos + count); | ||
788 | if (error) { | 782 | if (error) { |
789 | xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock); | 783 | xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock); |
790 | goto out_unlock_mutex; | 784 | goto out_unlock_mutex; |