/*
* compare two keys in a memcmp fashion
*/
-int comp_keys(struct key *k1, struct key *k2)
+int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
{
- if (k1->objectid > k2->objectid)
+ struct btrfs_key k1;
+
+ btrfs_disk_key_to_cpu(&k1, disk);
+
+ if (k1.objectid > k2->objectid)
return 1;
- if (k1->objectid < k2->objectid)
+ if (k1.objectid < k2->objectid)
return -1;
- if (k1->flags > k2->flags)
+ if (k1.flags > k2->flags)
return 1;
- if (k1->flags < k2->flags)
+ if (k1.flags < k2->flags)
return -1;
- if (k1->offset > k2->offset)
+ if (k1.offset > k2->offset)
return 1;
- if (k1->offset < k2->offset)
+ if (k1.offset < k2->offset)
return -1;
return 0;
}
parent_slot = path->slots[level + 1];
BUG_ON(nritems == 0);
if (parent) {
- struct key *parent_key;
+ struct btrfs_disk_key *parent_key;
parent_key = &parent->keys[parent_slot];
- BUG_ON(memcmp(parent_key, node->keys, sizeof(struct key)));
+ BUG_ON(memcmp(parent_key, node->keys,
+ sizeof(struct btrfs_disk_key)));
BUG_ON(parent->blockptrs[parent_slot] !=
btrfs_header_blocknr(&node->header));
}
BUG_ON(nritems > NODEPTRS_PER_BLOCK);
for (i = 0; nritems > 1 && i < nritems - 2; i++) {
- BUG_ON(comp_keys(&node->keys[i], &node->keys[i+1]) >= 0);
+ struct btrfs_key cpukey;
+ btrfs_disk_key_to_cpu(&cpukey, &node->keys[i + 1]);
+ BUG_ON(comp_keys(&node->keys[i], &cpukey) >= 0);
}
return 0;
}
return 0;
if (parent) {
- struct key *parent_key;
+ struct btrfs_disk_key *parent_key;
parent_key = &parent->keys[parent_slot];
BUG_ON(memcmp(parent_key, &leaf->items[0].key,
- sizeof(struct key)));
+ sizeof(struct btrfs_disk_key)));
BUG_ON(parent->blockptrs[parent_slot] !=
btrfs_header_blocknr(&leaf->header));
}
for (i = 0; nritems > 1 && i < nritems - 2; i++) {
+ struct btrfs_key cpukey;
+ btrfs_disk_key_to_cpu(&cpukey, &leaf->items[i + 1].key);
BUG_ON(comp_keys(&leaf->items[i].key,
- &leaf->items[i+1].key) >= 0);
+ &cpukey) >= 0);
BUG_ON(leaf->items[i].offset != leaf->items[i + 1].offset +
leaf->items[i + 1].size);
if (i == 0) {
*
* slot may point to max if the key is bigger than all of the keys
*/
-int generic_bin_search(char *p, int item_size, struct key *key,
+int generic_bin_search(char *p, int item_size, struct btrfs_key *key,
int max, int *slot)
{
int low = 0;
int high = max;
int mid;
int ret;
- struct key *tmp;
+ struct btrfs_disk_key *tmp;
while(low < high) {
mid = (low + high) / 2;
- tmp = (struct key *)(p + mid * item_size);
+ tmp = (struct btrfs_disk_key *)(p + mid * item_size);
ret = comp_keys(tmp, key);
if (ret < 0)
* simple bin_search frontend that does the right thing for
* leaves vs nodes
*/
-int bin_search(struct node *c, struct key *key, int *slot)
+int bin_search(struct node *c, struct btrfs_key *key, int *slot)
{
if (btrfs_is_leaf(c)) {
struct leaf *l = (struct leaf *)c;
key, btrfs_header_nritems(&c->header),
slot);
} else {
- return generic_bin_search((void *)c->keys, sizeof(struct key),
+ return generic_bin_search((void *)c->keys,
+ sizeof(struct btrfs_disk_key),
key, btrfs_header_nritems(&c->header),
slot);
}
ret = wret;
} else {
memcpy(parent->keys + pslot + 1, right->keys,
- sizeof(struct key));
+ sizeof(struct btrfs_disk_key));
BUG_ON(list_empty(&parent_buf->dirty));
}
}
ret = wret;
} else {
/* update the parent key to reflect our changes */
- memcpy(parent->keys + pslot, mid->keys, sizeof(struct key));
+ memcpy(parent->keys + pslot, mid->keys,
+ sizeof(struct btrfs_disk_key));
BUG_ON(list_empty(&parent_buf->dirty));
}
* tree. if ins_len < 0, nodes will be merged as we walk down the tree (if
* possible)
*/
-int search_slot(struct ctree_root *root, struct key *key,
+int search_slot(struct ctree_root *root, struct btrfs_key *key,
struct ctree_path *p, int ins_len, int cow)
{
struct tree_buffer *b;
* fixing up the blocks in ram so the tree is consistent.
*/
static int fixup_low_keys(struct ctree_root *root,
- struct ctree_path *path, struct key *key,
+ struct ctree_path *path, struct btrfs_disk_key *key,
int level)
{
int i;
push_items = src_nritems;
memcpy(dst->keys + dst_nritems, src->keys,
- push_items * sizeof(struct key));
+ push_items * sizeof(struct btrfs_disk_key));
memcpy(dst->blockptrs + dst_nritems, src->blockptrs,
push_items * sizeof(u64));
if (push_items < src_nritems) {
memmove(src->keys, src->keys + push_items,
- (src_nritems - push_items) * sizeof(struct key));
+ (src_nritems - push_items) *
+ sizeof(struct btrfs_disk_key));
memmove(src->blockptrs, src->blockptrs + push_items,
(src_nritems - push_items) * sizeof(u64));
}
push_items = max_push;
memmove(dst->keys + push_items, dst->keys,
- dst_nritems * sizeof(struct key));
+ dst_nritems * sizeof(struct btrfs_disk_key));
memmove(dst->blockptrs + push_items, dst->blockptrs,
dst_nritems * sizeof(u64));
memcpy(dst->keys, src->keys + src_nritems - push_items,
- push_items * sizeof(struct key));
+ push_items * sizeof(struct btrfs_disk_key));
memcpy(dst->blockptrs, src->blockptrs + src_nritems - push_items,
push_items * sizeof(u64));
struct tree_buffer *t;
struct node *lower;
struct node *c;
- struct key *lower_key;
+ struct btrfs_disk_key *lower_key;
BUG_ON(path->nodes[level]);
BUG_ON(path->nodes[level-1] != root->node);
lower_key = &((struct leaf *)lower)->items[0].key;
else
lower_key = lower->keys;
- memcpy(c->keys, lower_key, sizeof(struct key));
+ memcpy(c->keys, lower_key, sizeof(struct btrfs_disk_key));
c->blockptrs[0] = path->nodes[level-1]->blocknr;
/* the super has an extra ref to root->node */
tree_block_release(root, root->node);
* returns zero on success and < 0 on any error
*/
static int insert_ptr(struct ctree_root *root,
- struct ctree_path *path, struct key *key,
+ struct ctree_path *path, struct btrfs_disk_key *key,
u64 blocknr, int slot, int level)
{
struct node *lower;
BUG();
if (slot != nritems) {
memmove(lower->keys + slot + 1, lower->keys + slot,
- (nritems - slot) * sizeof(struct key));
+ (nritems - slot) * sizeof(struct btrfs_disk_key));
memmove(lower->blockptrs + slot + 1, lower->blockptrs + slot,
(nritems - slot) * sizeof(u64));
}
- memcpy(lower->keys + slot, key, sizeof(struct key));
+ memcpy(lower->keys + slot, key, sizeof(struct btrfs_disk_key));
lower->blockptrs[slot] = blocknr;
btrfs_set_header_nritems(&lower->header, nritems + 1);
if (lower->keys[1].objectid == 0)
btrfs_header_parentid(&root->node->node.header));
mid = (c_nritems + 1) / 2;
memcpy(split->keys, c->keys + mid,
- (c_nritems - mid) * sizeof(struct key));
+ (c_nritems - mid) * sizeof(struct btrfs_disk_key));
memcpy(split->blockptrs, c->blockptrs + mid,
(c_nritems - mid) * sizeof(u64));
btrfs_set_header_nritems(&split->header, c_nritems - mid);
BUG_ON(list_empty(&left_buf->dirty));
BUG_ON(list_empty(&right_buf->dirty));
memcpy(upper->node.keys + slot + 1,
- &right->items[0].key, sizeof(struct key));
+ &right->items[0].key, sizeof(struct btrfs_disk_key));
BUG_ON(list_empty(&upper->dirty));
/* then fixup the leaf pointer in the path */
* Given a key and some data, insert an item into the tree.
* This does all the path init required, making room in the tree if needed.
*/
-int insert_item(struct ctree_root *root, struct key *key,
+int insert_item(struct ctree_root *root, struct btrfs_key *cpu_key,
void *data, int data_size)
{
int ret = 0;
u32 nritems;
unsigned int data_end;
struct ctree_path path;
+ struct btrfs_disk_key disk_key;
+
+ btrfs_cpu_key_to_disk(&disk_key, cpu_key);
/* create a root if there isn't one */
if (!root->node)
BUG();
init_path(&path);
- ret = search_slot(root, key, &path, data_size, 1);
+ ret = search_slot(root, cpu_key, &path, data_size, 1);
if (ret == 0) {
release_path(root, &path);
return -EEXIST;
data_end = old_data;
}
/* copy the new data in */
- memcpy(&leaf->items[slot].key, key, sizeof(struct key));
+ memcpy(&leaf->items[slot].key, &disk_key,
+ sizeof(struct btrfs_disk_key));
leaf->items[slot].offset = data_end - data_size;
leaf->items[slot].size = data_size;
memcpy(leaf->data + data_end - data_size, data, data_size);
ret = 0;
if (slot == 0)
- ret = fixup_low_keys(root, &path, key, 1);
+ ret = fixup_low_keys(root, &path, &disk_key, 1);
BUG_ON(list_empty(&leaf_buf->dirty));
if (leaf_free_space(leaf) < 0)
nritems = btrfs_header_nritems(&node->header);
if (slot != nritems -1) {
memmove(node->keys + slot, node->keys + slot + 1,
- sizeof(struct key) * (nritems - slot - 1));
+ sizeof(struct btrfs_disk_key) * (nritems - slot - 1));
memmove(node->blockptrs + slot,
node->blockptrs + slot + 1,
sizeof(u64) * (nritems - slot - 1));
#define __CTREE__
#include "list.h"
+#include "kerncompat.h"
#define CTREE_BLOCKSIZE 1024
* may point to extents.
*
* offset is the starting byte offset for this key in the stream.
+ *
+ * btrfs_disk_key is in disk byte order. struct btrfs_key is always
+ * in cpu native order. Otherwise they are identical and their sizes
+ * should be the same (ie both packed)
*/
-struct key {
+struct btrfs_disk_key {
+ __le64 objectid;
+ __le32 flags;
+ __le64 offset;
+} __attribute__ ((__packed__));
+
+struct btrfs_key {
u64 objectid;
u32 flags;
u64 offset;
#define MAX_LEVEL 8
#define NODEPTRS_PER_BLOCK ((CTREE_BLOCKSIZE - sizeof(struct btrfs_header)) / \
- (sizeof(struct key) + sizeof(u64)))
+ (sizeof(struct btrfs_disk_key) + sizeof(u64)))
struct tree_buffer;
struct tree_buffer *node;
struct tree_buffer *commit_root;
struct ctree_root *extent_root;
- struct key current_insert;
- struct key last_insert;
+ struct btrfs_key current_insert;
+ struct btrfs_key last_insert;
int fp;
struct radix_tree_root cache_radix;
struct radix_tree_root pinned_radix;
* the item in the leaf (relative to the start of the data area)
*/
struct item {
- struct key key;
+ struct btrfs_disk_key key;
u16 offset;
u16 size;
} __attribute__ ((__packed__));
*/
struct node {
struct btrfs_header header;
- struct key keys[NODEPTRS_PER_BLOCK];
+ struct btrfs_disk_key keys[NODEPTRS_PER_BLOCK];
u64 blockptrs[NODEPTRS_PER_BLOCK];
} __attribute__ ((__packed__));
int slots[MAX_LEVEL];
};
+static inline void btrfs_disk_key_to_cpu(struct btrfs_key *cpu,
+ struct btrfs_disk_key *disk)
+{
+ cpu->offset = le64_to_cpu(disk->offset);
+ cpu->flags = le32_to_cpu(disk->flags);
+ cpu->objectid = le64_to_cpu(disk->objectid);
+}
+
+static inline void btrfs_cpu_key_to_disk(struct btrfs_disk_key *disk,
+ struct btrfs_key *cpu)
+{
+ disk->offset = cpu_to_le64(cpu->offset);
+ disk->flags = cpu_to_le32(cpu->flags);
+ disk->objectid = cpu_to_le64(cpu->objectid);
+}
+
+static inline u64 btrfs_key_objectid(struct btrfs_disk_key *disk)
+{
+ return le64_to_cpu(disk->objectid);
+}
+
+static inline void btrfs_set_key_objectid(struct btrfs_disk_key *disk,
+ u64 val)
+{
+ disk->objectid = cpu_to_le64(val);
+}
+
+static inline u64 btrfs_key_offset(struct btrfs_disk_key *disk)
+{
+ return le64_to_cpu(disk->offset);
+}
+
+static inline void btrfs_set_key_offset(struct btrfs_disk_key *disk,
+ u64 val)
+{
+ disk->offset = cpu_to_le64(val);
+}
+
+static inline u32 btrfs_key_flags(struct btrfs_disk_key *disk)
+{
+ return le32_to_cpu(disk->flags);
+}
+
+static inline void btrfs_set_key_flags(struct btrfs_disk_key *disk,
+ u32 val)
+{
+ disk->flags = cpu_to_le32(val);
+}
+
static inline u64 btrfs_header_blocknr(struct btrfs_header *h)
{
return le64_to_cpu(h->blocknr);
struct tree_buffer *alloc_free_block(struct ctree_root *root);
int btrfs_inc_ref(struct ctree_root *root, struct tree_buffer *buf);
int free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks);
-int search_slot(struct ctree_root *root, struct key *key, struct ctree_path *p, int ins_len, int cow);
+int search_slot(struct ctree_root *root, struct btrfs_key *key,
+ struct ctree_path *p, int ins_len, int cow);
void release_path(struct ctree_root *root, struct ctree_path *p);
void init_path(struct ctree_path *p);
int del_item(struct ctree_root *root, struct ctree_path *path);
-int insert_item(struct ctree_root *root, struct key *key, void *data, int data_size);
+int insert_item(struct ctree_root *root, struct btrfs_key *key,
+ void *data, int data_size);
int next_leaf(struct ctree_root *root, struct ctree_path *path);
int leaf_free_space(struct leaf *leaf);
int btrfs_drop_snapshot(struct ctree_root *root, struct tree_buffer *snap);
#include "print-tree.h"
static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks,
- u64 search_start, u64 search_end, struct key *ins);
+ u64 search_start, u64 search_end,
+ struct btrfs_key *ins);
static int finish_current_insert(struct ctree_root *extent_root);
static int run_pending(struct ctree_root *extent_root);
{
struct ctree_path path;
int ret;
- struct key key;
+ struct btrfs_key key;
struct leaf *l;
struct extent_item *item;
- struct key ins;
+ struct btrfs_key ins;
find_free_extent(root->extent_root, 0, 0, (u64)-1, &ins);
init_path(&path);
{
struct ctree_path path;
int ret;
- struct key key;
+ struct btrfs_key key;
struct leaf *l;
struct extent_item *item;
init_path(&path);
static int finish_current_insert(struct ctree_root *extent_root)
{
- struct key ins;
+ struct btrfs_key ins;
struct extent_item extent_item;
int i;
int ret;
int __free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks)
{
struct ctree_path path;
- struct key key;
+ struct btrfs_key key;
struct ctree_root *extent_root = root->extent_root;
int ret;
struct item *item;
struct extent_item *ei;
- struct key ins;
+ struct btrfs_key ins;
key.objectid = blocknr;
key.flags = 0;
*/
int free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks)
{
- struct key key;
+ struct btrfs_key key;
struct ctree_root *extent_root = root->extent_root;
struct tree_buffer *t;
int pending_ret;
* Any available blocks before search_start are skipped.
*/
static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks,
- u64 search_start, u64 search_end, struct key *ins)
+ u64 search_start, u64 search_end,
+ struct btrfs_key *ins)
{
struct ctree_path path;
- struct key *key;
+ struct btrfs_key key;
int ret;
u64 hole_size = 0;
int slot = 0;
ins->offset = (u64)-1;
goto check_pending;
}
- key = &l->items[slot].key;
- if (key->objectid >= search_start) {
+ btrfs_disk_key_to_cpu(&key, &l->items[slot].key);
+ if (key.objectid >= search_start) {
if (start_found) {
if (last_block < search_start)
last_block = search_start;
- hole_size = key->objectid - last_block;
+ hole_size = key.objectid - last_block;
if (hole_size > total_needed) {
ins->objectid = last_block;
ins->offset = hole_size;
}
}
start_found = 1;
- last_block = key->objectid + key->offset;
+ last_block = key.objectid + key.offset;
path.slots[0]++;
}
// FIXME -ENOSPC
* returns 0 if everything worked, non-zero otherwise.
*/
int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start,
- u64 search_end, u64 owner, struct key *ins)
+ u64 search_end, u64 owner, struct btrfs_key *ins)
{
int ret;
int pending_ret;
*/
struct tree_buffer *alloc_free_block(struct ctree_root *root)
{
- struct key ins;
+ struct btrfs_key ins;
int ret;
struct tree_buffer *buf;