mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/kdave/btrfs-progs.git
synced 2024-11-16 00:34:32 +08:00
start of support for subvolumes
This commit is contained in:
parent
d785b7d058
commit
8accdae27a
28
ctree.h
28
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);
|
||||
|
14
dir-item.c
14
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);
|
||||
|
14
dir-test.c
14
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);
|
||||
|
75
mkfs.c
75
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);
|
||||
|
20
print-tree.c
20
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,
|
||||
|
Loading…
Reference in New Issue
Block a user