Skip to content

Commit a9cc643

Browse files
fdmananakdave
authored andcommitted
btrfs: don't loop again over pinned extent maps when shrinking extent maps
During extent map shrinking, while iterating over the extent maps of an inode, if we happen to find a lot of pinned extent maps and we need to reschedule, we'll start iterating the extent map tree from its first extent map. This can result in visiting the same extent maps again, and if they are not yet unpinned, we are just wasting time and can end up iterating over them again if we happen to reschedule again before finding an extent map that is not pinned - this could happen yet more times if the unpinning doesn't happen soon (at ordered extent completion). So improve on this by starting on the next extent map ever ytime we need to reschedule. Any previously pinned extent maps will be checked again the next time the extent map shrinker is run (if needed). Reviewed-by: Qu Wenruo <wqu@suse.com> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 5157e19 commit a9cc643

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

fs/btrfs/extent_map.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,8 +1144,10 @@ static long btrfs_scan_inode(struct btrfs_inode *inode, long *scanned, long nr_t
11441144
while (node) {
11451145
struct rb_node *next = rb_next(node);
11461146
struct extent_map *em;
1147+
u64 next_min_offset;
11471148

11481149
em = rb_entry(node, struct extent_map, rb_node);
1150+
next_min_offset = extent_map_end(em);
11491151
(*scanned)++;
11501152

11511153
if (em->flags & EXTENT_FLAG_PINNED)
@@ -1171,14 +1173,24 @@ static long btrfs_scan_inode(struct btrfs_inode *inode, long *scanned, long nr_t
11711173
break;
11721174

11731175
/*
1174-
* Restart if we had to reschedule, and any extent maps that were
1175-
* pinned before may have become unpinned after we released the
1176-
* lock and took it again.
1176+
* If we had to reschedule start from where we were before. We
1177+
* could start from the first extent map in the tree in case we
1178+
* passed through pinned extent maps that may have become
1179+
* unpinned in the meanwhile, but it might be the case that they
1180+
* haven't been unpinned yet, so if we have many still unpinned
1181+
* extent maps, we could be wasting a lot of time and cpu. So
1182+
* don't consider previously pinned extent maps, we'll consider
1183+
* them in future calls of the extent map shrinker.
11771184
*/
1178-
if (cond_resched_rwlock_write(&tree->lock))
1179-
node = rb_first(&tree->root);
1180-
else
1185+
if (cond_resched_rwlock_write(&tree->lock)) {
1186+
em = search_extent_mapping(tree, next_min_offset, 0);
1187+
if (em)
1188+
node = &em->rb_node;
1189+
else
1190+
node = NULL;
1191+
} else {
11811192
node = next;
1193+
}
11821194
}
11831195
write_unlock(&tree->lock);
11841196
up_read(&inode->i_mmap_lock);

0 commit comments

Comments
 (0)