diff --git a/kmod/src/btree.c b/kmod/src/btree.c index 0a7405b4..0aa2edd6 100644 --- a/kmod/src/btree.c +++ b/kmod/src/btree.c @@ -84,32 +84,22 @@ enum { BTW_DELETE = (1 << 7), /* walking to delete, try merging */ }; -/* - * This greatest key value is stored down the right spine of the tree - * and has to be sorted by memcmp() greater than all possible keys in - * all btrees. - */ -static char max_key[SCOUTFS_BTREE_MAX_KEY_LEN] = { - [0 ... (SCOUTFS_BTREE_MAX_KEY_LEN - 1)] = 0xff, -}; - -/* number of contiguous bytes used by the item header, key, and value */ -static inline unsigned int len_bytes(unsigned key_len, unsigned val_len) +/* number of contiguous bytes used by the item and it's value */ +static inline unsigned int len_bytes(unsigned val_len) { - return sizeof(struct scoutfs_btree_item) + key_len + val_len; + return sizeof(struct scoutfs_btree_item) + val_len; } /* number of contiguous bytes used an existing item */ static inline unsigned int item_bytes(struct scoutfs_btree_item *item) { - return len_bytes(le16_to_cpu(item->key_len), le16_to_cpu(item->val_len)); + return len_bytes(le16_to_cpu(item->val_len)); } /* total block bytes used by an item: header, item, key, value */ -static inline unsigned int all_len_bytes(unsigned key_len, unsigned val_len) +static inline unsigned int all_len_bytes(unsigned val_len) { - return sizeof(struct scoutfs_btree_item_header) + - len_bytes(key_len, val_len); + return sizeof(struct scoutfs_btree_item_header) + len_bytes(val_len); } /* @@ -138,8 +128,7 @@ static inline int min_used_bytes(int block_size) /* total block bytes used by an existing item */ static inline unsigned int all_item_bytes(struct scoutfs_btree_item *item) { - return all_len_bytes(le16_to_cpu(item->key_len), - le16_to_cpu(item->val_len)); + return all_len_bytes(le16_to_cpu(item->val_len)); } /* number of free bytes between last item header and first item */ @@ -176,19 +165,14 @@ last_item(struct scoutfs_btree_block *bt) return pos_item(bt, le32_to_cpu(bt->nr_items) - 1); } -static inline void *item_key(struct scoutfs_btree_item *item) +static inline struct scoutfs_key *item_key(struct scoutfs_btree_item *item) { - return item->data; -} - -static inline unsigned item_key_len(struct scoutfs_btree_item *item) -{ - return le16_to_cpu(item->key_len); + return &item->key; } static inline void *item_val(struct scoutfs_btree_item *item) { - return item_key(item) + le16_to_cpu(item->key_len); + return item->val; } static inline unsigned item_val_len(struct scoutfs_btree_item *item) @@ -196,12 +180,6 @@ static inline unsigned item_val_len(struct scoutfs_btree_item *item) return le16_to_cpu(item->val_len); } -static inline int cmp_keys(void *a, unsigned a_len, void *b, unsigned b_len) -{ - return memcmp(a, b, min(a_len, b_len)) ?: - a_len < b_len ? -1 : a_len > b_len ? 1 : 0; -} - /* * Returns the sorted item position that an item with the given key * should occupy. @@ -213,7 +191,7 @@ static inline int cmp_keys(void *a, unsigned a_len, void *b, unsigned b_len) * If the given key is greater then all items' keys then the number of * items can be returned. */ -static int find_pos(struct scoutfs_btree_block *bt, void *key, unsigned key_len, +static int find_pos(struct scoutfs_btree_block *bt, struct scoutfs_key *key, int *cmp) { struct scoutfs_btree_item *item; @@ -227,7 +205,7 @@ static int find_pos(struct scoutfs_btree_block *bt, void *key, unsigned key_len, pos = start + (end - start) / 2; item = pos_item(bt, pos); - *cmp = cmp_keys(key, key_len, item_key(item), item_key_len(item)); + *cmp = scoutfs_key_compare(key, item_key(item)); if (*cmp < 0) { end = pos; } else if (*cmp > 0) { @@ -250,20 +228,19 @@ static int find_pos(struct scoutfs_btree_block *bt, void *key, unsigned key_len, * there's space for the item and its metadata. */ static void create_item(struct scoutfs_btree_block *bt, unsigned int pos, - void *key, unsigned key_len, void *val, - unsigned val_len) + struct scoutfs_key *key, void *val, unsigned val_len) { unsigned int nr = le32_to_cpu(bt->nr_items); struct scoutfs_btree_item *item; unsigned all_bytes; - all_bytes = all_len_bytes(key_len, val_len); + all_bytes = all_len_bytes(val_len); BUG_ON(free_bytes(bt) < all_bytes); if (pos < nr) memmove_arr(bt->item_hdrs, pos + 1, pos, nr - pos); - le32_add_cpu(&bt->free_end, -len_bytes(key_len, val_len)); + le32_add_cpu(&bt->free_end, -len_bytes(val_len)); bt->item_hdrs[pos].off = bt->free_end; nr++; bt->nr_items = cpu_to_le32(nr); @@ -272,10 +249,9 @@ static void create_item(struct scoutfs_btree_block *bt, unsigned int pos, offsetof(struct scoutfs_btree_block, item_hdrs[nr])); item = pos_item(bt, pos); - item->key_len = cpu_to_le16(key_len); + *item_key(item) = *key; item->val_len = cpu_to_le16(val_len); - memcpy(item_key(item), key, key_len); if (val_len) memcpy(item_val(item), val, val_len); } @@ -361,8 +337,8 @@ static void move_items(struct scoutfs_btree_block *dst, while (f < le32_to_cpu(src->nr_items) && to_move > 0) { from = pos_item(src, f); - create_item(dst, t, item_key(from), item_key_len(from), - item_val(from), item_val_len(from)); + create_item(dst, t, item_key(from), item_val(from), + item_val_len(from)); to_move -= all_item_bytes(from); @@ -522,14 +498,14 @@ out: */ static void create_parent_item(struct scoutfs_btree_block *parent, unsigned pos, struct scoutfs_btree_block *child, - void *key, unsigned key_len) + struct scoutfs_key *key) { struct scoutfs_btree_ref ref = { .blkno = child->hdr.blkno, .seq = child->hdr.seq, }; - create_item(parent, pos, key, key_len, &ref, sizeof(ref)); + create_item(parent, pos, key, &ref, sizeof(ref)); } /* @@ -543,8 +519,7 @@ static void update_parent_item(struct scoutfs_btree_block *parent, struct scoutfs_btree_item *item = last_item(child); delete_item(parent, pos); - create_parent_item(parent, pos, child, - item_key(item), item_key_len(item)); + create_parent_item(parent, pos, child, item_key(item)); } /* @@ -562,7 +537,7 @@ static int try_split(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - void *key, unsigned key_len, unsigned val_len, + struct scoutfs_key *key, unsigned val_len, struct scoutfs_btree_block *parent, unsigned pos, struct scoutfs_btree_block *right) { @@ -570,6 +545,7 @@ static int try_split(struct super_block *sb, struct scoutfs_block *par_bl = NULL; struct scoutfs_btree_block *left; struct scoutfs_btree_item *item; + struct scoutfs_key max_key; unsigned int all_bytes; int ret; int err; @@ -579,7 +555,7 @@ static int try_split(struct super_block *sb, else if (right->level) all_bytes = SCOUTFS_BTREE_PARENT_MIN_FREE_BYTES; else - all_bytes = all_len_bytes(key_len, val_len); + all_bytes = all_len_bytes(val_len); if (free_bytes(right) >= all_bytes) return 0; @@ -608,16 +584,16 @@ static int try_split(struct super_block *sb, root->ref.blkno = parent->hdr.blkno; root->ref.seq = parent->hdr.seq; + scoutfs_key_set_ones(&max_key); + pos = 0; - create_parent_item(parent, pos, right, - &max_key, sizeof(max_key)); + create_parent_item(parent, pos, right, &max_key); } move_items(left, right, false, used_total(right) / 2); item = last_item(left); - create_parent_item(parent, pos, left, - item_key(item), item_key_len(item)); + create_parent_item(parent, pos, left, item_key(item)); scoutfs_block_put(sb, left_bl); scoutfs_block_put(sb, par_bl); @@ -751,8 +727,8 @@ static int verify_btree_block(struct scoutfs_btree_block *bt, int level) item = pos_item(bt, i); bytes += item_bytes(item); - if (i > 0 && cmp_keys(item_key(item), item_key_len(item), - item_key(prev), item_key_len(prev)) <= 0) + if (i > 0 && scoutfs_key_compare(item_key(item), + item_key(prev)) <= 0) goto out; prev = item; @@ -773,9 +749,9 @@ out: after_off, bytes); for (i = 0; i < nr; i++) { item = pos_item(bt, i); - printk(" [%u] off %u key_len %u val_len %u\n", + printk(" [%u] off %u val_len %u\n", i, le32_to_cpu(bt->item_hdrs[i].off), - item_key_len(item), item_val_len(item)); + item_val_len(item)); } BUG_ON(bad); } @@ -783,22 +759,6 @@ out: return 0; } -/* XXX bleh, this should probably share code with the key_buf equivalent */ -static void inc_key(u8 *bytes, unsigned *len) -{ - int i; - - if (*len < SCOUTFS_BTREE_MAX_KEY_LEN) { - memset(bytes + *len, 0, SCOUTFS_BTREE_MAX_KEY_LEN - *len); - *len = SCOUTFS_BTREE_MAX_KEY_LEN; - } - - for (i = *len - 1; i >= 0; i--) { - if (++bytes[i] != 0) - break; - } -} - /* * Return the leaf block that should contain the given key. The caller * is responsible for searching the leaf block and performing their @@ -819,10 +779,10 @@ static int btree_walk(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - int flags, void *key, unsigned key_len, + int flags, struct scoutfs_key *key, unsigned int val_len, - struct scoutfs_block **bl_ret, void *iter_key, - unsigned *iter_len) + struct scoutfs_block **bl_ret, + struct scoutfs_key *iter_key) { struct scoutfs_block *par_bl = NULL; struct scoutfs_block *bl = NULL; @@ -848,8 +808,6 @@ restart: bl = NULL; bt = NULL; level = root->height; - if (iter_len) - *iter_len = 0; pos = 0; ret = 0; @@ -906,8 +864,8 @@ restart: */ ret = 0; if (flags & (BTW_INSERT | BTW_DELETE)) - ret = try_split(sb, alloc, wri, root, key, key_len, - val_len, parent, pos, bt); + ret = try_split(sb, alloc, wri, root, key, val_len, + parent, pos, bt); if (ret == 0 && (flags & BTW_DELETE) && parent) ret = try_merge(sb, alloc, wri, root, parent, pos, bt); if (ret > 0) @@ -922,7 +880,7 @@ restart: nr = le32_to_cpu(bt->nr_items); /* Find the next child block for the search key. */ - pos = find_pos(bt, key, key_len, &cmp); + pos = find_pos(bt, key, &cmp); if (pos >= nr) { scoutfs_corruption(sb, SC_BTREE_NO_CHILD_REF, corrupt_btree_block_level, @@ -940,14 +898,12 @@ restart: /* give the caller the next key to iterate towards */ if (iter_key && (flags & BTW_NEXT) && (pos < (nr - 1))) { item = pos_item(bt, pos); - *iter_len = item_key_len(item); - memcpy(iter_key, item_key(item), *iter_len); - inc_key(iter_key, iter_len); + *iter_key = *item_key(item); + scoutfs_key_inc(iter_key); } else if (iter_key && (flags & BTW_PREV) && (pos > 0)) { item = pos_item(bt, pos - 1); - *iter_len = item_key_len(item); - memcpy(iter_key, item_key(item), *iter_len); + *iter_key = *item_key(item); } scoutfs_block_put(sb, par_bl); @@ -982,7 +938,6 @@ static void init_item_ref(struct scoutfs_btree_item_ref *iref, iref->sb = sb; iref->bl = bl; iref->key = item_key(item); - iref->key_len = le16_to_cpu(item->key_len); iref->val = item_val(item); iref->val_len = le16_to_cpu(item->val_len); } @@ -1000,8 +955,9 @@ void scoutfs_btree_put_iref(struct scoutfs_btree_item_ref *iref) * item ref. They're given a reference to the block that they'll drop * when they're done. */ -int scoutfs_btree_lookup(struct super_block *sb, struct scoutfs_btree_root *root, - void *key, unsigned key_len, +int scoutfs_btree_lookup(struct super_block *sb, + struct scoutfs_btree_root *root, + struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref) { struct scoutfs_btree_item *item; @@ -1014,11 +970,10 @@ int scoutfs_btree_lookup(struct super_block *sb, struct scoutfs_btree_root *root if (WARN_ON_ONCE(iref->key)) return -EINVAL; - ret = btree_walk(sb, NULL, NULL, root, 0, key, key_len, 0, &bl, - NULL, NULL); + ret = btree_walk(sb, NULL, NULL, root, 0, key, 0, &bl, NULL); if (ret == 0) { bt = bl->data; - pos = find_pos(bt, key, key_len, &cmp); + pos = find_pos(bt, key, &cmp); if (cmp == 0) { item = pos_item(bt, pos); init_item_ref(iref, sb, bl, item); @@ -1033,11 +988,9 @@ int scoutfs_btree_lookup(struct super_block *sb, struct scoutfs_btree_root *root return ret; } -static bool invalid_item(void *key, unsigned key_len, unsigned val_len) +static bool invalid_item(unsigned val_len) { - return WARN_ON_ONCE(key_len == 0) || - WARN_ON_ONCE(key_len > SCOUTFS_BTREE_MAX_KEY_LEN) || - WARN_ON_ONCE(val_len > SCOUTFS_BTREE_MAX_VAL_LEN); + return WARN_ON_ONCE(val_len > SCOUTFS_BTREE_MAX_VAL_LEN); } /* @@ -1053,7 +1006,7 @@ int scoutfs_btree_insert(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, void *val, unsigned val_len) { struct scoutfs_btree_block *bt; @@ -1062,16 +1015,16 @@ int scoutfs_btree_insert(struct super_block *sb, int cmp; int ret; - if (invalid_item(key, key_len, val_len)) + if (invalid_item(val_len)) return -EINVAL; - ret = btree_walk(sb, alloc, wri, root, BTW_DIRTY | BTW_INSERT, - key, key_len, val_len, &bl, NULL, NULL); + ret = btree_walk(sb, alloc, wri, root, BTW_DIRTY | BTW_INSERT, key, + val_len, &bl, NULL); if (ret == 0) { bt = bl->data; - pos = find_pos(bt, key, key_len, &cmp); + pos = find_pos(bt, key, &cmp); if (cmp) { - create_item(bt, pos, key, key_len, val, val_len); + create_item(bt, pos, key, val, val_len); ret = 0; } else { ret = -EEXIST; @@ -1097,7 +1050,7 @@ int scoutfs_btree_update(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, void *val, unsigned val_len) { struct scoutfs_btree_block *bt; @@ -1106,17 +1059,17 @@ int scoutfs_btree_update(struct super_block *sb, int cmp; int ret; - if (invalid_item(key, key_len, val_len)) + if (invalid_item(val_len)) return -EINVAL; - ret = btree_walk(sb, alloc, wri, root, BTW_DIRTY | BTW_INSERT, - key, key_len, val_len, &bl, NULL, NULL); + ret = btree_walk(sb, alloc, wri, root, BTW_DIRTY | BTW_INSERT, key, + val_len, &bl, NULL); if (ret == 0) { bt = bl->data; - pos = find_pos(bt, key, key_len, &cmp); + pos = find_pos(bt, key, &cmp); if (cmp == 0) { delete_item(bt, pos); - create_item(bt, pos, key, key_len, val, val_len); + create_item(bt, pos, key, val, val_len); ret = 0; } else { ret = -ENOENT; @@ -1136,7 +1089,7 @@ int scoutfs_btree_force(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, void *val, unsigned val_len) { struct scoutfs_btree_block *bt; @@ -1145,17 +1098,17 @@ int scoutfs_btree_force(struct super_block *sb, int cmp; int ret; - if (invalid_item(key, key_len, val_len)) + if (invalid_item(val_len)) return -EINVAL; - ret = btree_walk(sb, alloc, wri, root, BTW_DIRTY | BTW_INSERT, - key, key_len, val_len, &bl, NULL, NULL); + ret = btree_walk(sb, alloc, wri, root, BTW_DIRTY | BTW_INSERT, key, + val_len, &bl, NULL); if (ret == 0) { bt = bl->data; - pos = find_pos(bt, key, key_len, &cmp); + pos = find_pos(bt, key, &cmp); if (cmp == 0) delete_item(bt, pos); - create_item(bt, pos, key, key_len, val, val_len); + create_item(bt, pos, key, val, val_len); scoutfs_block_put(sb, bl); } @@ -1170,7 +1123,7 @@ int scoutfs_btree_delete(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - void *key, unsigned key_len) + struct scoutfs_key *key) { struct scoutfs_btree_block *bt; struct scoutfs_block *bl; @@ -1178,11 +1131,11 @@ int scoutfs_btree_delete(struct super_block *sb, int cmp; int ret; - ret = btree_walk(sb, alloc, wri, root, BTW_DELETE | BTW_DIRTY, - key, key_len, 0, &bl, NULL, NULL); + ret = btree_walk(sb, alloc, wri, root, BTW_DELETE | BTW_DIRTY, key, + 0, &bl, NULL); if (ret == 0) { bt = bl->data; - pos = find_pos(bt, key, key_len, &cmp); + pos = find_pos(bt, key, &cmp); if (cmp == 0) { if (le32_to_cpu(bt->nr_items) == 1) { /* remove final empty block */ @@ -1220,16 +1173,14 @@ int scoutfs_btree_delete(struct super_block *sb, * blocks. */ static int btree_iter(struct super_block *sb,struct scoutfs_btree_root *root, - int flags, void *key, unsigned key_len, + int flags, struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref) { struct scoutfs_btree_item *item; struct scoutfs_btree_block *bt; struct scoutfs_block *bl; - unsigned iter_len; - unsigned walk_len; - void *iter_key; - void *walk_key; + struct scoutfs_key iter_key; + struct scoutfs_key walk_key; int pos; int cmp; int ret; @@ -1238,24 +1189,17 @@ static int btree_iter(struct super_block *sb,struct scoutfs_btree_root *root, WARN_ON_ONCE(iref->key)) return -EINVAL; - walk_key = kmalloc(SCOUTFS_BTREE_MAX_KEY_LEN, GFP_NOFS); - iter_key = kmalloc(SCOUTFS_BTREE_MAX_KEY_LEN, GFP_NOFS); - if (!walk_key || !iter_key) { - ret = -ENOMEM; - goto out; - } - - memcpy(walk_key, key, key_len); - walk_len = key_len; + walk_key = *key; for (;;) { - ret = btree_walk(sb, NULL, NULL, root, flags, walk_key, - walk_len, 0, &bl, iter_key, &iter_len); + scoutfs_key_set_zeros(&iter_key); + ret = btree_walk(sb, NULL, NULL, root, flags, &walk_key, + 0, &bl, &iter_key); if (ret < 0) break; bt = bl->data; - pos = find_pos(bt, key, key_len, &cmp); + pos = find_pos(bt, key, &cmp); /* point pos towards iteration, find_pos already for _NEXT */ if ((flags & BTW_AFTER) && cmp == 0) @@ -1276,9 +1220,8 @@ static int btree_iter(struct super_block *sb,struct scoutfs_btree_root *root, scoutfs_block_put(sb, bl); /* nothing in this leaf, walk gave us a key */ - if (iter_len > 0) { - memcpy(walk_key, iter_key, iter_len); - walk_len = iter_len; + if (!scoutfs_key_is_zeros(&iter_key)) { + walk_key = iter_key; continue; } @@ -1286,39 +1229,36 @@ static int btree_iter(struct super_block *sb,struct scoutfs_btree_root *root, break; } -out: - kfree(walk_key); - kfree(iter_key); - return ret; } int scoutfs_btree_next(struct super_block *sb, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref) { - return btree_iter(sb, root, BTW_NEXT, key, key_len, iref); + return btree_iter(sb, root, BTW_NEXT, key, iref); } int scoutfs_btree_after(struct super_block *sb, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref) { - return btree_iter(sb, root, BTW_NEXT | BTW_AFTER, key, key_len, iref); + return btree_iter(sb, root, BTW_NEXT | BTW_AFTER, key, iref); } int scoutfs_btree_prev(struct super_block *sb, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref) { - return btree_iter(sb, root, BTW_PREV, key, key_len, iref); + return btree_iter(sb, root, BTW_PREV, key, iref); } -int scoutfs_btree_before(struct super_block *sb, struct scoutfs_btree_root *root, - void *key, unsigned key_len, +int scoutfs_btree_before(struct super_block *sb, + struct scoutfs_btree_root *root, + struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref) { - return btree_iter(sb, root, BTW_PREV | BTW_BEFORE, key, key_len, iref); + return btree_iter(sb, root, BTW_PREV | BTW_BEFORE, key, iref); } /* @@ -1332,18 +1272,17 @@ int scoutfs_btree_dirty(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - void *key, unsigned key_len) + struct scoutfs_key *key) { struct scoutfs_btree_block *bt; struct scoutfs_block *bl; int cmp; int ret; - ret = btree_walk(sb, alloc, wri, root, BTW_DIRTY, key, key_len, 0, &bl, - NULL, NULL); + ret = btree_walk(sb, alloc, wri, root, BTW_DIRTY, key, 0, &bl, NULL); if (ret == 0) { bt = bl->data; - find_pos(bt, key, key_len, &cmp); + find_pos(bt, key, &cmp); if (cmp == 0) ret = 0; else diff --git a/kmod/src/btree.h b/kmod/src/btree.h index e37ab023..133832ba 100644 --- a/kmod/src/btree.h +++ b/kmod/src/btree.h @@ -10,8 +10,7 @@ struct scoutfs_block; struct scoutfs_btree_item_ref { struct super_block *sb; struct scoutfs_block *bl; - void *key; - unsigned key_len; + struct scoutfs_key *key; void *val; unsigned val_len; }; @@ -20,49 +19,51 @@ struct scoutfs_btree_item_ref { struct scoutfs_btree_item_ref name = {NULL,} -int scoutfs_btree_lookup(struct super_block *sb, struct scoutfs_btree_root *root, - void *key, unsigned key_len, +int scoutfs_btree_lookup(struct super_block *sb, + struct scoutfs_btree_root *root, + struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref); int scoutfs_btree_insert(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, void *val, unsigned val_len); int scoutfs_btree_update(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, void *val, unsigned val_len); int scoutfs_btree_force(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, void *val, unsigned val_len); int scoutfs_btree_delete(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - void *key, unsigned key_len); + struct scoutfs_key *key); int scoutfs_btree_next(struct super_block *sb, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref); int scoutfs_btree_after(struct super_block *sb, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref); int scoutfs_btree_prev(struct super_block *sb, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref); -int scoutfs_btree_before(struct super_block *sb, struct scoutfs_btree_root *root, - void *key, unsigned key_len, +int scoutfs_btree_before(struct super_block *sb, + struct scoutfs_btree_root *root, + struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref); int scoutfs_btree_dirty(struct super_block *sb, struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, - void *key, unsigned key_len); + struct scoutfs_key *key); void scoutfs_btree_put_iref(struct scoutfs_btree_item_ref *iref); diff --git a/kmod/src/forest.c b/kmod/src/forest.c index bcb7b809..af44204e 100644 --- a/kmod/src/forest.c +++ b/kmod/src/forest.c @@ -301,7 +301,6 @@ static int refresh_bloom_roots(struct super_block *sb, { DECLARE_FOREST_INFO(sb, finf); struct forest_lock_private *lpriv = ACCESS_ONCE(lock->forest_private); - struct scoutfs_log_trees_key ltk; struct scoutfs_log_trees_val ltv; SCOUTFS_BTREE_ITEM_REF(iref); struct forest_bloom_nrs bloom; @@ -309,6 +308,7 @@ static int refresh_bloom_roots(struct super_block *sb, struct forest_root *fr = NULL; struct scoutfs_bloom_block *bb; struct scoutfs_block *bl; + struct scoutfs_key key; int ret; int i; @@ -328,11 +328,10 @@ static int refresh_bloom_roots(struct super_block *sb, calc_bloom_nrs(&bloom, &lock->start); - memset(<k, 0, sizeof(ltk)); - for (;; be64_add_cpu(<k.nr, 1)) { + scoutfs_key_init_log_trees(&key, 0, 0); + for (;; scoutfs_key_inc(&key)) { - ret = scoutfs_btree_next(sb, &super.logs_root, - <k, sizeof(ltk), &iref); + ret = scoutfs_btree_next(sb, &super.logs_root, &key, &iref); if (ret == -ENOENT) { ret = 0; break; @@ -340,9 +339,8 @@ static int refresh_bloom_roots(struct super_block *sb, if (ret < 0) goto out; - if (iref.key_len == sizeof(struct scoutfs_log_trees_key) && - iref.val_len == sizeof(struct scoutfs_log_trees_val)) { - memcpy(<k, iref.key, iref.key_len); + if (iref.val_len == sizeof(struct scoutfs_log_trees_val)) { + key = *iref.key; memcpy(<v, iref.val, iref.val_len); } else { ret = -EIO; @@ -369,8 +367,8 @@ static int refresh_bloom_roots(struct super_block *sb, scoutfs_block_put(sb, bl); trace_scoutfs_forest_bloom_search(sb, &lock->start, - be64_to_cpu(ltk.rid), - be64_to_cpu(ltk.nr), + le64_to_cpu(key.sklt_rid), + le64_to_cpu(key.sklt_nr), le64_to_cpu(ltv.bloom_ref.blkno), le64_to_cpu(ltv.bloom_ref.seq), i); @@ -380,8 +378,8 @@ static int refresh_bloom_roots(struct super_block *sb, continue; /* use our dirty log instead of the old committed version */ - if (be64_to_cpu(ltk.rid) == le64_to_cpu(finf->our_log.rid) && - be64_to_cpu(ltk.nr) == le64_to_cpu(finf->our_log.nr)) { + if (key.sklt_rid == finf->our_log.rid && + key.sklt_nr == finf->our_log.nr) { add_our_log_root(finf, lpriv); continue; } @@ -394,8 +392,8 @@ static int refresh_bloom_roots(struct super_block *sb, } fr->item_root = ltv.item_root; - fr->rid = be64_to_cpu(ltk.rid); - fr->nr = be64_to_cpu(ltk.nr); + fr->rid = le64_to_cpu(key.sklt_rid); + fr->nr = le64_to_cpu(key.sklt_nr); list_add_tail(&fr->entry, &lpriv->roots); @@ -568,7 +566,6 @@ int scoutfs_forest_lookup(struct super_block *sb, struct scoutfs_key *key, DECLARE_STALE_TRACKING_SUPER_REFS(prev_srefs, srefs); struct forest_lock_private *lpriv; SCOUTFS_BTREE_ITEM_REF(iref); - struct scoutfs_key_be kbe; struct forest_root *fr; u64 found_vers; u64 vers; @@ -584,8 +581,6 @@ int scoutfs_forest_lookup(struct super_block *sb, struct scoutfs_key *key, goto out; } - scoutfs_key_to_be(&kbe, key); - retry: down_read(&lpriv->rwsem); @@ -600,8 +595,7 @@ retry: break; read_lock_forest_root(finf, lpriv, fr); - err = scoutfs_btree_lookup(sb, &fr->item_root, - &kbe, sizeof(kbe), &iref); + err = scoutfs_btree_lookup(sb, &fr->item_root, key, &iref); if (err < 0) read_unlock_forest_root(finf, lpriv, fr); if (err == -ENOENT) @@ -705,14 +699,14 @@ static inline bool forest_iter_key_within(struct scoutfs_key *a, static inline int forest_iter_btree_search(struct super_block *sb, struct scoutfs_btree_root *root, - void *key, unsigned key_len, + struct scoutfs_key *key, struct scoutfs_btree_item_ref *iref, bool forward) { if (forward) - return scoutfs_btree_next(sb, root, key, key_len, iref); + return scoutfs_btree_next(sb, root, key, iref); else - return scoutfs_btree_prev(sb, root, key, key_len, iref); + return scoutfs_btree_prev(sb, root, key, iref); } struct forest_iter_pos { @@ -835,7 +829,6 @@ static int forest_iter(struct super_block *sb, struct scoutfs_key *key, SCOUTFS_BTREE_ITEM_REF(iref); struct rb_root iter_root = RB_ROOT; struct scoutfs_key found_key; - struct scoutfs_key_be kbe; struct forest_iter_pos *nip; struct forest_iter_pos *ip; struct forest_root *fr; @@ -896,12 +889,9 @@ retry: /* search for the next item in the root */ if (ip->vers == 0) { - scoutfs_key_to_be(&kbe, &ip->key); - read_lock_forest_root(finf, lpriv, fr); ret = forest_iter_btree_search(sb, &fr->item_root, - &kbe, sizeof(kbe), - &iref, fwd); + &ip->key, &iref, fwd); if (ret < 0) read_unlock_forest_root(finf, lpriv, fr); if (ret == -ENOENT) { @@ -911,7 +901,7 @@ retry: if (ret < 0) goto unlock; - scoutfs_key_from_be(&ip->key, iref.key); + ip->key = *iref.key; ip->vers = item_vers(lpriv, fr, iref.val); ip->deletion = item_is_deletion(lpriv, fr, iref.val); @@ -1026,11 +1016,10 @@ int scoutfs_forest_next_hint(struct super_block *sb, struct scoutfs_key *key, { DECLARE_STALE_TRACKING_SUPER_REFS(prev_srefs, srefs); struct scoutfs_super_block super; - struct scoutfs_log_trees_key ltk; struct scoutfs_log_trees_val ltv; SCOUTFS_BTREE_ITEM_REF(iref); - struct scoutfs_key_be kbe; struct scoutfs_key found; + struct scoutfs_key ltk; bool have_next; int ret; @@ -1042,13 +1031,12 @@ retry: srefs.fs_ref = super.fs_root.ref; srefs.logs_ref = super.logs_root.ref; - memset(<k, 0, sizeof(ltk)); + scoutfs_key_init_log_trees(<k, 0, 0); have_next = false; - for (;; be64_add_cpu(<k.nr, 1)) { + for (;; scoutfs_key_inc(<k)) { - ret = scoutfs_btree_next(sb, &super.logs_root, - <k, sizeof(ltk), &iref); + ret = scoutfs_btree_next(sb, &super.logs_root, <k, &iref); if (ret == -ENOENT) { if (have_next) ret = 0; @@ -1059,9 +1047,8 @@ retry: if (ret < 0) goto out; - if (iref.key_len == sizeof(ltk) && - iref.val_len == sizeof(ltv)) { - memcpy(<k, iref.key, iref.key_len); + if (iref.val_len == sizeof(ltv)) { + ltk = *iref.key; memcpy(<v, iref.val, iref.val_len); } else { ret = -EIO; @@ -1070,9 +1057,7 @@ retry: if (ret < 0) goto out; - scoutfs_key_to_be(&kbe, key); - ret = scoutfs_btree_next(sb, <v.item_root, - &kbe, sizeof(kbe), &iref); + ret = scoutfs_btree_next(sb, <v.item_root, key, &iref); if (ret == -ENOENT) continue; if (ret == -ESTALE) @@ -1080,13 +1065,8 @@ retry: if (ret < 0) goto out; - if (iref.key_len == sizeof(kbe)) - scoutfs_key_from_be(&found, iref.key); - else - ret = -EIO; + found = *iref.key; scoutfs_btree_put_iref(&iref); - if (ret < 0) - goto out; if (!have_next || scoutfs_key_compare(&found, next) < 0) { have_next = true; @@ -1274,7 +1254,6 @@ static int forest_insert(struct super_block *sb, struct scoutfs_key *key, bool check_eexist, bool check_enoent) { DECLARE_FOREST_INFO(sb, finf); - struct scoutfs_key_be kbe; struct kvec *iv = NULL; int ret; @@ -1303,11 +1282,9 @@ static int forest_insert(struct super_block *sb, struct scoutfs_key *key, goto out; } - scoutfs_key_to_be(&kbe, key); - down_write(&finf->rwsem); ret = scoutfs_btree_force(sb, finf->alloc, finf->wri, - &finf->our_log.item_root, &kbe, sizeof(kbe), + &finf->our_log.item_root, key, iv->iov_base, iv->iov_len); up_write(&finf->rwsem); kfree(iv); @@ -1372,7 +1349,6 @@ static int forest_delete(struct super_block *sb, struct scoutfs_key *key, { DECLARE_FOREST_INFO(sb, finf); struct scoutfs_log_item_value liv; - struct scoutfs_key_be kbe; int ret; if (check_enoent) { @@ -1385,14 +1361,13 @@ static int forest_delete(struct super_block *sb, struct scoutfs_key *key, if (ret < 0) goto out; - scoutfs_key_to_be(&kbe, key); liv.vers = cpu_to_le64(lock->write_version); liv.flags = SCOUTFS_LOG_ITEM_FLAG_DELETION; down_write(&finf->rwsem); ret = scoutfs_btree_force(sb, finf->alloc, finf->wri, - &finf->our_log.item_root, - &kbe, sizeof(kbe), &liv, sizeof(liv)); + &finf->our_log.item_root, key, &liv, + sizeof(liv)); up_write(&finf->rwsem); out: return ret; diff --git a/kmod/src/format.h b/kmod/src/format.h index 493a4ae3..740a64fb 100644 --- a/kmod/src/format.h +++ b/kmod/src/format.h @@ -133,6 +133,20 @@ struct scoutfs_key { #define skpe_base _sk_second #define skpe_part _sk_fourth +/* log trees */ +#define sklt_rid _sk_first +#define sklt_nr _sk_second + +/* lock clients */ +#define sklc_rid _sk_first + +/* seqs */ +#define skts_trans_seq _sk_first +#define skts_rid _sk_second + +/* mounted clients */ +#define skmc_rid _sk_first + struct scoutfs_radix_block { struct scoutfs_block_header hdr; __le32 sm_first; @@ -170,34 +184,17 @@ struct scoutfs_radix_root { ~(__u64)SCOUTFS_RADIX_LG_MASK) #define SCOUTFS_RADIX_BITS_BYTES (SCOUTFS_RADIX_BITS / 8) -/* - * The btree still uses memcmp() to compare keys. We should fix that - * before too long. - */ -struct scoutfs_key_be { - __u8 sk_zone; - __be64 _sk_first; - __u8 sk_type; - __be64 _sk_second; - __be64 _sk_third; - __u8 _sk_fourth; -}__packed; - -/* chose reasonable max key lens that have room for some u64s */ -#define SCOUTFS_BTREE_MAX_KEY_LEN 40 /* when we split we want to have multiple items on each side */ #define SCOUTFS_BTREE_MAX_VAL_LEN (SCOUTFS_BLOCK_SIZE / 8) /* * The min number of free bytes we must leave in a parent as we descend - * to modify. This leaves enough free bytes to insert a possibly maximal - * sized key as a seperator for a child block. Fewer bytes then this - * and split/merge might try to insert a max child item in the parent - * that wouldn't fit. + * to modify. This guarantees enough free bytes in a parent to insert a + * new child reference item as a child block splits. */ #define SCOUTFS_BTREE_PARENT_MIN_FREE_BYTES \ (sizeof(struct scoutfs_btree_item_header) + \ - sizeof(struct scoutfs_btree_item) + SCOUTFS_BTREE_MAX_KEY_LEN +\ + sizeof(struct scoutfs_btree_item) + \ sizeof(struct scoutfs_btree_ref)) /* @@ -233,9 +230,9 @@ struct scoutfs_btree_item_header { } __packed; struct scoutfs_btree_item { - __le16 key_len; + struct scoutfs_key key; __le16 val_len; - __u8 data[0]; + __u8 val[0]; } __packed; struct scoutfs_btree_block { @@ -246,30 +243,6 @@ struct scoutfs_btree_block { struct scoutfs_btree_item_header item_hdrs[0]; } __packed; -/* - * The lock server keeps a persistent record of connected clients so that - * server failover knows who to wait for before resuming operations. - */ -struct scoutfs_lock_client_btree_key { - __be64 rid; -} __packed; - -/* - * The server tracks transaction sequence numbers that clients have - * open. This limits results that can be returned from the seq indices. - */ -struct scoutfs_trans_seq_btree_key { - __be64 trans_seq; - __be64 rid; -} __packed; - -/* - * The server keeps a persistent record of mounted clients. - */ -struct scoutfs_mounted_client_btree_key { - __be64 rid; -} __packed; - struct scoutfs_mounted_client_btree_val { __u8 flags; } __packed; @@ -292,11 +265,6 @@ struct scoutfs_log_trees { __le64 nr; } __packed; -struct scoutfs_log_trees_key { - __be64 rid; - __be64 nr; -} __packed; - struct scoutfs_log_trees_val { struct scoutfs_radix_root meta_avail; struct scoutfs_radix_root meta_freed; @@ -348,6 +316,11 @@ struct scoutfs_bloom_block { #define SCOUTFS_RID_ZONE 3 #define SCOUTFS_FS_ZONE 4 #define SCOUTFS_LOCK_ZONE 5 +/* Items only stored in server btrees */ +#define SCOUTFS_LOG_TREES_ZONE 6 +#define SCOUTFS_LOCK_CLIENTS_ZONE 7 +#define SCOUTFS_TRANS_SEQ_ZONE 8 +#define SCOUTFS_MOUNTED_CLIENT_ZONE 9 /* inode index zone */ #define SCOUTFS_INODE_INDEX_META_SEQ_TYPE 1 diff --git a/kmod/src/key.h b/kmod/src/key.h index 9427f2e4..76b245c9 100644 --- a/kmod/src/key.h +++ b/kmod/src/key.h @@ -186,29 +186,19 @@ static inline void scoutfs_key_dec(struct scoutfs_key *key) key->sk_zone--; } -static inline void scoutfs_key_to_be(struct scoutfs_key_be *be, - struct scoutfs_key *key) -{ - BUILD_BUG_ON(sizeof(struct scoutfs_key_be) != - sizeof(struct scoutfs_key)); +/* + * Some key types are used by multiple subsystems and shouldn't have + * duplicate private key init functions. + */ - be->sk_zone = key->sk_zone; - be->_sk_first = le64_to_be64(key->_sk_first); - be->sk_type = key->sk_type; - be->_sk_second = le64_to_be64(key->_sk_second); - be->_sk_third = le64_to_be64(key->_sk_third); - be->_sk_fourth = key->_sk_fourth; -} - -static inline void scoutfs_key_from_be(struct scoutfs_key *key, - struct scoutfs_key_be *be) +static inline void scoutfs_key_init_log_trees(struct scoutfs_key *key, + u64 rid, u64 nr) { - key->sk_zone = be->sk_zone; - key->_sk_first = be64_to_le64(be->_sk_first); - key->sk_type = be->sk_type; - key->_sk_second = be64_to_le64(be->_sk_second); - key->_sk_third = be64_to_le64(be->_sk_third); - key->_sk_fourth = be->_sk_fourth; + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_LOG_TREES_ZONE, + .sklt_rid = cpu_to_le64(rid), + .sklt_nr = cpu_to_le64(nr), + }; } #endif diff --git a/kmod/src/lock_server.c b/kmod/src/lock_server.c index 03460ef3..117d163e 100644 --- a/kmod/src/lock_server.c +++ b/kmod/src/lock_server.c @@ -575,6 +575,14 @@ out: return ret; } +static void init_lock_clients_key(struct scoutfs_key *key, u64 rid) +{ + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_LOCK_CLIENTS_ZONE, + .sklc_rid = cpu_to_le64(rid), + }; +} + /* * The server received a greeting from a client for the first time. If * the client had already talked to the server then we must find an @@ -589,23 +597,22 @@ int scoutfs_lock_server_greeting(struct super_block *sb, u64 rid, { DECLARE_LOCK_SERVER_INFO(sb, inf); struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; - struct scoutfs_lock_client_btree_key cbk; SCOUTFS_BTREE_ITEM_REF(iref); struct scoutfs_key key; int ret; - cbk.rid = cpu_to_be64(rid); + init_lock_clients_key(&key, rid); mutex_lock(&inf->mutex); if (should_exist) { - ret = scoutfs_btree_lookup(sb, &super->lock_clients, - &cbk, sizeof(cbk), &iref); + ret = scoutfs_btree_lookup(sb, &super->lock_clients, &key, + &iref); if (ret == 0) scoutfs_btree_put_iref(&iref); } else { ret = scoutfs_btree_insert(sb, inf->alloc, inf->wri, &super->lock_clients, - &cbk, sizeof(cbk), NULL, 0); + &key, NULL, 0); } mutex_unlock(&inf->mutex); @@ -738,15 +745,12 @@ out: return ret; } -static int get_rid_and_put_ref(struct scoutfs_btree_item_ref *iref, - u64 *rid) +static int get_rid_and_put_ref(struct scoutfs_btree_item_ref *iref, u64 *rid) { - struct scoutfs_lock_client_btree_key *cbk; int ret; - if (iref->key_len == sizeof(*cbk) && iref->val_len == 0) { - cbk = iref->key; - *rid = be64_to_cpu(cbk->rid); + if (iref->val_len == 0) { + *rid = le64_to_cpu(iref->key->sklc_rid); ret = 0; } else { ret = -EIO; @@ -767,8 +771,8 @@ static void scoutfs_lock_server_recovery_timeout(struct work_struct *work) recovery_dwork.work); struct super_block *sb = inf->sb; struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; - struct scoutfs_lock_client_btree_key cbk; SCOUTFS_BTREE_ITEM_REF(iref); + struct scoutfs_key key; bool timed_out; u64 rid; int ret; @@ -779,9 +783,8 @@ static void scoutfs_lock_server_recovery_timeout(struct work_struct *work) /* we enter recovery if there are any client records */ for (rid = 0; ; rid++) { - cbk.rid = cpu_to_be64(rid); - ret = scoutfs_btree_next(sb, &super->lock_clients, - &cbk, sizeof(cbk), &iref); + init_lock_clients_key(&key, rid); + ret = scoutfs_btree_next(sb, &super->lock_clients, &key, &iref); if (ret == -ENOENT) { ret = 0; break; @@ -806,10 +809,9 @@ static void scoutfs_lock_server_recovery_timeout(struct work_struct *work) scoutfs_err(sb, "client rid %016llx lock recovery timed out", rid); - cbk.rid = cpu_to_be64(rid); + init_lock_clients_key(&key, rid); ret = scoutfs_btree_delete(sb, inf->alloc, inf->wri, - &super->lock_clients, - &cbk, sizeof(cbk)); + &super->lock_clients, &key); if (ret) break; } @@ -838,7 +840,6 @@ int scoutfs_lock_server_farewell(struct super_block *sb, u64 rid) { DECLARE_LOCK_SERVER_INFO(sb, inf); struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; - struct scoutfs_lock_client_btree_key cli; struct client_lock_entry *clent; struct client_lock_entry *tmp; struct server_lock_node *snode; @@ -847,10 +848,10 @@ int scoutfs_lock_server_farewell(struct super_block *sb, u64 rid) bool freed; int ret = 0; - cli.rid = cpu_to_be64(rid); mutex_lock(&inf->mutex); + init_lock_clients_key(&key, rid); ret = scoutfs_btree_delete(sb, inf->alloc, inf->wri, - &super->lock_clients, &cli, sizeof(cli)); + &super->lock_clients, &key); mutex_unlock(&inf->mutex); if (ret == -ENOENT) { ret = 0; @@ -958,7 +959,7 @@ int scoutfs_lock_server_setup(struct super_block *sb, struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; struct lock_server_info *inf; SCOUTFS_BTREE_ITEM_REF(iref); - struct scoutfs_lock_client_btree_key cbk; + struct scoutfs_key key; unsigned int nr; u64 rid; int ret; @@ -990,9 +991,8 @@ int scoutfs_lock_server_setup(struct super_block *sb, /* we enter recovery if there are any client records */ nr = 0; for (rid = 0; ; rid++) { - cbk.rid = cpu_to_be64(rid); - ret = scoutfs_btree_next(sb, &super->lock_clients, - &cbk, sizeof(cbk), &iref); + init_lock_clients_key(&key, rid); + ret = scoutfs_btree_next(sb, &super->lock_clients, &key, &iref); if (ret == -ENOENT) break; if (ret == 0) diff --git a/kmod/src/server.c b/kmod/src/server.c index 7cd47f18..f6db3179 100644 --- a/kmod/src/server.c +++ b/kmod/src/server.c @@ -340,9 +340,9 @@ static int server_get_log_trees(struct super_block *sb, u64 rid = scoutfs_net_client_rid(conn); DECLARE_SERVER_INFO(sb, server); SCOUTFS_BTREE_ITEM_REF(iref); - struct scoutfs_log_trees_key ltk; struct scoutfs_log_trees_val ltv; struct scoutfs_log_trees lt; + struct scoutfs_key key; u64 count; u64 target; int ret; @@ -358,20 +358,16 @@ static int server_get_log_trees(struct super_block *sb, mutex_lock(&server->logs_mutex); - memset(<k, 0, sizeof(ltk)); - ltk.rid = cpu_to_be64(rid); - ltk.nr = cpu_to_be64(U64_MAX); + scoutfs_key_init_log_trees(&key, rid, U64_MAX); - ret = scoutfs_btree_prev(sb, &super->logs_root, - <k, sizeof(ltk), &iref); + ret = scoutfs_btree_prev(sb, &super->logs_root, &key, &iref); if (ret < 0 && ret != -ENOENT) goto unlock; if (ret == 0) { - if (iref.key_len == sizeof(struct scoutfs_log_trees_key) && - iref.val_len == sizeof(struct scoutfs_log_trees_val)) { - memcpy(<k, iref.key, iref.key_len); + if (iref.val_len == sizeof(struct scoutfs_log_trees_val)) { + key = *iref.key; memcpy(<v, iref.val, iref.val_len); - if (be64_to_cpu(ltk.rid) != rid) + if (le64_to_cpu(key.sklt_rid) != rid) ret = -ENOENT; } else { ret = -EIO; @@ -383,8 +379,8 @@ static int server_get_log_trees(struct super_block *sb, /* initialize new roots if we don't have any */ if (ret == -ENOENT) { - ltk.rid = cpu_to_be64(rid); - ltk.nr = cpu_to_be64(1); + key.sklt_rid = cpu_to_le64(rid); + key.sklt_nr = cpu_to_le64(1); memset(<v, 0, sizeof(ltv)); scoutfs_radix_root_init(sb, <v.meta_avail, true); scoutfs_radix_root_init(sb, <v.meta_freed, true); @@ -432,8 +428,7 @@ static int server_get_log_trees(struct super_block *sb, /* update client's log tree's item */ ret = scoutfs_btree_force(sb, &server->alloc, &server->wri, - &super->logs_root, <k, sizeof(ltk), - <v, sizeof(ltv)); + &super->logs_root, &key, <v, sizeof(ltv)); unlock: mutex_unlock(&server->logs_mutex); @@ -445,8 +440,8 @@ unlock: lt.bloom_ref = ltv.bloom_ref; lt.data_avail = ltv.data_avail; lt.data_freed = ltv.data_freed; - lt.rid = be64_to_le64(ltk.rid); - lt.nr = be64_to_le64(ltk.nr); + lt.rid = key.sklt_rid; + lt.nr = key.sklt_nr; } out: @@ -467,9 +462,9 @@ static int server_commit_log_trees(struct super_block *sb, struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; DECLARE_SERVER_INFO(sb, server); SCOUTFS_BTREE_ITEM_REF(iref); - struct scoutfs_log_trees_key ltk; struct scoutfs_log_trees_val ltv; struct scoutfs_log_trees *lt; + struct scoutfs_key key; int ret; if (arg_len != sizeof(struct scoutfs_log_trees)) { @@ -487,11 +482,9 @@ static int server_commit_log_trees(struct super_block *sb, mutex_lock(&server->logs_mutex); /* find the client's existing item */ - memset(<k, 0, sizeof(ltk)); - ltk.rid = le64_to_be64(lt->rid); - ltk.nr = le64_to_be64(lt->nr); - ret = scoutfs_btree_lookup(sb, &super->logs_root, - <k, sizeof(ltk), &iref); + scoutfs_key_init_log_trees(&key, le64_to_cpu(lt->rid), + le64_to_cpu(lt->nr)); + ret = scoutfs_btree_lookup(sb, &super->logs_root, &key, &iref); if (ret < 0 && ret != -ENOENT) { scoutfs_err(sb, "server error finding client logs: %d", ret); goto unlock; @@ -526,8 +519,7 @@ static int server_commit_log_trees(struct super_block *sb, ltv.data_freed = lt->data_freed; ret = scoutfs_btree_update(sb, &server->alloc, &server->wri, - &super->logs_root, <k, sizeof(ltk), - <v, sizeof(ltv)); + &super->logs_root, &key, <v, sizeof(ltv)); if (ret < 0) scoutfs_err(sb, "server error updating client logs: %d", ret); @@ -564,8 +556,8 @@ static int reclaim_log_trees(struct super_block *sb, u64 rid) struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; DECLARE_SERVER_INFO(sb, server); SCOUTFS_BTREE_ITEM_REF(iref); - struct scoutfs_log_trees_key ltk; struct scoutfs_log_trees_val ltv; + struct scoutfs_key key; int ret; int err; @@ -573,16 +565,13 @@ static int reclaim_log_trees(struct super_block *sb, u64 rid) down_write(&server->alloc_rwsem); /* find the client's existing item */ - ltk.rid = cpu_to_be64(rid); - ltk.nr = 0; - ret = scoutfs_btree_next(sb, &super->logs_root, - <k, sizeof(ltk), &iref); + scoutfs_key_init_log_trees(&key, rid, 0); + ret = scoutfs_btree_next(sb, &super->logs_root, &key, &iref); if (ret == 0) { - if (iref.key_len == sizeof(struct scoutfs_log_trees_key) && - iref.val_len == sizeof(struct scoutfs_log_trees_val)) { - memcpy(<k, iref.key, iref.key_len); + if (iref.val_len == sizeof(struct scoutfs_log_trees_val)) { + key = *iref.key; memcpy(<v, iref.val, iref.val_len); - if (be64_to_cpu(ltk.rid) != rid) + if (le64_to_cpu(key.sklt_rid) != rid) ret = -ENOENT; } else { ret = -EIO; @@ -618,8 +607,7 @@ static int reclaim_log_trees(struct super_block *sb, u64 rid) le64_to_cpu(ltv.data_freed.ref.sm_total)); err = scoutfs_btree_update(sb, &server->alloc, &server->wri, - &super->logs_root, <k, sizeof(ltk), - <v, sizeof(ltv)); + &super->logs_root, &key, <v, sizeof(ltv)); BUG_ON(err != 0); /* alloc and log item roots out of sync */ out: @@ -629,6 +617,15 @@ out: return ret; } +static void init_trans_seq_key(struct scoutfs_key *key, u64 seq, u64 rid) +{ + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_TRANS_SEQ_ZONE, + .skts_trans_seq = cpu_to_le64(seq), + .skts_rid = cpu_to_le64(rid), + }; +} + /* * Give the client the next sequence number for their transaction. They * provide their previous transaction sequence number that they've @@ -653,8 +650,8 @@ static int server_advance_seq(struct super_block *sb, struct scoutfs_super_block *super = &sbi->super; __le64 their_seq; __le64 next_seq; - struct scoutfs_trans_seq_btree_key tsk; u64 rid = scoutfs_net_client_rid(conn); + struct scoutfs_key key; int ret; if (arg_len != sizeof(__le64)) { @@ -670,12 +667,9 @@ static int server_advance_seq(struct super_block *sb, down_write(&server->seq_rwsem); if (their_seq != 0) { - tsk.trans_seq = le64_to_be64(their_seq); - tsk.rid = cpu_to_be64(rid); - + init_trans_seq_key(&key, le64_to_cpu(their_seq), rid); ret = scoutfs_btree_delete(sb, &server->alloc, &server->wri, - &super->trans_seqs, - &tsk, sizeof(tsk)); + &super->trans_seqs, &key); if (ret < 0 && ret != -ENOENT) goto out; } @@ -686,12 +680,9 @@ static int server_advance_seq(struct super_block *sb, trace_scoutfs_trans_seq_advance(sb, rid, le64_to_cpu(their_seq), le64_to_cpu(next_seq)); - tsk.trans_seq = le64_to_be64(next_seq); - tsk.rid = cpu_to_be64(rid); - + init_trans_seq_key(&key, le64_to_cpu(next_seq), rid); ret = scoutfs_btree_insert(sb, &server->alloc, &server->wri, - &super->trans_seqs, - &tsk, sizeof(tsk), NULL, 0); + &super->trans_seqs, &key, NULL, 0); out: up_write(&server->seq_rwsem); ret = scoutfs_server_apply_commit(sb, ret); @@ -712,39 +703,35 @@ static int remove_trans_seq(struct super_block *sb, u64 rid) DECLARE_SERVER_INFO(sb, server); struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_super_block *super = &sbi->super; - struct scoutfs_trans_seq_btree_key tsk; SCOUTFS_BTREE_ITEM_REF(iref); + struct scoutfs_key key; int ret = 0; down_write(&server->seq_rwsem); - tsk.trans_seq = 0; - tsk.rid = 0; + init_trans_seq_key(&key, 0, 0); for (;;) { - ret = scoutfs_btree_next(sb, &super->trans_seqs, - &tsk, sizeof(tsk), &iref); + ret = scoutfs_btree_next(sb, &super->trans_seqs, &key, &iref); if (ret < 0) { if (ret == -ENOENT) ret = 0; break; } - memcpy(&tsk, iref.key, iref.key_len); + key = *iref.key; scoutfs_btree_put_iref(&iref); - if (be64_to_cpu(tsk.rid) == rid) { + if (le64_to_cpu(key.skts_rid) == rid) { trace_scoutfs_trans_seq_farewell(sb, rid, - be64_to_cpu(tsk.trans_seq)); + le64_to_cpu(key.skts_trans_seq)); ret = scoutfs_btree_delete(sb, &server->alloc, &server->wri, - &super->trans_seqs, - &tsk, sizeof(tsk)); + &super->trans_seqs, &key); break; } - be64_add_cpu(&tsk.trans_seq, 1); - tsk.rid = 0; + scoutfs_key_inc(&key); } up_write(&server->seq_rwsem); @@ -767,9 +754,9 @@ static int server_get_last_seq(struct super_block *sb, DECLARE_SERVER_INFO(sb, server); struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_super_block *super = &sbi->super; - struct scoutfs_trans_seq_btree_key tsk; SCOUTFS_BTREE_ITEM_REF(iref); u64 rid = scoutfs_net_client_rid(conn); + struct scoutfs_key key; __le64 last_seq = 0; int ret; @@ -780,26 +767,19 @@ static int server_get_last_seq(struct super_block *sb, down_read(&server->seq_rwsem); - tsk.trans_seq = 0; - tsk.rid = 0; - - ret = scoutfs_btree_next(sb, &super->trans_seqs, - &tsk, sizeof(tsk), &iref); + init_trans_seq_key(&key, 0, 0); + ret = scoutfs_btree_next(sb, &super->trans_seqs, &key, &iref); if (ret == 0) { - if (iref.key_len != sizeof(tsk)) { - ret = -EINVAL; - } else { - memcpy(&tsk, iref.key, iref.key_len); - last_seq = cpu_to_le64(be64_to_cpu(tsk.trans_seq) - 1); - } + key = *iref.key; scoutfs_btree_put_iref(&iref); + last_seq = key.skts_trans_seq; } else if (ret == -ENOENT) { last_seq = super->next_trans_seq; - le64_add_cpu(&last_seq, -1ULL); ret = 0; } + le64_add_cpu(&last_seq, -1ULL); trace_scoutfs_trans_seq_last(sb, rid, le64_to_cpu(last_seq)); up_read(&server->seq_rwsem); @@ -926,22 +906,30 @@ int scoutfs_server_lock_recover_request(struct super_block *sb, u64 rid, NULL, NULL); } +static void init_mounted_client_key(struct scoutfs_key *key, u64 rid) +{ + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_MOUNTED_CLIENT_ZONE, + .skmc_rid = cpu_to_le64(rid), + }; +} + static int insert_mounted_client(struct super_block *sb, u64 rid, u64 gr_flags) { DECLARE_SERVER_INFO(sb, server); struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; - struct scoutfs_mounted_client_btree_key mck; struct scoutfs_mounted_client_btree_val mcv; + struct scoutfs_key key; - mck.rid = cpu_to_be64(rid); + init_mounted_client_key(&key, rid); mcv.flags = 0; if (gr_flags & SCOUTFS_NET_GREETING_FLAG_VOTER) mcv.flags |= SCOUTFS_MOUNTED_CLIENT_VOTER; return scoutfs_btree_insert(sb, &server->alloc, &server->wri, - &super->mounted_clients, - &mck, sizeof(mck), &mcv, sizeof(mcv)); + &super->mounted_clients, &key, &mcv, + sizeof(mcv)); } /* @@ -958,14 +946,13 @@ static int delete_mounted_client(struct super_block *sb, u64 rid) { DECLARE_SERVER_INFO(sb, server); struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; - struct scoutfs_mounted_client_btree_key mck; + struct scoutfs_key key; int ret; - mck.rid = cpu_to_be64(rid); + init_mounted_client_key(&key, rid); ret = scoutfs_btree_delete(sb, &server->alloc, &server->wri, - &super->mounted_clients, - &mck, sizeof(mck)); + &super->mounted_clients, &key); if (ret == -ENOENT) ret = 0; @@ -1101,9 +1088,7 @@ struct farewell_request { static bool invalid_mounted_client_item(struct scoutfs_btree_item_ref *iref) { - return (iref->key_len != - sizeof(struct scoutfs_mounted_client_btree_key)) || - (iref->val_len != + return (iref->val_len != sizeof(struct scoutfs_mounted_client_btree_val)); } @@ -1139,13 +1124,13 @@ static void farewell_worker(struct work_struct *work) farewell_work); struct super_block *sb = server->sb; struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; - struct scoutfs_mounted_client_btree_key mck; struct scoutfs_mounted_client_btree_val *mcv; struct farewell_request *tmp; struct farewell_request *fw; SCOUTFS_BTREE_ITEM_REF(iref); unsigned int nr_unmounting = 0; unsigned int nr_mounted = 0; + struct scoutfs_key key; LIST_HEAD(reqs); LIST_HEAD(send); bool deleted = false; @@ -1161,9 +1146,9 @@ static void farewell_worker(struct work_struct *work) /* count how many reqs requests are from voting clients */ nr_unmounting = 0; list_for_each_entry_safe(fw, tmp, &reqs, entry) { - mck.rid = cpu_to_be64(fw->rid); - ret = scoutfs_btree_lookup(sb, &super->mounted_clients, - &mck, sizeof(mck), &iref); + init_mounted_client_key(&key, fw->rid); + ret = scoutfs_btree_lookup(sb, &super->mounted_clients, &key, + &iref); if (ret == 0 && invalid_mounted_client_item(&iref)) { scoutfs_btree_put_iref(&iref); ret = -EIO; @@ -1189,10 +1174,10 @@ static void farewell_worker(struct work_struct *work) } /* see how many mounted clients could vote for quorum */ - memset(&mck, 0, sizeof(mck)); + init_mounted_client_key(&key, 0); for (;;) { - ret = scoutfs_btree_next(sb, &super->mounted_clients, - &mck, sizeof(mck), &iref); + ret = scoutfs_btree_next(sb, &super->mounted_clients, &key, + &iref); if (ret == 0 && invalid_mounted_client_item(&iref)) { scoutfs_btree_put_iref(&iref); ret = -EIO; @@ -1203,15 +1188,14 @@ static void farewell_worker(struct work_struct *work) goto out; } - memcpy(&mck, iref.key, sizeof(mck)); + key = *iref.key; mcv = iref.val; if (mcv->flags & SCOUTFS_MOUNTED_CLIENT_VOTER) nr_mounted++; scoutfs_btree_put_iref(&iref); - be64_add_cpu(&mck.rid, 1); - + scoutfs_key_inc(&key); } /* send as many responses as we can to maintain quorum */