static struct dentry *btrfs_get_parent(struct dentry *child) { struct inode *dir = d_inode(child); struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb); struct btrfs_root *root = BTRFS_I(dir)->root; struct btrfs_path *path; struct extent_buffer *leaf; struct btrfs_root_ref *ref; struct btrfs_key key; struct btrfs_key found_key; int ret; path = btrfs_alloc_path(); if (!path) return ERR_PTR(-ENOMEM); if (btrfs_ino(BTRFS_I(dir)) == BTRFS_FIRST_FREE_OBJECTID) { key.objectid = root->root_key.objectid; key.type = BTRFS_ROOT_BACKREF_KEY; key.offset = (u64)-1; root = fs_info->tree_root; } else { key.objectid = btrfs_ino(BTRFS_I(dir)); key.type = BTRFS_INODE_REF_KEY; key.offset = (u64)-1; } ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) goto fail; BUG_ON(ret == 0); /* Key with offset of -1 found */ if (path->slots[0] == 0) { ret = -ENOENT; goto fail; } path->slots[0]--; leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); if (found_key.objectid != key.objectid || found_key.type != key.type) { ret = -ENOENT; goto fail; } if (found_key.type == BTRFS_ROOT_BACKREF_KEY) { ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref); key.objectid = btrfs_root_ref_dirid(leaf, ref); } else {
static void print_root_ref(struct extent_buffer *leaf, int slot, char *tag) { struct btrfs_root_ref *ref; char namebuf[BTRFS_NAME_LEN]; int namelen; ref = btrfs_item_ptr(leaf, slot, struct btrfs_root_ref); namelen = btrfs_root_ref_name_len(leaf, ref); read_extent_buffer(leaf, namebuf, (unsigned long)(ref + 1), namelen); printf("\t\troot %s key dirid %llu sequence %llu name %.*s\n", tag, (unsigned long long)btrfs_root_ref_dirid(leaf, ref), (unsigned long long)btrfs_root_ref_sequence(leaf, ref), namelen, namebuf); }
int btrfs_del_root_ref(struct btrfs_trans_handle *trans, struct btrfs_root *tree_root, u64 root_id, u64 ref_id, u64 dirid, u64 *sequence, const char *name, int name_len) { struct btrfs_path *path; struct btrfs_root_ref *ref; struct extent_buffer *leaf; struct btrfs_key key; unsigned long ptr; int err = 0; int ret; path = btrfs_alloc_path(); if (!path) return -ENOMEM; key.objectid = root_id; key.type = BTRFS_ROOT_BACKREF_KEY; key.offset = ref_id; again: ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); BUG_ON(ret < 0); if (ret == 0) { leaf = path->nodes[0]; ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref); WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid); WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len); ptr = (unsigned long)(ref + 1); WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len)); *sequence = btrfs_root_ref_sequence(leaf, ref); ret = btrfs_del_item(trans, tree_root, path); if (ret) { err = ret; goto out; } } else