From 2b94a8e472a394bc5c630dbac7404264b414f7cf Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 15 Sep 2016 11:49:35 -0400 Subject: [PATCH] add patch bugfix-for-mmaped-pages-in-mpage_release_unused_pages --- ...-for-mmaped-pages-in-mpage_release_unused_pages | 63 ++++++++++++++++++++++ series | 2 + 2 files changed, 65 insertions(+) create mode 100644 bugfix-for-mmaped-pages-in-mpage_release_unused_pages diff --git a/bugfix-for-mmaped-pages-in-mpage_release_unused_pages b/bugfix-for-mmaped-pages-in-mpage_release_unused_pages new file mode 100644 index 00000000..f3ff1886 --- /dev/null +++ b/bugfix-for-mmaped-pages-in-mpage_release_unused_pages @@ -0,0 +1,63 @@ +ext4: bugfix for mmaped pages in mpage_release_unused_pages() + +From: wangguang + +Pages clear buffers after ext4 delayed block allocation failed, +However, it does not clean its pte_dirty flag. +if the pages unmap ,in cording to the pte_dirty , +unmap_page_range may try to call __set_page_dirty, + +which may lead to the bugon at +mpage_prepare_extent_to_map:head = page_buffers(page);. + +This patch just call clear_page_dirty_for_io to clean pte_dirty +at mpage_release_unused_pages for pages mmaped. + +Steps to reproduce the bug: + +(1) mmap a file in ext4 + addr = (char *)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, + fd, 0); + memset(addr, 'i', 4096); + +(2) return EIO at + + ext4_writepages->mpage_map_and_submit_extent->mpage_map_one_extent + +which causes this log message to be print: + + ext4_msg(sb, KERN_CRIT, + "Delayed block allocation failed for " + "inode %lu at logical offset %llu with" + " max blocks %u with error %d", + inode->i_ino, + (unsigned long long)map->m_lblk, + (unsigned)map->m_len, -err); + +(3)Unmap the addr cause warning at + + __set_page_dirty:WARN_ON_ONCE(warn && !PageUptodate(page)); + +(4) wait for a minute,then bugon happen. + +Signed-off-by: wangguang +Signed-off-by: Theodore Ts'o + + +--- + fs/ext4/inode.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index f058afb..9b464e5 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -1649,6 +1649,8 @@ static void mpage_release_unused_pages(struct mpage_da_data *mpd, + BUG_ON(!PageLocked(page)); + BUG_ON(PageWriteback(page)); + if (invalidate) { ++ if (page_mapped(page)) ++ clear_page_dirty_for_io(page); + block_invalidatepage(page, 0, PAGE_SIZE); + ClearPageUptodate(page); + } diff --git a/series b/series index f95dc184..81b3e482 100644 --- a/series +++ b/series @@ -16,6 +16,8 @@ remove-old-feature-helpers cleanup-ext4_sync_parent improve-ext4lazyinit-scalability +bugfix-for-mmaped-pages-in-mpage_release_unused_pages + ########################################## # unstable patches #################################################### -- 2.11.4.GIT