spinlock_t list_lock;
struct list_head dead_list;
struct list_head orphan_list;
+
+ /*
+ * right now this just gets used so that a root has its own devid
+ * for stat. It may be used for more later
+ */
+ struct super_block anon_super;
};
/*
root->defrag_running = 0;
root->defrag_level = 0;
root->root_key.objectid = objectid;
+ root->anon_super.s_root = NULL;
+ root->anon_super.s_dev = 0;
+ INIT_LIST_HEAD(&root->anon_super.s_list);
+ INIT_LIST_HEAD(&root->anon_super.s_instances);
+ init_rwsem(&root->anon_super.s_umount);
+
return 0;
}
root = btrfs_read_fs_root_no_radix(fs_info->tree_root, location);
if (IS_ERR(root))
return root;
+
+ set_anon_super(&root->anon_super, NULL);
+
ret = radix_tree_insert(&fs_info->fs_roots_radix,
(unsigned long)root->root_key.objectid,
root);
{
radix_tree_delete(&fs_info->fs_roots_radix,
(unsigned long)root->root_key.objectid);
+ if (root->anon_super.s_dev) {
+ down_write(&root->anon_super.s_umount);
+ kill_anon_super(&root->anon_super);
+ }
if (root->in_sysfs)
btrfs_sysfs_del_root(root);
if (root->node)
struct btrfs_trans_handle *trans;
unsigned long nr = 0;
- if (inode->i_size > BTRFS_EMPTY_DIR_SIZE) {
+ /*
+ * the FIRST_FREE_OBJECTID check makes sure we don't try to rmdir
+ * the root of a subvolume or snapshot
+ */
+ if (inode->i_size > BTRFS_EMPTY_DIR_SIZE ||
+ inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
return -ENOTEMPTY;
}
if (error)
return error;
- atomic_inc(&inode->i_count);
d_instantiate(dentry, inode);
return 0;
}
{
struct inode *inode = dentry->d_inode;
generic_fillattr(inode, stat);
+ stat->dev = BTRFS_I(inode)->root->anon_super.s_dev;
stat->blksize = PAGE_CACHE_SIZE;
stat->blocks = (inode_get_bytes(inode) +
BTRFS_I(inode)->delalloc_bytes) >> 9;
u64 index = 0;
int ret;
+ /* we're not allowed to rename between subvolumes */
+ if (BTRFS_I(old_inode)->root->root_key.objectid !=
+ BTRFS_I(new_dir)->root->root_key.objectid)
+ return -EXDEV;
+
if (S_ISDIR(old_inode->i_mode) && new_inode &&
new_inode->i_size > BTRFS_EMPTY_DIR_SIZE) {
return -ENOTEMPTY;
}
static struct inode_operations btrfs_dir_inode_operations = {
+ .getattr = btrfs_getattr,
.lookup = btrfs_lookup,
.create = btrfs_create,
.unlink = btrfs_unlink,
key.objectid = objectid;
key.offset = 1;
btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
-printk("inserting root objectid %Lu\n", objectid);
ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
&root_item);
if (ret)
ret = err;
fail_commit:
btrfs_btree_balance_dirty(root, nr);
-printk("all done ret %d\n", ret);
return ret;
}
struct inode *parent_inode;
struct inode *inode;
- trans = btrfs_start_transaction(fs_info->fs_root, 1);
+ parent_inode = pending->dentry->d_parent->d_inode;
+ trans = btrfs_start_transaction(BTRFS_I(parent_inode)->root, 1);
/*
* insert the directory item
*/
namelen = strlen(pending->name);
- parent_inode = pending->dentry->d_parent->d_inode;
ret = btrfs_set_inode_index(parent_inode, &index);
ret = btrfs_insert_dir_item(trans,
BTRFS_I(parent_inode)->root,