浏览代码

[GFS2] Bug fix to gfs2_readpages()

This fixes a bug where we were releasing a page incorrectly
sometimes when reading a stuffed file. This fixes the bug
that Kevin reported when using Xen.

Cc: Kevin Anderson <kanderso@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Steven Whitehouse 19 年之前
父节点
当前提交
ffeb874b2b
共有 1 个文件被更改,包括 5 次插入5 次删除
  1. 5 5
      fs/gfs2/ops_address.c

+ 5 - 5
fs/gfs2/ops_address.c

@@ -249,8 +249,6 @@ out_unlock:
 	goto out;
 	goto out;
 }
 }
 
 
-#define list_to_page(head) (list_entry((head)->prev, struct page, lru))
-
 /**
 /**
  * gfs2_readpages - Read a bunch of pages at once
  * gfs2_readpages - Read a bunch of pages at once
  *
  *
@@ -290,7 +288,8 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping,
 		struct pagevec lru_pvec;
 		struct pagevec lru_pvec;
 		pagevec_init(&lru_pvec, 0);
 		pagevec_init(&lru_pvec, 0);
 		for (page_idx = 0; page_idx < nr_pages; page_idx++) {
 		for (page_idx = 0; page_idx < nr_pages; page_idx++) {
-			struct page *page = list_to_page(pages);
+			struct page *page = list_entry(pages->prev, struct page, lru);
+			prefetchw(&page->flags);
 			list_del(&page->lru);
 			list_del(&page->lru);
 			if (!add_to_page_cache(page, mapping,
 			if (!add_to_page_cache(page, mapping,
 					       page->index, GFP_KERNEL)) {
 					       page->index, GFP_KERNEL)) {
@@ -298,8 +297,9 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping,
 				unlock_page(page);
 				unlock_page(page);
 				if (!pagevec_add(&lru_pvec, page))
 				if (!pagevec_add(&lru_pvec, page))
 					 __pagevec_lru_add(&lru_pvec);
 					 __pagevec_lru_add(&lru_pvec);
+			} else {
+				page_cache_release(page);
 			}
 			}
-			page_cache_release(page);
 		}
 		}
 		pagevec_lru_add(&lru_pvec);
 		pagevec_lru_add(&lru_pvec);
 		ret = 0;
 		ret = 0;
@@ -321,7 +321,7 @@ out_noerror:
 out_unlock:
 out_unlock:
 	/* unlock all pages, we can't do any I/O right now */
 	/* unlock all pages, we can't do any I/O right now */
 	for (page_idx = 0; page_idx < nr_pages; page_idx++) {
 	for (page_idx = 0; page_idx < nr_pages; page_idx++) {
-		struct page *page = list_to_page(pages);
+		struct page *page = list_entry(pages->prev, struct page, lru);
 		list_del(&page->lru);
 		list_del(&page->lru);
 		unlock_page(page);
 		unlock_page(page);
 		page_cache_release(page);
 		page_cache_release(page);