^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2007 Oracle. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "ctree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "disk-io.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "transaction.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "print-tree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct btrfs_inode_ref *btrfs_find_name_in_backref(struct extent_buffer *leaf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) int slot, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) int name_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct btrfs_inode_ref *ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) unsigned long ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) unsigned long name_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) u32 item_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) u32 cur_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) item_size = btrfs_item_size_nr(leaf, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) ptr = btrfs_item_ptr_offset(leaf, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) while (cur_offset < item_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) ref = (struct btrfs_inode_ref *)(ptr + cur_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) len = btrfs_inode_ref_name_len(leaf, ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) name_ptr = (unsigned long)(ref + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) cur_offset += len + sizeof(*ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (len != name_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct btrfs_inode_extref *btrfs_find_name_in_ext_backref(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct extent_buffer *leaf, int slot, u64 ref_objectid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) const char *name, int name_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct btrfs_inode_extref *extref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) unsigned long ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned long name_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u32 item_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u32 cur_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int ref_name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) item_size = btrfs_item_size_nr(leaf, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ptr = btrfs_item_ptr_offset(leaf, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * Search all extended backrefs in this item. We're only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * looking through any collisions so most of the time this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * just going to compare against one buffer. If all is well,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * we'll return success and the inode ref object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) while (cur_offset < item_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) extref = (struct btrfs_inode_extref *) (ptr + cur_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) name_ptr = (unsigned long)(&extref->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ref_name_len = btrfs_inode_extref_name_len(leaf, extref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (ref_name_len == name_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) btrfs_inode_extref_parent(leaf, extref) == ref_objectid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) (memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return extref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) cur_offset += ref_name_len + sizeof(*extref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* Returns NULL if no extref found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct btrfs_inode_extref *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct btrfs_path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) const char *name, int name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u64 inode_objectid, u64 ref_objectid, int ins_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int cow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct btrfs_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) key.objectid = inode_objectid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) key.type = BTRFS_INODE_EXTREF_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) key.offset = btrfs_extref_hash(ref_objectid, name, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return btrfs_find_name_in_ext_backref(path->nodes[0], path->slots[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) ref_objectid, name, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static int btrfs_del_inode_extref(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) const char *name, int name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) u64 inode_objectid, u64 ref_objectid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u64 *index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct btrfs_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct btrfs_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct btrfs_inode_extref *extref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct extent_buffer *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int del_len = name_len + sizeof(*extref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) unsigned long ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) unsigned long item_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u32 item_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) key.objectid = inode_objectid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) key.type = BTRFS_INODE_EXTREF_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) key.offset = btrfs_extref_hash(ref_objectid, name, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) path = btrfs_alloc_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) path->leave_spinning = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * Sanity check - did we find the right item for this name?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * This should always succeed so error here will make the FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * readonly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) extref = btrfs_find_name_in_ext_backref(path->nodes[0], path->slots[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ref_objectid, name, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (!extref) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) btrfs_handle_fs_error(root->fs_info, -ENOENT, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ret = -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) item_size = btrfs_item_size_nr(leaf, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *index = btrfs_inode_extref_index(leaf, extref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (del_len == item_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Common case only one ref in the item, remove the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * whole item.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) ret = btrfs_del_item(trans, root, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ptr = (unsigned long)extref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) item_start = btrfs_item_ptr_offset(leaf, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) memmove_extent_buffer(leaf, ptr, ptr + del_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) item_size - (ptr + del_len - item_start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) btrfs_truncate_item(path, item_size - del_len, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) btrfs_free_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) const char *name, int name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) u64 inode_objectid, u64 ref_objectid, u64 *index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct btrfs_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct btrfs_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct btrfs_inode_ref *ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct extent_buffer *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) unsigned long ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) unsigned long item_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u32 item_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) u32 sub_item_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) int search_ext_refs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int del_len = name_len + sizeof(*ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) key.objectid = inode_objectid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) key.offset = ref_objectid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) key.type = BTRFS_INODE_REF_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) path = btrfs_alloc_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) path->leave_spinning = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) search_ext_refs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) } else if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ref = btrfs_find_name_in_backref(path->nodes[0], path->slots[0], name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (!ref) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) search_ext_refs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) item_size = btrfs_item_size_nr(leaf, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) *index = btrfs_inode_ref_index(leaf, ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (del_len == item_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ret = btrfs_del_item(trans, root, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ptr = (unsigned long)ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) sub_item_len = name_len + sizeof(*ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) item_start = btrfs_item_ptr_offset(leaf, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) item_size - (ptr + sub_item_len - item_start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) btrfs_truncate_item(path, item_size - sub_item_len, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) btrfs_free_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (search_ext_refs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * No refs were found, or we could not find the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * name in our ref array. Find and remove the extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * inode ref then.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return btrfs_del_inode_extref(trans, root, name, name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) inode_objectid, ref_objectid, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * btrfs_insert_inode_extref() - Inserts an extended inode ref into a tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * The caller must have checked against BTRFS_LINK_MAX already.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int btrfs_insert_inode_extref(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) const char *name, int name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) u64 inode_objectid, u64 ref_objectid, u64 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct btrfs_inode_extref *extref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int ins_len = name_len + sizeof(*extref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) unsigned long ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct btrfs_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct btrfs_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct extent_buffer *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct btrfs_item *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) key.objectid = inode_objectid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) key.type = BTRFS_INODE_EXTREF_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) key.offset = btrfs_extref_hash(ref_objectid, name, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) path = btrfs_alloc_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) path->leave_spinning = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ret = btrfs_insert_empty_item(trans, root, path, &key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ins_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (ret == -EEXIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (btrfs_find_name_in_ext_backref(path->nodes[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) path->slots[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ref_objectid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) name, name_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) btrfs_extend_item(path, ins_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) item = btrfs_item_nr(path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ptr = (unsigned long)btrfs_item_ptr(leaf, path->slots[0], char);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ptr += btrfs_item_size(leaf, item) - ins_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) extref = (struct btrfs_inode_extref *)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) btrfs_set_inode_extref_name_len(path->nodes[0], extref, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) btrfs_set_inode_extref_index(path->nodes[0], extref, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) btrfs_set_inode_extref_parent(path->nodes[0], extref, ref_objectid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ptr = (unsigned long)&extref->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) write_extent_buffer(path->nodes[0], name, ptr, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) btrfs_mark_buffer_dirty(path->nodes[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) btrfs_free_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* Will return 0, -ENOMEM, -EMLINK, or -EEXIST or anything from the CoW path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) const char *name, int name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) u64 inode_objectid, u64 ref_objectid, u64 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct btrfs_fs_info *fs_info = root->fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct btrfs_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct btrfs_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct btrfs_inode_ref *ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) unsigned long ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int ins_len = name_len + sizeof(*ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) key.objectid = inode_objectid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) key.offset = ref_objectid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) key.type = BTRFS_INODE_REF_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) path = btrfs_alloc_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) path->leave_spinning = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) path->skip_release_on_error = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ret = btrfs_insert_empty_item(trans, root, path, &key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ins_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (ret == -EEXIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) u32 old_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ref = btrfs_find_name_in_backref(path->nodes[0], path->slots[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) name, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) old_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) btrfs_extend_item(path, ins_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct btrfs_inode_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ref = (struct btrfs_inode_ref *)((unsigned long)ref + old_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) btrfs_set_inode_ref_index(path->nodes[0], ref, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ptr = (unsigned long)(ref + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) } else if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (ret == -EOVERFLOW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (btrfs_find_name_in_backref(path->nodes[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) path->slots[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) name, name_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ret = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) ret = -EMLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct btrfs_inode_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) btrfs_set_inode_ref_index(path->nodes[0], ref, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) ptr = (unsigned long)(ref + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) write_extent_buffer(path->nodes[0], name, ptr, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) btrfs_mark_buffer_dirty(path->nodes[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) btrfs_free_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (ret == -EMLINK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct btrfs_super_block *disk_super = fs_info->super_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* We ran out of space in the ref array. Need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * add an extended ref. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (btrfs_super_incompat_flags(disk_super)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) & BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) ret = btrfs_insert_inode_extref(trans, root, name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) inode_objectid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) ref_objectid, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) int btrfs_insert_empty_inode(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct btrfs_path *path, u64 objectid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) struct btrfs_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) key.objectid = objectid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) key.type = BTRFS_INODE_ITEM_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) key.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ret = btrfs_insert_empty_item(trans, root, path, &key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) sizeof(struct btrfs_inode_item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) *root, struct btrfs_path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct btrfs_key *location, int mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) int ins_len = mod < 0 ? -1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int cow = mod != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) int slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct extent_buffer *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct btrfs_key found_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ret = btrfs_search_slot(trans, root, location, path, ins_len, cow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (ret > 0 && location->type == BTRFS_ROOT_ITEM_KEY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) location->offset == (u64)-1 && path->slots[0] != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) slot = path->slots[0] - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) btrfs_item_key_to_cpu(leaf, &found_key, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (found_key.objectid == location->objectid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) found_key.type == location->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) path->slots[0]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }