diff options
author | Hugh Dickins <hughd@google.com> | 2011-07-25 20:12:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-25 23:57:11 -0400 |
commit | 9276aad6c898dbcc31d095f2934dedd5cbb2e93e (patch) | |
tree | 7ba68f82aa8b747e11d9cfb79c4fe06188b7b2c7 /mm/shmem.c | |
parent | 68da9f055755ee2609a1686722e6d6a7980019ee (diff) |
tmpfs: remove_shmem_readpage
Remove that pernicious shmem_readpage() at last: the things we needed it
for (splice, loop, sendfile, i915 GEM) are now fully taken care of by
shmem_file_splice_read() and shmem_read_mapping_page_gfp().
This removal clears the way for a simpler shmem_getpage_gfp(), since page
is never passed in; but leave most of that cleanup until after.
sys_readahead() and sys_fadvise(POSIX_FADV_WILLNEED) will now EINVAL,
instead of unexpectedly trying to read ahead on tmpfs: if that proves to
be an issue for someone, then we can either arrange for them to return
success instead, or try to implement async readahead on tmpfs.
Signed-off-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 40 |
1 files changed, 6 insertions, 34 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index f6c94ba87808..ff6713a2579e 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1246,7 +1246,7 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t idx, | |||
1246 | struct address_space *mapping = inode->i_mapping; | 1246 | struct address_space *mapping = inode->i_mapping; |
1247 | struct shmem_inode_info *info = SHMEM_I(inode); | 1247 | struct shmem_inode_info *info = SHMEM_I(inode); |
1248 | struct shmem_sb_info *sbinfo; | 1248 | struct shmem_sb_info *sbinfo; |
1249 | struct page *filepage = *pagep; | 1249 | struct page *filepage; |
1250 | struct page *swappage; | 1250 | struct page *swappage; |
1251 | struct page *prealloc_page = NULL; | 1251 | struct page *prealloc_page = NULL; |
1252 | swp_entry_t *entry; | 1252 | swp_entry_t *entry; |
@@ -1255,18 +1255,8 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t idx, | |||
1255 | 1255 | ||
1256 | if (idx >= SHMEM_MAX_INDEX) | 1256 | if (idx >= SHMEM_MAX_INDEX) |
1257 | return -EFBIG; | 1257 | return -EFBIG; |
1258 | |||
1259 | /* | ||
1260 | * Normally, filepage is NULL on entry, and either found | ||
1261 | * uptodate immediately, or allocated and zeroed, or read | ||
1262 | * in under swappage, which is then assigned to filepage. | ||
1263 | * But shmem_readpage (required for splice) passes in a locked | ||
1264 | * filepage, which may be found not uptodate by other callers | ||
1265 | * too, and may need to be copied from the swappage read in. | ||
1266 | */ | ||
1267 | repeat: | 1258 | repeat: |
1268 | if (!filepage) | 1259 | filepage = find_lock_page(mapping, idx); |
1269 | filepage = find_lock_page(mapping, idx); | ||
1270 | if (filepage && PageUptodate(filepage)) | 1260 | if (filepage && PageUptodate(filepage)) |
1271 | goto done; | 1261 | goto done; |
1272 | if (!filepage) { | 1262 | if (!filepage) { |
@@ -1513,8 +1503,7 @@ nospace: | |||
1513 | * Perhaps the page was brought in from swap between find_lock_page | 1503 | * Perhaps the page was brought in from swap between find_lock_page |
1514 | * and taking info->lock? We allow for that at add_to_page_cache_lru, | 1504 | * and taking info->lock? We allow for that at add_to_page_cache_lru, |
1515 | * but must also avoid reporting a spurious ENOSPC while working on a | 1505 | * but must also avoid reporting a spurious ENOSPC while working on a |
1516 | * full tmpfs. (When filepage has been passed in to shmem_getpage, it | 1506 | * full tmpfs. |
1517 | * is already in page cache, which prevents this race from occurring.) | ||
1518 | */ | 1507 | */ |
1519 | if (!filepage) { | 1508 | if (!filepage) { |
1520 | struct page *page = find_get_page(mapping, idx); | 1509 | struct page *page = find_get_page(mapping, idx); |
@@ -1527,7 +1516,7 @@ nospace: | |||
1527 | spin_unlock(&info->lock); | 1516 | spin_unlock(&info->lock); |
1528 | error = -ENOSPC; | 1517 | error = -ENOSPC; |
1529 | failed: | 1518 | failed: |
1530 | if (*pagep != filepage) { | 1519 | if (filepage) { |
1531 | unlock_page(filepage); | 1520 | unlock_page(filepage); |
1532 | page_cache_release(filepage); | 1521 | page_cache_release(filepage); |
1533 | } | 1522 | } |
@@ -1673,19 +1662,6 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode | |||
1673 | static const struct inode_operations shmem_symlink_inode_operations; | 1662 | static const struct inode_operations shmem_symlink_inode_operations; |
1674 | static const struct inode_operations shmem_symlink_inline_operations; | 1663 | static const struct inode_operations shmem_symlink_inline_operations; |
1675 | 1664 | ||
1676 | /* | ||
1677 | * Normally tmpfs avoids the use of shmem_readpage and shmem_write_begin; | ||
1678 | * but providing them allows a tmpfs file to be used for splice, sendfile, and | ||
1679 | * below the loop driver, in the generic fashion that many filesystems support. | ||
1680 | */ | ||
1681 | static int shmem_readpage(struct file *file, struct page *page) | ||
1682 | { | ||
1683 | struct inode *inode = page->mapping->host; | ||
1684 | int error = shmem_getpage(inode, page->index, &page, SGP_CACHE, NULL); | ||
1685 | unlock_page(page); | ||
1686 | return error; | ||
1687 | } | ||
1688 | |||
1689 | static int | 1665 | static int |
1690 | shmem_write_begin(struct file *file, struct address_space *mapping, | 1666 | shmem_write_begin(struct file *file, struct address_space *mapping, |
1691 | loff_t pos, unsigned len, unsigned flags, | 1667 | loff_t pos, unsigned len, unsigned flags, |
@@ -1693,7 +1669,6 @@ shmem_write_begin(struct file *file, struct address_space *mapping, | |||
1693 | { | 1669 | { |
1694 | struct inode *inode = mapping->host; | 1670 | struct inode *inode = mapping->host; |
1695 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; | 1671 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; |
1696 | *pagep = NULL; | ||
1697 | return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL); | 1672 | return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL); |
1698 | } | 1673 | } |
1699 | 1674 | ||
@@ -1893,7 +1868,6 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, | |||
1893 | error = 0; | 1868 | error = 0; |
1894 | 1869 | ||
1895 | while (spd.nr_pages < nr_pages) { | 1870 | while (spd.nr_pages < nr_pages) { |
1896 | page = NULL; | ||
1897 | error = shmem_getpage(inode, index, &page, SGP_CACHE, NULL); | 1871 | error = shmem_getpage(inode, index, &page, SGP_CACHE, NULL); |
1898 | if (error) | 1872 | if (error) |
1899 | break; | 1873 | break; |
@@ -1916,7 +1890,6 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, | |||
1916 | page = spd.pages[page_nr]; | 1890 | page = spd.pages[page_nr]; |
1917 | 1891 | ||
1918 | if (!PageUptodate(page) || page->mapping != mapping) { | 1892 | if (!PageUptodate(page) || page->mapping != mapping) { |
1919 | page = NULL; | ||
1920 | error = shmem_getpage(inode, index, &page, | 1893 | error = shmem_getpage(inode, index, &page, |
1921 | SGP_CACHE, NULL); | 1894 | SGP_CACHE, NULL); |
1922 | if (error) | 1895 | if (error) |
@@ -2125,7 +2098,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s | |||
2125 | int error; | 2098 | int error; |
2126 | int len; | 2099 | int len; |
2127 | struct inode *inode; | 2100 | struct inode *inode; |
2128 | struct page *page = NULL; | 2101 | struct page *page; |
2129 | char *kaddr; | 2102 | char *kaddr; |
2130 | struct shmem_inode_info *info; | 2103 | struct shmem_inode_info *info; |
2131 | 2104 | ||
@@ -2803,7 +2776,6 @@ static const struct address_space_operations shmem_aops = { | |||
2803 | .writepage = shmem_writepage, | 2776 | .writepage = shmem_writepage, |
2804 | .set_page_dirty = __set_page_dirty_no_writeback, | 2777 | .set_page_dirty = __set_page_dirty_no_writeback, |
2805 | #ifdef CONFIG_TMPFS | 2778 | #ifdef CONFIG_TMPFS |
2806 | .readpage = shmem_readpage, | ||
2807 | .write_begin = shmem_write_begin, | 2779 | .write_begin = shmem_write_begin, |
2808 | .write_end = shmem_write_end, | 2780 | .write_end = shmem_write_end, |
2809 | #endif | 2781 | #endif |
@@ -3175,7 +3147,7 @@ struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, | |||
3175 | { | 3147 | { |
3176 | #ifdef CONFIG_SHMEM | 3148 | #ifdef CONFIG_SHMEM |
3177 | struct inode *inode = mapping->host; | 3149 | struct inode *inode = mapping->host; |
3178 | struct page *page = NULL; | 3150 | struct page *page; |
3179 | int error; | 3151 | int error; |
3180 | 3152 | ||
3181 | BUG_ON(mapping->a_ops != &shmem_aops); | 3153 | BUG_ON(mapping->a_ops != &shmem_aops); |