16cbd5570SChris Mason /* 26cbd5570SChris Mason * Copyright (C) 2007 Oracle. All rights reserved. 36cbd5570SChris Mason * 46cbd5570SChris Mason * This program is free software; you can redistribute it and/or 56cbd5570SChris Mason * modify it under the terms of the GNU General Public 66cbd5570SChris Mason * License v2 as published by the Free Software Foundation. 76cbd5570SChris Mason * 86cbd5570SChris Mason * This program is distributed in the hope that it will be useful, 96cbd5570SChris Mason * but WITHOUT ANY WARRANTY; without even the implied warranty of 106cbd5570SChris Mason * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 116cbd5570SChris Mason * General Public License for more details. 126cbd5570SChris Mason * 136cbd5570SChris Mason * You should have received a copy of the GNU General Public 146cbd5570SChris Mason * License along with this program; if not, write to the 156cbd5570SChris Mason * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 166cbd5570SChris Mason * Boston, MA 021110-1307, USA. 176cbd5570SChris Mason */ 186cbd5570SChris Mason 191e1d2701SChris Mason #include "ctree.h" 201e1d2701SChris Mason #include "disk-io.h" 21f186373fSMark Fasheh #include "hash.h" 22e089f05cSChris Mason #include "transaction.h" 23727011e0SChris Mason #include "print-tree.h" 241e1d2701SChris Mason 25b2950863SChristoph Hellwig static int find_name_in_backref(struct btrfs_path *path, const char *name, 263954401fSChris Mason int name_len, struct btrfs_inode_ref **ref_ret) 273954401fSChris Mason { 283954401fSChris Mason struct extent_buffer *leaf; 293954401fSChris Mason struct btrfs_inode_ref *ref; 303954401fSChris Mason unsigned long ptr; 313954401fSChris Mason unsigned long name_ptr; 323954401fSChris Mason u32 item_size; 333954401fSChris Mason u32 cur_offset = 0; 343954401fSChris Mason int len; 353954401fSChris Mason 363954401fSChris Mason leaf = path->nodes[0]; 373954401fSChris Mason item_size = btrfs_item_size_nr(leaf, path->slots[0]); 383954401fSChris Mason ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); 393954401fSChris Mason while (cur_offset < item_size) { 403954401fSChris Mason ref = (struct btrfs_inode_ref *)(ptr + cur_offset); 413954401fSChris Mason len = btrfs_inode_ref_name_len(leaf, ref); 423954401fSChris Mason name_ptr = (unsigned long)(ref + 1); 433954401fSChris Mason cur_offset += len + sizeof(*ref); 443954401fSChris Mason if (len != name_len) 453954401fSChris Mason continue; 463954401fSChris Mason if (memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0) { 473954401fSChris Mason *ref_ret = ref; 483954401fSChris Mason return 1; 493954401fSChris Mason } 503954401fSChris Mason } 513954401fSChris Mason return 0; 523954401fSChris Mason } 533954401fSChris Mason 54f186373fSMark Fasheh int btrfs_find_name_in_ext_backref(struct btrfs_path *path, u64 ref_objectid, 55f186373fSMark Fasheh const char *name, int name_len, 56f186373fSMark Fasheh struct btrfs_inode_extref **extref_ret) 57f186373fSMark Fasheh { 58f186373fSMark Fasheh struct extent_buffer *leaf; 59f186373fSMark Fasheh struct btrfs_inode_extref *extref; 60f186373fSMark Fasheh unsigned long ptr; 61f186373fSMark Fasheh unsigned long name_ptr; 62f186373fSMark Fasheh u32 item_size; 63f186373fSMark Fasheh u32 cur_offset = 0; 64f186373fSMark Fasheh int ref_name_len; 65f186373fSMark Fasheh 66f186373fSMark Fasheh leaf = path->nodes[0]; 67f186373fSMark Fasheh item_size = btrfs_item_size_nr(leaf, path->slots[0]); 68f186373fSMark Fasheh ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); 69f186373fSMark Fasheh 70f186373fSMark Fasheh /* 71f186373fSMark Fasheh * Search all extended backrefs in this item. We're only 72f186373fSMark Fasheh * looking through any collisions so most of the time this is 73f186373fSMark Fasheh * just going to compare against one buffer. If all is well, 74f186373fSMark Fasheh * we'll return success and the inode ref object. 75f186373fSMark Fasheh */ 76f186373fSMark Fasheh while (cur_offset < item_size) { 77f186373fSMark Fasheh extref = (struct btrfs_inode_extref *) (ptr + cur_offset); 78f186373fSMark Fasheh name_ptr = (unsigned long)(&extref->name); 79f186373fSMark Fasheh ref_name_len = btrfs_inode_extref_name_len(leaf, extref); 80f186373fSMark Fasheh 81f186373fSMark Fasheh if (ref_name_len == name_len && 82f186373fSMark Fasheh btrfs_inode_extref_parent(leaf, extref) == ref_objectid && 83f186373fSMark Fasheh (memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0)) { 84f186373fSMark Fasheh if (extref_ret) 85f186373fSMark Fasheh *extref_ret = extref; 86f186373fSMark Fasheh return 1; 87f186373fSMark Fasheh } 88f186373fSMark Fasheh 89f186373fSMark Fasheh cur_offset += ref_name_len + sizeof(*extref); 90f186373fSMark Fasheh } 91f186373fSMark Fasheh return 0; 92f186373fSMark Fasheh } 93f186373fSMark Fasheh 94f186373fSMark Fasheh /* Returns NULL if no extref found */ 95f186373fSMark Fasheh struct btrfs_inode_extref * 96f186373fSMark Fasheh btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans, 97f186373fSMark Fasheh struct btrfs_root *root, 98f186373fSMark Fasheh struct btrfs_path *path, 99f186373fSMark Fasheh const char *name, int name_len, 100f186373fSMark Fasheh u64 inode_objectid, u64 ref_objectid, int ins_len, 101f186373fSMark Fasheh int cow) 102f186373fSMark Fasheh { 103f186373fSMark Fasheh int ret; 104f186373fSMark Fasheh struct btrfs_key key; 105f186373fSMark Fasheh struct btrfs_inode_extref *extref; 106f186373fSMark Fasheh 107f186373fSMark Fasheh key.objectid = inode_objectid; 108f186373fSMark Fasheh key.type = BTRFS_INODE_EXTREF_KEY; 109f186373fSMark Fasheh key.offset = btrfs_extref_hash(ref_objectid, name, name_len); 110f186373fSMark Fasheh 111f186373fSMark Fasheh ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); 112f186373fSMark Fasheh if (ret < 0) 113f186373fSMark Fasheh return ERR_PTR(ret); 114f186373fSMark Fasheh if (ret > 0) 115f186373fSMark Fasheh return NULL; 116f186373fSMark Fasheh if (!btrfs_find_name_in_ext_backref(path, ref_objectid, name, name_len, &extref)) 117f186373fSMark Fasheh return NULL; 118f186373fSMark Fasheh return extref; 119f186373fSMark Fasheh } 120f186373fSMark Fasheh 12148a3b636SEric Sandeen static int btrfs_del_inode_extref(struct btrfs_trans_handle *trans, 122f186373fSMark Fasheh struct btrfs_root *root, 123f186373fSMark Fasheh const char *name, int name_len, 12448a3b636SEric Sandeen u64 inode_objectid, u64 ref_objectid, 12548a3b636SEric Sandeen u64 *index) 126f186373fSMark Fasheh { 127f186373fSMark Fasheh struct btrfs_path *path; 128f186373fSMark Fasheh struct btrfs_key key; 129f186373fSMark Fasheh struct btrfs_inode_extref *extref; 130f186373fSMark Fasheh struct extent_buffer *leaf; 131f186373fSMark Fasheh int ret; 132f186373fSMark Fasheh int del_len = name_len + sizeof(*extref); 133f186373fSMark Fasheh unsigned long ptr; 134f186373fSMark Fasheh unsigned long item_start; 135f186373fSMark Fasheh u32 item_size; 136f186373fSMark Fasheh 137f186373fSMark Fasheh key.objectid = inode_objectid; 138962a298fSDavid Sterba key.type = BTRFS_INODE_EXTREF_KEY; 139f186373fSMark Fasheh key.offset = btrfs_extref_hash(ref_objectid, name, name_len); 140f186373fSMark Fasheh 141f186373fSMark Fasheh path = btrfs_alloc_path(); 142f186373fSMark Fasheh if (!path) 143f186373fSMark Fasheh return -ENOMEM; 144f186373fSMark Fasheh 145f186373fSMark Fasheh path->leave_spinning = 1; 146f186373fSMark Fasheh 147f186373fSMark Fasheh ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 148f186373fSMark Fasheh if (ret > 0) 149f186373fSMark Fasheh ret = -ENOENT; 150f186373fSMark Fasheh if (ret < 0) 151f186373fSMark Fasheh goto out; 152f186373fSMark Fasheh 153f186373fSMark Fasheh /* 154f186373fSMark Fasheh * Sanity check - did we find the right item for this name? 155f186373fSMark Fasheh * This should always succeed so error here will make the FS 156f186373fSMark Fasheh * readonly. 157f186373fSMark Fasheh */ 158f186373fSMark Fasheh if (!btrfs_find_name_in_ext_backref(path, ref_objectid, 159f186373fSMark Fasheh name, name_len, &extref)) { 16034d97007SAnand Jain btrfs_handle_fs_error(root->fs_info, -ENOENT, NULL); 161f186373fSMark Fasheh ret = -EROFS; 162f186373fSMark Fasheh goto out; 163f186373fSMark Fasheh } 164f186373fSMark Fasheh 165f186373fSMark Fasheh leaf = path->nodes[0]; 166f186373fSMark Fasheh item_size = btrfs_item_size_nr(leaf, path->slots[0]); 167f186373fSMark Fasheh if (index) 168f186373fSMark Fasheh *index = btrfs_inode_extref_index(leaf, extref); 169f186373fSMark Fasheh 170f186373fSMark Fasheh if (del_len == item_size) { 171f186373fSMark Fasheh /* 172f186373fSMark Fasheh * Common case only one ref in the item, remove the 173f186373fSMark Fasheh * whole item. 174f186373fSMark Fasheh */ 175f186373fSMark Fasheh ret = btrfs_del_item(trans, root, path); 176f186373fSMark Fasheh goto out; 177f186373fSMark Fasheh } 178f186373fSMark Fasheh 179f186373fSMark Fasheh ptr = (unsigned long)extref; 180f186373fSMark Fasheh item_start = btrfs_item_ptr_offset(leaf, path->slots[0]); 181f186373fSMark Fasheh 182f186373fSMark Fasheh memmove_extent_buffer(leaf, ptr, ptr + del_len, 183f186373fSMark Fasheh item_size - (ptr + del_len - item_start)); 184f186373fSMark Fasheh 185afe5fea7STsutomu Itoh btrfs_truncate_item(root, path, item_size - del_len, 1); 186f186373fSMark Fasheh 187f186373fSMark Fasheh out: 188f186373fSMark Fasheh btrfs_free_path(path); 189f186373fSMark Fasheh 190f186373fSMark Fasheh return ret; 191f186373fSMark Fasheh } 192f186373fSMark Fasheh 1933954401fSChris Mason int btrfs_del_inode_ref(struct btrfs_trans_handle *trans, 1943954401fSChris Mason struct btrfs_root *root, 1953954401fSChris Mason const char *name, int name_len, 196aec7477bSJosef Bacik u64 inode_objectid, u64 ref_objectid, u64 *index) 1973954401fSChris Mason { 1983954401fSChris Mason struct btrfs_path *path; 1993954401fSChris Mason struct btrfs_key key; 2003954401fSChris Mason struct btrfs_inode_ref *ref; 2013954401fSChris Mason struct extent_buffer *leaf; 2023954401fSChris Mason unsigned long ptr; 2033954401fSChris Mason unsigned long item_start; 2043954401fSChris Mason u32 item_size; 2053954401fSChris Mason u32 sub_item_len; 2063954401fSChris Mason int ret; 207f186373fSMark Fasheh int search_ext_refs = 0; 2083954401fSChris Mason int del_len = name_len + sizeof(*ref); 2093954401fSChris Mason 2103954401fSChris Mason key.objectid = inode_objectid; 2113954401fSChris Mason key.offset = ref_objectid; 212962a298fSDavid Sterba key.type = BTRFS_INODE_REF_KEY; 2133954401fSChris Mason 2143954401fSChris Mason path = btrfs_alloc_path(); 2153954401fSChris Mason if (!path) 2163954401fSChris Mason return -ENOMEM; 2173954401fSChris Mason 218b9473439SChris Mason path->leave_spinning = 1; 219b9473439SChris Mason 2203954401fSChris Mason ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 2213954401fSChris Mason if (ret > 0) { 2223954401fSChris Mason ret = -ENOENT; 223f186373fSMark Fasheh search_ext_refs = 1; 2243954401fSChris Mason goto out; 2253954401fSChris Mason } else if (ret < 0) { 2263954401fSChris Mason goto out; 2273954401fSChris Mason } 2283954401fSChris Mason if (!find_name_in_backref(path, name, name_len, &ref)) { 2293954401fSChris Mason ret = -ENOENT; 230f186373fSMark Fasheh search_ext_refs = 1; 2313954401fSChris Mason goto out; 2323954401fSChris Mason } 2333954401fSChris Mason leaf = path->nodes[0]; 2343954401fSChris Mason item_size = btrfs_item_size_nr(leaf, path->slots[0]); 235aec7477bSJosef Bacik 236aec7477bSJosef Bacik if (index) 237aec7477bSJosef Bacik *index = btrfs_inode_ref_index(leaf, ref); 238aec7477bSJosef Bacik 2393954401fSChris Mason if (del_len == item_size) { 2403954401fSChris Mason ret = btrfs_del_item(trans, root, path); 2413954401fSChris Mason goto out; 2423954401fSChris Mason } 2433954401fSChris Mason ptr = (unsigned long)ref; 2443954401fSChris Mason sub_item_len = name_len + sizeof(*ref); 2453954401fSChris Mason item_start = btrfs_item_ptr_offset(leaf, path->slots[0]); 2463954401fSChris Mason memmove_extent_buffer(leaf, ptr, ptr + sub_item_len, 2473954401fSChris Mason item_size - (ptr + sub_item_len - item_start)); 248afe5fea7STsutomu Itoh btrfs_truncate_item(root, path, item_size - sub_item_len, 1); 249f186373fSMark Fasheh out: 250f186373fSMark Fasheh btrfs_free_path(path); 251f186373fSMark Fasheh 252f186373fSMark Fasheh if (search_ext_refs) { 253f186373fSMark Fasheh /* 254f186373fSMark Fasheh * No refs were found, or we could not find the 255f186373fSMark Fasheh * name in our ref array. Find and remove the extended 256f186373fSMark Fasheh * inode ref then. 257f186373fSMark Fasheh */ 258f186373fSMark Fasheh return btrfs_del_inode_extref(trans, root, name, name_len, 259f186373fSMark Fasheh inode_objectid, ref_objectid, index); 260f186373fSMark Fasheh } 261f186373fSMark Fasheh 262f186373fSMark Fasheh return ret; 263f186373fSMark Fasheh } 264f186373fSMark Fasheh 265f186373fSMark Fasheh /* 266f186373fSMark Fasheh * btrfs_insert_inode_extref() - Inserts an extended inode ref into a tree. 267f186373fSMark Fasheh * 268f186373fSMark Fasheh * The caller must have checked against BTRFS_LINK_MAX already. 269f186373fSMark Fasheh */ 270f186373fSMark Fasheh static int btrfs_insert_inode_extref(struct btrfs_trans_handle *trans, 271f186373fSMark Fasheh struct btrfs_root *root, 272f186373fSMark Fasheh const char *name, int name_len, 273f186373fSMark Fasheh u64 inode_objectid, u64 ref_objectid, u64 index) 274f186373fSMark Fasheh { 275f186373fSMark Fasheh struct btrfs_inode_extref *extref; 276f186373fSMark Fasheh int ret; 277f186373fSMark Fasheh int ins_len = name_len + sizeof(*extref); 278f186373fSMark Fasheh unsigned long ptr; 279f186373fSMark Fasheh struct btrfs_path *path; 280f186373fSMark Fasheh struct btrfs_key key; 281f186373fSMark Fasheh struct extent_buffer *leaf; 282f186373fSMark Fasheh struct btrfs_item *item; 283f186373fSMark Fasheh 284f186373fSMark Fasheh key.objectid = inode_objectid; 285f186373fSMark Fasheh key.type = BTRFS_INODE_EXTREF_KEY; 286f186373fSMark Fasheh key.offset = btrfs_extref_hash(ref_objectid, name, name_len); 287f186373fSMark Fasheh 288f186373fSMark Fasheh path = btrfs_alloc_path(); 289f186373fSMark Fasheh if (!path) 290f186373fSMark Fasheh return -ENOMEM; 291f186373fSMark Fasheh 292f186373fSMark Fasheh path->leave_spinning = 1; 293f186373fSMark Fasheh ret = btrfs_insert_empty_item(trans, root, path, &key, 294f186373fSMark Fasheh ins_len); 295f186373fSMark Fasheh if (ret == -EEXIST) { 296f186373fSMark Fasheh if (btrfs_find_name_in_ext_backref(path, ref_objectid, 297f186373fSMark Fasheh name, name_len, NULL)) 298f186373fSMark Fasheh goto out; 299f186373fSMark Fasheh 3004b90c680STsutomu Itoh btrfs_extend_item(root, path, ins_len); 301f186373fSMark Fasheh ret = 0; 302f186373fSMark Fasheh } 303f186373fSMark Fasheh if (ret < 0) 304f186373fSMark Fasheh goto out; 305f186373fSMark Fasheh 306f186373fSMark Fasheh leaf = path->nodes[0]; 307dd3cc16bSRoss Kirk item = btrfs_item_nr(path->slots[0]); 308f186373fSMark Fasheh ptr = (unsigned long)btrfs_item_ptr(leaf, path->slots[0], char); 309f186373fSMark Fasheh ptr += btrfs_item_size(leaf, item) - ins_len; 310f186373fSMark Fasheh extref = (struct btrfs_inode_extref *)ptr; 311f186373fSMark Fasheh 312f186373fSMark Fasheh btrfs_set_inode_extref_name_len(path->nodes[0], extref, name_len); 313f186373fSMark Fasheh btrfs_set_inode_extref_index(path->nodes[0], extref, index); 314f186373fSMark Fasheh btrfs_set_inode_extref_parent(path->nodes[0], extref, ref_objectid); 315f186373fSMark Fasheh 316f186373fSMark Fasheh ptr = (unsigned long)&extref->name; 317f186373fSMark Fasheh write_extent_buffer(path->nodes[0], name, ptr, name_len); 318f186373fSMark Fasheh btrfs_mark_buffer_dirty(path->nodes[0]); 319f186373fSMark Fasheh 3203954401fSChris Mason out: 3213954401fSChris Mason btrfs_free_path(path); 3223954401fSChris Mason return ret; 3233954401fSChris Mason } 3243954401fSChris Mason 32579787eaaSJeff Mahoney /* Will return 0, -ENOMEM, -EMLINK, or -EEXIST or anything from the CoW path */ 3263954401fSChris Mason int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans, 3273954401fSChris Mason struct btrfs_root *root, 3283954401fSChris Mason const char *name, int name_len, 329aec7477bSJosef Bacik u64 inode_objectid, u64 ref_objectid, u64 index) 3303954401fSChris Mason { 3313954401fSChris Mason struct btrfs_path *path; 3323954401fSChris Mason struct btrfs_key key; 3333954401fSChris Mason struct btrfs_inode_ref *ref; 3343954401fSChris Mason unsigned long ptr; 3353954401fSChris Mason int ret; 3363954401fSChris Mason int ins_len = name_len + sizeof(*ref); 3373954401fSChris Mason 3383954401fSChris Mason key.objectid = inode_objectid; 3393954401fSChris Mason key.offset = ref_objectid; 340962a298fSDavid Sterba key.type = BTRFS_INODE_REF_KEY; 3413954401fSChris Mason 3423954401fSChris Mason path = btrfs_alloc_path(); 3433954401fSChris Mason if (!path) 3443954401fSChris Mason return -ENOMEM; 3453954401fSChris Mason 346b9473439SChris Mason path->leave_spinning = 1; 347df8d116fSFilipe Manana path->skip_release_on_error = 1; 3483954401fSChris Mason ret = btrfs_insert_empty_item(trans, root, path, &key, 3493954401fSChris Mason ins_len); 3503954401fSChris Mason if (ret == -EEXIST) { 3513954401fSChris Mason u32 old_size; 3523954401fSChris Mason 3533954401fSChris Mason if (find_name_in_backref(path, name, name_len, &ref)) 3543954401fSChris Mason goto out; 3553954401fSChris Mason 3563954401fSChris Mason old_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]); 3574b90c680STsutomu Itoh btrfs_extend_item(root, path, ins_len); 3583954401fSChris Mason ref = btrfs_item_ptr(path->nodes[0], path->slots[0], 3593954401fSChris Mason struct btrfs_inode_ref); 3603954401fSChris Mason ref = (struct btrfs_inode_ref *)((unsigned long)ref + old_size); 3613954401fSChris Mason btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len); 362aec7477bSJosef Bacik btrfs_set_inode_ref_index(path->nodes[0], ref, index); 3633954401fSChris Mason ptr = (unsigned long)(ref + 1); 3643954401fSChris Mason ret = 0; 3653954401fSChris Mason } else if (ret < 0) { 366df8d116fSFilipe Manana if (ret == -EOVERFLOW) { 367df8d116fSFilipe Manana if (find_name_in_backref(path, name, name_len, &ref)) 368df8d116fSFilipe Manana ret = -EEXIST; 369df8d116fSFilipe Manana else 370a5719521SYan, Zheng ret = -EMLINK; 371df8d116fSFilipe Manana } 3723954401fSChris Mason goto out; 3733954401fSChris Mason } else { 3743954401fSChris Mason ref = btrfs_item_ptr(path->nodes[0], path->slots[0], 3753954401fSChris Mason struct btrfs_inode_ref); 3763954401fSChris Mason btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len); 377aec7477bSJosef Bacik btrfs_set_inode_ref_index(path->nodes[0], ref, index); 3783954401fSChris Mason ptr = (unsigned long)(ref + 1); 3793954401fSChris Mason } 3803954401fSChris Mason write_extent_buffer(path->nodes[0], name, ptr, name_len); 3813954401fSChris Mason btrfs_mark_buffer_dirty(path->nodes[0]); 3823954401fSChris Mason 3833954401fSChris Mason out: 3843954401fSChris Mason btrfs_free_path(path); 385f186373fSMark Fasheh 386f186373fSMark Fasheh if (ret == -EMLINK) { 387f186373fSMark Fasheh struct btrfs_super_block *disk_super = root->fs_info->super_copy; 388f186373fSMark Fasheh /* We ran out of space in the ref array. Need to 389f186373fSMark Fasheh * add an extended ref. */ 390f186373fSMark Fasheh if (btrfs_super_incompat_flags(disk_super) 391f186373fSMark Fasheh & BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF) 392f186373fSMark Fasheh ret = btrfs_insert_inode_extref(trans, root, name, 393f186373fSMark Fasheh name_len, 394f186373fSMark Fasheh inode_objectid, 395f186373fSMark Fasheh ref_objectid, index); 396f186373fSMark Fasheh } 397f186373fSMark Fasheh 3983954401fSChris Mason return ret; 3993954401fSChris Mason } 4003954401fSChris Mason 4015f39d397SChris Mason int btrfs_insert_empty_inode(struct btrfs_trans_handle *trans, 4025f39d397SChris Mason struct btrfs_root *root, 4035f39d397SChris Mason struct btrfs_path *path, u64 objectid) 4041e1d2701SChris Mason { 4051e1d2701SChris Mason struct btrfs_key key; 4061e1d2701SChris Mason int ret; 4071e1d2701SChris Mason key.objectid = objectid; 408962a298fSDavid Sterba key.type = BTRFS_INODE_ITEM_KEY; 4091e1d2701SChris Mason key.offset = 0; 4101e1d2701SChris Mason 4115f39d397SChris Mason ret = btrfs_insert_empty_item(trans, root, path, &key, 4125f39d397SChris Mason sizeof(struct btrfs_inode_item)); 4131e1d2701SChris Mason return ret; 4141e1d2701SChris Mason } 4151e1d2701SChris Mason 416e089f05cSChris Mason int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root 417d6e4a428SChris Mason *root, struct btrfs_path *path, 418d6e4a428SChris Mason struct btrfs_key *location, int mod) 4191e1d2701SChris Mason { 4201e1d2701SChris Mason int ins_len = mod < 0 ? -1 : 0; 4211e1d2701SChris Mason int cow = mod != 0; 422d6e4a428SChris Mason int ret; 423d6e4a428SChris Mason int slot; 4245f39d397SChris Mason struct extent_buffer *leaf; 425d6e4a428SChris Mason struct btrfs_key found_key; 4261e1d2701SChris Mason 427d6e4a428SChris Mason ret = btrfs_search_slot(trans, root, location, path, ins_len, cow); 428962a298fSDavid Sterba if (ret > 0 && location->type == BTRFS_ROOT_ITEM_KEY && 429d6e4a428SChris Mason location->offset == (u64)-1 && path->slots[0] != 0) { 430d6e4a428SChris Mason slot = path->slots[0] - 1; 4315f39d397SChris Mason leaf = path->nodes[0]; 4325f39d397SChris Mason btrfs_item_key_to_cpu(leaf, &found_key, slot); 433d6e4a428SChris Mason if (found_key.objectid == location->objectid && 434962a298fSDavid Sterba found_key.type == location->type) { 435d6e4a428SChris Mason path->slots[0]--; 436d6e4a428SChris Mason return 0; 437d6e4a428SChris Mason } 438d6e4a428SChris Mason } 439d6e4a428SChris Mason return ret; 4401e1d2701SChris Mason } 441