Commit 60484cd9 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

btrfs: subpage: make readahead work properly



In readahead infrastructure, we are using a lot of hard coded PAGE_SHIFT
while we're not doing anything specific to PAGE_SIZE.

One of the most affected part is the radix tree operation of
btrfs_fs_info::reada_tree.

If using PAGE_SHIFT, subpage metadata readahead is broken and does no
help reading metadata ahead.

Fix the problem by using btrfs_fs_info::sectorsize_bits so that
readahead could work for subpage.

Reviewed-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent d9bb77d5
Loading
Loading
Loading
Loading
+18 −17
Original line number Diff line number Diff line
@@ -209,7 +209,7 @@ int btree_readahead_hook(struct extent_buffer *eb, int err)
	/* find extent */
	spin_lock(&fs_info->reada_lock);
	re = radix_tree_lookup(&fs_info->reada_tree,
			       eb->start >> PAGE_SHIFT);
			       eb->start >> fs_info->sectorsize_bits);
	if (re)
		re->refcnt++;
	spin_unlock(&fs_info->reada_lock);
@@ -240,7 +240,7 @@ static struct reada_zone *reada_find_zone(struct btrfs_device *dev, u64 logical,
	zone = NULL;
	spin_lock(&fs_info->reada_lock);
	ret = radix_tree_gang_lookup(&dev->reada_zones, (void **)&zone,
				     logical >> PAGE_SHIFT, 1);
				     logical >> fs_info->sectorsize_bits, 1);
	if (ret == 1 && logical >= zone->start && logical <= zone->end) {
		kref_get(&zone->refcnt);
		spin_unlock(&fs_info->reada_lock);
@@ -283,13 +283,13 @@ static struct reada_zone *reada_find_zone(struct btrfs_device *dev, u64 logical,

	spin_lock(&fs_info->reada_lock);
	ret = radix_tree_insert(&dev->reada_zones,
				(unsigned long)(zone->end >> PAGE_SHIFT),
			(unsigned long)(zone->end >> fs_info->sectorsize_bits),
			zone);

	if (ret == -EEXIST) {
		kfree(zone);
		ret = radix_tree_gang_lookup(&dev->reada_zones, (void **)&zone,
					     logical >> PAGE_SHIFT, 1);
					logical >> fs_info->sectorsize_bits, 1);
		if (ret == 1 && logical >= zone->start && logical <= zone->end)
			kref_get(&zone->refcnt);
		else
@@ -315,7 +315,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
	u64 length;
	int real_stripes;
	int nzones = 0;
	unsigned long index = logical >> PAGE_SHIFT;
	unsigned long index = logical >> fs_info->sectorsize_bits;
	int dev_replace_is_ongoing;
	int have_zone = 0;

@@ -497,7 +497,7 @@ static void reada_extent_put(struct btrfs_fs_info *fs_info,
			     struct reada_extent *re)
{
	int i;
	unsigned long index = re->logical >> PAGE_SHIFT;
	unsigned long index = re->logical >> fs_info->sectorsize_bits;

	spin_lock(&fs_info->reada_lock);
	if (--re->refcnt) {
@@ -538,11 +538,12 @@ static void reada_extent_put(struct btrfs_fs_info *fs_info,
static void reada_zone_release(struct kref *kref)
{
	struct reada_zone *zone = container_of(kref, struct reada_zone, refcnt);
	struct btrfs_fs_info *fs_info = zone->device->fs_info;

	lockdep_assert_held(&zone->device->fs_info->reada_lock);
	lockdep_assert_held(&fs_info->reada_lock);

	radix_tree_delete(&zone->device->reada_zones,
			  zone->end >> PAGE_SHIFT);
			  zone->end >> fs_info->sectorsize_bits);

	kfree(zone);
}
@@ -593,7 +594,7 @@ static int reada_add_block(struct reada_control *rc, u64 logical,
static void reada_peer_zones_set_lock(struct reada_zone *zone, int lock)
{
	int i;
	unsigned long index = zone->end >> PAGE_SHIFT;
	unsigned long index = zone->end >> zone->device->fs_info->sectorsize_bits;

	for (i = 0; i < zone->ndevs; ++i) {
		struct reada_zone *peer;
@@ -628,7 +629,7 @@ static int reada_pick_zone(struct btrfs_device *dev)
					     (void **)&zone, index, 1);
		if (ret == 0)
			break;
		index = (zone->end >> PAGE_SHIFT) + 1;
		index = (zone->end >> dev->fs_info->sectorsize_bits) + 1;
		if (zone->locked) {
			if (zone->elems > top_locked_elems) {
				top_locked_elems = zone->elems;
@@ -709,7 +710,7 @@ static int reada_start_machine_dev(struct btrfs_device *dev)
	 * plugging to speed things up
	 */
	ret = radix_tree_gang_lookup(&dev->reada_extents, (void **)&re,
				     dev->reada_next >> PAGE_SHIFT, 1);
				dev->reada_next >> fs_info->sectorsize_bits, 1);
	if (ret == 0 || re->logical > dev->reada_curr_zone->end) {
		ret = reada_pick_zone(dev);
		if (!ret) {
@@ -718,7 +719,7 @@ static int reada_start_machine_dev(struct btrfs_device *dev)
		}
		re = NULL;
		ret = radix_tree_gang_lookup(&dev->reada_extents, (void **)&re,
					dev->reada_next >> PAGE_SHIFT, 1);
				dev->reada_next >> fs_info->sectorsize_bits, 1);
	}
	if (ret == 0) {
		spin_unlock(&fs_info->reada_lock);
@@ -885,7 +886,7 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all)
				pr_cont(" curr off %llu",
					device->reada_next - zone->start);
			pr_cont("\n");
			index = (zone->end >> PAGE_SHIFT) + 1;
			index = (zone->end >> fs_info->sectorsize_bits) + 1;
		}
		cnt = 0;
		index = 0;
@@ -910,7 +911,7 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all)
				}
			}
			pr_cont("\n");
			index = (re->logical >> PAGE_SHIFT) + 1;
			index = (re->logical >> fs_info->sectorsize_bits) + 1;
			if (++cnt > 15)
				break;
		}
@@ -926,7 +927,7 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all)
		if (ret == 0)
			break;
		if (!re->scheduled) {
			index = (re->logical >> PAGE_SHIFT) + 1;
			index = (re->logical >> fs_info->sectorsize_bits) + 1;
			continue;
		}
		pr_debug("re: logical %llu size %u list empty %d scheduled %d",
@@ -942,7 +943,7 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all)
			}
		}
		pr_cont("\n");
		index = (re->logical >> PAGE_SHIFT) + 1;
		index = (re->logical >> fs_info->sectorsize_bits) + 1;
	}
	spin_unlock(&fs_info->reada_lock);
}