aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDavid Chinner <dgc@sgi.com>2007-05-24 01:27:03 -0400
committerTim Shimmin <tes@chook.melbourne.sgi.com>2007-05-29 04:15:17 -0400
commitdf3c7244264f1d12562413aa32d56be802486516 (patch)
tree99570b393dc5890fc1751c56aad3deffb0d1c95b /fs
parentc420bc9f09a0926b708c3edb27eacba434a4f4ba (diff)
[XFS] Write at EOF may not update filesize correctly.
The recent fix for preventing NULL files from being left around does not update the file size corectly in all cases. The missing case is a write extending the file that does not need to allocate a block. In that case we used a read mapping of the extent which forced the use of the read I/O completion handler instead of the write I/O completion handle. Hence the file size was not updated on I/O completion. SGI-PV: 965068 SGI-Modid: xfs-linux-melb:xfs-kern:28657a Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Nathan Scott <nscott@aconex.com> Signed-off-by: Tim Shimmin <tes@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 4475588e973a..7361861e3aac 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -701,7 +701,7 @@ xfs_is_delayed_page(
701 else if (buffer_delay(bh)) 701 else if (buffer_delay(bh))
702 acceptable = (type == IOMAP_DELAY); 702 acceptable = (type == IOMAP_DELAY);
703 else if (buffer_dirty(bh) && buffer_mapped(bh)) 703 else if (buffer_dirty(bh) && buffer_mapped(bh))
704 acceptable = (type == 0); 704 acceptable = (type == IOMAP_NEW);
705 else 705 else
706 break; 706 break;
707 } while ((bh = bh->b_this_page) != head); 707 } while ((bh = bh->b_this_page) != head);
@@ -810,7 +810,7 @@ xfs_convert_page(
810 page_dirty--; 810 page_dirty--;
811 count++; 811 count++;
812 } else { 812 } else {
813 type = 0; 813 type = IOMAP_NEW;
814 if (buffer_mapped(bh) && all_bh && startio) { 814 if (buffer_mapped(bh) && all_bh && startio) {
815 lock_buffer(bh); 815 lock_buffer(bh);
816 xfs_add_to_ioend(inode, bh, offset, 816 xfs_add_to_ioend(inode, bh, offset,
@@ -968,8 +968,8 @@ xfs_page_state_convert(
968 968
969 bh = head = page_buffers(page); 969 bh = head = page_buffers(page);
970 offset = page_offset(page); 970 offset = page_offset(page);
971 flags = -1; 971 flags = BMAPI_READ;
972 type = IOMAP_READ; 972 type = IOMAP_NEW;
973 973
974 /* TODO: cleanup count and page_dirty */ 974 /* TODO: cleanup count and page_dirty */
975 975
@@ -999,14 +999,14 @@ xfs_page_state_convert(
999 * 999 *
1000 * Third case, an unmapped buffer was found, and we are 1000 * Third case, an unmapped buffer was found, and we are
1001 * in a path where we need to write the whole page out. 1001 * in a path where we need to write the whole page out.
1002 */ 1002 */
1003 if (buffer_unwritten(bh) || buffer_delay(bh) || 1003 if (buffer_unwritten(bh) || buffer_delay(bh) ||
1004 ((buffer_uptodate(bh) || PageUptodate(page)) && 1004 ((buffer_uptodate(bh) || PageUptodate(page)) &&
1005 !buffer_mapped(bh) && (unmapped || startio))) { 1005 !buffer_mapped(bh) && (unmapped || startio))) {
1006 /* 1006 /*
1007 * Make sure we don't use a read-only iomap 1007 * Make sure we don't use a read-only iomap
1008 */ 1008 */
1009 if (flags == BMAPI_READ) 1009 if (flags == BMAPI_READ)
1010 iomap_valid = 0; 1010 iomap_valid = 0;
1011 1011
1012 if (buffer_unwritten(bh)) { 1012 if (buffer_unwritten(bh)) {
@@ -1055,7 +1055,7 @@ xfs_page_state_convert(
1055 * That means it must already have extents allocated 1055 * That means it must already have extents allocated
1056 * underneath it. Map the extent by reading it. 1056 * underneath it. Map the extent by reading it.
1057 */ 1057 */
1058 if (!iomap_valid || type != IOMAP_READ) { 1058 if (!iomap_valid || flags != BMAPI_READ) {
1059 flags = BMAPI_READ; 1059 flags = BMAPI_READ;
1060 size = xfs_probe_cluster(inode, page, bh, 1060 size = xfs_probe_cluster(inode, page, bh,
1061 head, 1); 1061 head, 1);
@@ -1066,7 +1066,15 @@ xfs_page_state_convert(
1066 iomap_valid = xfs_iomap_valid(&iomap, offset); 1066 iomap_valid = xfs_iomap_valid(&iomap, offset);
1067 } 1067 }
1068 1068
1069 type = IOMAP_READ; 1069 /*
1070 * We set the type to IOMAP_NEW in case we are doing a
1071 * small write at EOF that is extending the file but
1072 * without needing an allocation. We need to update the
1073 * file size on I/O completion in this case so it is
1074 * the same case as having just allocated a new extent
1075 * that we are writing into for the first time.
1076 */
1077 type = IOMAP_NEW;
1070 if (!test_and_set_bit(BH_Lock, &bh->b_state)) { 1078 if (!test_and_set_bit(BH_Lock, &bh->b_state)) {
1071 ASSERT(buffer_mapped(bh)); 1079 ASSERT(buffer_mapped(bh));
1072 if (iomap_valid) 1080 if (iomap_valid)