aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2007-05-06 17:49:04 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:12:51 -0400
commit6fe6900e1e5b6fa9e5c59aa5061f244fe3f467e2 (patch)
tree8bbfe5072279227cc50a941ad4813908082426a1
parent714b8171af9c930a59a0da8f6fe50518e70ab035 (diff)
mm: make read_cache_page synchronous
Ensure pages are uptodate after returning from read_cache_page, which allows us to cut out most of the filesystem-internal PageUptodate calls. I didn't have a great look down the call chains, but this appears to fixes 7 possible use-before uptodate in hfs, 2 in hfsplus, 1 in jfs, a few in ecryptfs, 1 in jffs2, and a possible cleared data overwritten with readpage in block2mtd. All depending on whether the filler is async and/or can return with a !uptodate page. Signed-off-by: Nick Piggin <npiggin@suse.de> Cc: Hugh Dickins <hugh@veritas.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/mtd/devices/block2mtd.c6
-rw-r--r--fs/afs/dir.c3
-rw-r--r--fs/afs/mntpt.c11
-rw-r--r--fs/cramfs/inode.c3
-rw-r--r--fs/ecryptfs/mmap.c11
-rw-r--r--fs/ext2/dir.c3
-rw-r--r--fs/freevxfs/vxfs_subr.c3
-rw-r--r--fs/minix/dir.c1
-rw-r--r--fs/namei.c12
-rw-r--r--fs/nfs/dir.c5
-rw-r--r--fs/nfs/symlink.c6
-rw-r--r--fs/ntfs/aops.h3
-rw-r--r--fs/ntfs/attrib.c18
-rw-r--r--fs/ntfs/file.c3
-rw-r--r--fs/ntfs/super.c30
-rw-r--r--fs/ocfs2/symlink.c7
-rw-r--r--fs/partitions/check.c3
-rw-r--r--fs/reiserfs/xattr.c4
-rw-r--r--fs/sysv/dir.c10
-rw-r--r--fs/ufs/dir.c6
-rw-r--r--fs/ufs/util.c6
-rw-r--r--include/linux/pagemap.h11
-rw-r--r--mm/filemap.c49
-rw-r--r--mm/swapfile.c3
24 files changed, 71 insertions, 146 deletions
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index ce47544dc120..fc4cc8ba9e29 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -40,13 +40,11 @@ struct block2mtd_dev {
40static LIST_HEAD(blkmtd_device_list); 40static LIST_HEAD(blkmtd_device_list);
41 41
42 42
43static struct page* page_read(struct address_space *mapping, int index) 43static struct page *page_read(struct address_space *mapping, int index)
44{ 44{
45 filler_t *filler = (filler_t*)mapping->a_ops->readpage; 45 return read_mapping_page(mapping, index, NULL);
46 return read_cache_page(mapping, index, filler, NULL);
47} 46}
48 47
49
50/* erase a specified part of the device */ 48/* erase a specified part of the device */
51static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len) 49static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len)
52{ 50{
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index dac5b990c0cd..0c1e902f17a3 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -194,10 +194,7 @@ static struct page *afs_dir_get_page(struct inode *dir, unsigned long index,
194 194
195 page = read_mapping_page(dir->i_mapping, index, &file); 195 page = read_mapping_page(dir->i_mapping, index, &file);
196 if (!IS_ERR(page)) { 196 if (!IS_ERR(page)) {
197 wait_on_page_locked(page);
198 kmap(page); 197 kmap(page);
199 if (!PageUptodate(page))
200 goto fail;
201 if (!PageChecked(page)) 198 if (!PageChecked(page))
202 afs_dir_check_page(dir, page); 199 afs_dir_check_page(dir, page);
203 if (PageError(page)) 200 if (PageError(page))
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index b905ae37f912..034fcfd4e330 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -68,13 +68,11 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key)
68 } 68 }
69 69
70 ret = -EIO; 70 ret = -EIO;
71 wait_on_page_locked(page);
72 buf = kmap(page);
73 if (!PageUptodate(page))
74 goto out_free;
75 if (PageError(page)) 71 if (PageError(page))
76 goto out_free; 72 goto out_free;
77 73
74 buf = kmap(page);
75
78 /* examine the symlink's contents */ 76 /* examine the symlink's contents */
79 size = vnode->status.size; 77 size = vnode->status.size;
80 _debug("symlink to %*.*s", (int) size, (int) size, buf); 78 _debug("symlink to %*.*s", (int) size, (int) size, buf);
@@ -91,8 +89,8 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key)
91 89
92 ret = 0; 90 ret = 0;
93 91
94out_free:
95 kunmap(page); 92 kunmap(page);
93out_free:
96 page_cache_release(page); 94 page_cache_release(page);
97out: 95out:
98 _leave(" = %d", ret); 96 _leave(" = %d", ret);
@@ -171,8 +169,7 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
171 } 169 }
172 170
173 ret = -EIO; 171 ret = -EIO;
174 wait_on_page_locked(page); 172 if (PageError(page))
175 if (!PageUptodate(page) || PageError(page))
176 goto error; 173 goto error;
177 174
178 buf = kmap(page); 175 buf = kmap(page);
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index facd0c89be8f..3d194a2be3f5 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -180,7 +180,8 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
180 struct page *page = NULL; 180 struct page *page = NULL;
181 181
182 if (blocknr + i < devsize) { 182 if (blocknr + i < devsize) {
183 page = read_mapping_page(mapping, blocknr + i, NULL); 183 page = read_mapping_page_async(mapping, blocknr + i,
184 NULL);
184 /* synchronous error? */ 185 /* synchronous error? */
185 if (IS_ERR(page)) 186 if (IS_ERR(page))
186 page = NULL; 187 page = NULL;
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index b731b09499cb..0770c4b66f53 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -46,7 +46,6 @@ struct kmem_cache *ecryptfs_lower_page_cache;
46 */ 46 */
47static struct page *ecryptfs_get1page(struct file *file, int index) 47static struct page *ecryptfs_get1page(struct file *file, int index)
48{ 48{
49 struct page *page;
50 struct dentry *dentry; 49 struct dentry *dentry;
51 struct inode *inode; 50 struct inode *inode;
52 struct address_space *mapping; 51 struct address_space *mapping;
@@ -54,14 +53,7 @@ static struct page *ecryptfs_get1page(struct file *file, int index)
54 dentry = file->f_path.dentry; 53 dentry = file->f_path.dentry;
55 inode = dentry->d_inode; 54 inode = dentry->d_inode;
56 mapping = inode->i_mapping; 55 mapping = inode->i_mapping;
57 page = read_cache_page(mapping, index, 56 return read_mapping_page(mapping, index, (void *)file);
58 (filler_t *)mapping->a_ops->readpage,
59 (void *)file);
60 if (IS_ERR(page))
61 goto out;
62 wait_on_page_locked(page);
63out:
64 return page;
65} 57}
66 58
67static 59static
@@ -233,7 +225,6 @@ int ecryptfs_do_readpage(struct file *file, struct page *page,
233 ecryptfs_printk(KERN_ERR, "Error reading from page cache\n"); 225 ecryptfs_printk(KERN_ERR, "Error reading from page cache\n");
234 goto out; 226 goto out;
235 } 227 }
236 wait_on_page_locked(lower_page);
237 page_data = kmap_atomic(page, KM_USER0); 228 page_data = kmap_atomic(page, KM_USER0);
238 lower_page_data = kmap_atomic(lower_page, KM_USER1); 229 lower_page_data = kmap_atomic(lower_page, KM_USER1);
239 memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE); 230 memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index e89bfc8cf957..1d1e7e30d70e 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -161,10 +161,7 @@ static struct page * ext2_get_page(struct inode *dir, unsigned long n)
161 struct address_space *mapping = dir->i_mapping; 161 struct address_space *mapping = dir->i_mapping;
162 struct page *page = read_mapping_page(mapping, n, NULL); 162 struct page *page = read_mapping_page(mapping, n, NULL);
163 if (!IS_ERR(page)) { 163 if (!IS_ERR(page)) {
164 wait_on_page_locked(page);
165 kmap(page); 164 kmap(page);
166 if (!PageUptodate(page))
167 goto fail;
168 if (!PageChecked(page)) 165 if (!PageChecked(page))
169 ext2_check_page(page); 166 ext2_check_page(page);
170 if (PageError(page)) 167 if (PageError(page))
diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c
index decac62efe57..ed8f0b0dd880 100644
--- a/fs/freevxfs/vxfs_subr.c
+++ b/fs/freevxfs/vxfs_subr.c
@@ -74,10 +74,7 @@ vxfs_get_page(struct address_space *mapping, u_long n)
74 pp = read_mapping_page(mapping, n, NULL); 74 pp = read_mapping_page(mapping, n, NULL);
75 75
76 if (!IS_ERR(pp)) { 76 if (!IS_ERR(pp)) {
77 wait_on_page_locked(pp);
78 kmap(pp); 77 kmap(pp);
79 if (!PageUptodate(pp))
80 goto fail;
81 /** if (!PageChecked(pp)) **/ 78 /** if (!PageChecked(pp)) **/
82 /** vxfs_check_page(pp); **/ 79 /** vxfs_check_page(pp); **/
83 if (PageError(pp)) 80 if (PageError(pp))
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index cb4cb571fddf..e207cbe70951 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -65,7 +65,6 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n)
65 struct address_space *mapping = dir->i_mapping; 65 struct address_space *mapping = dir->i_mapping;
66 struct page *page = read_mapping_page(mapping, n, NULL); 66 struct page *page = read_mapping_page(mapping, n, NULL);
67 if (!IS_ERR(page)) { 67 if (!IS_ERR(page)) {
68 wait_on_page_locked(page);
69 kmap(page); 68 kmap(page);
70 if (!PageUptodate(page)) 69 if (!PageUptodate(page))
71 goto fail; 70 goto fail;
diff --git a/fs/namei.c b/fs/namei.c
index 880052cadbcd..94b2f60aec22 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2671,19 +2671,9 @@ static char *page_getlink(struct dentry * dentry, struct page **ppage)
2671 struct address_space *mapping = dentry->d_inode->i_mapping; 2671 struct address_space *mapping = dentry->d_inode->i_mapping;
2672 page = read_mapping_page(mapping, 0, NULL); 2672 page = read_mapping_page(mapping, 0, NULL);
2673 if (IS_ERR(page)) 2673 if (IS_ERR(page))
2674 goto sync_fail; 2674 return (char*)page;
2675 wait_on_page_locked(page);
2676 if (!PageUptodate(page))
2677 goto async_fail;
2678 *ppage = page; 2675 *ppage = page;
2679 return kmap(page); 2676 return kmap(page);
2680
2681async_fail:
2682 page_cache_release(page);
2683 return ERR_PTR(-EIO);
2684
2685sync_fail:
2686 return (char*)page;
2687} 2677}
2688 2678
2689int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) 2679int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index e59fd31c9a22..625d8e5fb39d 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -334,8 +334,6 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc)
334 status = PTR_ERR(page); 334 status = PTR_ERR(page);
335 goto out; 335 goto out;
336 } 336 }
337 if (!PageUptodate(page))
338 goto read_error;
339 337
340 /* NOTE: Someone else may have changed the READDIRPLUS flag */ 338 /* NOTE: Someone else may have changed the READDIRPLUS flag */
341 desc->page = page; 339 desc->page = page;
@@ -349,9 +347,6 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc)
349 out: 347 out:
350 dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __FUNCTION__, status); 348 dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __FUNCTION__, status);
351 return status; 349 return status;
352 read_error:
353 page_cache_release(page);
354 return -EIO;
355} 350}
356 351
357/* 352/*
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index f4a0548b9ce8..bc2821331c29 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -61,15 +61,9 @@ static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
61 err = page; 61 err = page;
62 goto read_failed; 62 goto read_failed;
63 } 63 }
64 if (!PageUptodate(page)) {
65 err = ERR_PTR(-EIO);
66 goto getlink_read_error;
67 }
68 nd_set_link(nd, kmap(page)); 64 nd_set_link(nd, kmap(page));
69 return page; 65 return page;
70 66
71getlink_read_error:
72 page_cache_release(page);
73read_failed: 67read_failed:
74 nd_set_link(nd, err); 68 nd_set_link(nd, err);
75 return NULL; 69 return NULL;
diff --git a/fs/ntfs/aops.h b/fs/ntfs/aops.h
index 9393f4b1e298..caecc58f529c 100644
--- a/fs/ntfs/aops.h
+++ b/fs/ntfs/aops.h
@@ -89,9 +89,8 @@ static inline struct page *ntfs_map_page(struct address_space *mapping,
89 struct page *page = read_mapping_page(mapping, index, NULL); 89 struct page *page = read_mapping_page(mapping, index, NULL);
90 90
91 if (!IS_ERR(page)) { 91 if (!IS_ERR(page)) {
92 wait_on_page_locked(page);
93 kmap(page); 92 kmap(page);
94 if (PageUptodate(page) && !PageError(page)) 93 if (!PageError(page))
95 return page; 94 return page;
96 ntfs_unmap_page(page); 95 ntfs_unmap_page(page);
97 return ERR_PTR(-EIO); 96 return ERR_PTR(-EIO);
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index 7659cc192995..1c08fefe487a 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -2532,14 +2532,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
2532 page = read_mapping_page(mapping, idx, NULL); 2532 page = read_mapping_page(mapping, idx, NULL);
2533 if (IS_ERR(page)) { 2533 if (IS_ERR(page)) {
2534 ntfs_error(vol->sb, "Failed to read first partial " 2534 ntfs_error(vol->sb, "Failed to read first partial "
2535 "page (sync error, index 0x%lx).", idx); 2535 "page (error, index 0x%lx).", idx);
2536 return PTR_ERR(page);
2537 }
2538 wait_on_page_locked(page);
2539 if (unlikely(!PageUptodate(page))) {
2540 ntfs_error(vol->sb, "Failed to read first partial page "
2541 "(async error, index 0x%lx).", idx);
2542 page_cache_release(page);
2543 return PTR_ERR(page); 2536 return PTR_ERR(page);
2544 } 2537 }
2545 /* 2538 /*
@@ -2602,14 +2595,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
2602 page = read_mapping_page(mapping, idx, NULL); 2595 page = read_mapping_page(mapping, idx, NULL);
2603 if (IS_ERR(page)) { 2596 if (IS_ERR(page)) {
2604 ntfs_error(vol->sb, "Failed to read last partial page " 2597 ntfs_error(vol->sb, "Failed to read last partial page "
2605 "(sync error, index 0x%lx).", idx); 2598 "(error, index 0x%lx).", idx);
2606 return PTR_ERR(page);
2607 }
2608 wait_on_page_locked(page);
2609 if (unlikely(!PageUptodate(page))) {
2610 ntfs_error(vol->sb, "Failed to read last partial page "
2611 "(async error, index 0x%lx).", idx);
2612 page_cache_release(page);
2613 return PTR_ERR(page); 2599 return PTR_ERR(page);
2614 } 2600 }
2615 kaddr = kmap_atomic(page, KM_USER0); 2601 kaddr = kmap_atomic(page, KM_USER0);
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index d69c4595ccd0..dbbac5593106 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -236,8 +236,7 @@ do_non_resident_extend:
236 err = PTR_ERR(page); 236 err = PTR_ERR(page);
237 goto init_err_out; 237 goto init_err_out;
238 } 238 }
239 wait_on_page_locked(page); 239 if (unlikely(PageError(page))) {
240 if (unlikely(!PageUptodate(page) || PageError(page))) {
241 page_cache_release(page); 240 page_cache_release(page);
242 err = -EIO; 241 err = -EIO;
243 goto init_err_out; 242 goto init_err_out;
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 1594c90b7164..2ddde534db0a 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -2471,7 +2471,6 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
2471 s64 nr_free = vol->nr_clusters; 2471 s64 nr_free = vol->nr_clusters;
2472 u32 *kaddr; 2472 u32 *kaddr;
2473 struct address_space *mapping = vol->lcnbmp_ino->i_mapping; 2473 struct address_space *mapping = vol->lcnbmp_ino->i_mapping;
2474 filler_t *readpage = (filler_t*)mapping->a_ops->readpage;
2475 struct page *page; 2474 struct page *page;
2476 pgoff_t index, max_index; 2475 pgoff_t index, max_index;
2477 2476
@@ -2494,24 +2493,14 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
2494 * Read the page from page cache, getting it from backing store 2493 * Read the page from page cache, getting it from backing store
2495 * if necessary, and increment the use count. 2494 * if necessary, and increment the use count.
2496 */ 2495 */
2497 page = read_cache_page(mapping, index, (filler_t*)readpage, 2496 page = read_mapping_page(mapping, index, NULL);
2498 NULL);
2499 /* Ignore pages which errored synchronously. */ 2497 /* Ignore pages which errored synchronously. */
2500 if (IS_ERR(page)) { 2498 if (IS_ERR(page)) {
2501 ntfs_debug("Sync read_cache_page() error. Skipping " 2499 ntfs_debug("read_mapping_page() error. Skipping "
2502 "page (index 0x%lx).", index); 2500 "page (index 0x%lx).", index);
2503 nr_free -= PAGE_CACHE_SIZE * 8; 2501 nr_free -= PAGE_CACHE_SIZE * 8;
2504 continue; 2502 continue;
2505 } 2503 }
2506 wait_on_page_locked(page);
2507 /* Ignore pages which errored asynchronously. */
2508 if (!PageUptodate(page)) {
2509 ntfs_debug("Async read_cache_page() error. Skipping "
2510 "page (index 0x%lx).", index);
2511 page_cache_release(page);
2512 nr_free -= PAGE_CACHE_SIZE * 8;
2513 continue;
2514 }
2515 kaddr = (u32*)kmap_atomic(page, KM_USER0); 2504 kaddr = (u32*)kmap_atomic(page, KM_USER0);
2516 /* 2505 /*
2517 * For each 4 bytes, subtract the number of set bits. If this 2506 * For each 4 bytes, subtract the number of set bits. If this
@@ -2562,7 +2551,6 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
2562{ 2551{
2563 u32 *kaddr; 2552 u32 *kaddr;
2564 struct address_space *mapping = vol->mftbmp_ino->i_mapping; 2553 struct address_space *mapping = vol->mftbmp_ino->i_mapping;
2565 filler_t *readpage = (filler_t*)mapping->a_ops->readpage;
2566 struct page *page; 2554 struct page *page;
2567 pgoff_t index; 2555 pgoff_t index;
2568 2556
@@ -2576,21 +2564,11 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
2576 * Read the page from page cache, getting it from backing store 2564 * Read the page from page cache, getting it from backing store
2577 * if necessary, and increment the use count. 2565 * if necessary, and increment the use count.
2578 */ 2566 */
2579 page = read_cache_page(mapping, index, (filler_t*)readpage, 2567 page = read_mapping_page(mapping, index, NULL);
2580 NULL);
2581 /* Ignore pages which errored synchronously. */ 2568 /* Ignore pages which errored synchronously. */
2582 if (IS_ERR(page)) { 2569 if (IS_ERR(page)) {
2583 ntfs_debug("Sync read_cache_page() error. Skipping " 2570 ntfs_debug("read_mapping_page() error. Skipping "
2584 "page (index 0x%lx).", index);
2585 nr_free -= PAGE_CACHE_SIZE * 8;
2586 continue;
2587 }
2588 wait_on_page_locked(page);
2589 /* Ignore pages which errored asynchronously. */
2590 if (!PageUptodate(page)) {
2591 ntfs_debug("Async read_cache_page() error. Skipping "
2592 "page (index 0x%lx).", index); 2571 "page (index 0x%lx).", index);
2593 page_cache_release(page);
2594 nr_free -= PAGE_CACHE_SIZE * 8; 2572 nr_free -= PAGE_CACHE_SIZE * 8;
2595 continue; 2573 continue;
2596 } 2574 }
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index 40dc1a51f4a9..7134007ba22f 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -67,16 +67,9 @@ static char *ocfs2_page_getlink(struct dentry * dentry,
67 page = read_mapping_page(mapping, 0, NULL); 67 page = read_mapping_page(mapping, 0, NULL);
68 if (IS_ERR(page)) 68 if (IS_ERR(page))
69 goto sync_fail; 69 goto sync_fail;
70 wait_on_page_locked(page);
71 if (!PageUptodate(page))
72 goto async_fail;
73 *ppage = page; 70 *ppage = page;
74 return kmap(page); 71 return kmap(page);
75 72
76async_fail:
77 page_cache_release(page);
78 return ERR_PTR(-EIO);
79
80sync_fail: 73sync_fail:
81 return (char*)page; 74 return (char*)page;
82} 75}
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index f01572fca02f..6b9dae3f0e6c 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -569,9 +569,6 @@ unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
569 page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)), 569 page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)),
570 NULL); 570 NULL);
571 if (!IS_ERR(page)) { 571 if (!IS_ERR(page)) {
572 wait_on_page_locked(page);
573 if (!PageUptodate(page))
574 goto fail;
575 if (PageError(page)) 572 if (PageError(page))
576 goto fail; 573 goto fail;
577 p->v = page; 574 p->v = page;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 2cac56210e2b..bf6e58214538 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -410,11 +410,7 @@ static struct page *reiserfs_get_page(struct inode *dir, unsigned long n)
410 mapping_set_gfp_mask(mapping, GFP_NOFS); 410 mapping_set_gfp_mask(mapping, GFP_NOFS);
411 page = read_mapping_page(mapping, n, NULL); 411 page = read_mapping_page(mapping, n, NULL);
412 if (!IS_ERR(page)) { 412 if (!IS_ERR(page)) {
413 wait_on_page_locked(page);
414 kmap(page); 413 kmap(page);
415 if (!PageUptodate(page))
416 goto fail;
417
418 if (PageError(page)) 414 if (PageError(page))
419 goto fail; 415 goto fail;
420 } 416 }
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index ebf7007fa161..e566b387fcf9 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -54,17 +54,9 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n)
54{ 54{
55 struct address_space *mapping = dir->i_mapping; 55 struct address_space *mapping = dir->i_mapping;
56 struct page *page = read_mapping_page(mapping, n, NULL); 56 struct page *page = read_mapping_page(mapping, n, NULL);
57 if (!IS_ERR(page)) { 57 if (!IS_ERR(page))
58 wait_on_page_locked(page);
59 kmap(page); 58 kmap(page);
60 if (!PageUptodate(page))
61 goto fail;
62 }
63 return page; 59 return page;
64
65fail:
66 dir_put_page(page);
67 return ERR_PTR(-EIO);
68} 60}
69 61
70static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) 62static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 4890ddf1518e..4fb8b2e077ee 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -180,13 +180,9 @@ fail:
180static struct page *ufs_get_page(struct inode *dir, unsigned long n) 180static struct page *ufs_get_page(struct inode *dir, unsigned long n)
181{ 181{
182 struct address_space *mapping = dir->i_mapping; 182 struct address_space *mapping = dir->i_mapping;
183 struct page *page = read_cache_page(mapping, n, 183 struct page *page = read_mapping_page(mapping, n, NULL);
184 (filler_t*)mapping->a_ops->readpage, NULL);
185 if (!IS_ERR(page)) { 184 if (!IS_ERR(page)) {
186 wait_on_page_locked(page);
187 kmap(page); 185 kmap(page);
188 if (!PageUptodate(page))
189 goto fail;
190 if (!PageChecked(page)) 186 if (!PageChecked(page))
191 ufs_check_page(page); 187 ufs_check_page(page);
192 if (PageError(page)) 188 if (PageError(page))
diff --git a/fs/ufs/util.c b/fs/ufs/util.c
index 17437574f79c..84357f1ff0ec 100644
--- a/fs/ufs/util.c
+++ b/fs/ufs/util.c
@@ -251,13 +251,11 @@ struct page *ufs_get_locked_page(struct address_space *mapping,
251 251
252 page = find_lock_page(mapping, index); 252 page = find_lock_page(mapping, index);
253 if (!page) { 253 if (!page) {
254 page = read_cache_page(mapping, index, 254 page = read_mapping_page(mapping, index, NULL);
255 (filler_t*)mapping->a_ops->readpage,
256 NULL);
257 255
258 if (IS_ERR(page)) { 256 if (IS_ERR(page)) {
259 printk(KERN_ERR "ufs_change_blocknr: " 257 printk(KERN_ERR "ufs_change_blocknr: "
260 "read_cache_page error: ino %lu, index: %lu\n", 258 "read_mapping_page error: ino %lu, index: %lu\n",
261 mapping->host->i_ino, index); 259 mapping->host->i_ino, index);
262 goto out; 260 goto out;
263 } 261 }
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 7a8dcb82a699..b4def5e083ed 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -95,12 +95,23 @@ static inline struct page *grab_cache_page(struct address_space *mapping, unsign
95 95
96extern struct page * grab_cache_page_nowait(struct address_space *mapping, 96extern struct page * grab_cache_page_nowait(struct address_space *mapping,
97 unsigned long index); 97 unsigned long index);
98extern struct page * read_cache_page_async(struct address_space *mapping,
99 unsigned long index, filler_t *filler,
100 void *data);
98extern struct page * read_cache_page(struct address_space *mapping, 101extern struct page * read_cache_page(struct address_space *mapping,
99 unsigned long index, filler_t *filler, 102 unsigned long index, filler_t *filler,
100 void *data); 103 void *data);
101extern int read_cache_pages(struct address_space *mapping, 104extern int read_cache_pages(struct address_space *mapping,
102 struct list_head *pages, filler_t *filler, void *data); 105 struct list_head *pages, filler_t *filler, void *data);
103 106
107static inline struct page *read_mapping_page_async(
108 struct address_space *mapping,
109 unsigned long index, void *data)
110{
111 filler_t *filler = (filler_t *)mapping->a_ops->readpage;
112 return read_cache_page_async(mapping, index, filler, data);
113}
114
104static inline struct page *read_mapping_page(struct address_space *mapping, 115static inline struct page *read_mapping_page(struct address_space *mapping,
105 unsigned long index, void *data) 116 unsigned long index, void *data)
106{ 117{
diff --git a/mm/filemap.c b/mm/filemap.c
index 5dfc093ceb3d..070e7547d5b5 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1726,7 +1726,7 @@ int generic_file_readonly_mmap(struct file * file, struct vm_area_struct * vma)
1726EXPORT_SYMBOL(generic_file_mmap); 1726EXPORT_SYMBOL(generic_file_mmap);
1727EXPORT_SYMBOL(generic_file_readonly_mmap); 1727EXPORT_SYMBOL(generic_file_readonly_mmap);
1728 1728
1729static inline struct page *__read_cache_page(struct address_space *mapping, 1729static struct page *__read_cache_page(struct address_space *mapping,
1730 unsigned long index, 1730 unsigned long index,
1731 int (*filler)(void *,struct page*), 1731 int (*filler)(void *,struct page*),
1732 void *data) 1732 void *data)
@@ -1763,17 +1763,11 @@ repeat:
1763 return page; 1763 return page;
1764} 1764}
1765 1765
1766/** 1766/*
1767 * read_cache_page - read into page cache, fill it if needed 1767 * Same as read_cache_page, but don't wait for page to become unlocked
1768 * @mapping: the page's address_space 1768 * after submitting it to the filler.
1769 * @index: the page index
1770 * @filler: function to perform the read
1771 * @data: destination for read data
1772 *
1773 * Read into the page cache. If a page already exists,
1774 * and PageUptodate() is not set, try to fill the page.
1775 */ 1769 */
1776struct page *read_cache_page(struct address_space *mapping, 1770struct page *read_cache_page_async(struct address_space *mapping,
1777 unsigned long index, 1771 unsigned long index,
1778 int (*filler)(void *,struct page*), 1772 int (*filler)(void *,struct page*),
1779 void *data) 1773 void *data)
@@ -1805,6 +1799,39 @@ retry:
1805 page = ERR_PTR(err); 1799 page = ERR_PTR(err);
1806 } 1800 }
1807 out: 1801 out:
1802 mark_page_accessed(page);
1803 return page;
1804}
1805EXPORT_SYMBOL(read_cache_page_async);
1806
1807/**
1808 * read_cache_page - read into page cache, fill it if needed
1809 * @mapping: the page's address_space
1810 * @index: the page index
1811 * @filler: function to perform the read
1812 * @data: destination for read data
1813 *
1814 * Read into the page cache. If a page already exists, and PageUptodate() is
1815 * not set, try to fill the page then wait for it to become unlocked.
1816 *
1817 * If the page does not get brought uptodate, return -EIO.
1818 */
1819struct page *read_cache_page(struct address_space *mapping,
1820 unsigned long index,
1821 int (*filler)(void *,struct page*),
1822 void *data)
1823{
1824 struct page *page;
1825
1826 page = read_cache_page_async(mapping, index, filler, data);
1827 if (IS_ERR(page))
1828 goto out;
1829 wait_on_page_locked(page);
1830 if (!PageUptodate(page)) {
1831 page_cache_release(page);
1832 page = ERR_PTR(-EIO);
1833 }
1834 out:
1808 return page; 1835 return page;
1809} 1836}
1810EXPORT_SYMBOL(read_cache_page); 1837EXPORT_SYMBOL(read_cache_page);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index a2d9bb4e80df..acc172cbe3aa 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1531,9 +1531,6 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
1531 error = PTR_ERR(page); 1531 error = PTR_ERR(page);
1532 goto bad_swap; 1532 goto bad_swap;
1533 } 1533 }
1534 wait_on_page_locked(page);
1535 if (!PageUptodate(page))
1536 goto bad_swap;
1537 kmap(page); 1534 kmap(page);
1538 swap_header = page_address(page); 1535 swap_header = page_address(page);
1539 1536