aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/data.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2015-04-09 14:20:42 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2015-05-28 18:41:30 -0400
commitf1e8866016b53bd0ea108ae9adbb52da1dd53dab (patch)
treea88d57784acff179c93b4119c0b55d0656860d6b /fs/f2fs/data.c
parent26d815ad75156a1cf2f6c7ba94cdfd32849879d7 (diff)
f2fs: expose f2fs_mpage_readpages
This patch implements f2fs_mpage_readpages for further optimization on encryption support. The basic code was taken from fs/mpage.c, and changed to be simple by adjusting that block_size is equal to page_size in f2fs. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/data.c')
-rw-r--r--fs/f2fs/data.c157
1 files changed, 154 insertions, 3 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index aa3c079ffd94..2a3a9cd008da 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -18,6 +18,7 @@
18#include <linux/bio.h> 18#include <linux/bio.h>
19#include <linux/prefetch.h> 19#include <linux/prefetch.h>
20#include <linux/uio.h> 20#include <linux/uio.h>
21#include <linux/cleancache.h>
21 22
22#include "f2fs.h" 23#include "f2fs.h"
23#include "node.h" 24#include "node.h"
@@ -47,6 +48,30 @@ static void f2fs_read_end_io(struct bio *bio, int err)
47 bio_put(bio); 48 bio_put(bio);
48} 49}
49 50
51/*
52 * I/O completion handler for multipage BIOs.
53 * copied from fs/mpage.c
54 */
55static void mpage_end_io(struct bio *bio, int err)
56{
57 struct bio_vec *bv;
58 int i;
59
60 bio_for_each_segment_all(bv, bio, i) {
61 struct page *page = bv->bv_page;
62
63 if (!err) {
64 SetPageUptodate(page);
65 } else {
66 ClearPageUptodate(page);
67 SetPageError(page);
68 }
69 unlock_page(page);
70 }
71
72 bio_put(bio);
73}
74
50static void f2fs_write_end_io(struct bio *bio, int err) 75static void f2fs_write_end_io(struct bio *bio, int err)
51{ 76{
52 struct f2fs_sb_info *sbi = bio->bi_private; 77 struct f2fs_sb_info *sbi = bio->bi_private;
@@ -1349,6 +1374,133 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
1349 start, len, get_data_block_fiemap); 1374 start, len, get_data_block_fiemap);
1350} 1375}
1351 1376
1377/*
1378 * This function was originally taken from fs/mpage.c, and customized for f2fs.
1379 * Major change was from block_size == page_size in f2fs by default.
1380 */
1381static int f2fs_mpage_readpages(struct address_space *mapping,
1382 struct list_head *pages, struct page *page,
1383 unsigned nr_pages)
1384{
1385 struct bio *bio = NULL;
1386 unsigned page_idx;
1387 sector_t last_block_in_bio = 0;
1388 struct inode *inode = mapping->host;
1389 const unsigned blkbits = inode->i_blkbits;
1390 const unsigned blocksize = 1 << blkbits;
1391 sector_t block_in_file;
1392 sector_t last_block;
1393 sector_t last_block_in_file;
1394 sector_t block_nr;
1395 struct block_device *bdev = inode->i_sb->s_bdev;
1396 struct f2fs_map_blocks map;
1397
1398 map.m_pblk = 0;
1399 map.m_lblk = 0;
1400 map.m_len = 0;
1401 map.m_flags = 0;
1402
1403 for (page_idx = 0; nr_pages; page_idx++, nr_pages--) {
1404
1405 prefetchw(&page->flags);
1406 if (pages) {
1407 page = list_entry(pages->prev, struct page, lru);
1408 list_del(&page->lru);
1409 if (add_to_page_cache_lru(page, mapping,
1410 page->index, GFP_KERNEL))
1411 goto next_page;
1412 }
1413
1414 block_in_file = (sector_t)page->index;
1415 last_block = block_in_file + nr_pages;
1416 last_block_in_file = (i_size_read(inode) + blocksize - 1) >>
1417 blkbits;
1418 if (last_block > last_block_in_file)
1419 last_block = last_block_in_file;
1420
1421 /*
1422 * Map blocks using the previous result first.
1423 */
1424 if ((map.m_flags & F2FS_MAP_MAPPED) &&
1425 block_in_file > map.m_lblk &&
1426 block_in_file < (map.m_lblk + map.m_len))
1427 goto got_it;
1428
1429 /*
1430 * Then do more f2fs_map_blocks() calls until we are
1431 * done with this page.
1432 */
1433 map.m_flags = 0;
1434
1435 if (block_in_file < last_block) {
1436 map.m_lblk = block_in_file;
1437 map.m_len = last_block - block_in_file;
1438
1439 if (f2fs_map_blocks(inode, &map, 0, false))
1440 goto set_error_page;
1441 }
1442got_it:
1443 if ((map.m_flags & F2FS_MAP_MAPPED)) {
1444 block_nr = map.m_pblk + block_in_file - map.m_lblk;
1445 SetPageMappedToDisk(page);
1446
1447 if (!PageUptodate(page) && !cleancache_get_page(page)) {
1448 SetPageUptodate(page);
1449 goto confused;
1450 }
1451 } else {
1452 zero_user_segment(page, 0, PAGE_CACHE_SIZE);
1453 SetPageUptodate(page);
1454 unlock_page(page);
1455 goto next_page;
1456 }
1457
1458 /*
1459 * This page will go to BIO. Do we need to send this
1460 * BIO off first?
1461 */
1462 if (bio && (last_block_in_bio != block_nr - 1)) {
1463submit_and_realloc:
1464 submit_bio(READ, bio);
1465 bio = NULL;
1466 }
1467 if (bio == NULL) {
1468 bio = bio_alloc(GFP_KERNEL,
1469 min_t(int, nr_pages, bio_get_nr_vecs(bdev)));
1470 if (!bio)
1471 goto set_error_page;
1472 bio->bi_bdev = bdev;
1473 bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(block_nr);
1474 bio->bi_end_io = mpage_end_io;
1475 bio->bi_private = NULL;
1476 }
1477
1478 if (bio_add_page(bio, page, blocksize, 0) < blocksize)
1479 goto submit_and_realloc;
1480
1481 last_block_in_bio = block_nr;
1482 goto next_page;
1483set_error_page:
1484 SetPageError(page);
1485 zero_user_segment(page, 0, PAGE_CACHE_SIZE);
1486 unlock_page(page);
1487 goto next_page;
1488confused:
1489 if (bio) {
1490 submit_bio(READ, bio);
1491 bio = NULL;
1492 }
1493 unlock_page(page);
1494next_page:
1495 if (pages)
1496 page_cache_release(page);
1497 }
1498 BUG_ON(pages && !list_empty(pages));
1499 if (bio)
1500 submit_bio(READ, bio);
1501 return 0;
1502}
1503
1352static int f2fs_read_data_page(struct file *file, struct page *page) 1504static int f2fs_read_data_page(struct file *file, struct page *page)
1353{ 1505{
1354 struct inode *inode = page->mapping->host; 1506 struct inode *inode = page->mapping->host;
@@ -1360,8 +1512,7 @@ static int f2fs_read_data_page(struct file *file, struct page *page)
1360 if (f2fs_has_inline_data(inode)) 1512 if (f2fs_has_inline_data(inode))
1361 ret = f2fs_read_inline_data(inode, page); 1513 ret = f2fs_read_inline_data(inode, page);
1362 if (ret == -EAGAIN) 1514 if (ret == -EAGAIN)
1363 ret = mpage_readpage(page, get_data_block); 1515 ret = f2fs_mpage_readpages(page->mapping, NULL, page, 1);
1364
1365 return ret; 1516 return ret;
1366} 1517}
1367 1518
@@ -1375,7 +1526,7 @@ static int f2fs_read_data_pages(struct file *file,
1375 if (f2fs_has_inline_data(inode)) 1526 if (f2fs_has_inline_data(inode))
1376 return 0; 1527 return 0;
1377 1528
1378 return mpage_readpages(mapping, pages, nr_pages, get_data_block); 1529 return f2fs_mpage_readpages(mapping, pages, NULL, nr_pages);
1379} 1530}
1380 1531
1381int do_write_data_page(struct page *page, struct f2fs_io_info *fio) 1532int do_write_data_page(struct page *page, struct f2fs_io_info *fio)