Skip to content
Open
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
6 changes: 5 additions & 1 deletion check/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -8601,7 +8601,11 @@ int check_chunks(struct cache_tree *chunk_cache,
dext_rec->objectid,
dext_rec->offset,
dext_rec->length);
if (!ret)
err = -ENOENT;
if (opt_check_repair)
err = btrfs_remove_dev_extent(gfs_info, dext_rec->objectid,
dext_rec->offset);
if (err && !ret)
ret = 1;
}
return ret;
Expand Down
7 changes: 6 additions & 1 deletion check/mode-lowmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -4749,7 +4749,12 @@ static int check_dev_extent_item(struct extent_buffer *eb, int slot)
error(
"device extent[%llu, %llu, %llu] did not find the related chunk",
devext_key.objectid, devext_key.offset, length);
return REFERENCER_MISSING;
ret = -ENOENT;
if (opt_check_repair)
ret = btrfs_remove_dev_extent(gfs_info, devext_key.objectid,
devext_key.offset);
if (ret < 0)
return REFERENCER_MISSING;
}
return 0;
}
Expand Down
78 changes: 78 additions & 0 deletions check/repair.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
#include "kernel-shared/extent_io.h"
#include "kernel-shared/disk-io.h"
#include "kernel-shared/tree-checker.h"
#include "kernel-shared/volumes.h"
#include "common/extent-cache.h"
#include "common/messages.h"
#include "check/repair.h"

int opt_check_repair = 0;
Expand Down Expand Up @@ -354,6 +356,82 @@ int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
return ret;
}

int btrfs_remove_dev_extent(struct btrfs_fs_info *fs_info, u64 devid, u64 physical)
{
struct btrfs_trans_handle *trans;
struct btrfs_root *dev_root = fs_info->dev_root;
struct btrfs_key key = {
.objectid = devid,
.type = BTRFS_DEV_EXTENT_KEY,
.offset = physical,
};
struct btrfs_path path = { 0 };
struct btrfs_dev_extent *dext;
struct btrfs_device *dev;
u64 length;
int ret;

dev = btrfs_find_device_by_devid(fs_info->fs_devices, devid, 0);
if (!dev) {
ret = -ENOENT;
error("failed to find devid %llu", devid);
return ret;
}
trans = btrfs_start_transaction(dev_root, 1);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
errno = -ret;
error_msg(ERROR_MSG_START_TRANS, "%m");
return ret;
}
ret = btrfs_search_slot(trans, dev_root, &key, &path, -1, 1);
if (ret > 0)
ret = -ENOENT;
if (ret < 0) {
errno = -ret;
error("failed to locate dev extent, devid %llu physical %llu: %m",
devid, physical);
goto abort;
}
dext = btrfs_item_ptr(path.nodes[0], path.slots[0], struct btrfs_dev_extent);
length = btrfs_dev_extent_length(path.nodes[0], dext);
ret = btrfs_del_item(trans, dev_root, &path);
if (ret < 0) {
errno = -ret;
error("failed to delete dev extent, devid %llu physical %llu: %m",
devid, physical);
goto abort;
}
btrfs_release_path(&path);
if (dev->bytes_used < length) {
warning("devid %llu has bytes_used %llu, smaller than %llu",
devid, dev->bytes_used, length);
dev->bytes_used = 0;
} else {
dev->bytes_used -= length;
}
ret = btrfs_update_device(trans, dev);
if (ret < 0) {
errno = -ret;
error("failed to update device, devid %llu: %m", devid);
goto abort;
}
ret = btrfs_commit_transaction(trans, dev_root);
if (ret < 0) {
errno = -ret;
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
} else {
printf("removed orphan dev extent, devid %llu physical %llu length %llu\n",
devid, physical, length);
}
return ret;

abort:
btrfs_release_path(&path);
btrfs_abort_transaction(trans, ret);
return ret;
}

enum btrfs_tree_block_status btrfs_check_block_for_repair(struct extent_buffer *eb,
struct btrfs_key *first_key)
{
Expand Down
1 change: 1 addition & 0 deletions check/repair.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ int btrfs_mark_used_tree_blocks(struct btrfs_fs_info *fs_info,
struct extent_io_tree *tree);
int btrfs_mark_used_blocks(struct btrfs_fs_info *fs_info,
struct extent_io_tree *tree);
int btrfs_remove_dev_extent(struct btrfs_fs_info *fs_info, u64 devid, u64 physical);
enum btrfs_tree_block_status btrfs_check_block_for_repair(struct extent_buffer *eb,
struct btrfs_key *first_key);
void btrfs_set_item_key_unsafe(struct btrfs_root *root, struct btrfs_path *path,
Expand Down
Empty file.
Binary file not shown.