aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-11-08 10:59:22 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:57 -0400
commit3ab2fb5a8cb003897016b6eb38ddad916226c1b2 (patch)
treedce5ac7ae586111c7e872193c09ced717b936549
parent856bf3e592f917e7d663cb7fa93e83fe795e8f4e (diff)
Btrfs: Add readpages support
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/extent_map.c70
-rw-r--r--fs/btrfs/extent_map.h4
-rw-r--r--fs/btrfs/inode.c12
3 files changed, 78 insertions, 8 deletions
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 754bc42c162a..0077c6c1d9f9 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -11,6 +11,7 @@
11#include <linux/swap.h> 11#include <linux/swap.h>
12#include <linux/version.h> 12#include <linux/version.h>
13#include <linux/writeback.h> 13#include <linux/writeback.h>
14#include <linux/pagevec.h>
14#include "extent_map.h" 15#include "extent_map.h"
15 16
16/* temporary define until extent_map moves out of btrfs */ 17/* temporary define until extent_map moves out of btrfs */
@@ -1503,7 +1504,7 @@ static int submit_extent_page(int rw, struct extent_map_tree *tree,
1503 size_t size, unsigned long offset, 1504 size_t size, unsigned long offset,
1504 struct block_device *bdev, 1505 struct block_device *bdev,
1505 struct bio **bio_ret, 1506 struct bio **bio_ret,
1506 int max_pages, 1507 unsigned long max_pages,
1507 bio_end_io_t end_io_func) 1508 bio_end_io_t end_io_func)
1508{ 1509{
1509 int ret = 0; 1510 int ret = 0;
@@ -1520,7 +1521,7 @@ static int submit_extent_page(int rw, struct extent_map_tree *tree,
1520 return 0; 1521 return 0;
1521 } 1522 }
1522 } 1523 }
1523 nr = min(max_pages, bio_get_nr_vecs(bdev)); 1524 nr = min_t(int, max_pages, bio_get_nr_vecs(bdev));
1524 bio = extent_bio_alloc(bdev, sector, nr, GFP_NOFS | __GFP_HIGH); 1525 bio = extent_bio_alloc(bdev, sector, nr, GFP_NOFS | __GFP_HIGH);
1525 if (!bio) { 1526 if (!bio) {
1526 printk("failed to allocate bio nr %d\n", nr); 1527 printk("failed to allocate bio nr %d\n", nr);
@@ -1552,8 +1553,10 @@ void set_page_extent_mapped(struct page *page)
1552 * into the tree that are removed when the IO is done (by the end_io 1553 * into the tree that are removed when the IO is done (by the end_io
1553 * handlers) 1554 * handlers)
1554 */ 1555 */
1555int extent_read_full_page(struct extent_map_tree *tree, struct page *page, 1556static int __extent_read_full_page(struct extent_map_tree *tree,
1556 get_extent_t *get_extent) 1557 struct page *page,
1558 get_extent_t *get_extent,
1559 struct bio **bio)
1557{ 1560{
1558 struct inode *inode = page->mapping->host; 1561 struct inode *inode = page->mapping->host;
1559 u64 start = (u64)page->index << PAGE_CACHE_SHIFT; 1562 u64 start = (u64)page->index << PAGE_CACHE_SHIFT;
@@ -1631,10 +1634,12 @@ int extent_read_full_page(struct extent_map_tree *tree, struct page *page,
1631 cur + iosize - 1); 1634 cur + iosize - 1);
1632 } 1635 }
1633 if (!ret) { 1636 if (!ret) {
1637 unsigned long nr = (last_byte >> PAGE_CACHE_SHIFT) + 1;
1638 nr -= page->index;
1634 ret = submit_extent_page(READ, tree, page, 1639 ret = submit_extent_page(READ, tree, page,
1635 sector, iosize, page_offset, 1640 sector, iosize, page_offset,
1636 bdev, NULL, 1, 1641 bdev, bio, nr,
1637 end_bio_extent_readpage); 1642 end_bio_extent_readpage);
1638 } 1643 }
1639 if (ret) 1644 if (ret)
1640 SetPageError(page); 1645 SetPageError(page);
@@ -1649,6 +1654,18 @@ int extent_read_full_page(struct extent_map_tree *tree, struct page *page,
1649 } 1654 }
1650 return 0; 1655 return 0;
1651} 1656}
1657
1658int extent_read_full_page(struct extent_map_tree *tree, struct page *page,
1659 get_extent_t *get_extent)
1660{
1661 struct bio *bio = NULL;
1662 int ret;
1663
1664 ret = __extent_read_full_page(tree, page, get_extent, &bio);
1665 if (bio)
1666 submit_one_bio(READ, bio);
1667 return ret;
1668}
1652EXPORT_SYMBOL(extent_read_full_page); 1669EXPORT_SYMBOL(extent_read_full_page);
1653 1670
1654/* 1671/*
@@ -1836,6 +1853,45 @@ int extent_writepages(struct extent_map_tree *tree,
1836} 1853}
1837EXPORT_SYMBOL(extent_writepages); 1854EXPORT_SYMBOL(extent_writepages);
1838 1855
1856int extent_readpages(struct extent_map_tree *tree,
1857 struct address_space *mapping,
1858 struct list_head *pages, unsigned nr_pages,
1859 get_extent_t get_extent)
1860{
1861 struct bio *bio = NULL;
1862 unsigned page_idx;
1863 struct pagevec pvec;
1864
1865 pagevec_init(&pvec, 0);
1866 for (page_idx = 0; page_idx < nr_pages; page_idx++) {
1867 struct page *page = list_entry(pages->prev, struct page, lru);
1868
1869 prefetchw(&page->flags);
1870 list_del(&page->lru);
1871 /*
1872 * what we want to do here is call add_to_page_cache_lru,
1873 * but that isn't exported, so we reproduce it here
1874 */
1875 if (!add_to_page_cache(page, mapping,
1876 page->index, GFP_KERNEL)) {
1877
1878 /* open coding of lru_cache_add, also not exported */
1879 page_cache_get(page);
1880 if (!pagevec_add(&pvec, page))
1881 __pagevec_lru_add(&pvec);
1882 __extent_read_full_page(tree, page, get_extent, &bio);
1883 }
1884 page_cache_release(page);
1885 }
1886 if (pagevec_count(&pvec))
1887 __pagevec_lru_add(&pvec);
1888 BUG_ON(!list_empty(pages));
1889 if (bio)
1890 submit_one_bio(READ, bio);
1891 return 0;
1892}
1893EXPORT_SYMBOL(extent_readpages);
1894
1839/* 1895/*
1840 * basic invalidatepage code, this waits on any locked or writeback 1896 * basic invalidatepage code, this waits on any locked or writeback
1841 * ranges corresponding to the page, and then deletes any extent state 1897 * ranges corresponding to the page, and then deletes any extent state
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h
index 0b0dcf19fe45..fbd23a72f53b 100644
--- a/fs/btrfs/extent_map.h
+++ b/fs/btrfs/extent_map.h
@@ -140,6 +140,10 @@ int extent_writepages(struct extent_map_tree *tree,
140 struct address_space *mapping, 140 struct address_space *mapping,
141 get_extent_t *get_extent, 141 get_extent_t *get_extent,
142 struct writeback_control *wbc); 142 struct writeback_control *wbc);
143int extent_readpages(struct extent_map_tree *tree,
144 struct address_space *mapping,
145 struct list_head *pages, unsigned nr_pages,
146 get_extent_t get_extent);
143int extent_prepare_write(struct extent_map_tree *tree, 147int extent_prepare_write(struct extent_map_tree *tree,
144 struct inode *inode, struct page *page, 148 struct inode *inode, struct page *page,
145 unsigned from, unsigned to, get_extent_t *get_extent); 149 unsigned from, unsigned to, get_extent_t *get_extent);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 90cb71d68294..d6d32465bc9a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1748,7 +1748,6 @@ static int btrfs_writepage(struct page *page, struct writeback_control *wbc)
1748 return extent_write_full_page(tree, page, btrfs_get_extent, wbc); 1748 return extent_write_full_page(tree, page, btrfs_get_extent, wbc);
1749} 1749}
1750 1750
1751
1752static int btrfs_writepages(struct address_space *mapping, 1751static int btrfs_writepages(struct address_space *mapping,
1753 struct writeback_control *wbc) 1752 struct writeback_control *wbc)
1754{ 1753{
@@ -1757,6 +1756,16 @@ static int btrfs_writepages(struct address_space *mapping,
1757 return extent_writepages(tree, mapping, btrfs_get_extent, wbc); 1756 return extent_writepages(tree, mapping, btrfs_get_extent, wbc);
1758} 1757}
1759 1758
1759static int
1760btrfs_readpages(struct file *file, struct address_space *mapping,
1761 struct list_head *pages, unsigned nr_pages)
1762{
1763 struct extent_map_tree *tree;
1764 tree = &BTRFS_I(mapping->host)->extent_tree;
1765 return extent_readpages(tree, mapping, pages, nr_pages,
1766 btrfs_get_extent);
1767}
1768
1760static int btrfs_releasepage(struct page *page, gfp_t unused_gfp_flags) 1769static int btrfs_releasepage(struct page *page, gfp_t unused_gfp_flags)
1761{ 1770{
1762 struct extent_map_tree *tree; 1771 struct extent_map_tree *tree;
@@ -2537,6 +2546,7 @@ static struct address_space_operations btrfs_aops = {
2537 .readpage = btrfs_readpage, 2546 .readpage = btrfs_readpage,
2538 .writepage = btrfs_writepage, 2547 .writepage = btrfs_writepage,
2539 .writepages = btrfs_writepages, 2548 .writepages = btrfs_writepages,
2549 .readpages = btrfs_readpages,
2540 .sync_page = block_sync_page, 2550 .sync_page = block_sync_page,
2541 .prepare_write = btrfs_prepare_write, 2551 .prepare_write = btrfs_prepare_write,
2542 .commit_write = btrfs_commit_write, 2552 .commit_write = btrfs_commit_write,