btrfs: drop root refs properly when orphan cleanup fails
authorJosef Bacik <josef@toxicpanda.com>
Tue, 7 Feb 2023 16:57:23 +0000 (11:57 -0500)
committerDavid Sterba <dsterba@suse.com>
Mon, 17 Apr 2023 16:01:13 +0000 (18:01 +0200)
When we mount the file system we do something like this:

while (1) {
lookup fs roots;

for (i = 0; i < num_roots; i++) {
ret = btrfs_orphan_cleanup(roots[i]);
if (ret)
break;
btrfs_put_root(roots[i]);
}
}

for (; i < num_roots; i++)
btrfs_put_root(roots[i]);

As you can see if we break in that inner loop we just go back to the
outer loop and lose the fact that we have to drop references on the
remaining roots we looked up.  Fix this by making an out label and
jumping to that on error so we don't leak a reference to the roots we
looked up.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c

index 9e1596bb208db09ff69d441c9ca3330ea7b940c2..d9f66f411c025e34a0a154d6906e4ed04b3d7eb1 100644 (file)
@@ -4404,12 +4404,12 @@ int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info)
                        root_objectid = gang[i]->root_key.objectid;
                        err = btrfs_orphan_cleanup(gang[i]);
                        if (err)
-                               break;
+                               goto out;
                        btrfs_put_root(gang[i]);
                }
                root_objectid++;
        }
-
+out:
        /* release the uncleaned roots due to error */
        for (; i < ret; i++) {
                if (gang[i])