summaryrefslogtreecommitdiffstats
path: root/fs/f2fs
diff options
context:
space:
mode:
authorChao Yu <chao2.yu@samsung.com>2016-01-26 02:42:58 -0500
committerJaegeuk Kim <jaegeuk@kernel.org>2016-02-22 19:07:23 -0500
commitda85985c6142decea67ee5ff67eadf3f13103a91 (patch)
tree3a8b2b04014b0cd73270e61f94625353769171b4 /fs/f2fs
parent3cf4574705b4e1a1a0aeaae0332e8c2c8b56cc8f (diff)
f2fs: speed up handling holes in fiemap
This patch makes f2fs_map_blocks supporting returning next potential page offset which skips hole region in indirect tree of inode, and use it to speed up fiemap in handling big hole case. Test method: xfs_io -f /mnt/f2fs/file -c "pwrite 1099511627776 4096" time xfs_io -f /mnt/f2fs/file -c "fiemap -v" Before: time xfs_io -f /mnt/f2fs/file -c "fiemap -v" /mnt/f2fs/file: EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS 0: [0..2147483647]: hole 2147483648 1: [2147483648..2147483655]: 81920..81927 8 0x1 real 3m3.518s user 0m0.000s sys 3m3.456s After: time xfs_io -f /mnt/f2fs/file -c "fiemap -v" /mnt/f2fs/file: EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS 0: [0..2147483647]: hole 2147483648 1: [2147483648..2147483655]: 81920..81927 8 0x1 real 0m0.008s user 0m0.000s sys 0m0.008s Signed-off-by: Chao Yu <chao2.yu@samsung.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/data.c35
-rw-r--r--fs/f2fs/f2fs.h1
-rw-r--r--fs/f2fs/file.c2
3 files changed, 28 insertions, 10 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index bb60e6afbb72..e0b09c33fc0f 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -539,6 +539,7 @@ static int __allocate_data_blocks(struct inode *inode, loff_t offset,
539 539
540 map.m_lblk = F2FS_BYTES_TO_BLK(offset); 540 map.m_lblk = F2FS_BYTES_TO_BLK(offset);
541 map.m_len = F2FS_BYTES_TO_BLK(count); 541 map.m_len = F2FS_BYTES_TO_BLK(count);
542 map.m_next_pgofs = NULL;
542 543
543 return f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_DIO); 544 return f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_DIO);
544} 545}
@@ -586,8 +587,12 @@ next_dnode:
586 set_new_dnode(&dn, inode, NULL, NULL, 0); 587 set_new_dnode(&dn, inode, NULL, NULL, 0);
587 err = get_dnode_of_data(&dn, pgofs, mode); 588 err = get_dnode_of_data(&dn, pgofs, mode);
588 if (err) { 589 if (err) {
589 if (err == -ENOENT) 590 if (err == -ENOENT) {
590 err = 0; 591 err = 0;
592 if (map->m_next_pgofs)
593 *map->m_next_pgofs =
594 get_next_page_offset(&dn, pgofs);
595 }
591 goto unlock_out; 596 goto unlock_out;
592 } 597 }
593 598
@@ -609,6 +614,11 @@ next_block:
609 map->m_flags = F2FS_MAP_NEW; 614 map->m_flags = F2FS_MAP_NEW;
610 blkaddr = dn.data_blkaddr; 615 blkaddr = dn.data_blkaddr;
611 } else { 616 } else {
617 if (flag == F2FS_GET_BLOCK_FIEMAP &&
618 blkaddr == NULL_ADDR) {
619 if (map->m_next_pgofs)
620 *map->m_next_pgofs = pgofs + 1;
621 }
612 if (flag != F2FS_GET_BLOCK_FIEMAP || 622 if (flag != F2FS_GET_BLOCK_FIEMAP ||
613 blkaddr != NEW_ADDR) { 623 blkaddr != NEW_ADDR) {
614 if (flag == F2FS_GET_BLOCK_BMAP) 624 if (flag == F2FS_GET_BLOCK_BMAP)
@@ -669,13 +679,15 @@ out:
669} 679}
670 680
671static int __get_data_block(struct inode *inode, sector_t iblock, 681static int __get_data_block(struct inode *inode, sector_t iblock,
672 struct buffer_head *bh, int create, int flag) 682 struct buffer_head *bh, int create, int flag,
683 pgoff_t *next_pgofs)
673{ 684{
674 struct f2fs_map_blocks map; 685 struct f2fs_map_blocks map;
675 int ret; 686 int ret;
676 687
677 map.m_lblk = iblock; 688 map.m_lblk = iblock;
678 map.m_len = bh->b_size >> inode->i_blkbits; 689 map.m_len = bh->b_size >> inode->i_blkbits;
690 map.m_next_pgofs = next_pgofs;
679 691
680 ret = f2fs_map_blocks(inode, &map, create, flag); 692 ret = f2fs_map_blocks(inode, &map, create, flag);
681 if (!ret) { 693 if (!ret) {
@@ -687,16 +699,18 @@ static int __get_data_block(struct inode *inode, sector_t iblock,
687} 699}
688 700
689static int get_data_block(struct inode *inode, sector_t iblock, 701static int get_data_block(struct inode *inode, sector_t iblock,
690 struct buffer_head *bh_result, int create, int flag) 702 struct buffer_head *bh_result, int create, int flag,
703 pgoff_t *next_pgofs)
691{ 704{
692 return __get_data_block(inode, iblock, bh_result, create, flag); 705 return __get_data_block(inode, iblock, bh_result, create,
706 flag, next_pgofs);
693} 707}
694 708
695static int get_data_block_dio(struct inode *inode, sector_t iblock, 709static int get_data_block_dio(struct inode *inode, sector_t iblock,
696 struct buffer_head *bh_result, int create) 710 struct buffer_head *bh_result, int create)
697{ 711{
698 return __get_data_block(inode, iblock, bh_result, create, 712 return __get_data_block(inode, iblock, bh_result, create,
699 F2FS_GET_BLOCK_DIO); 713 F2FS_GET_BLOCK_DIO, NULL);
700} 714}
701 715
702static int get_data_block_bmap(struct inode *inode, sector_t iblock, 716static int get_data_block_bmap(struct inode *inode, sector_t iblock,
@@ -707,7 +721,7 @@ static int get_data_block_bmap(struct inode *inode, sector_t iblock,
707 return -EFBIG; 721 return -EFBIG;
708 722
709 return __get_data_block(inode, iblock, bh_result, create, 723 return __get_data_block(inode, iblock, bh_result, create,
710 F2FS_GET_BLOCK_BMAP); 724 F2FS_GET_BLOCK_BMAP, NULL);
711} 725}
712 726
713static inline sector_t logical_to_blk(struct inode *inode, loff_t offset) 727static inline sector_t logical_to_blk(struct inode *inode, loff_t offset)
@@ -725,6 +739,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
725{ 739{
726 struct buffer_head map_bh; 740 struct buffer_head map_bh;
727 sector_t start_blk, last_blk; 741 sector_t start_blk, last_blk;
742 pgoff_t next_pgofs;
728 loff_t isize; 743 loff_t isize;
729 u64 logical = 0, phys = 0, size = 0; 744 u64 logical = 0, phys = 0, size = 0;
730 u32 flags = 0; 745 u32 flags = 0;
@@ -760,14 +775,15 @@ next:
760 map_bh.b_size = len; 775 map_bh.b_size = len;
761 776
762 ret = get_data_block(inode, start_blk, &map_bh, 0, 777 ret = get_data_block(inode, start_blk, &map_bh, 0,
763 F2FS_GET_BLOCK_FIEMAP); 778 F2FS_GET_BLOCK_FIEMAP, &next_pgofs);
764 if (ret) 779 if (ret)
765 goto out; 780 goto out;
766 781
767 /* HOLE */ 782 /* HOLE */
768 if (!buffer_mapped(&map_bh)) { 783 if (!buffer_mapped(&map_bh)) {
784 start_blk = next_pgofs;
769 /* Go through holes util pass the EOF */ 785 /* Go through holes util pass the EOF */
770 if (blk_to_logical(inode, start_blk++) < isize) 786 if (blk_to_logical(inode, start_blk) < isize)
771 goto prep_next; 787 goto prep_next;
772 /* Found a hole beyond isize means no more extents. 788 /* Found a hole beyond isize means no more extents.
773 * Note that the premise is that filesystems don't 789 * Note that the premise is that filesystems don't
@@ -835,6 +851,7 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
835 map.m_lblk = 0; 851 map.m_lblk = 0;
836 map.m_len = 0; 852 map.m_len = 0;
837 map.m_flags = 0; 853 map.m_flags = 0;
854 map.m_next_pgofs = NULL;
838 855
839 for (page_idx = 0; nr_pages; page_idx++, nr_pages--) { 856 for (page_idx = 0; nr_pages; page_idx++, nr_pages--) {
840 857
@@ -873,7 +890,7 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
873 map.m_len = last_block - block_in_file; 890 map.m_len = last_block - block_in_file;
874 891
875 if (f2fs_map_blocks(inode, &map, 0, 892 if (f2fs_map_blocks(inode, &map, 0,
876 F2FS_GET_BLOCK_READ)) 893 F2FS_GET_BLOCK_READ))
877 goto set_error_page; 894 goto set_error_page;
878 } 895 }
879got_it: 896got_it:
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index d86b52169d6e..469a1f49a3cd 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -383,6 +383,7 @@ struct f2fs_map_blocks {
383 block_t m_lblk; 383 block_t m_lblk;
384 unsigned int m_len; 384 unsigned int m_len;
385 unsigned int m_flags; 385 unsigned int m_flags;
386 pgoff_t *m_next_pgofs; /* point next possible non-hole pgofs */
386}; 387};
387 388
388/* for flag in get_data_block */ 389/* for flag in get_data_block */
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 8c51fc7d9396..50fa296efa67 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1647,7 +1647,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
1647 struct f2fs_defragment *range) 1647 struct f2fs_defragment *range)
1648{ 1648{
1649 struct inode *inode = file_inode(filp); 1649 struct inode *inode = file_inode(filp);
1650 struct f2fs_map_blocks map; 1650 struct f2fs_map_blocks map = { .m_next_pgofs = NULL };
1651 struct extent_info ei; 1651 struct extent_info ei;
1652 pgoff_t pg_start, pg_end; 1652 pgoff_t pg_start, pg_end;
1653 unsigned int blk_per_seg = sbi->blocks_per_seg; 1653 unsigned int blk_per_seg = sbi->blocks_per_seg;