diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/shmem.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index 2c39925fe073..131f2938f3ad 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1108,7 +1108,7 @@ static int shmem_getpage(struct inode *inode, unsigned long idx, | |||
1108 | * Normally, filepage is NULL on entry, and either found | 1108 | * Normally, filepage is NULL on entry, and either found |
1109 | * uptodate immediately, or allocated and zeroed, or read | 1109 | * uptodate immediately, or allocated and zeroed, or read |
1110 | * in under swappage, which is then assigned to filepage. | 1110 | * in under swappage, which is then assigned to filepage. |
1111 | * But shmem_readpage and shmem_prepare_write pass in a locked | 1111 | * But shmem_readpage and shmem_write_begin pass in a locked |
1112 | * filepage, which may be found not uptodate by other callers | 1112 | * filepage, which may be found not uptodate by other callers |
1113 | * too, and may need to be copied from the swappage read in. | 1113 | * too, and may need to be copied from the swappage read in. |
1114 | */ | 1114 | */ |
@@ -1445,7 +1445,7 @@ static const struct inode_operations shmem_symlink_inode_operations; | |||
1445 | static const struct inode_operations shmem_symlink_inline_operations; | 1445 | static const struct inode_operations shmem_symlink_inline_operations; |
1446 | 1446 | ||
1447 | /* | 1447 | /* |
1448 | * Normally tmpfs avoids the use of shmem_readpage and shmem_prepare_write; | 1448 | * Normally tmpfs avoids the use of shmem_readpage and shmem_write_begin; |
1449 | * but providing them allows a tmpfs file to be used for splice, sendfile, and | 1449 | * but providing them allows a tmpfs file to be used for splice, sendfile, and |
1450 | * below the loop driver, in the generic fashion that many filesystems support. | 1450 | * below the loop driver, in the generic fashion that many filesystems support. |
1451 | */ | 1451 | */ |
@@ -1458,10 +1458,30 @@ static int shmem_readpage(struct file *file, struct page *page) | |||
1458 | } | 1458 | } |
1459 | 1459 | ||
1460 | static int | 1460 | static int |
1461 | shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) | 1461 | shmem_write_begin(struct file *file, struct address_space *mapping, |
1462 | loff_t pos, unsigned len, unsigned flags, | ||
1463 | struct page **pagep, void **fsdata) | ||
1462 | { | 1464 | { |
1463 | struct inode *inode = page->mapping->host; | 1465 | struct inode *inode = mapping->host; |
1464 | return shmem_getpage(inode, page->index, &page, SGP_WRITE, NULL); | 1466 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; |
1467 | *pagep = NULL; | ||
1468 | return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL); | ||
1469 | } | ||
1470 | |||
1471 | static int | ||
1472 | shmem_write_end(struct file *file, struct address_space *mapping, | ||
1473 | loff_t pos, unsigned len, unsigned copied, | ||
1474 | struct page *page, void *fsdata) | ||
1475 | { | ||
1476 | struct inode *inode = mapping->host; | ||
1477 | |||
1478 | set_page_dirty(page); | ||
1479 | page_cache_release(page); | ||
1480 | |||
1481 | if (pos+copied > inode->i_size) | ||
1482 | i_size_write(inode, pos+copied); | ||
1483 | |||
1484 | return copied; | ||
1465 | } | 1485 | } |
1466 | 1486 | ||
1467 | static ssize_t | 1487 | static ssize_t |
@@ -2337,8 +2357,8 @@ static const struct address_space_operations shmem_aops = { | |||
2337 | .set_page_dirty = __set_page_dirty_no_writeback, | 2357 | .set_page_dirty = __set_page_dirty_no_writeback, |
2338 | #ifdef CONFIG_TMPFS | 2358 | #ifdef CONFIG_TMPFS |
2339 | .readpage = shmem_readpage, | 2359 | .readpage = shmem_readpage, |
2340 | .prepare_write = shmem_prepare_write, | 2360 | .write_begin = shmem_write_begin, |
2341 | .commit_write = simple_commit_write, | 2361 | .write_end = shmem_write_end, |
2342 | #endif | 2362 | #endif |
2343 | .migratepage = migrate_page, | 2363 | .migratepage = migrate_page, |
2344 | }; | 2364 | }; |