diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-06-23 19:46:01 -0400 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-07-26 14:16:41 -0400 |
commit | 20cb52ebd1b5ca6fa8a5d9b6b1392292f5ca8a45 (patch) | |
tree | c4644ab4b8b12d2c6100fb47c7dfa4c5949107ca /fs/xfs | |
parent | 89f3b363967a958e756a549c8747c1fb9c930c1a (diff) |
xfs: simplify xfs_vm_writepage
The writepage implementation in XFS still tries to deal with dirty but
unmapped buffers which used to caused by writes through shared mmaps. Since
the introduction of ->page_mkwrite these can't happen anymore, so remove the
code dealing with them.
Note that the all_bh variable which causes us to start I/O on all buffers on
the pages was controlled by the count of unmapped buffers, which also
included those not actually dirty. It's now unconditionally initialized to
0 but set to 1 for the case of small file size extensions. It probably can
be removed entirely, but that's left for another patch.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 139 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.h | 2 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_trace.h | 10 |
3 files changed, 49 insertions, 102 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 7744a3b630e0..1776cdd944b5 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -85,18 +85,15 @@ void | |||
85 | xfs_count_page_state( | 85 | xfs_count_page_state( |
86 | struct page *page, | 86 | struct page *page, |
87 | int *delalloc, | 87 | int *delalloc, |
88 | int *unmapped, | ||
89 | int *unwritten) | 88 | int *unwritten) |
90 | { | 89 | { |
91 | struct buffer_head *bh, *head; | 90 | struct buffer_head *bh, *head; |
92 | 91 | ||
93 | *delalloc = *unmapped = *unwritten = 0; | 92 | *delalloc = *unwritten = 0; |
94 | 93 | ||
95 | bh = head = page_buffers(page); | 94 | bh = head = page_buffers(page); |
96 | do { | 95 | do { |
97 | if (buffer_uptodate(bh) && !buffer_mapped(bh)) | 96 | if (buffer_unwritten(bh)) |
98 | (*unmapped) = 1; | ||
99 | else if (buffer_unwritten(bh)) | ||
100 | (*unwritten) = 1; | 97 | (*unwritten) = 1; |
101 | else if (buffer_delay(bh)) | 98 | else if (buffer_delay(bh)) |
102 | (*delalloc) = 1; | 99 | (*delalloc) = 1; |
@@ -607,31 +604,30 @@ xfs_map_at_offset( | |||
607 | STATIC unsigned int | 604 | STATIC unsigned int |
608 | xfs_probe_page( | 605 | xfs_probe_page( |
609 | struct page *page, | 606 | struct page *page, |
610 | unsigned int pg_offset, | 607 | unsigned int pg_offset) |
611 | int mapped) | ||
612 | { | 608 | { |
609 | struct buffer_head *bh, *head; | ||
613 | int ret = 0; | 610 | int ret = 0; |
614 | 611 | ||
615 | if (PageWriteback(page)) | 612 | if (PageWriteback(page)) |
616 | return 0; | 613 | return 0; |
614 | if (!PageDirty(page)) | ||
615 | return 0; | ||
616 | if (!page->mapping) | ||
617 | return 0; | ||
618 | if (!page_has_buffers(page)) | ||
619 | return 0; | ||
617 | 620 | ||
618 | if (page->mapping && PageDirty(page)) { | 621 | bh = head = page_buffers(page); |
619 | if (page_has_buffers(page)) { | 622 | do { |
620 | struct buffer_head *bh, *head; | 623 | if (!buffer_uptodate(bh)) |
621 | 624 | break; | |
622 | bh = head = page_buffers(page); | 625 | if (!buffer_mapped(bh)) |
623 | do { | 626 | break; |
624 | if (!buffer_uptodate(bh)) | 627 | ret += bh->b_size; |
625 | break; | 628 | if (ret >= pg_offset) |
626 | if (mapped != buffer_mapped(bh)) | 629 | break; |
627 | break; | 630 | } while ((bh = bh->b_this_page) != head); |
628 | ret += bh->b_size; | ||
629 | if (ret >= pg_offset) | ||
630 | break; | ||
631 | } while ((bh = bh->b_this_page) != head); | ||
632 | } else | ||
633 | ret = mapped ? 0 : PAGE_CACHE_SIZE; | ||
634 | } | ||
635 | 631 | ||
636 | return ret; | 632 | return ret; |
637 | } | 633 | } |
@@ -641,8 +637,7 @@ xfs_probe_cluster( | |||
641 | struct inode *inode, | 637 | struct inode *inode, |
642 | struct page *startpage, | 638 | struct page *startpage, |
643 | struct buffer_head *bh, | 639 | struct buffer_head *bh, |
644 | struct buffer_head *head, | 640 | struct buffer_head *head) |
645 | int mapped) | ||
646 | { | 641 | { |
647 | struct pagevec pvec; | 642 | struct pagevec pvec; |
648 | pgoff_t tindex, tlast, tloff; | 643 | pgoff_t tindex, tlast, tloff; |
@@ -651,7 +646,7 @@ xfs_probe_cluster( | |||
651 | 646 | ||
652 | /* First sum forwards in this page */ | 647 | /* First sum forwards in this page */ |
653 | do { | 648 | do { |
654 | if (!buffer_uptodate(bh) || (mapped != buffer_mapped(bh))) | 649 | if (!buffer_uptodate(bh) || !buffer_mapped(bh)) |
655 | return total; | 650 | return total; |
656 | total += bh->b_size; | 651 | total += bh->b_size; |
657 | } while ((bh = bh->b_this_page) != head); | 652 | } while ((bh = bh->b_this_page) != head); |
@@ -685,7 +680,7 @@ xfs_probe_cluster( | |||
685 | pg_offset = PAGE_CACHE_SIZE; | 680 | pg_offset = PAGE_CACHE_SIZE; |
686 | 681 | ||
687 | if (page->index == tindex && trylock_page(page)) { | 682 | if (page->index == tindex && trylock_page(page)) { |
688 | pg_len = xfs_probe_page(page, pg_offset, mapped); | 683 | pg_len = xfs_probe_page(page, pg_offset); |
689 | unlock_page(page); | 684 | unlock_page(page); |
690 | } | 685 | } |
691 | 686 | ||
@@ -1021,18 +1016,12 @@ out_invalidate: | |||
1021 | * For delalloc space on the page we need to allocate space and flush it. | 1016 | * For delalloc space on the page we need to allocate space and flush it. |
1022 | * For unwritten space on the page we need to start the conversion to | 1017 | * For unwritten space on the page we need to start the conversion to |
1023 | * regular allocated space. | 1018 | * regular allocated space. |
1024 | * For unmapped buffer heads on the page we should allocate space if the | ||
1025 | * page is uptodate. | ||
1026 | * For any other dirty buffer heads on the page we should flush them. | 1019 | * For any other dirty buffer heads on the page we should flush them. |
1027 | * | 1020 | * |
1028 | * If we detect that a transaction would be required to flush the page, we | 1021 | * If we detect that a transaction would be required to flush the page, we |
1029 | * have to check the process flags first, if we are already in a transaction | 1022 | * have to check the process flags first, if we are already in a transaction |
1030 | * or disk I/O during allocations is off, we need to fail the writepage and | 1023 | * or disk I/O during allocations is off, we need to fail the writepage and |
1031 | * redirty the page. | 1024 | * redirty the page. |
1032 | * | ||
1033 | * The bh->b_state's cannot know if any of the blocks or which block for that | ||
1034 | * matter are dirty due to mmap writes, and therefore bh uptodate is only | ||
1035 | * valid if the page itself isn't completely uptodate. | ||
1036 | */ | 1025 | */ |
1037 | STATIC int | 1026 | STATIC int |
1038 | xfs_vm_writepage( | 1027 | xfs_vm_writepage( |
@@ -1040,8 +1029,7 @@ xfs_vm_writepage( | |||
1040 | struct writeback_control *wbc) | 1029 | struct writeback_control *wbc) |
1041 | { | 1030 | { |
1042 | struct inode *inode = page->mapping->host; | 1031 | struct inode *inode = page->mapping->host; |
1043 | int need_trans; | 1032 | int delalloc, unwritten; |
1044 | int delalloc, unmapped, unwritten; | ||
1045 | struct buffer_head *bh, *head; | 1033 | struct buffer_head *bh, *head; |
1046 | struct xfs_bmbt_irec imap; | 1034 | struct xfs_bmbt_irec imap; |
1047 | xfs_ioend_t *ioend = NULL, *iohead = NULL; | 1035 | xfs_ioend_t *ioend = NULL, *iohead = NULL; |
@@ -1052,10 +1040,12 @@ xfs_vm_writepage( | |||
1052 | ssize_t size, len; | 1040 | ssize_t size, len; |
1053 | int flags, err, imap_valid = 0, uptodate = 1; | 1041 | int flags, err, imap_valid = 0, uptodate = 1; |
1054 | int count = 0; | 1042 | int count = 0; |
1055 | int all_bh; | 1043 | int all_bh = 0; |
1056 | 1044 | ||
1057 | trace_xfs_writepage(inode, page, 0); | 1045 | trace_xfs_writepage(inode, page, 0); |
1058 | 1046 | ||
1047 | ASSERT(page_has_buffers(page)); | ||
1048 | |||
1059 | /* | 1049 | /* |
1060 | * Refuse to write the page out if we are called from reclaim context. | 1050 | * Refuse to write the page out if we are called from reclaim context. |
1061 | * | 1051 | * |
@@ -1072,29 +1062,15 @@ xfs_vm_writepage( | |||
1072 | goto out_fail; | 1062 | goto out_fail; |
1073 | 1063 | ||
1074 | /* | 1064 | /* |
1075 | * We need a transaction if: | 1065 | * We need a transaction if there are delalloc or unwritten buffers |
1076 | * 1. There are delalloc buffers on the page | 1066 | * on the page. |
1077 | * 2. The page is uptodate and we have unmapped buffers | 1067 | * |
1078 | * 3. The page is uptodate and we have no buffers | 1068 | * If we need a transaction and the process flags say we are already |
1079 | * 4. There are unwritten buffers on the page | 1069 | * in a transaction, or no IO is allowed then mark the page dirty |
1080 | */ | 1070 | * again and leave the page as is. |
1081 | if (!page_has_buffers(page)) { | ||
1082 | unmapped = 1; | ||
1083 | need_trans = 1; | ||
1084 | } else { | ||
1085 | xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); | ||
1086 | if (!PageUptodate(page)) | ||
1087 | unmapped = 0; | ||
1088 | need_trans = delalloc + unmapped + unwritten; | ||
1089 | } | ||
1090 | |||
1091 | /* | ||
1092 | * If we need a transaction and the process flags say | ||
1093 | * we are already in a transaction, or no IO is allowed | ||
1094 | * then mark the page dirty again and leave the page | ||
1095 | * as is. | ||
1096 | */ | 1071 | */ |
1097 | if (current_test_flags(PF_FSTRANS) && need_trans) | 1072 | xfs_count_page_state(page, &delalloc, &unwritten); |
1073 | if ((current->flags & PF_FSTRANS) && (delalloc || unwritten)) | ||
1098 | goto out_fail; | 1074 | goto out_fail; |
1099 | 1075 | ||
1100 | /* | 1076 | /* |
@@ -1117,7 +1093,8 @@ xfs_vm_writepage( | |||
1117 | } | 1093 | } |
1118 | 1094 | ||
1119 | end_offset = min_t(unsigned long long, | 1095 | end_offset = min_t(unsigned long long, |
1120 | (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset); | 1096 | (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, |
1097 | offset); | ||
1121 | len = 1 << inode->i_blkbits; | 1098 | len = 1 << inode->i_blkbits; |
1122 | 1099 | ||
1123 | bh = head = page_buffers(page); | 1100 | bh = head = page_buffers(page); |
@@ -1125,8 +1102,6 @@ xfs_vm_writepage( | |||
1125 | flags = BMAPI_READ; | 1102 | flags = BMAPI_READ; |
1126 | type = IO_NEW; | 1103 | type = IO_NEW; |
1127 | 1104 | ||
1128 | all_bh = unmapped; | ||
1129 | |||
1130 | do { | 1105 | do { |
1131 | if (offset >= end_offset) | 1106 | if (offset >= end_offset) |
1132 | break; | 1107 | break; |
@@ -1146,19 +1121,7 @@ xfs_vm_writepage( | |||
1146 | if (imap_valid) | 1121 | if (imap_valid) |
1147 | imap_valid = xfs_imap_valid(inode, &imap, offset); | 1122 | imap_valid = xfs_imap_valid(inode, &imap, offset); |
1148 | 1123 | ||
1149 | /* | 1124 | if (buffer_unwritten(bh) || buffer_delay(bh)) { |
1150 | * First case, map an unwritten extent and prepare for | ||
1151 | * extent state conversion transaction on completion. | ||
1152 | * | ||
1153 | * Second case, allocate space for a delalloc buffer. | ||
1154 | * We can return EAGAIN here in the release page case. | ||
1155 | * | ||
1156 | * Third case, an unmapped buffer was found, and we are | ||
1157 | * in a path where we need to write the whole page out. | ||
1158 | */ | ||
1159 | if (buffer_unwritten(bh) || buffer_delay(bh) || | ||
1160 | ((buffer_uptodate(bh) || PageUptodate(page)) && | ||
1161 | !buffer_mapped(bh))) { | ||
1162 | int new_ioend = 0; | 1125 | int new_ioend = 0; |
1163 | 1126 | ||
1164 | /* | 1127 | /* |
@@ -1177,14 +1140,11 @@ xfs_vm_writepage( | |||
1177 | if (wbc->sync_mode == WB_SYNC_NONE && | 1140 | if (wbc->sync_mode == WB_SYNC_NONE && |
1178 | wbc->nonblocking) | 1141 | wbc->nonblocking) |
1179 | flags |= BMAPI_TRYLOCK; | 1142 | flags |= BMAPI_TRYLOCK; |
1180 | } else { | ||
1181 | type = IO_NEW; | ||
1182 | flags = BMAPI_WRITE | BMAPI_MMAP; | ||
1183 | } | 1143 | } |
1184 | 1144 | ||
1185 | if (!imap_valid) { | 1145 | if (!imap_valid) { |
1186 | /* | 1146 | /* |
1187 | * if we didn't have a valid mapping then we | 1147 | * If we didn't have a valid mapping then we |
1188 | * need to ensure that we put the new mapping | 1148 | * need to ensure that we put the new mapping |
1189 | * in a new ioend structure. This needs to be | 1149 | * in a new ioend structure. This needs to be |
1190 | * done to ensure that the ioends correctly | 1150 | * done to ensure that the ioends correctly |
@@ -1192,14 +1152,7 @@ xfs_vm_writepage( | |||
1192 | * for unwritten extent conversion. | 1152 | * for unwritten extent conversion. |
1193 | */ | 1153 | */ |
1194 | new_ioend = 1; | 1154 | new_ioend = 1; |
1195 | if (type == IO_NEW) { | 1155 | err = xfs_map_blocks(inode, offset, len, |
1196 | size = xfs_probe_cluster(inode, | ||
1197 | page, bh, head, 0); | ||
1198 | } else { | ||
1199 | size = len; | ||
1200 | } | ||
1201 | |||
1202 | err = xfs_map_blocks(inode, offset, size, | ||
1203 | &imap, flags); | 1156 | &imap, flags); |
1204 | if (err) | 1157 | if (err) |
1205 | goto error; | 1158 | goto error; |
@@ -1220,8 +1173,7 @@ xfs_vm_writepage( | |||
1220 | */ | 1173 | */ |
1221 | if (!imap_valid || flags != BMAPI_READ) { | 1174 | if (!imap_valid || flags != BMAPI_READ) { |
1222 | flags = BMAPI_READ; | 1175 | flags = BMAPI_READ; |
1223 | size = xfs_probe_cluster(inode, page, bh, | 1176 | size = xfs_probe_cluster(inode, page, bh, head); |
1224 | head, 1); | ||
1225 | err = xfs_map_blocks(inode, offset, size, | 1177 | err = xfs_map_blocks(inode, offset, size, |
1226 | &imap, flags); | 1178 | &imap, flags); |
1227 | if (err) | 1179 | if (err) |
@@ -1240,7 +1192,6 @@ xfs_vm_writepage( | |||
1240 | */ | 1192 | */ |
1241 | type = IO_NEW; | 1193 | type = IO_NEW; |
1242 | if (trylock_buffer(bh)) { | 1194 | if (trylock_buffer(bh)) { |
1243 | ASSERT(buffer_mapped(bh)); | ||
1244 | if (imap_valid) | 1195 | if (imap_valid) |
1245 | all_bh = 1; | 1196 | all_bh = 1; |
1246 | xfs_add_to_ioend(inode, bh, offset, type, | 1197 | xfs_add_to_ioend(inode, bh, offset, type, |
@@ -1250,6 +1201,7 @@ xfs_vm_writepage( | |||
1250 | imap_valid = 0; | 1201 | imap_valid = 0; |
1251 | } | 1202 | } |
1252 | } else if (PageUptodate(page)) { | 1203 | } else if (PageUptodate(page)) { |
1204 | ASSERT(buffer_mapped(bh)); | ||
1253 | imap_valid = 0; | 1205 | imap_valid = 0; |
1254 | } | 1206 | } |
1255 | 1207 | ||
@@ -1291,8 +1243,7 @@ error: | |||
1291 | if (iohead) | 1243 | if (iohead) |
1292 | xfs_cancel_ioend(iohead); | 1244 | xfs_cancel_ioend(iohead); |
1293 | 1245 | ||
1294 | if (!unmapped) | 1246 | xfs_aops_discard_page(page); |
1295 | xfs_aops_discard_page(page); | ||
1296 | ClearPageUptodate(page); | 1247 | ClearPageUptodate(page); |
1297 | unlock_page(page); | 1248 | unlock_page(page); |
1298 | return err; | 1249 | return err; |
@@ -1324,11 +1275,11 @@ xfs_vm_releasepage( | |||
1324 | struct page *page, | 1275 | struct page *page, |
1325 | gfp_t gfp_mask) | 1276 | gfp_t gfp_mask) |
1326 | { | 1277 | { |
1327 | int delalloc, unmapped, unwritten; | 1278 | int delalloc, unwritten; |
1328 | 1279 | ||
1329 | trace_xfs_releasepage(page->mapping->host, page, 0); | 1280 | trace_xfs_releasepage(page->mapping->host, page, 0); |
1330 | 1281 | ||
1331 | xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); | 1282 | xfs_count_page_state(page, &delalloc, &unwritten); |
1332 | 1283 | ||
1333 | if (WARN_ON(delalloc)) | 1284 | if (WARN_ON(delalloc)) |
1334 | return 0; | 1285 | return 0; |
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 4cfc6ea87df8..319da173cc1a 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h | |||
@@ -45,6 +45,6 @@ extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); | |||
45 | extern void xfs_ioend_init(void); | 45 | extern void xfs_ioend_init(void); |
46 | extern void xfs_ioend_wait(struct xfs_inode *); | 46 | extern void xfs_ioend_wait(struct xfs_inode *); |
47 | 47 | ||
48 | extern void xfs_count_page_state(struct page *, int *, int *, int *); | 48 | extern void xfs_count_page_state(struct page *, int *, int *); |
49 | 49 | ||
50 | #endif /* __XFS_AOPS_H__ */ | 50 | #endif /* __XFS_AOPS_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h index 0aea6d5f705a..3f2eec28c70d 100644 --- a/fs/xfs/linux-2.6/xfs_trace.h +++ b/fs/xfs/linux-2.6/xfs_trace.h | |||
@@ -832,33 +832,29 @@ DECLARE_EVENT_CLASS(xfs_page_class, | |||
832 | __field(loff_t, size) | 832 | __field(loff_t, size) |
833 | __field(unsigned long, offset) | 833 | __field(unsigned long, offset) |
834 | __field(int, delalloc) | 834 | __field(int, delalloc) |
835 | __field(int, unmapped) | ||
836 | __field(int, unwritten) | 835 | __field(int, unwritten) |
837 | ), | 836 | ), |
838 | TP_fast_assign( | 837 | TP_fast_assign( |
839 | int delalloc = -1, unmapped = -1, unwritten = -1; | 838 | int delalloc = -1, unwritten = -1; |
840 | 839 | ||
841 | if (page_has_buffers(page)) | 840 | if (page_has_buffers(page)) |
842 | xfs_count_page_state(page, &delalloc, | 841 | xfs_count_page_state(page, &delalloc, &unwritten); |
843 | &unmapped, &unwritten); | ||
844 | __entry->dev = inode->i_sb->s_dev; | 842 | __entry->dev = inode->i_sb->s_dev; |
845 | __entry->ino = XFS_I(inode)->i_ino; | 843 | __entry->ino = XFS_I(inode)->i_ino; |
846 | __entry->pgoff = page_offset(page); | 844 | __entry->pgoff = page_offset(page); |
847 | __entry->size = i_size_read(inode); | 845 | __entry->size = i_size_read(inode); |
848 | __entry->offset = off; | 846 | __entry->offset = off; |
849 | __entry->delalloc = delalloc; | 847 | __entry->delalloc = delalloc; |
850 | __entry->unmapped = unmapped; | ||
851 | __entry->unwritten = unwritten; | 848 | __entry->unwritten = unwritten; |
852 | ), | 849 | ), |
853 | TP_printk("dev %d:%d ino 0x%llx pgoff 0x%lx size 0x%llx offset %lx " | 850 | TP_printk("dev %d:%d ino 0x%llx pgoff 0x%lx size 0x%llx offset %lx " |
854 | "delalloc %d unmapped %d unwritten %d", | 851 | "delalloc %d unwritten %d", |
855 | MAJOR(__entry->dev), MINOR(__entry->dev), | 852 | MAJOR(__entry->dev), MINOR(__entry->dev), |
856 | __entry->ino, | 853 | __entry->ino, |
857 | __entry->pgoff, | 854 | __entry->pgoff, |
858 | __entry->size, | 855 | __entry->size, |
859 | __entry->offset, | 856 | __entry->offset, |
860 | __entry->delalloc, | 857 | __entry->delalloc, |
861 | __entry->unmapped, | ||
862 | __entry->unwritten) | 858 | __entry->unwritten) |
863 | ) | 859 | ) |
864 | 860 | ||