diff options
author | Hugh Dickins <hugh@veritas.com> | 2007-06-04 04:00:39 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2007-07-10 02:04:15 -0400 |
commit | ae976416464b741913a13eea62eb6953ee065733 (patch) | |
tree | 48ac14023b494c9f6522ad390f60e4decac41ac3 | |
parent | 1db60cf2056511c7c8cebcbaee308ef6c79b4728 (diff) |
shmem: convert to using splice instead of sendfile()
Remove shmem_file_sendfile and resurrect shmem_readpage, as used by tmpfs
to support loop and sendfile in 2.4 and 2.5. Now tmpfs can support splice,
loop and sendfile in the simplest way, using generic_file_splice_read and
generic_file_splice_write (with the aid of shmem_prepare_write).
We could make some efficiency tweaks later, if there's a real need;
but this is stable and works well as is.
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | mm/shmem.c | 42 |
1 files changed, 17 insertions, 25 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index b6aae2b33393..0493e4d0bcaa 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1100,9 +1100,9 @@ static int shmem_getpage(struct inode *inode, unsigned long idx, | |||
1100 | * Normally, filepage is NULL on entry, and either found | 1100 | * Normally, filepage is NULL on entry, and either found |
1101 | * uptodate immediately, or allocated and zeroed, or read | 1101 | * uptodate immediately, or allocated and zeroed, or read |
1102 | * in under swappage, which is then assigned to filepage. | 1102 | * in under swappage, which is then assigned to filepage. |
1103 | * But shmem_prepare_write passes in a locked filepage, | 1103 | * But shmem_readpage and shmem_prepare_write pass in a locked |
1104 | * which may be found not uptodate by other callers too, | 1104 | * filepage, which may be found not uptodate by other callers |
1105 | * and may need to be copied from the swappage read in. | 1105 | * too, and may need to be copied from the swappage read in. |
1106 | */ | 1106 | */ |
1107 | repeat: | 1107 | repeat: |
1108 | if (!filepage) | 1108 | if (!filepage) |
@@ -1485,9 +1485,18 @@ static const struct inode_operations shmem_symlink_inode_operations; | |||
1485 | static const struct inode_operations shmem_symlink_inline_operations; | 1485 | static const struct inode_operations shmem_symlink_inline_operations; |
1486 | 1486 | ||
1487 | /* | 1487 | /* |
1488 | * Normally tmpfs makes no use of shmem_prepare_write, but it | 1488 | * Normally tmpfs avoids the use of shmem_readpage and shmem_prepare_write; |
1489 | * lets a tmpfs file be used read-write below the loop driver. | 1489 | * but providing them allows a tmpfs file to be used for splice, sendfile, and |
1490 | * below the loop driver, in the generic fashion that many filesystems support. | ||
1490 | */ | 1491 | */ |
1492 | static int shmem_readpage(struct file *file, struct page *page) | ||
1493 | { | ||
1494 | struct inode *inode = page->mapping->host; | ||
1495 | int error = shmem_getpage(inode, page->index, &page, SGP_CACHE, NULL); | ||
1496 | unlock_page(page); | ||
1497 | return error; | ||
1498 | } | ||
1499 | |||
1491 | static int | 1500 | static int |
1492 | shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) | 1501 | shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) |
1493 | { | 1502 | { |
@@ -1711,25 +1720,6 @@ static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count | |||
1711 | return desc.error; | 1720 | return desc.error; |
1712 | } | 1721 | } |
1713 | 1722 | ||
1714 | static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos, | ||
1715 | size_t count, read_actor_t actor, void *target) | ||
1716 | { | ||
1717 | read_descriptor_t desc; | ||
1718 | |||
1719 | if (!count) | ||
1720 | return 0; | ||
1721 | |||
1722 | desc.written = 0; | ||
1723 | desc.count = count; | ||
1724 | desc.arg.data = target; | ||
1725 | desc.error = 0; | ||
1726 | |||
1727 | do_shmem_file_read(in_file, ppos, &desc, actor); | ||
1728 | if (desc.written) | ||
1729 | return desc.written; | ||
1730 | return desc.error; | ||
1731 | } | ||
1732 | |||
1733 | static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf) | 1723 | static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf) |
1734 | { | 1724 | { |
1735 | struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb); | 1725 | struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb); |
@@ -2386,6 +2376,7 @@ static const struct address_space_operations shmem_aops = { | |||
2386 | .writepage = shmem_writepage, | 2376 | .writepage = shmem_writepage, |
2387 | .set_page_dirty = __set_page_dirty_no_writeback, | 2377 | .set_page_dirty = __set_page_dirty_no_writeback, |
2388 | #ifdef CONFIG_TMPFS | 2378 | #ifdef CONFIG_TMPFS |
2379 | .readpage = shmem_readpage, | ||
2389 | .prepare_write = shmem_prepare_write, | 2380 | .prepare_write = shmem_prepare_write, |
2390 | .commit_write = simple_commit_write, | 2381 | .commit_write = simple_commit_write, |
2391 | #endif | 2382 | #endif |
@@ -2399,7 +2390,8 @@ static const struct file_operations shmem_file_operations = { | |||
2399 | .read = shmem_file_read, | 2390 | .read = shmem_file_read, |
2400 | .write = shmem_file_write, | 2391 | .write = shmem_file_write, |
2401 | .fsync = simple_sync_file, | 2392 | .fsync = simple_sync_file, |
2402 | .sendfile = shmem_file_sendfile, | 2393 | .splice_read = generic_file_splice_read, |
2394 | .splice_write = generic_file_splice_write, | ||
2403 | #endif | 2395 | #endif |
2404 | }; | 2396 | }; |
2405 | 2397 | ||