Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Documentation/mkfs.btrfs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ OPTIONS

Default on a single device filesystem is *DUP* and is recommended for metadata
in general. The duplication might not be necessary in some use cases and it's
up to the user to changed that at mkfs time or later. This depends on hardware
up to the user to change that at mkfs time or later. This depends on hardware
that could potentially deduplicate the blocks again but this cannot be detected
at mkfs time.

Expand Down
5 changes: 5 additions & 0 deletions check/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3550,6 +3550,11 @@ static int check_root_refs(struct btrfs_root *root,
*/
if (!rec->found_root_item)
continue;
if (opt_check_repair) {
ret = repair_subvol_orphan_item(gfs_info, rec->objectid);
if (!ret)
continue;
}
errors++;
fprintf(stderr, "fs tree %llu missing orphan item\n", rec->objectid);
}
Expand Down
33 changes: 33 additions & 0 deletions check/mode-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1672,3 +1672,36 @@ int check_and_repair_super_num_devs(struct btrfs_fs_info *fs_info)
printf("Successfully reset super num devices to %u\n", found_devs);
return 0;
}

int repair_subvol_orphan_item(struct btrfs_fs_info *fs_info, u64 rootid)
{
struct btrfs_root *tree_root = fs_info->tree_root;
struct btrfs_trans_handle *trans;
struct btrfs_path path = { 0 };
int ret;

trans = btrfs_start_transaction(tree_root, 1);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
errno = -ret;
error_msg(ERROR_MSG_START_TRANS, "%m");
return ret;
}
ret = btrfs_add_orphan_item(trans, tree_root, &path, rootid);
btrfs_release_path(&path);
if (ret < 0) {
errno = -ret;
error("failed to insert orphan item for subvolume %llu: %m", rootid);
btrfs_abort_transaction(trans, ret);
btrfs_commit_transaction(trans, tree_root);
return ret;
}
ret = btrfs_commit_transaction(trans, tree_root);
if (ret < 0) {
errno = -ret;
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
return ret;
}
printf("Added back missing orphan item for subvolume %llu\n", rootid);
return 0;
}
1 change: 1 addition & 0 deletions check/mode-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,5 +197,6 @@ int repair_dev_item_bytes_used(struct btrfs_fs_info *fs_info,
int fill_csum_tree(struct btrfs_trans_handle *trans, bool search_fs_tree);

int check_and_repair_super_num_devs(struct btrfs_fs_info *fs_info);
int repair_subvol_orphan_item(struct btrfs_fs_info *fs_info, u64 rootid);

#endif
13 changes: 10 additions & 3 deletions check/mode-lowmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -5569,9 +5569,16 @@ static int check_btrfs_root(struct btrfs_root *root, int check_all)
* If this tree is a subvolume (not a reloc tree) and has no refs, there
* should be an orphan item for it, or this subvolume will never be deleted.
*/
if (btrfs_root_refs(root_item) == 0 && is_fstree(btrfs_root_id(root))) {
if (!has_orphan_item(root->fs_info->tree_root,
btrfs_root_id(root))) {
if (btrfs_root_refs(root_item) == 0 && is_fstree(btrfs_root_id(root)) &&
!has_orphan_item(root->fs_info->tree_root, btrfs_root_id(root))) {
bool repaired = false;

if (opt_check_repair) {
ret = repair_subvol_orphan_item(root->fs_info, btrfs_root_id(root));
if (!ret)
repaired = true;
}
if (!repaired) {
error("missing orphan item for root %lld", btrfs_root_id(root));
err |= REFERENCER_MISSING;
}
Expand Down
Empty file.
14 changes: 0 additions & 14 deletions tests/fsck-tests/066-missing-root-orphan-item/test.sh

This file was deleted.