static struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, u64 root_objectid, u32 generation) { struct btrfs_root *root; struct inode *inode; struct btrfs_key key; key.objectid = root_objectid; btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); key.offset = (u64)-1; root = btrfs_read_fs_root_no_name(btrfs_sb(sb)->fs_info, &key); if (IS_ERR(root)) return ERR_CAST(root); key.objectid = objectid; btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); key.offset = 0; inode = btrfs_iget(sb, &key, root, NULL); if (IS_ERR(inode)) return (void *)inode; if (generation != inode->i_generation) { iput(inode); return ERR_PTR(-ESTALE); } return d_obtain_alias(inode); }
static struct dentry *btrfs_get_parent(struct dentry *child) { struct inode *dir = child->d_inode; struct btrfs_root *root = BTRFS_I(dir)->root; struct btrfs_key key; struct btrfs_path *path; struct extent_buffer *leaf; int slot; u64 objectid; int ret; path = btrfs_alloc_path(); key.objectid = dir->i_ino; btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY); key.offset = (u64)-1; ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) { /* Error */ btrfs_free_path(path); return ERR_PTR(ret); } leaf = path->nodes[0]; slot = path->slots[0]; if (ret) { /* btrfs_search_slot() returns the slot where we'd want to insert a backref for parent inode #0xFFFFFFFFFFFFFFFF. The _real_ backref, telling us what the parent inode _actually_ is, will be in the slot _before_ the one that btrfs_search_slot() returns. */ if (!slot) { /* Unless there is _no_ key in the tree before... */ btrfs_free_path(path); return ERR_PTR(-EIO); } slot--; } btrfs_item_key_to_cpu(leaf, &key, slot); btrfs_free_path(path); if (key.objectid != dir->i_ino || key.type != BTRFS_INODE_REF_KEY) return ERR_PTR(-EINVAL); objectid = key.offset; /* If we are already at the root of a subvol, return the real root */ if (objectid == dir->i_ino) return dget(dir->i_sb->s_root); /* Build a new key for the inode item */ key.objectid = objectid; btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); key.offset = 0; return d_obtain_alias(btrfs_iget(root->fs_info->sb, &key, root, NULL)); }
static struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, u64 root_objectid, u32 generation, int check_generation) { struct btrfs_fs_info *fs_info = btrfs_sb(sb); struct btrfs_root *root; struct inode *inode; struct btrfs_key key; int index; int err = 0; if (objectid < BTRFS_FIRST_FREE_OBJECTID) return ERR_PTR(-ESTALE); key.objectid = root_objectid; btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); key.offset = (u64)-1; index = srcu_read_lock(&fs_info->subvol_srcu); root = btrfs_read_fs_root_no_name(fs_info, &key); if (IS_ERR(root)) { err = PTR_ERR(root); goto fail; } if (btrfs_root_refs(&root->root_item) == 0) { err = -ENOENT; goto fail; } key.objectid = objectid; btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); key.offset = 0; inode = btrfs_iget(sb, &key, root, NULL); if (IS_ERR(inode)) { err = PTR_ERR(inode); goto fail; } srcu_read_unlock(&fs_info->subvol_srcu, index); if (check_generation && generation != inode->i_generation) { iput(inode); return ERR_PTR(-ESTALE); } return d_obtain_alias(inode); fail: srcu_read_unlock(&fs_info->subvol_srcu, index); return ERR_PTR(err); }
/* * run through the list of inodes in the FS that need * defragging */ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info) { struct inode_defrag *defrag; struct btrfs_root *inode_root; struct inode *inode; struct rb_node *n; struct btrfs_key key; struct btrfs_ioctl_defrag_range_args range; u64 first_ino = 0; u64 root_objectid = 0; int num_defrag; int defrag_batch = 1024; memset(&range, 0, sizeof(range)); range.len = (u64)-1; atomic_inc(&fs_info->defrag_running); spin_lock(&fs_info->defrag_inodes_lock); while(1) { n = NULL; /* find an inode to defrag */ defrag = btrfs_find_defrag_inode(fs_info, root_objectid, first_ino, &n); if (!defrag) { if (n) { defrag = rb_entry(n, struct inode_defrag, rb_node); } else if (root_objectid || first_ino) { root_objectid = 0; first_ino = 0; continue; } else { break; } } /* remove it from the rbtree */ first_ino = defrag->ino + 1; root_objectid = defrag->root; rb_erase(&defrag->rb_node, &fs_info->defrag_inodes); if (btrfs_fs_closing(fs_info)) goto next_free; spin_unlock(&fs_info->defrag_inodes_lock); /* get the inode */ key.objectid = defrag->root; btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); key.offset = (u64)-1; inode_root = btrfs_read_fs_root_no_name(fs_info, &key); if (IS_ERR(inode_root)) goto next; key.objectid = defrag->ino; btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); key.offset = 0; inode = btrfs_iget(fs_info->sb, &key, inode_root, NULL); if (IS_ERR(inode)) goto next; /* do a chunk of defrag */ clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags); range.start = defrag->last_offset; num_defrag = btrfs_defrag_file(inode, NULL, &range, defrag->transid, defrag_batch); /* * if we filled the whole defrag batch, there * must be more work to do. Queue this defrag * again */ if (num_defrag == defrag_batch) { defrag->last_offset = range.start; __btrfs_add_inode_defrag(inode, defrag); /* * we don't want to kfree defrag, we added it back to * the rbtree */ defrag = NULL; } else if (defrag->last_offset && !defrag->cycled) { /* * we didn't fill our defrag batch, but * we didn't start at zero. Make sure we loop * around to the start of the file. */ defrag->last_offset = 0; defrag->cycled = 1; __btrfs_add_inode_defrag(inode, defrag); defrag = NULL; } iput(inode); next: spin_lock(&fs_info->defrag_inodes_lock); next_free: kfree(defrag); }