aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext3/inode.c6
-rw-r--r--fs/jbd/transaction.c19
-rw-r--r--include/linux/jbd.h2
-rw-r--r--include/trace/events/ext3.h12
4 files changed, 25 insertions, 14 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index b6e5934f5dd6..f67668f724ba 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1830,15 +1830,15 @@ static void ext3_invalidatepage(struct page *page, unsigned int offset,
1830{ 1830{
1831 journal_t *journal = EXT3_JOURNAL(page->mapping->host); 1831 journal_t *journal = EXT3_JOURNAL(page->mapping->host);
1832 1832
1833 trace_ext3_invalidatepage(page, offset); 1833 trace_ext3_invalidatepage(page, offset, length);
1834 1834
1835 /* 1835 /*
1836 * If it's a full truncate we just forget about the pending dirtying 1836 * If it's a full truncate we just forget about the pending dirtying
1837 */ 1837 */
1838 if (offset == 0) 1838 if (offset == 0 && length == PAGE_CACHE_SIZE)
1839 ClearPageChecked(page); 1839 ClearPageChecked(page);
1840 1840
1841 journal_invalidatepage(journal, page, offset); 1841 journal_invalidatepage(journal, page, offset, length);
1842} 1842}
1843 1843
1844static int ext3_releasepage(struct page *page, gfp_t wait) 1844static int ext3_releasepage(struct page *page, gfp_t wait)
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index e3e255c0a509..be0c39b66fe0 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -2019,16 +2019,20 @@ zap_buffer_unlocked:
2019 * void journal_invalidatepage() - invalidate a journal page 2019 * void journal_invalidatepage() - invalidate a journal page
2020 * @journal: journal to use for flush 2020 * @journal: journal to use for flush
2021 * @page: page to flush 2021 * @page: page to flush
2022 * @offset: length of page to invalidate. 2022 * @offset: offset of the range to invalidate
2023 * @length: length of the range to invalidate
2023 * 2024 *
2024 * Reap page buffers containing data after offset in page. 2025 * Reap page buffers containing data in specified range in page.
2025 */ 2026 */
2026void journal_invalidatepage(journal_t *journal, 2027void journal_invalidatepage(journal_t *journal,
2027 struct page *page, 2028 struct page *page,
2028 unsigned long offset) 2029 unsigned int offset,
2030 unsigned int length)
2029{ 2031{
2030 struct buffer_head *head, *bh, *next; 2032 struct buffer_head *head, *bh, *next;
2033 unsigned int stop = offset + length;
2031 unsigned int curr_off = 0; 2034 unsigned int curr_off = 0;
2035 int partial_page = (offset || length < PAGE_CACHE_SIZE);
2032 int may_free = 1; 2036 int may_free = 1;
2033 2037
2034 if (!PageLocked(page)) 2038 if (!PageLocked(page))
@@ -2036,6 +2040,8 @@ void journal_invalidatepage(journal_t *journal,
2036 if (!page_has_buffers(page)) 2040 if (!page_has_buffers(page))
2037 return; 2041 return;
2038 2042
2043 BUG_ON(stop > PAGE_CACHE_SIZE || stop < length);
2044
2039 /* We will potentially be playing with lists other than just the 2045 /* We will potentially be playing with lists other than just the
2040 * data lists (especially for journaled data mode), so be 2046 * data lists (especially for journaled data mode), so be
2041 * cautious in our locking. */ 2047 * cautious in our locking. */
@@ -2045,11 +2051,14 @@ void journal_invalidatepage(journal_t *journal,
2045 unsigned int next_off = curr_off + bh->b_size; 2051 unsigned int next_off = curr_off + bh->b_size;
2046 next = bh->b_this_page; 2052 next = bh->b_this_page;
2047 2053
2054 if (next_off > stop)
2055 return;
2056
2048 if (offset <= curr_off) { 2057 if (offset <= curr_off) {
2049 /* This block is wholly outside the truncation point */ 2058 /* This block is wholly outside the truncation point */
2050 lock_buffer(bh); 2059 lock_buffer(bh);
2051 may_free &= journal_unmap_buffer(journal, bh, 2060 may_free &= journal_unmap_buffer(journal, bh,
2052 offset > 0); 2061 partial_page);
2053 unlock_buffer(bh); 2062 unlock_buffer(bh);
2054 } 2063 }
2055 curr_off = next_off; 2064 curr_off = next_off;
@@ -2057,7 +2066,7 @@ void journal_invalidatepage(journal_t *journal,
2057 2066
2058 } while (bh != head); 2067 } while (bh != head);
2059 2068
2060 if (!offset) { 2069 if (!partial_page) {
2061 if (may_free && try_to_free_buffers(page)) 2070 if (may_free && try_to_free_buffers(page))
2062 J_ASSERT(!page_has_buffers(page)); 2071 J_ASSERT(!page_has_buffers(page));
2063 } 2072 }
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 7e0b622503c4..9c505f1aa1fd 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -840,7 +840,7 @@ extern void journal_release_buffer (handle_t *, struct buffer_head *);
840extern int journal_forget (handle_t *, struct buffer_head *); 840extern int journal_forget (handle_t *, struct buffer_head *);
841extern void journal_sync_buffer (struct buffer_head *); 841extern void journal_sync_buffer (struct buffer_head *);
842extern void journal_invalidatepage(journal_t *, 842extern void journal_invalidatepage(journal_t *,
843 struct page *, unsigned long); 843 struct page *, unsigned int, unsigned int);
844extern int journal_try_to_free_buffers(journal_t *, struct page *, gfp_t); 844extern int journal_try_to_free_buffers(journal_t *, struct page *, gfp_t);
845extern int journal_stop(handle_t *); 845extern int journal_stop(handle_t *);
846extern int journal_flush (journal_t *); 846extern int journal_flush (journal_t *);
diff --git a/include/trace/events/ext3.h b/include/trace/events/ext3.h
index 15d11a39be47..6797b9de90ed 100644
--- a/include/trace/events/ext3.h
+++ b/include/trace/events/ext3.h
@@ -290,13 +290,14 @@ DEFINE_EVENT(ext3__page_op, ext3_releasepage,
290); 290);
291 291
292TRACE_EVENT(ext3_invalidatepage, 292TRACE_EVENT(ext3_invalidatepage,
293 TP_PROTO(struct page *page, unsigned long offset), 293 TP_PROTO(struct page *page, unsigned int offset, unsigned int length),
294 294
295 TP_ARGS(page, offset), 295 TP_ARGS(page, offset, length),
296 296
297 TP_STRUCT__entry( 297 TP_STRUCT__entry(
298 __field( pgoff_t, index ) 298 __field( pgoff_t, index )
299 __field( unsigned long, offset ) 299 __field( unsigned int, offset )
300 __field( unsigned int, length )
300 __field( ino_t, ino ) 301 __field( ino_t, ino )
301 __field( dev_t, dev ) 302 __field( dev_t, dev )
302 303
@@ -305,14 +306,15 @@ TRACE_EVENT(ext3_invalidatepage,
305 TP_fast_assign( 306 TP_fast_assign(
306 __entry->index = page->index; 307 __entry->index = page->index;
307 __entry->offset = offset; 308 __entry->offset = offset;
309 __entry->length = length;
308 __entry->ino = page->mapping->host->i_ino; 310 __entry->ino = page->mapping->host->i_ino;
309 __entry->dev = page->mapping->host->i_sb->s_dev; 311 __entry->dev = page->mapping->host->i_sb->s_dev;
310 ), 312 ),
311 313
312 TP_printk("dev %d,%d ino %lu page_index %lu offset %lu", 314 TP_printk("dev %d,%d ino %lu page_index %lu offset %u length %u",
313 MAJOR(__entry->dev), MINOR(__entry->dev), 315 MAJOR(__entry->dev), MINOR(__entry->dev),
314 (unsigned long) __entry->ino, 316 (unsigned long) __entry->ino,
315 __entry->index, __entry->offset) 317 __entry->index, __entry->offset, __entry->length)
316); 318);
317 319
318TRACE_EVENT(ext3_discard_blocks, 320TRACE_EVENT(ext3_discard_blocks,