From 8accdae27a678a47f021128121f2975e6fc25201 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 6 Apr 2007 15:39:12 -0400 Subject: [PATCH] start of support for subvolumes --- ctree.h | 28 +++++++++++--------- dir-item.c | 14 ++++++---- dir-test.c | 14 +++++++--- mkfs.c | 75 ++++++++++++++++++++++++++++++++++++++-------------- print-tree.c | 20 +++++++------- 5 files changed, 100 insertions(+), 51 deletions(-) diff --git a/ctree.h b/ctree.h index d35db820..19e79270 100644 --- a/ctree.h +++ b/ctree.h @@ -180,13 +180,15 @@ struct btrfs_inline_data_item { } __attribute__ ((__packed__)); struct btrfs_dir_item { - __le64 objectid; + struct btrfs_disk_key location; __le16 flags; __le16 name_len; u8 type; } __attribute__ ((__packed__)); struct btrfs_root_item { + struct btrfs_inode_item inode; + __le64 root_dirid; __le64 blocknr; __le32 flags; __le64 block_limit; @@ -498,16 +500,6 @@ static inline void btrfs_set_item_size(struct btrfs_item *item, u16 val) item->size = cpu_to_le16(val); } -static inline u64 btrfs_dir_objectid(struct btrfs_dir_item *d) -{ - return le64_to_cpu(d->objectid); -} - -static inline void btrfs_set_dir_objectid(struct btrfs_dir_item *d, u64 val) -{ - d->objectid = cpu_to_le64(val); -} - static inline u16 btrfs_dir_flags(struct btrfs_dir_item *d) { return le16_to_cpu(d->flags); @@ -718,6 +710,16 @@ static inline void btrfs_set_root_blocknr(struct btrfs_root_item *item, u64 val) item->blocknr = cpu_to_le64(val); } +static inline u64 btrfs_root_dirid(struct btrfs_root_item *item) +{ + return le64_to_cpu(item->root_dirid); +} + +static inline void btrfs_set_root_dirid(struct btrfs_root_item *item, u64 val) +{ + item->root_dirid = cpu_to_le64(val); +} + static inline u32 btrfs_root_refs(struct btrfs_root_item *item) { return le32_to_cpu(item->refs); @@ -899,8 +901,8 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct btrfs_root_item *item, struct btrfs_key *key); int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root - *root, char *name, int name_len, u64 dir, u64 - objectid, u8 type); + *root, char *name, int name_len, u64 dir, + struct btrfs_key *location, u8 type); int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, u64 dir, char *name, int name_len, int mod); diff --git a/dir-item.c b/dir-item.c index fff16348..7058b89f 100644 --- a/dir-item.c +++ b/dir-item.c @@ -28,8 +28,8 @@ int insert_with_overflow(struct btrfs_trans_handle *trans, struct btrfs_root } int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root - *root, char *name, int name_len, u64 dir, u64 - objectid, u8 type) + *root, char *name, int name_len, u64 dir, + struct btrfs_key *location, u8 type) { int ret = 0; struct btrfs_path path; @@ -56,23 +56,27 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root dir_item = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], struct btrfs_dir_item); - btrfs_set_dir_objectid(dir_item, objectid); + btrfs_cpu_key_to_disk(&dir_item->location, location); btrfs_set_dir_type(dir_item, type); btrfs_set_dir_flags(dir_item, 0); btrfs_set_dir_name_len(dir_item, name_len); name_ptr = (char *)(dir_item + 1); memcpy(name_ptr, name, name_len); + /* FIXME, use some real flag for selecting the extra index */ + if (root == root->fs_info->tree_root) + goto out; + btrfs_release_path(root, &path); btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); - key.offset = objectid; + key.offset = location->objectid; ret = insert_with_overflow(trans, root, &path, &key, data_size); if (ret) goto out; dir_item = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], struct btrfs_dir_item); - btrfs_set_dir_objectid(dir_item, objectid); + btrfs_cpu_key_to_disk(&dir_item->location, location); btrfs_set_dir_type(dir_item, type); btrfs_set_dir_flags(dir_item, 0); btrfs_set_dir_name_len(dir_item, name_len); diff --git a/dir-test.c b/dir-test.c index 6117d225..078284ea 100644 --- a/dir-test.c +++ b/dir-test.c @@ -69,6 +69,7 @@ static int ins_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, inode_map.objectid = objectid; inode_map.flags = 0; + btrfs_set_key_type(&inode_map, BTRFS_INODE_ITEM_KEY); inode_map.offset = 0; ret = btrfs_insert_inode_map(trans, root, objectid, &inode_map); @@ -80,7 +81,7 @@ static int ins_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, if (ret) goto error; ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid, - objectid, 1); + &inode_map, 1); if (ret) goto error; @@ -134,14 +135,19 @@ static int insert_dup(struct btrfs_trans_handle *trans, struct btrfs_root int ret; char buf[128]; unsigned long oid; + struct btrfs_key key; ret = find_num(radix, &oid, 1); if (ret < 0) return 0; sprintf(buf, "str-%lu", oid); + key.objectid = file_oid; + key.flags = 0; + btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); + key.offset = 0; ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid, - file_oid, 1); + &key, 1); if (ret != -EEXIST) { printf("insert on %s gave us %d\n", buf, ret); return 1; @@ -163,7 +169,7 @@ static int del_dir_item(struct btrfs_trans_handle *trans, /* find the inode number of the file */ di = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0], struct btrfs_dir_item); - file_objectid = btrfs_dir_objectid(di); + file_objectid = btrfs_disk_key_objectid(&di->location); /* delete the directory item */ ret = btrfs_del_item(trans, root, path); @@ -254,7 +260,7 @@ static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root if (!ret) { di = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], struct btrfs_dir_item); - objectid = btrfs_dir_objectid(di); + objectid = btrfs_disk_key_objectid(&di->location); btrfs_release_path(root, &path); btrfs_init_path(&path); ret = btrfs_lookup_inode_map(trans, root, &path, objectid, 0); diff --git a/mkfs.c b/mkfs.c index 9337cc0c..f182a190 100644 --- a/mkfs.c +++ b/mkfs.c @@ -21,33 +21,25 @@ static inline int ioctl(int fd, int define, u64 *size) { return 0; } #endif -static int make_root_dir(int fd) { - struct btrfs_root *root; - struct btrfs_super_block super; +static int __make_root_dir(struct btrfs_trans_handle *trans, + struct btrfs_root *root) +{ int ret; char buf[8]; u64 objectid; struct btrfs_key inode_map; struct btrfs_inode_item inode_item; - struct btrfs_trans_handle *trans; - - root = open_ctree_fd(fd, &super); - - if (!root) { - fprintf(stderr, "ctree init failed\n"); - return -1; - } buf[0] = '.'; buf[1] = '.'; - trans = btrfs_start_transaction(root, 1); ret = btrfs_find_free_objectid(trans, root, 1, &objectid); if (ret) goto error; inode_map.objectid = objectid; inode_map.flags = 0; + btrfs_set_key_type(&inode_map, BTRFS_INODE_ITEM_KEY); inode_map.offset = 0; ret = btrfs_insert_inode_map(trans, root, objectid, &inode_map); @@ -59,29 +51,62 @@ static int make_root_dir(int fd) { btrfs_set_inode_size(&inode_item, 3); btrfs_set_inode_nlink(&inode_item, 1); btrfs_set_inode_nblocks(&inode_item, 1); - btrfs_set_inode_mode(&inode_item, S_IFDIR | 0755); + btrfs_set_inode_mode(&inode_item, S_IFDIR | 0555); - btrfs_set_super_root_dir(&super, objectid); + if (root->fs_info->tree_root == root) + btrfs_set_super_root_dir(root->fs_info->disk_super, objectid); ret = btrfs_insert_inode(trans, root, objectid, &inode_item); if (ret) goto error; ret = btrfs_insert_dir_item(trans, root, buf, 1, objectid, - objectid, 1); + &inode_map, 1); if (ret) goto error; ret = btrfs_insert_dir_item(trans, root, buf, 2, objectid, - objectid, 1); + &inode_map, 1); if (ret) goto error; - ret = btrfs_commit_transaction(trans, root, &super); - if (ret) - goto error; - ret = close_ctree(root, &super); + btrfs_set_root_dirid(&root->root_item, objectid); + ret = 0; error: return ret; } +static int make_root_dir(int fd) { + struct btrfs_root *root; + struct btrfs_super_block super; + struct btrfs_trans_handle *trans; + int ret; + struct btrfs_key location; + + root = open_ctree_fd(fd, &super); + + if (!root) { + fprintf(stderr, "ctree init failed\n"); + return -1; + } + trans = btrfs_start_transaction(root, 1); + ret = __make_root_dir(trans, root->fs_info->tree_root); + if (ret) + goto err; + ret = __make_root_dir(trans, root); + if (ret) + goto err; + memcpy(&location, &root->fs_info->fs_root->root_key, sizeof(location)); + location.offset = (u64)-1; + ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, + "default", strlen("default"), + btrfs_super_root_dir(root->fs_info->disk_super), + &location, 1); + if (ret) + goto err; + btrfs_commit_transaction(trans, root, root->fs_info->disk_super); + ret = close_ctree(root, &super); +err: + return ret; +} + int mkfs(int fd, u64 num_blocks, u32 blocksize) { struct btrfs_super_block super; @@ -89,6 +114,7 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) struct btrfs_root_item root_item; struct btrfs_item item; struct btrfs_extent_item extent_item; + struct btrfs_inode_item *inode_item; char *block; int ret; u32 itemoff; @@ -121,6 +147,15 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) sizeof(empty_leaf->header.fsid)); /* create the items for the root tree */ + inode_item = &root_item.inode; + memset(inode_item, 0, sizeof(*inode_item)); + btrfs_set_inode_generation(inode_item, 1); + btrfs_set_inode_size(inode_item, 3); + btrfs_set_inode_nlink(inode_item, 1); + btrfs_set_inode_nblocks(inode_item, 1); + btrfs_set_inode_mode(inode_item, S_IFDIR | 0755); + + btrfs_set_root_dirid(&root_item, 0); btrfs_set_root_blocknr(&root_item, start_block + 2); btrfs_set_root_refs(&root_item, 1); itemoff = __BTRFS_LEAF_DATA_SIZE(blocksize) - sizeof(root_item); diff --git a/print-tree.c b/print-tree.c index ca3c653c..0a6332d1 100644 --- a/print-tree.c +++ b/print-tree.c @@ -28,11 +28,11 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) for (i = 0 ; i < nr ; i++) { item = l->items + i; type = btrfs_disk_key_type(&item->key); - printf("\titem %d key (%Lu %u %Lu) itemoff %d itemsize %d\n", + printf("\titem %d key (%Lu %Lu %u) itemoff %d itemsize %d\n", i, btrfs_disk_key_objectid(&item->key), - btrfs_disk_key_flags(&item->key), btrfs_disk_key_offset(&item->key), + btrfs_disk_key_flags(&item->key), btrfs_item_offset(item), btrfs_item_size(item)); switch (type) { @@ -50,7 +50,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) case BTRFS_DIR_ITEM_KEY: di = btrfs_item_ptr(l, i, struct btrfs_dir_item); printf("\t\tdir oid %Lu flags %u type %u\n", - btrfs_dir_objectid(di), + btrfs_disk_key_objectid(&di->location), btrfs_dir_flags(di), btrfs_dir_type(di)); printf("\t\tname %.*s\n", @@ -59,7 +59,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) case BTRFS_DIR_INDEX_KEY: di = btrfs_item_ptr(l, i, struct btrfs_dir_item); printf("\t\tdir index %Lu flags %u type %u\n", - btrfs_dir_objectid(di), + btrfs_disk_key_objectid(&di->location), btrfs_dir_flags(di), btrfs_dir_type(di)); printf("\t\tname %.*s\n", @@ -67,8 +67,10 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) break; case BTRFS_ROOT_ITEM_KEY: ri = btrfs_item_ptr(l, i, struct btrfs_root_item); - printf("\t\troot data blocknr %Lu refs %u\n", - btrfs_root_blocknr(ri), btrfs_root_refs(ri)); + printf("\t\troot data blocknr %Lu dirid %Lu refs %u\n", + btrfs_root_blocknr(ri), + btrfs_root_dirid(ri), + btrfs_root_refs(ri)); break; case BTRFS_EXTENT_ITEM_KEY: ei = btrfs_item_ptr(l, i, struct btrfs_extent_item); @@ -77,10 +79,10 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) break; case BTRFS_INODE_MAP_ITEM_KEY: mi = btrfs_item_ptr(l, i, struct btrfs_inode_map_item); - printf("\t\tinode map key %Lu %u %Lu\n", + printf("\t\tinode map key %Lu %Lu %u\n", btrfs_disk_key_objectid(&mi->key), - btrfs_disk_key_flags(&mi->key), - btrfs_disk_key_offset(&mi->key)); + btrfs_disk_key_offset(&mi->key), + btrfs_disk_key_flags(&mi->key)); break; case BTRFS_EXTENT_DATA_KEY: fi = btrfs_item_ptr(l, i,