Message ID | 20170420195255.GA32370@lim.localdomain (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Apr 20, 2017 at 12:52:55PM -0700, Liu Bo wrote: > On Thu, Apr 20, 2017 at 10:09:39AM +0800, Qu Wenruo wrote: > > > > > > At 04/20/2017 09:58 AM, Liu Bo wrote: > > > On Thu, Apr 20, 2017 at 09:52:00AM +0800, Qu Wenruo wrote: > > > > > > > > > [...] > > > > > > > > > > If I understand it correctly, what it's missing currently is 'merge', a > > > > > straightfoward idea is to make use of the 'merge' ability of btrfs_get_extent. > > > > > > Since btrfs_get_extent_fiemap is a wrapper of btrfs_get_extent, does it make > > > > > sense if we make btrfs_get_extent_fiemap iterate all extent maps within the > > > > > range passing to it or just one more extent map to check if btrfs_get_extent > > > > > could return a merged extent map before returning? > > > > > > > > So your idea to to do the merging inside btrfs_get_extent(), instead of > > > > merging it in extent_fiemap()? > > > > > > > > > > No, merge ems inside the wrapper, ie. btrfs_get_extent_fiemap(). > > > > Then llseek() with SEEK_HOLE/SEEK_DATA also get affected. > > > > So limiting the extra time to merging extent maps in fiemap is still valid. > > > > Per my test, the v3 patch doesn't make big difference on the side of > performance. I think the point was not to improve performance, but to make the fiemap output correct. But anyway it's good that the performance does not degrade. -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index a18510b..db59557 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7045,9 +7045,27 @@ struct extent_map *btrfs_get_extent_fiemap(struct btrfs_inode *inode, * there might actually be delalloc bytes behind it. */ if (em->block_start != EXTENT_MAP_HOLE && - !test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) + !test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) { + u64 merge_start = start; + u64 merge_len = len; + struct extent_map *tmp = em; + + while ((start + len) > extent_map_end(tmp)) { + merge_start = extent_map_end(tmp); + merge_len = (start + len) - extent_map_end(tmp); + tmp = btrfs_get_extent(inode, page, pg_offset, merge_start, merge_len, create); + if (IS_ERR(tmp)) + break; + if (tmp->start != start) { + free_extent_map(tmp); + break; + } + /* now tmp is the merged one */ + free_extent_map(em); + em = tmp; + } return em; - else + } else hole_em = em; }