From ad99636af8582c9774c4c98bc11e2c3a6b185987 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Thu, 23 Apr 2020 10:29:23 -0700 Subject: [PATCH] scoutfs: use scoutfs_key as btree key The btree currently uses variable length big-endian buffers that are compared with memcmp() as keys. This is a historical relic of the time when keys could be very large. We had dirent keys that included the name and manifest entries that included those fs keys. But now all the btree callers are jumping through hoops to translate their fs keys into big-endian btree keys. And the memcmp() of the keys is showing up in profiles. This makes the btree take native scoutfs_key structs as its key. The forest callers which are working with fs keys can just pass their keys straight through. The server btree callers with their private btrees get key fields definied for their use instead of having individual big-endian key structs. A nice side-effect of this is that splitting parents doesn't have to assume that a maximal key will be inserted by a child split. We can have more keys in parents and wider trees. Signed-off-by: Zach Brown --- kmod/src/btree.c | 247 ++++++++++++++++------------------------- kmod/src/btree.h | 29 ++--- kmod/src/forest.c | 83 +++++--------- kmod/src/format.h | 75 ++++--------- kmod/src/key.h | 32 ++---- kmod/src/lock_server.c | 50 ++++----- kmod/src/server.c | 168 +++++++++++++--------------- 7 files changed, 273 insertions(+), 411 deletions(-) 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 */