aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-11-17 20:42:26 -0500
committerChris Mason <chris.mason@oracle.com>2008-11-17 20:42:26 -0500
commit3394e1607eaf870ebba37d303fbd590a4c569908 (patch)
tree7833927ae6137122bea670544147be6a69f804ad /fs
parent3de4586c5278a28107030c336956381f69ff7a9d (diff)
Btrfs: Give each subvol and snapshot their own anonymous devid
Each subvolume has its own private inode number space, and so we need to fill in different device numbers for each subvolume to avoid confusing applications. This commit puts a struct super_block into struct btrfs_root so it can call set_anon_super() and get a different device number generated for each root. btrfs_rename is changed to prevent renames across subvols. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h6
-rw-r--r--fs/btrfs/disk-io.c13
-rw-r--r--fs/btrfs/inode.c15
-rw-r--r--fs/btrfs/ioctl.c2
-rw-r--r--fs/btrfs/transaction.c4
5 files changed, 34 insertions, 6 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 5611f8e035a4..b3bc65b08c6a 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -799,6 +799,12 @@ struct btrfs_root {
799 spinlock_t list_lock; 799 spinlock_t list_lock;
800 struct list_head dead_list; 800 struct list_head dead_list;
801 struct list_head orphan_list; 801 struct list_head orphan_list;
802
803 /*
804 * right now this just gets used so that a root has its own devid
805 * for stat. It may be used for more later
806 */
807 struct super_block anon_super;
802}; 808};
803 809
804/* 810/*
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 0a5350573f61..8d7866b733d6 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -877,6 +877,12 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
877 root->defrag_running = 0; 877 root->defrag_running = 0;
878 root->defrag_level = 0; 878 root->defrag_level = 0;
879 root->root_key.objectid = objectid; 879 root->root_key.objectid = objectid;
880 root->anon_super.s_root = NULL;
881 root->anon_super.s_dev = 0;
882 INIT_LIST_HEAD(&root->anon_super.s_list);
883 INIT_LIST_HEAD(&root->anon_super.s_instances);
884 init_rwsem(&root->anon_super.s_umount);
885
880 return 0; 886 return 0;
881} 887}
882 888
@@ -1083,6 +1089,9 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
1083 root = btrfs_read_fs_root_no_radix(fs_info->tree_root, location); 1089 root = btrfs_read_fs_root_no_radix(fs_info->tree_root, location);
1084 if (IS_ERR(root)) 1090 if (IS_ERR(root))
1085 return root; 1091 return root;
1092
1093 set_anon_super(&root->anon_super, NULL);
1094
1086 ret = radix_tree_insert(&fs_info->fs_roots_radix, 1095 ret = radix_tree_insert(&fs_info->fs_roots_radix,
1087 (unsigned long)root->root_key.objectid, 1096 (unsigned long)root->root_key.objectid,
1088 root); 1097 root);
@@ -1950,6 +1959,10 @@ int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
1950{ 1959{
1951 radix_tree_delete(&fs_info->fs_roots_radix, 1960 radix_tree_delete(&fs_info->fs_roots_radix,
1952 (unsigned long)root->root_key.objectid); 1961 (unsigned long)root->root_key.objectid);
1962 if (root->anon_super.s_dev) {
1963 down_write(&root->anon_super.s_umount);
1964 kill_anon_super(&root->anon_super);
1965 }
1953 if (root->in_sysfs) 1966 if (root->in_sysfs)
1954 btrfs_sysfs_del_root(root); 1967 btrfs_sysfs_del_root(root);
1955 if (root->node) 1968 if (root->node)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index e163b1b74707..7ef79ce86e25 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2212,7 +2212,12 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
2212 struct btrfs_trans_handle *trans; 2212 struct btrfs_trans_handle *trans;
2213 unsigned long nr = 0; 2213 unsigned long nr = 0;
2214 2214
2215 if (inode->i_size > BTRFS_EMPTY_DIR_SIZE) { 2215 /*
2216 * the FIRST_FREE_OBJECTID check makes sure we don't try to rmdir
2217 * the root of a subvolume or snapshot
2218 */
2219 if (inode->i_size > BTRFS_EMPTY_DIR_SIZE ||
2220 inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
2216 return -ENOTEMPTY; 2221 return -ENOTEMPTY;
2217 } 2222 }
2218 2223
@@ -4410,7 +4415,6 @@ int btrfs_create_subvol_root(struct btrfs_root *new_root, struct dentry *dentry,
4410 if (error) 4415 if (error)
4411 return error; 4416 return error;
4412 4417
4413 atomic_inc(&inode->i_count);
4414 d_instantiate(dentry, inode); 4418 d_instantiate(dentry, inode);
4415 return 0; 4419 return 0;
4416} 4420}
@@ -4548,6 +4552,7 @@ static int btrfs_getattr(struct vfsmount *mnt,
4548{ 4552{
4549 struct inode *inode = dentry->d_inode; 4553 struct inode *inode = dentry->d_inode;
4550 generic_fillattr(inode, stat); 4554 generic_fillattr(inode, stat);
4555 stat->dev = BTRFS_I(inode)->root->anon_super.s_dev;
4551 stat->blksize = PAGE_CACHE_SIZE; 4556 stat->blksize = PAGE_CACHE_SIZE;
4552 stat->blocks = (inode_get_bytes(inode) + 4557 stat->blocks = (inode_get_bytes(inode) +
4553 BTRFS_I(inode)->delalloc_bytes) >> 9; 4558 BTRFS_I(inode)->delalloc_bytes) >> 9;
@@ -4565,6 +4570,11 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
4565 u64 index = 0; 4570 u64 index = 0;
4566 int ret; 4571 int ret;
4567 4572
4573 /* we're not allowed to rename between subvolumes */
4574 if (BTRFS_I(old_inode)->root->root_key.objectid !=
4575 BTRFS_I(new_dir)->root->root_key.objectid)
4576 return -EXDEV;
4577
4568 if (S_ISDIR(old_inode->i_mode) && new_inode && 4578 if (S_ISDIR(old_inode->i_mode) && new_inode &&
4569 new_inode->i_size > BTRFS_EMPTY_DIR_SIZE) { 4579 new_inode->i_size > BTRFS_EMPTY_DIR_SIZE) {
4570 return -ENOTEMPTY; 4580 return -ENOTEMPTY;
@@ -4920,6 +4930,7 @@ static int btrfs_permission(struct inode *inode, int mask)
4920} 4930}
4921 4931
4922static struct inode_operations btrfs_dir_inode_operations = { 4932static struct inode_operations btrfs_dir_inode_operations = {
4933 .getattr = btrfs_getattr,
4923 .lookup = btrfs_lookup, 4934 .lookup = btrfs_lookup,
4924 .create = btrfs_create, 4935 .create = btrfs_create,
4925 .unlink = btrfs_unlink, 4936 .unlink = btrfs_unlink,
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index ec45b3086136..773db07b5f72 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -127,7 +127,6 @@ static noinline int create_subvol(struct btrfs_root *root,
127 key.objectid = objectid; 127 key.objectid = objectid;
128 key.offset = 1; 128 key.offset = 1;
129 btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); 129 btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
130printk("inserting root objectid %Lu\n", objectid);
131 ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, 130 ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
132 &root_item); 131 &root_item);
133 if (ret) 132 if (ret)
@@ -175,7 +174,6 @@ fail:
175 ret = err; 174 ret = err;
176fail_commit: 175fail_commit:
177 btrfs_btree_balance_dirty(root, nr); 176 btrfs_btree_balance_dirty(root, nr);
178printk("all done ret %d\n", ret);
179 return ret; 177 return ret;
180} 178}
181 179
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index eec8b2465039..93f23a456a36 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -832,13 +832,13 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
832 struct inode *parent_inode; 832 struct inode *parent_inode;
833 struct inode *inode; 833 struct inode *inode;
834 834
835 trans = btrfs_start_transaction(fs_info->fs_root, 1); 835 parent_inode = pending->dentry->d_parent->d_inode;
836 trans = btrfs_start_transaction(BTRFS_I(parent_inode)->root, 1);
836 837
837 /* 838 /*
838 * insert the directory item 839 * insert the directory item
839 */ 840 */
840 namelen = strlen(pending->name); 841 namelen = strlen(pending->name);
841 parent_inode = pending->dentry->d_parent->d_inode;
842 ret = btrfs_set_inode_index(parent_inode, &index); 842 ret = btrfs_set_inode_index(parent_inode, &index);
843 ret = btrfs_insert_dir_item(trans, 843 ret = btrfs_insert_dir_item(trans,
844 BTRFS_I(parent_inode)->root, 844 BTRFS_I(parent_inode)->root,