summaryrefslogtreecommitdiff
path: root/check/mode-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'check/mode-common.c')
-rw-r--r--check/mode-common.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/check/mode-common.c b/check/mode-common.c
index 2efa4dc..fed102b 100644
--- a/check/mode-common.c
+++ b/check/mode-common.c
@@ -744,3 +744,54 @@ void cleanup_excluded_extents(struct btrfs_fs_info *fs_info)
}
fs_info->excluded_extents = NULL;
}
+
+/*
+ * Delete one corrupted dir item whose hash doesn't match its name.
+ *
+ * Since its hash is incorrect, we can't use btrfs_name_hash() to calculate
+ * the search key, but rely on @di_key parameter to do the search.
+ */
+int delete_corrupted_dir_item(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ struct btrfs_key *di_key, char *namebuf,
+ u32 namelen)
+{
+ struct btrfs_dir_item *di_item;
+ struct btrfs_path path;
+ int ret;
+
+ btrfs_init_path(&path);
+ ret = btrfs_search_slot(trans, root, di_key, &path, 0, 1);
+ if (ret > 0) {
+ error("key (%llu %u %llu) doesn't exist in root %llu",
+ di_key->objectid, di_key->type, di_key->offset,
+ root->root_key.objectid);
+ ret = -ENOENT;
+ goto out;
+ }
+ if (ret < 0) {
+ error("failed to search root %llu: %d",
+ root->root_key.objectid, ret);
+ goto out;
+ }
+
+ di_item = btrfs_match_dir_item_name(root, &path, namebuf, namelen);
+ if (!di_item) {
+ /*
+ * This is possible if the dir_item has incorrect namelen.
+ * But in that case, we shouldn't reach repair path here.
+ */
+ error("no dir item named '%s' found with key (%llu %u %llu)",
+ namebuf, di_key->objectid, di_key->type,
+ di_key->offset);
+ ret = -ENOENT;
+ goto out;
+ }
+ ret = btrfs_delete_one_dir_name(trans, root, &path, di_item);
+ if (ret < 0)
+ error("failed to delete one dir name: %d", ret);
+
+out:
+ btrfs_release_path(&path);
+ return ret;
+}