diff --git a/kmod/src/client.c b/kmod/src/client.c index 174f7f17..e40cc214 100644 --- a/kmod/src/client.c +++ b/kmod/src/client.c @@ -589,22 +589,14 @@ int scoutfs_client_record_segment(struct super_block *sb, struct scoutfs_segment *seg, u8 level) { struct client_info *client = SCOUTFS_SB(sb)->client_info; - struct scoutfs_net_manifest_entry *net_ment; + struct scoutfs_net_manifest_entry net_ment; struct scoutfs_manifest_entry ment; - int ret; scoutfs_seg_init_ment(&ment, level, seg); - net_ment = scoutfs_alloc_net_ment(&ment); - if (net_ment) { - ret = client_request(client, SCOUTFS_NET_RECORD_SEGMENT, - net_ment, scoutfs_net_ment_bytes(net_ment), - NULL, 0); - kfree(net_ment); - } else { - ret = -ENOMEM; - } + scoutfs_init_ment_to_net(&net_ment, &ment); - return ret; + return client_request(client, SCOUTFS_NET_RECORD_SEGMENT, &net_ment, + sizeof(net_ment), NULL, 0); } static int sort_cmp_u64s(const void *A, const void *B) diff --git a/kmod/src/cmp.h b/kmod/src/cmp.h index 3230c043..23c6d8a6 100644 --- a/kmod/src/cmp.h +++ b/kmod/src/cmp.h @@ -1,7 +1,19 @@ #ifndef _SCOUTFS_CMP_H_ #define _SCOUTFS_CMP_H_ -#include +/* + * A generic ternary comparison macro with strict type checking. + */ +#define scoutfs_cmp(a, b) \ +({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + int _ret; \ + \ + (void) (&_a == &_b); \ + _ret = _a < _b ? -1 : _a > _b ? 1 : 0; \ + _ret; \ +}) static inline int scoutfs_cmp_u64s(u64 a, u64 b) { diff --git a/kmod/src/compact.c b/kmod/src/compact.c index 58087381..4047e5e7 100644 --- a/kmod/src/compact.c +++ b/kmod/src/compact.c @@ -66,8 +66,8 @@ struct compact_seg { u64 segno; u64 seq; u8 level; - struct scoutfs_key_buf *first; - struct scoutfs_key_buf *last; + struct scoutfs_key first; + struct scoutfs_key last; struct scoutfs_segment *seg; int off; bool part_of_move; @@ -101,27 +101,20 @@ static void free_cseg(struct super_block *sb, struct compact_seg *cseg) WARN_ON_ONCE(!list_empty(&cseg->entry)); scoutfs_seg_put(cseg->seg); - scoutfs_key_free(sb, cseg->first); - scoutfs_key_free(sb, cseg->last); - kfree(cseg); } static struct compact_seg *alloc_cseg(struct super_block *sb, - struct scoutfs_key_buf *first, - struct scoutfs_key_buf *last) + struct scoutfs_key *first, + struct scoutfs_key *last) { struct compact_seg *cseg; cseg = kzalloc(sizeof(struct compact_seg), GFP_NOFS); if (cseg) { INIT_LIST_HEAD(&cseg->entry); - cseg->first = scoutfs_key_dup(sb, first); - cseg->last = scoutfs_key_dup(sb, last); - if (!cseg->first || !cseg->last) { - free_cseg(sb, cseg); - cseg = NULL; - } + cseg->first = *first; + cseg->last = *last; } return cseg; @@ -179,12 +172,12 @@ static struct compact_seg *next_spos(struct compact_cursor *curs, * incremental update items. */ static int next_item(struct super_block *sb, struct compact_cursor *curs, - struct scoutfs_key_buf *item_key, struct kvec *item_val, + struct scoutfs_key *item_key, struct kvec *item_val, u8 *item_flags) { struct compact_seg *upper = curs->upper; struct compact_seg *lower = curs->lower; - struct scoutfs_key_buf lower_key; + struct scoutfs_key lower_key; struct kvec lower_val; u8 lower_flags; int cmp; @@ -192,8 +185,8 @@ static int next_item(struct super_block *sb, struct compact_cursor *curs, retry: if (upper) { - ret = scoutfs_seg_item_ptrs(upper->seg, upper->off, - item_key, item_val, item_flags); + ret = scoutfs_seg_get_item(upper->seg, upper->off, + item_key, item_val, item_flags); if (ret < 0) upper = NULL; } @@ -203,9 +196,9 @@ retry: if (ret) goto out; - ret = scoutfs_seg_item_ptrs(lower->seg, lower->off, - &lower_key, &lower_val, - &lower_flags); + ret = scoutfs_seg_get_item(lower->seg, lower->off, + &lower_key, &lower_val, + &lower_flags); if (ret == 0) break; lower = next_spos(curs, lower); @@ -230,7 +223,7 @@ retry: cmp = 1; if (cmp > 0) { - scoutfs_key_clone(item_key, &lower_key); + *item_key = lower_key; *item_val = lower_val; *item_flags = lower_flags; } @@ -243,7 +236,7 @@ retry: */ if (curs->sticky && curs->lower && (!lower || lower == curs->last_lower) && - scoutfs_key_compare(item_key, curs->last_lower->last) > 0) { + scoutfs_key_compare(item_key, &curs->last_lower->last) > 0) { ret = 0; goto out; } @@ -276,7 +269,7 @@ static int compact_segments(struct super_block *sb, struct scoutfs_bio_completion *comp, struct list_head *results) { - struct scoutfs_key_buf item_key; + struct scoutfs_key item_key; struct scoutfs_segment *seg; struct compact_seg *cseg; struct compact_seg *upper; @@ -315,7 +308,7 @@ static int compact_segments(struct super_block *sb, * entry iterator that reading and compacting * can use. */ - cseg = alloc_cseg(sb, upper->first, upper->last); + cseg = alloc_cseg(sb, &upper->first, &upper->last); if (!cseg) { ret = -ENOMEM; break; @@ -535,7 +528,7 @@ int scoutfs_compact_commit(struct super_block *sb, void *c, void *r) } scoutfs_manifest_init_entry(&ment, cseg->level, 0, cseg->seq, - cseg->first, NULL); + &cseg->first, NULL); ret = scoutfs_manifest_del(sb, &ment); BUG_ON(ret); } @@ -548,7 +541,7 @@ int scoutfs_compact_commit(struct super_block *sb, void *c, void *r) else scoutfs_manifest_init_entry(&ment, cseg->level, cseg->segno, cseg->seq, - cseg->first, cseg->last); + &cseg->first, &cseg->last); ret = scoutfs_manifest_add(sb, &ment); BUG_ON(ret); } @@ -590,7 +583,8 @@ static void scoutfs_compact_func(struct work_struct *work) /* trace compaction ranges */ list_for_each_entry(cseg, &curs.csegs, entry) { trace_scoutfs_compact_input(sb, cseg->level, cseg->segno, - cseg->seq, cseg->first, cseg->last); + cseg->seq, &cseg->first, + &cseg->last); } if (ret == 0 && !list_empty(&curs.csegs)) { diff --git a/kmod/src/count.h b/kmod/src/count.h index f115d034..759c736d 100644 --- a/kmod/src/count.h +++ b/kmod/src/count.h @@ -2,10 +2,8 @@ #define _SCOUTFS_COUNT_H_ /* - * Our estimate of the space consumed while dirtying items isn't a - * single value. We're packing items into segments which have different - * overheads for items (header overhead), keys (block aligned), and - * values (can span blocks, not aligned). + * Our estimate of the space consumed while dirtying items is based on + * the number of items and the size of their values. * * The estimate is still a read-only input to entering the transaction. * We'd like to use it as a clean rhs arg to hold_trans. We define SIC_ @@ -21,7 +19,6 @@ struct scoutfs_item_count { signed items; - signed keys; signed vals; }; @@ -33,8 +30,6 @@ static inline void __count_alloc_inode(struct scoutfs_item_count *cnt) const int nr_indices = SCOUTFS_INODE_INDEX_NR; cnt->items += 1 + nr_indices; - cnt->keys += sizeof(struct scoutfs_inode_key) + - (nr_indices * sizeof(struct scoutfs_inode_index_key)); cnt->vals += sizeof(struct scoutfs_inode); } @@ -47,8 +42,6 @@ static inline void __count_dirty_inode(struct scoutfs_item_count *cnt) const int nr_indices = 2 * SCOUTFS_INODE_INDEX_NR; cnt->items += 1 + nr_indices; - cnt->keys += sizeof(struct scoutfs_inode_key) + - (nr_indices * sizeof(struct scoutfs_inode_index_key)); cnt->vals += sizeof(struct scoutfs_inode); } @@ -77,7 +70,6 @@ static inline void __count_dirents(struct scoutfs_item_count *cnt, unsigned name_len) { cnt->items += 3; - cnt->keys += 3 * sizeof(struct scoutfs_dirent_key); cnt->vals += 3 * offsetof(struct scoutfs_dirent, name[name_len]); } @@ -87,7 +79,6 @@ static inline void __count_sym_target(struct scoutfs_item_count *cnt, unsigned nr = DIV_ROUND_UP(size, SCOUTFS_MAX_VAL_SIZE); cnt->items += nr; - cnt->keys += nr * sizeof(struct scoutfs_symlink_key); cnt->vals += size; } @@ -95,7 +86,6 @@ static inline void __count_orphan(struct scoutfs_item_count *cnt) { cnt->items += 1; - cnt->keys += sizeof(struct scoutfs_orphan_key); } static inline void __count_mknod(struct scoutfs_item_count *cnt, @@ -197,16 +187,13 @@ static inline const struct scoutfs_item_count SIC_XATTR_SET(unsigned old_parts, __count_dirty_inode(&cnt); - if (old_parts) { + if (old_parts) cnt.items += old_parts; - cnt.keys += old_parts * sizeof(struct scoutfs_xattr_key); - } if (creating) { new_parts = SCOUTFS_XATTR_NR_PARTS(name_len, size) cnt.items += new_parts; - cnt.keys += new_parts * sizeof(struct scoutfs_xattr_key); cnt.vals += sizeof(struct scoutfs_xattr) + name_len + size; } @@ -225,8 +212,6 @@ static inline const struct scoutfs_item_count SIC_WRITE_BEGIN(void) __count_dirty_inode(&cnt); cnt.items += 1 + nr_free; - cnt.keys += sizeof(struct scoutfs_block_mapping_key) + - (nr_free * sizeof(struct scoutfs_free_bits_key)); cnt.vals += SCOUTFS_BLOCK_MAPPING_MAX_BYTES + (nr_free * sizeof(struct scoutfs_free_bits)); @@ -244,8 +229,6 @@ static inline const struct scoutfs_item_count SIC_TRUNC_BLOCK(void) unsigned nr_free = (2 * SCOUTFS_BLOCK_MAPPING_BLOCKS); cnt.items += 1 + nr_free; - cnt.keys += sizeof(struct scoutfs_block_mapping_key) + - (nr_free * sizeof(struct scoutfs_free_bits_key)); cnt.vals += SCOUTFS_BLOCK_MAPPING_MAX_BYTES + (nr_free * sizeof(struct scoutfs_free_bits)); diff --git a/kmod/src/data.c b/kmod/src/data.c index 19108c40..fb4d19bb 100644 --- a/kmod/src/data.c +++ b/kmod/src/data.c @@ -319,30 +319,25 @@ static int decode_mapping(struct block_mapping *map, int size) return 0; } -static void init_mapping_key(struct scoutfs_key_buf *key, - struct scoutfs_block_mapping_key *bmk, - u64 ino, u64 iblock) +static void init_mapping_key(struct scoutfs_key *key, u64 ino, u64 iblock) { - - bmk->zone = SCOUTFS_FS_ZONE; - bmk->ino = cpu_to_be64(ino); - bmk->type = SCOUTFS_BLOCK_MAPPING_TYPE; - bmk->base = cpu_to_be64(iblock >> SCOUTFS_BLOCK_MAPPING_SHIFT); - - scoutfs_key_init(key, bmk, sizeof(struct scoutfs_block_mapping_key)); + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_FS_ZONE, + .skm_ino = cpu_to_le64(ino), + .sk_type = SCOUTFS_BLOCK_MAPPING_TYPE, + .skm_base = cpu_to_le64(iblock >> SCOUTFS_BLOCK_MAPPING_SHIFT), + }; } - -static void init_free_key(struct scoutfs_key_buf *key, - struct scoutfs_free_bits_key *fbk, u64 node_id, - u64 full_bit, u8 type) +static void init_free_key(struct scoutfs_key *key, u64 node_id, u64 full_bit, + u8 type) { - fbk->zone = SCOUTFS_NODE_ZONE; - fbk->node_id = cpu_to_be64(node_id); - fbk->type = type; - fbk->base = cpu_to_be64(full_bit >> SCOUTFS_FREE_BITS_SHIFT); - - scoutfs_key_init(key, fbk, sizeof(struct scoutfs_free_bits_key)); + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_NODE_ZONE, + .skf_node_id = cpu_to_le64(node_id), + .sk_type = type, + .skf_base = cpu_to_le64(full_bit >> SCOUTFS_FREE_BITS_SHIFT), + }; } /* @@ -353,15 +348,13 @@ static int set_segno_free(struct super_block *sb, u64 segno) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_lock *lock = sbi->node_id_lock; - struct scoutfs_free_bits_key fbk = {0,}; struct scoutfs_free_bits frb; - struct scoutfs_key_buf key; + struct scoutfs_key key; struct kvec val; int bit = 0; int ret; - init_free_key(&key, &fbk, sbi->node_id, segno, - SCOUTFS_FREE_BITS_SEGNO_TYPE); + init_free_key(&key, sbi->node_id, segno, SCOUTFS_FREE_BITS_SEGNO_TYPE); kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits)); ret = scoutfs_item_lookup_exact(sb, &key, &val, lock); if (ret && ret != -ENOENT) @@ -383,7 +376,7 @@ static int set_segno_free(struct super_block *sb, u64 segno) ret = scoutfs_item_update(sb, &key, &val, lock); out: - trace_scoutfs_data_set_segno_free(sb, segno, be64_to_cpu(fbk.base), + trace_scoutfs_data_set_segno_free(sb, segno, le64_to_cpu(key.skf_base), bit, ret); return ret; } @@ -394,8 +387,7 @@ out: * need to. */ static int create_blkno_free(struct super_block *sb, u64 blkno, - struct scoutfs_key_buf *key, - struct scoutfs_free_bits_key *fbk) + struct scoutfs_key *key) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_lock *lock = sbi->node_id_lock; @@ -403,8 +395,7 @@ static int create_blkno_free(struct super_block *sb, u64 blkno, struct kvec val; int bit; - init_free_key(key, fbk, sbi->node_id, blkno, - SCOUTFS_FREE_BITS_BLKNO_TYPE); + init_free_key(key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE); kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits)); bit = blkno & SCOUTFS_FREE_BITS_MASK; @@ -429,18 +420,15 @@ static int clear_segno_free(struct super_block *sb, u64 segno) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_lock *lock = sbi->node_id_lock; - struct scoutfs_free_bits_key b_fbk; - struct scoutfs_free_bits_key fbk; struct scoutfs_free_bits frb; - struct scoutfs_key_buf b_key; - struct scoutfs_key_buf key; + struct scoutfs_key b_key; + struct scoutfs_key key; struct kvec val; u64 blkno; int bit; int ret; - init_free_key(&key, &fbk, sbi->node_id, segno, - SCOUTFS_FREE_BITS_SEGNO_TYPE); + init_free_key(&key, sbi->node_id, segno, SCOUTFS_FREE_BITS_SEGNO_TYPE); kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits)); ret = scoutfs_item_lookup_exact(sb, &key, &val, lock); if (ret) { @@ -459,7 +447,7 @@ static int clear_segno_free(struct super_block *sb, u64 segno) /* create the new blkno item, we can safely delete it */ blkno = segno << SCOUTFS_SEGMENT_BLOCK_SHIFT; - ret = create_blkno_free(sb, blkno, &b_key, &b_fbk); + ret = create_blkno_free(sb, blkno, &b_key); if (ret) goto out; @@ -482,17 +470,15 @@ static int set_blkno_free(struct super_block *sb, u64 blkno) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_lock *lock = sbi->node_id_lock; - struct scoutfs_free_bits_key fbk; struct scoutfs_free_bits frb; - struct scoutfs_key_buf key; + struct scoutfs_key key; struct kvec val; u64 segno; int bit; int ret; /* get the specified item */ - init_free_key(&key, &fbk, sbi->node_id, blkno, - SCOUTFS_FREE_BITS_BLKNO_TYPE); + init_free_key(&key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE); kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits)); ret = scoutfs_item_lookup_exact(sb, &key, &val, lock); if (ret && ret != -ENOENT) @@ -542,16 +528,14 @@ static int clear_blkno_free(struct super_block *sb, u64 blkno) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_lock *lock = sbi->node_id_lock; - struct scoutfs_free_bits_key fbk; struct scoutfs_free_bits frb; - struct scoutfs_key_buf key; + struct scoutfs_key key; struct kvec val; int bit; int ret; /* get the specified item */ - init_free_key(&key, &fbk, sbi->node_id, blkno, - SCOUTFS_FREE_BITS_BLKNO_TYPE); + init_free_key(&key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE); kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits)); ret = scoutfs_item_lookup_exact(sb, &key, &val, lock); if (ret) { @@ -607,10 +591,8 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode, struct scoutfs_lock *lock) { DECLARE_DATA_INFO(sb, datinf); - struct scoutfs_key_buf last_key; - struct scoutfs_key_buf key; - struct scoutfs_block_mapping_key last_bmk; - struct scoutfs_block_mapping_key bmk; + struct scoutfs_key last_key; + struct scoutfs_key key; struct block_mapping *map; struct kvec val; bool holding = false; @@ -629,11 +611,11 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode, if (!map) return -ENOMEM; - init_mapping_key(&last_key, &last_bmk, ino, last); + init_mapping_key(&last_key, ino, last); while (iblock <= last) { /* find the mapping that could include iblock */ - init_mapping_key(&key, &bmk, ino, iblock); + init_mapping_key(&key, ino, iblock); kvec_init(&val, map->encoded, sizeof(map->encoded)); ret = scoutfs_hold_trans(sb, SIC_TRUNC_BLOCK()); @@ -655,7 +637,7 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode, break; /* set iblock to the first in the next item inside last */ - iblock = max(iblock, be64_to_cpu(bmk.base) << + iblock = max(iblock, le64_to_cpu(key.skm_base) << SCOUTFS_BLOCK_MAPPING_SHIFT); dirtied = false; @@ -838,15 +820,13 @@ static int find_free_blkno(struct super_block *sb, u64 blkno, u64 *blkno_ret) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_lock *lock = sbi->node_id_lock; - struct scoutfs_free_bits_key fbk; struct scoutfs_free_bits frb; - struct scoutfs_key_buf key; + struct scoutfs_key key; struct kvec val; int ret; int bit; - init_free_key(&key, &fbk, sbi->node_id, blkno, - SCOUTFS_FREE_BITS_BLKNO_TYPE); + init_free_key(&key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE); kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits)); ret = scoutfs_item_lookup_exact(sb, &key, &val, lock); @@ -860,7 +840,8 @@ static int find_free_blkno(struct super_block *sb, u64 blkno, u64 *blkno_ret) goto out; } - *blkno_ret = (be64_to_cpu(fbk.base) << SCOUTFS_FREE_BITS_SHIFT) + bit; + *blkno_ret = (le64_to_cpu(key.skf_base) << SCOUTFS_FREE_BITS_SHIFT) + + bit; ret = 0; out: return ret; @@ -874,18 +855,15 @@ static int find_free_segno(struct super_block *sb, u64 *segno) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_lock *lock = sbi->node_id_lock; - struct scoutfs_free_bits_key last_fbk; - struct scoutfs_free_bits_key fbk; struct scoutfs_free_bits frb; - struct scoutfs_key_buf last_key; - struct scoutfs_key_buf key; + struct scoutfs_key last_key; + struct scoutfs_key key; struct kvec val; int bit; int ret; - init_free_key(&key, &fbk, sbi->node_id, 0, - SCOUTFS_FREE_BITS_SEGNO_TYPE); - init_free_key(&last_key, &last_fbk, sbi->node_id, ~0, + init_free_key(&key, sbi->node_id, 0, SCOUTFS_FREE_BITS_SEGNO_TYPE); + init_free_key(&last_key, sbi->node_id, U64_MAX, SCOUTFS_FREE_BITS_SEGNO_TYPE); kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits)); @@ -900,7 +878,7 @@ static int find_free_segno(struct super_block *sb, u64 *segno) goto out; } - *segno = (be64_to_cpu(fbk.base) << SCOUTFS_FREE_BITS_SHIFT) + bit; + *segno = (le64_to_cpu(key.skf_base) << SCOUTFS_FREE_BITS_SHIFT) + bit; ret = 0; out: return ret; @@ -916,7 +894,7 @@ out: */ static int find_alloc_block(struct super_block *sb, struct inode *inode, struct block_mapping *map, - struct scoutfs_key_buf *map_key, + struct scoutfs_key *map_key, unsigned map_ind, bool map_exists, struct scoutfs_lock *data_lock) { @@ -1013,8 +991,7 @@ static int scoutfs_get_block(struct inode *inode, sector_t iblock, { struct scoutfs_inode_info *si = SCOUTFS_I(inode); struct super_block *sb = inode->i_sb; - struct scoutfs_block_mapping_key bmk; - struct scoutfs_key_buf key; + struct scoutfs_key key; struct scoutfs_lock *lock; struct block_mapping *map; struct kvec val; @@ -1031,7 +1008,7 @@ static int scoutfs_get_block(struct inode *inode, sector_t iblock, if (!map) return -ENOMEM; - init_mapping_key(&key, &bmk, scoutfs_ino(inode), iblock); + init_mapping_key(&key, scoutfs_ino(inode), iblock); kvec_init(&val, map->encoded, sizeof(map->encoded)); /* find the mapping item that covers the logical block */ @@ -1310,13 +1287,11 @@ int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, { struct super_block *sb = inode->i_sb; const u64 ino = scoutfs_ino(inode); - struct scoutfs_key_buf last_key; - struct scoutfs_key_buf key; + struct scoutfs_key last_key; + struct scoutfs_key key; struct scoutfs_lock *inode_lock = NULL; struct block_mapping *map; struct pending_fiemap pend; - struct scoutfs_block_mapping_key last_bmk; - struct scoutfs_block_mapping_key bmk; struct kvec val; loff_t i_size; bool offline; @@ -1351,14 +1326,14 @@ int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, blk_off = start >> SCOUTFS_BLOCK_SHIFT; final = min_t(loff_t, i_size - 1, start + len - 1) >> SCOUTFS_BLOCK_SHIFT; - init_mapping_key(&last_key, &last_bmk, ino, final); + init_mapping_key(&last_key, ino, final); ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, 0, inode, &inode_lock); if (ret) goto out; while (blk_off <= final) { - init_mapping_key(&key, &bmk, ino, blk_off); + init_mapping_key(&key, ino, blk_off); kvec_init(&val, &map->encoded, sizeof(map->encoded)); ret = scoutfs_item_next(sb, &key, &last_key, &val, inode_lock); @@ -1373,7 +1348,7 @@ int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, break; /* set blk_off to the first in the next item inside last */ - blk_off = max(blk_off, be64_to_cpu(bmk.base) << + blk_off = max(blk_off, le64_to_cpu(key.skm_base) << SCOUTFS_BLOCK_MAPPING_SHIFT); for_each_block(i, blk_off, final) { diff --git a/kmod/src/dir.c b/kmod/src/dir.c index f32dfe6c..7b813922 100644 --- a/kmod/src/dir.c +++ b/kmod/src/dir.c @@ -191,17 +191,16 @@ static u64 dentry_info_pos(struct dentry *dentry) return di->pos; } -static void init_dirent_key(struct scoutfs_key_buf *key, - struct scoutfs_dirent_key *dkey, u8 type, - u64 ino, u64 major, u64 minor) +static void init_dirent_key(struct scoutfs_key *key, u8 type, u64 ino, + u64 major, u64 minor) { - dkey->zone = SCOUTFS_FS_ZONE; - dkey->ino = cpu_to_be64(ino); - dkey->type = type; - dkey->major = cpu_to_be64(major); - dkey->minor = cpu_to_be64(minor); - - scoutfs_key_init(key, dkey, sizeof(struct scoutfs_dirent_key)); + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_FS_ZONE, + .skd_ino = cpu_to_le64(ino), + .sk_type = type, + .skd_major = cpu_to_le64(major), + .skd_minor = cpu_to_le64(minor), + }; } static unsigned int dirent_bytes(unsigned int name_len) @@ -237,10 +236,8 @@ static int lookup_dirent(struct super_block *sb, u64 dir_ino, const char *name, struct scoutfs_dirent *dent_ret, struct scoutfs_lock *lock) { - struct scoutfs_dirent_key last_dkey; - struct scoutfs_dirent_key dkey; - struct scoutfs_key_buf last_key; - struct scoutfs_key_buf key; + struct scoutfs_key last_key; + struct scoutfs_key key; struct scoutfs_dirent *dent = NULL; struct kvec val; int ret; @@ -251,10 +248,8 @@ static int lookup_dirent(struct super_block *sb, u64 dir_ino, const char *name, goto out; } - init_dirent_key(&key, &dkey, SCOUTFS_DIRENT_TYPE, - dir_ino, hash, 0); - init_dirent_key(&last_key, &last_dkey, SCOUTFS_DIRENT_TYPE, - dir_ino, hash, U64_MAX); + init_dirent_key(&key, SCOUTFS_DIRENT_TYPE, dir_ino, hash, 0); + init_dirent_key(&last_key, SCOUTFS_DIRENT_TYPE, dir_ino, hash, U64_MAX); kvec_init(&val, dent, dirent_bytes(SCOUTFS_NAME_LEN)); for (;;) { @@ -275,11 +270,11 @@ static int lookup_dirent(struct super_block *sb, u64 dir_ino, const char *name, break; } - if (be64_to_cpu(dkey.minor) == U64_MAX) { + if (le64_to_cpu(key.skd_minor) == U64_MAX) { ret = -ENOENT; break; } - be64_add_cpu(&dkey.minor, 1); + le64_add_cpu(&key.skd_minor, 1); } out: @@ -472,13 +467,11 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir) struct inode *inode = file_inode(file); struct super_block *sb = inode->i_sb; struct scoutfs_dirent *dent; - struct scoutfs_key_buf key; - struct scoutfs_key_buf last_key; - struct scoutfs_dirent_key dkey; - struct scoutfs_dirent_key last_dkey; + struct scoutfs_key key; + struct scoutfs_key last_key; struct scoutfs_lock *dir_lock; - unsigned int name_len; struct kvec val; + int name_len; u64 pos; int ret; @@ -491,8 +484,8 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir) goto out; } - init_dirent_key(&last_key, &last_dkey, SCOUTFS_READDIR_TYPE, - scoutfs_ino(inode), SCOUTFS_DIRENT_LAST_POS, 0); + init_dirent_key(&last_key, SCOUTFS_READDIR_TYPE, scoutfs_ino(inode), + SCOUTFS_DIRENT_LAST_POS, 0); kvec_init(&val, dent, dirent_bytes(SCOUTFS_NAME_LEN)); ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, 0, inode, &dir_lock); @@ -500,11 +493,10 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir) goto out; for (;;) { - init_dirent_key(&key, &dkey, SCOUTFS_READDIR_TYPE, - scoutfs_ino(inode), file->f_pos, 0); + init_dirent_key(&key, SCOUTFS_READDIR_TYPE, scoutfs_ino(inode), + file->f_pos, 0); - ret = scoutfs_item_next_same_min(sb, &key, &last_key, &val, - dirent_bytes(1), dir_lock); + ret = scoutfs_item_next(sb, &key, &last_key, &val, dir_lock); if (ret < 0) { if (ret == -ENOENT) ret = 0; @@ -512,7 +504,13 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir) } name_len = ret - sizeof(struct scoutfs_dirent); - pos = be64_to_cpu(dkey.major); + /* XXX corruption */ + if (name_len < 1 || name_len > SCOUTFS_NAME_LEN) { + ret = -EIO; + goto out; + } + + pos = le64_to_cpu(key.skd_major); if (filldir(dirent, dent->name, name_len, pos, le64_to_cpu(dent->ino), dentry_type(dent->type))) { @@ -542,12 +540,9 @@ static int add_entry_items(struct super_block *sb, u64 dir_ino, u64 hash, u64 ino, umode_t mode, struct scoutfs_lock *dir_lock, struct scoutfs_lock *inode_lock) { - struct scoutfs_dirent_key rdir_dkey; - struct scoutfs_dirent_key ent_dkey; - struct scoutfs_dirent_key lb_dkey; - struct scoutfs_key_buf rdir_key; - struct scoutfs_key_buf ent_key; - struct scoutfs_key_buf lb_key; + struct scoutfs_key rdir_key; + struct scoutfs_key ent_key; + struct scoutfs_key lb_key; struct scoutfs_dirent *dent; bool del_ent = false; bool del_rdir = false; @@ -567,12 +562,9 @@ static int add_entry_items(struct super_block *sb, u64 dir_ino, u64 hash, dent->type = mode_to_type(mode); memcpy(dent->name, name, name_len); - init_dirent_key(&ent_key, &ent_dkey, SCOUTFS_DIRENT_TYPE, - dir_ino, hash, pos); - init_dirent_key(&rdir_key, &rdir_dkey, SCOUTFS_READDIR_TYPE, - dir_ino, pos, 0); - init_dirent_key(&lb_key, &lb_dkey, SCOUTFS_LINK_BACKREF_TYPE, - ino, dir_ino, pos); + init_dirent_key(&ent_key, SCOUTFS_DIRENT_TYPE, dir_ino, hash, pos); + init_dirent_key(&rdir_key, SCOUTFS_READDIR_TYPE, dir_ino, pos, 0); + init_dirent_key(&lb_key, SCOUTFS_LINK_BACKREF_TYPE, ino, dir_ino, pos); kvec_init(&val, dent, dirent_bytes(name_len)); ret = scoutfs_item_create(sb, &ent_key, &val, dir_lock); @@ -610,22 +602,16 @@ static int del_entry_items(struct super_block *sb, u64 dir_ino, u64 hash, u64 pos, u64 ino, struct scoutfs_lock *dir_lock, struct scoutfs_lock *inode_lock) { - struct scoutfs_dirent_key rdir_dkey; - struct scoutfs_dirent_key ent_dkey; - struct scoutfs_dirent_key lb_dkey; - struct scoutfs_key_buf rdir_key; - struct scoutfs_key_buf ent_key; - struct scoutfs_key_buf lb_key; + struct scoutfs_key rdir_key; + struct scoutfs_key ent_key; + struct scoutfs_key lb_key; LIST_HEAD(dir_saved); LIST_HEAD(inode_saved); int ret; - init_dirent_key(&ent_key, &ent_dkey, SCOUTFS_DIRENT_TYPE, - dir_ino, hash, pos); - init_dirent_key(&rdir_key, &rdir_dkey, SCOUTFS_READDIR_TYPE, - dir_ino, pos, 0); - init_dirent_key(&lb_key, &lb_dkey, SCOUTFS_LINK_BACKREF_TYPE, - ino, dir_ino, pos); + init_dirent_key(&ent_key, SCOUTFS_DIRENT_TYPE, dir_ino, hash, pos); + init_dirent_key(&rdir_key, SCOUTFS_READDIR_TYPE, dir_ino, pos, 0); + init_dirent_key(&lb_key, SCOUTFS_LINK_BACKREF_TYPE, ino, dir_ino, pos); ret = scoutfs_item_delete_save(sb, &ent_key, &dir_saved, dir_lock) ?: scoutfs_item_delete_save(sb, &rdir_key, &dir_saved, dir_lock) ?: @@ -959,15 +945,14 @@ unlock: return ret; } -static void init_symlink_key(struct scoutfs_key_buf *key, - struct scoutfs_symlink_key *skey, u64 ino, u8 nr) +static void init_symlink_key(struct scoutfs_key *key, u64 ino, u8 nr) { - skey->zone = SCOUTFS_FS_ZONE; - skey->ino = cpu_to_be64(ino); - skey->type = SCOUTFS_SYMLINK_TYPE; - skey->nr = nr; - - scoutfs_key_init(key, skey, sizeof(struct scoutfs_symlink_key)); + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_FS_ZONE, + .sks_ino = cpu_to_le64(ino), + .sk_type = SCOUTFS_SYMLINK_TYPE, + .sks_nr = cpu_to_le64(nr), + }; } /* @@ -991,8 +976,7 @@ static int symlink_item_ops(struct super_block *sb, int op, u64 ino, struct scoutfs_lock *lock, const char *target, size_t size) { - struct scoutfs_symlink_key skey; - struct scoutfs_key_buf key; + struct scoutfs_key key; struct kvec val; unsigned bytes; unsigned nr; @@ -1006,7 +990,7 @@ static int symlink_item_ops(struct super_block *sb, int op, u64 ino, nr = DIV_ROUND_UP(size, SCOUTFS_MAX_VAL_SIZE); for (i = 0; i < nr; i++) { - init_symlink_key(&key, &skey, ino, i); + init_symlink_key(&key, ino, i); bytes = min_t(u64, size, SCOUTFS_MAX_VAL_SIZE); kvec_init(&val, (void *)target, bytes); @@ -1213,10 +1197,8 @@ int scoutfs_dir_add_next_linkref(struct super_block *sb, u64 ino, struct list_head *list) { struct scoutfs_link_backref_entry *ent; - struct scoutfs_dirent_key last_dkey; - struct scoutfs_dirent_key dkey; - struct scoutfs_key_buf last_key; - struct scoutfs_key_buf key; + struct scoutfs_key last_key; + struct scoutfs_key key; struct scoutfs_lock *lock = NULL; struct kvec val; int len; @@ -1229,10 +1211,9 @@ int scoutfs_dir_add_next_linkref(struct super_block *sb, u64 ino, INIT_LIST_HEAD(&ent->head); - init_dirent_key(&key, &dkey, SCOUTFS_LINK_BACKREF_TYPE, - ino, dir_ino, dir_pos); - init_dirent_key(&last_key, &last_dkey, SCOUTFS_LINK_BACKREF_TYPE, - ino, U64_MAX, U64_MAX); + init_dirent_key(&key, SCOUTFS_LINK_BACKREF_TYPE, ino, dir_ino, dir_pos); + init_dirent_key(&last_key, SCOUTFS_LINK_BACKREF_TYPE, ino, U64_MAX, + U64_MAX); kvec_init(&val, &ent->dent, dirent_bytes(SCOUTFS_NAME_LEN)); ret = scoutfs_lock_ino(sb, DLM_LOCK_PR, 0, ino, &lock); @@ -1243,7 +1224,7 @@ int scoutfs_dir_add_next_linkref(struct super_block *sb, u64 ino, scoutfs_unlock(sb, lock, DLM_LOCK_PR); lock = NULL; - trace_scoutfs_dir_add_next_linkref(sb, ino, dir_ino, ret, key.key_len); + trace_scoutfs_dir_add_next_linkref(sb, ino, dir_ino, dir_pos, ret); if (ret < 0) goto out; @@ -1255,8 +1236,8 @@ int scoutfs_dir_add_next_linkref(struct super_block *sb, u64 ino, } list_add(&ent->head, list); - ent->dir_ino = be64_to_cpu(dkey.major); - ent->dir_pos = be64_to_cpu(dkey.minor); + ent->dir_ino = le64_to_cpu(key.skd_major); + ent->dir_pos = le64_to_cpu(key.skd_minor); ent->name_len = len; ret = 0; out: diff --git a/kmod/src/format.h b/kmod/src/format.h index 0509e647..27e467a5 100644 --- a/kmod/src/format.h +++ b/kmod/src/format.h @@ -52,6 +52,75 @@ struct scoutfs_block_header { __le64 blkno; } __packed; +/* + * scoutfs identifies all file system metadata items by a small key + * struct. + * + * Each item type maps their logical structures to the fixed fields in + * sort order. This lets us print keys without needing per-type + * formats. + * + * The keys are compared by considering the fields in struct order from + * most to least significant. They are considered a multi precision + * value when navigating the keys in ordered key space. We can + * increment them, subtract them from each other, etc. + */ +struct scoutfs_key { + __u8 sk_zone; + __le64 _sk_first; + __u8 sk_type; + __le64 _sk_second; + __le64 _sk_third; + __u8 _sk_fourth; +}__packed; + +/* inode index */ +#define skii_major _sk_second +#define skii_ino _sk_third + +/* node free bit map */ +#define skf_node_id _sk_first +#define skf_base _sk_second + +/* node orphan inode */ +#define sko_node_id _sk_first +#define sko_ino _sk_second + +/* inode */ +#define ski_ino _sk_first + +/* xattr parts */ +#define skx_ino _sk_first +#define skx_name_hash _sk_second +#define skx_id _sk_third +#define skx_part _sk_fourth + +/* directory entries */ +#define skd_ino _sk_first +#define skd_major _sk_second +#define skd_minor _sk_third + +/* symlink target */ +#define sks_ino _sk_first +#define sks_nr _sk_second + +/* file data mapping */ +#define skm_ino _sk_first +#define skm_base _sk_second + +/* + * 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; + /* * Assert that we'll be able to represent all possible keys with 8 64bit * primary sort values. @@ -143,34 +212,24 @@ struct scoutfs_manifest { } __packed; /* - * Manifest entries are packed into btree keys and values in a very - * fiddly way so that we can sort them with memcmp first by level then - * by their position in the level. First comes the level. + * Manifest entries are split across btree keys and values. Putting + * some entry fields in the value keeps the key smaller and increases + * the fanout of the btree which keeps the tree smaller and reduces + * block IO. * - * Level 0 segments are sorted by their seq so they don't have the first - * segment key in the manifest btree key. Both of their keys are in the - * value. - * - * Level 1 segments are sorted by their first key so their last key is - * in the value. - * - * We go to all this trouble so that we can communicate a version of the - * manifest with one btree root, have dense btree keys which are used as - * seperators in parent blocks, and don't duplicate the large keys in - * the manifest btree key and value. + * The key is made up of the level, first key, and seq. At level 0 + * segments can completely overlap and have identical key ranges but we + * avoid duplicate btree keys by including the unique seq. */ - struct scoutfs_manifest_btree_key { __u8 level; - __u8 bkey[0]; + struct scoutfs_key_be first_key; + __be64 seq; } __packed; struct scoutfs_manifest_btree_val { __le64 segno; - __le64 seq; - __le16 first_key_len; - __le16 last_key_len; - __u8 keys[0]; + struct scoutfs_key last_key; } __packed; #define SCOUTFS_ALLOC_REGION_SHIFT 8 @@ -201,15 +260,12 @@ struct scoutfs_alloc_region_btree_val { * They're not allowed to cross a block boundary. */ struct scoutfs_segment_item { - __le16 key_len; + struct scoutfs_key key; __le16 val_len; __u8 flags; __u8 nr_links; __le32 skip_links[0]; - /* - * __u8 key_bytes[key_len] - * __u8 val_bytes[val_len] - */ + /* __u8 val_bytes[val_len] */ } __packed; #define SCOUTFS_ITEM_FLAG_DELETION (1 << 0) @@ -259,30 +315,6 @@ struct scoutfs_segment_block { #define SCOUTFS_MAX_TYPE 16 /* power of 2 is efficient */ -/* value is struct scoutfs_inode */ -struct scoutfs_inode_key { - __u8 zone; - __be64 ino; - __u8 type; -} __packed; - -/* value is struct scoutfs_dirent with the name */ -struct scoutfs_dirent_key { - __u8 zone; - __be64 ino; - __u8 type; - __be64 major; - __be64 minor; -} __packed; - -/* key is bytes of encoded block mapping */ -struct scoutfs_block_mapping_key { - __u8 zone; - __be64 ino; - __u8 type; - __be64 base; -} __packed; - /* each mapping item describes a fixed number of blocks */ #define SCOUTFS_BLOCK_MAPPING_SHIFT 6 #define SCOUTFS_BLOCK_MAPPING_BLOCKS (1 << SCOUTFS_BLOCK_MAPPING_SHIFT) @@ -328,33 +360,10 @@ struct scoutfs_block_mapping_key { #define SCOUTFS_FREE_BITS_U64S \ DIV_ROUND_UP(SCOUTFS_FREE_BITS_BITS, 64) -struct scoutfs_free_bits_key { - __u8 zone; - __be64 node_id; - __u8 type; - __be64 base; -} __packed; - struct scoutfs_free_bits { __le64 bits[SCOUTFS_FREE_BITS_U64S]; } __packed; -struct scoutfs_orphan_key { - __u8 zone; - __be64 node_id; - __u8 type; - __be64 ino; -} __packed; - -struct scoutfs_xattr_key { - __u8 zone; - __be64 ino; - __u8 type; - __be32 name_hash; - __be64 id; - __u8 part; -} __packed; - /* * The first xattr part item has a header that describes the xattr. The * name and value are then packed into the following bytes in the first @@ -366,27 +375,11 @@ struct scoutfs_xattr { __u8 name[0]; } __packed; -/* size determines nr needed to store full target path in their values */ -struct scoutfs_symlink_key { - __u8 zone; - __be64 ino; - __u8 type; - __u8 nr; -} __packed; - struct scoutfs_betimespec { __be64 sec; __be32 nsec; } __packed; -struct scoutfs_inode_index_key { - __u8 zone; - __u8 type; - __be64 major; - __be32 minor; - __be64 ino; -} __packed; - /* XXX does this exist upstream somewhere? */ #define member_sizeof(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER)) @@ -514,9 +507,6 @@ enum { SCOUTFS_DT_WHT, }; -#define SCOUTFS_MAX_KEY_SIZE \ - sizeof(struct scoutfs_dirent_key) - #define SCOUTFS_MAX_VAL_SIZE SCOUTFS_BLOCK_MAPPING_MAX_BYTES #define SCOUTFS_XATTR_MAX_NAME_LEN 255 @@ -591,8 +581,8 @@ struct scoutfs_net_key_range { struct scoutfs_net_manifest_entry { __le64 segno; __le64 seq; - __le16 first_key_len; - __le16 last_key_len; + struct scoutfs_key first; + struct scoutfs_key last; __u8 level; __u8 keys[0]; } __packed; diff --git a/kmod/src/inode.c b/kmod/src/inode.c index a5ae0d0a..6708c0a8 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -247,6 +247,15 @@ static void load_inode(struct inode *inode, struct scoutfs_inode *cinode) set_item_info(ci, cinode); } +static void init_inode_key(struct scoutfs_key *key, u64 ino) +{ + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_FS_ZONE, + .ski_ino = cpu_to_le64(ino), + .sk_type = SCOUTFS_INODE_TYPE, + }; +} + /* * Refresh the vfs inode fields if the lock indicates that the current * contents could be stale. @@ -263,8 +272,7 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock, { struct scoutfs_inode_info *si = SCOUTFS_I(inode); struct super_block *sb = inode->i_sb; - struct scoutfs_key_buf key; - struct scoutfs_inode_key ikey; + struct scoutfs_key key; struct scoutfs_inode sinode; struct kvec val; const u64 refresh_gen = lock->refresh_gen; @@ -281,7 +289,7 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock, if (atomic64_read(&si->last_refreshed) == refresh_gen) return 0; - scoutfs_inode_init_key(&key, &ikey, scoutfs_ino(inode)); + init_inode_key(&key, scoutfs_ino(inode)); kvec_init(&val, &sinode, sizeof(sinode)); mutex_lock(&si->item_mutex); @@ -299,16 +307,6 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock, return ret; } -void scoutfs_inode_init_key(struct scoutfs_key_buf *key, - struct scoutfs_inode_key *ikey, u64 ino) -{ - ikey->zone = SCOUTFS_FS_ZONE; - ikey->ino = cpu_to_be64(ino); - ikey->type = SCOUTFS_INODE_TYPE; - - scoutfs_key_init(key, ikey, sizeof(struct scoutfs_inode_key)); -} - int scoutfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { @@ -694,14 +692,13 @@ static void store_inode(struct scoutfs_inode *cinode, struct inode *inode) int scoutfs_dirty_inode_item(struct inode *inode, struct scoutfs_lock *lock) { struct super_block *sb = inode->i_sb; - struct scoutfs_inode_key ikey; - struct scoutfs_key_buf key; + struct scoutfs_key key; struct scoutfs_inode sinode; int ret; store_inode(&sinode, inode); - scoutfs_inode_init_key(&key, &ikey, scoutfs_ino(inode)); + init_inode_key(&key, scoutfs_ino(inode)); ret = scoutfs_item_dirty(sb, &key, lock); if (!ret) @@ -759,13 +756,13 @@ static int cmp_index_lock(void *priv, struct list_head *A, struct list_head *B) static void clamp_inode_index(u8 type, u64 *major, u32 *minor, u64 *ino) { - struct scoutfs_inode_index_key start; + struct scoutfs_key start; scoutfs_lock_get_index_item_range(type, *major, *ino, &start, NULL); - *major = be64_to_cpu(start.major); - *minor = be32_to_cpu(start.minor); - *ino = be64_to_cpu(start.ino); + *major = le64_to_cpu(start.skii_major); + *minor = 0; + *ino = le64_to_cpu(start.skii_ino); } /* @@ -799,6 +796,17 @@ static struct scoutfs_lock *find_index_lock(struct list_head *lock_list, return NULL; } +void scoutfs_inode_init_index_key(struct scoutfs_key *key, u8 type, u64 major, + u32 minor, u64 ino) +{ + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_INODE_INDEX_ZONE, + .sk_type = type, + .skii_major = cpu_to_le64(major), + .skii_ino = cpu_to_le64(ino), + }; +} + /* * The inode info reflects the current inode index items. Create or delete * index items to bring the index in line with the caller's item. The list @@ -809,12 +817,10 @@ static int update_index_items(struct super_block *sb, u64 major, u32 minor, struct list_head *lock_list) { - struct scoutfs_inode_index_key ins_ikey; - struct scoutfs_inode_index_key del_ikey; struct scoutfs_lock *ins_lock; struct scoutfs_lock *del_lock; - struct scoutfs_key_buf ins; - struct scoutfs_key_buf del; + struct scoutfs_key ins; + struct scoutfs_key del; int ret; int err; @@ -823,12 +829,7 @@ static int update_index_items(struct super_block *sb, trace_scoutfs_create_index_item(sb, type, major, minor, ino); - ins_ikey.zone = SCOUTFS_INODE_INDEX_ZONE; - ins_ikey.type = type; - ins_ikey.major = cpu_to_be64(major); - ins_ikey.minor = cpu_to_be32(minor); - ins_ikey.ino = cpu_to_be64(ino); - scoutfs_key_init(&ins, &ins_ikey, sizeof(ins_ikey)); + scoutfs_inode_init_index_key(&ins, type, major, minor, ino); ins_lock = find_index_lock(lock_list, type, major, minor, ino); ret = scoutfs_item_create_force(sb, &ins, NULL, ins_lock); @@ -838,12 +839,8 @@ static int update_index_items(struct super_block *sb, trace_scoutfs_delete_index_item(sb, type, si->item_majors[type], si->item_minors[type], ino); - del_ikey.zone = SCOUTFS_INODE_INDEX_ZONE; - del_ikey.type = type; - del_ikey.major = cpu_to_be64(si->item_majors[type]); - del_ikey.minor = cpu_to_be32(si->item_minors[type]); - del_ikey.ino = cpu_to_be64(ino); - scoutfs_key_init(&del, &del_ikey, sizeof(del_ikey)); + scoutfs_inode_init_index_key(&del, type, si->item_majors[type], + si->item_minors[type], ino); del_lock = find_index_lock(lock_list, type, si->item_majors[type], si->item_minors[type], ino); @@ -906,8 +903,7 @@ void scoutfs_update_inode_item(struct inode *inode, struct scoutfs_lock *lock, struct scoutfs_inode_info *si = SCOUTFS_I(inode); struct super_block *sb = inode->i_sb; const u64 ino = scoutfs_ino(inode); - struct scoutfs_inode_key ikey; - struct scoutfs_key_buf key; + struct scoutfs_key key; struct scoutfs_inode sinode; struct kvec val; int ret; @@ -924,7 +920,7 @@ void scoutfs_update_inode_item(struct inode *inode, struct scoutfs_lock *lock, ret = update_indices(sb, si, ino, inode->i_mode, &sinode, lock_list); BUG_ON(ret); - scoutfs_inode_init_key(&key, &ikey, ino); + init_inode_key(&key, ino); kvec_init(&val, &sinode, sizeof(sinode)); err = scoutfs_item_update(sb, &key, &val, lock); @@ -1195,17 +1191,11 @@ void scoutfs_inode_index_unlock(struct super_block *sb, struct list_head *list) static int remove_index(struct super_block *sb, u64 ino, u8 type, u64 major, u32 minor, struct list_head *ind_locks) { - struct scoutfs_inode_index_key ikey; - struct scoutfs_key_buf key; + struct scoutfs_key key; struct scoutfs_lock *lock; int ret; - ikey.zone = SCOUTFS_INODE_INDEX_ZONE; - ikey.type = type; - ikey.major = cpu_to_be64(major); - ikey.minor = cpu_to_be32(minor); - ikey.ino = cpu_to_be64(ino); - scoutfs_key_init(&key, &ikey, sizeof(ikey)); + scoutfs_inode_init_index_key(&key, type, major, minor, ino); lock = find_index_lock(ind_locks, type, major, minor, ino); ret = scoutfs_item_delete_force(sb, &key, lock); @@ -1311,8 +1301,7 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir, struct scoutfs_lock *lock) { struct scoutfs_inode_info *ci; - struct scoutfs_inode_key ikey; - struct scoutfs_key_buf key; + struct scoutfs_key key; struct scoutfs_inode sinode; struct inode *inode; struct kvec val; @@ -1346,7 +1335,7 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir, set_inode_ops(inode); store_inode(&sinode, inode); - scoutfs_inode_init_key(&key, &ikey, scoutfs_ino(inode)); + init_inode_key(&key, scoutfs_ino(inode)); kvec_init(&val, &sinode, sizeof(sinode)); ret = scoutfs_item_create(sb, &key, &val, lock); @@ -1358,26 +1347,24 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir, return inode; } -static void init_orphan_key(struct scoutfs_key_buf *key, - struct scoutfs_orphan_key *okey, u64 node_id, u64 ino) +static void init_orphan_key(struct scoutfs_key *key, u64 node_id, u64 ino) { - okey->zone = SCOUTFS_NODE_ZONE; - okey->node_id = cpu_to_be64(node_id); - okey->type = SCOUTFS_ORPHAN_TYPE; - okey->ino = cpu_to_be64(ino); - - scoutfs_key_init(key, okey, sizeof(struct scoutfs_orphan_key)); + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_NODE_ZONE, + .sko_node_id = cpu_to_le64(node_id), + .sk_type = SCOUTFS_ORPHAN_TYPE, + .sko_ino = cpu_to_le64(ino), + }; } static int remove_orphan_item(struct super_block *sb, u64 ino) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_lock *lock = sbi->node_id_lock; - struct scoutfs_orphan_key okey; - struct scoutfs_key_buf key; + struct scoutfs_key key; int ret; - init_orphan_key(&key, &okey, sbi->node_id, ino); + init_orphan_key(&key, sbi->node_id, ino); ret = scoutfs_item_delete(sb, &key, lock); if (ret == -ENOENT) @@ -1397,9 +1384,8 @@ static int remove_orphan_item(struct super_block *sb, u64 ino) static int delete_inode_items(struct super_block *sb, u64 ino) { struct scoutfs_lock *lock = NULL; - struct scoutfs_inode_key ikey; struct scoutfs_inode sinode; - struct scoutfs_key_buf key; + struct scoutfs_key key; LIST_HEAD(ind_locks); bool release = false; struct kvec val; @@ -1411,7 +1397,7 @@ static int delete_inode_items(struct super_block *sb, u64 ino) if (ret) return ret; - scoutfs_inode_init_key(&key, &ikey, ino); + init_inode_key(&key, ino); kvec_init(&val, &sinode, sizeof(sinode)); ret = scoutfs_item_lookup_exact(sb, &key, &val, lock); @@ -1520,30 +1506,32 @@ int scoutfs_scan_orphans(struct super_block *sb) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_lock *lock = sbi->node_id_lock; - struct scoutfs_orphan_key okey; - struct scoutfs_orphan_key last_okey; - struct scoutfs_key_buf key; - struct scoutfs_key_buf last; + struct scoutfs_key key; + struct scoutfs_key last; int err = 0; int ret; trace_scoutfs_scan_orphans(sb); - init_orphan_key(&key, &okey, sbi->node_id, 0); - init_orphan_key(&last, &last_okey, sbi->node_id, ~0ULL); + init_orphan_key(&key, sbi->node_id, 0); + init_orphan_key(&last, sbi->node_id, ~0ULL); while (1) { - ret = scoutfs_item_next_same(sb, &key, &last, NULL, lock); + ret = scoutfs_item_next(sb, &key, &last, NULL, lock); if (ret == -ENOENT) /* No more orphan items */ break; if (ret < 0) goto out; - ret = delete_inode_items(sb, be64_to_cpu(okey.ino)); + ret = delete_inode_items(sb, le64_to_cpu(key.sko_ino)); if (ret && ret != -ENOENT && !err) err = ret; - scoutfs_key_inc_cur_len(&key); + if (le64_to_cpu(key.sko_ino) == U64_MAX) { + ret = -ENOENT; + break; + } + le64_add_cpu(&key.sko_ino, 1); } ret = 0; @@ -1556,13 +1544,12 @@ int scoutfs_orphan_inode(struct inode *inode) struct super_block *sb = inode->i_sb; struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_lock *lock = sbi->node_id_lock; - struct scoutfs_orphan_key okey; - struct scoutfs_key_buf key; + struct scoutfs_key key; int ret; trace_scoutfs_orphan_inode(sb, inode); - init_orphan_key(&key, &okey, sbi->node_id, scoutfs_ino(inode)); + init_orphan_key(&key, sbi->node_id, scoutfs_ino(inode)); ret = scoutfs_item_create(sb, &key, NULL, lock); diff --git a/kmod/src/inode.h b/kmod/src/inode.h index 39313955..d46f24d1 100644 --- a/kmod/src/inode.h +++ b/kmod/src/inode.h @@ -5,6 +5,7 @@ #include "lock.h" #include "per_task.h" #include "count.h" +#include "format.h" struct scoutfs_lock; @@ -62,9 +63,6 @@ static inline u64 scoutfs_ino(struct inode *inode) return SCOUTFS_I(inode)->ino; } -void scoutfs_inode_init_key(struct scoutfs_key_buf *key, - struct scoutfs_inode_key *ikey, u64 ino); - struct inode *scoutfs_alloc_inode(struct super_block *sb); void scoutfs_destroy_inode(struct inode *inode); int scoutfs_drop_inode(struct inode *inode); @@ -74,6 +72,8 @@ int scoutfs_orphan_inode(struct inode *inode); struct inode *scoutfs_iget(struct super_block *sb, u64 ino); struct inode *scoutfs_ilookup(struct super_block *sb, u64 ino); +void scoutfs_inode_init_index_key(struct scoutfs_key *key, u8 type, u64 major, + u32 minor, u64 ino); int scoutfs_inode_index_start(struct super_block *sb, u64 *seq); int scoutfs_inode_index_prepare(struct super_block *sb, struct list_head *list, struct inode *inode, bool set_data_seq); diff --git a/kmod/src/ioctl.c b/kmod/src/ioctl.c index fdfabab6..bd135650 100644 --- a/kmod/src/ioctl.c +++ b/kmod/src/ioctl.c @@ -55,11 +55,9 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg) struct scoutfs_ioctl_walk_inodes __user *uwalk = (void __user *)arg; struct scoutfs_ioctl_walk_inodes walk; struct scoutfs_ioctl_walk_inodes_entry ent; - struct scoutfs_inode_index_key last_ikey; - struct scoutfs_inode_index_key ikey; - struct scoutfs_key_buf *next_key; - struct scoutfs_key_buf last_key; - struct scoutfs_key_buf key; + struct scoutfs_key next_key; + struct scoutfs_key last_key; + struct scoutfs_key key; struct scoutfs_lock *lock; u64 last_seq; int ret = 0; @@ -93,23 +91,10 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg) } } - next_key = scoutfs_key_alloc(sb, SCOUTFS_MAX_KEY_SIZE); - if (!next_key) - return -ENOMEM; - - ikey.zone = SCOUTFS_INODE_INDEX_ZONE; - ikey.type = type; - ikey.major = cpu_to_be64(walk.first.major); - ikey.minor = cpu_to_be32(walk.first.minor); - ikey.ino = cpu_to_be64(walk.first.ino); - scoutfs_key_init(&key, &ikey, sizeof(ikey)); - - last_ikey.zone = ikey.zone; - last_ikey.type = ikey.type; - last_ikey.major = cpu_to_be64(walk.last.major); - last_ikey.minor = cpu_to_be32(walk.last.minor); - last_ikey.ino = cpu_to_be64(walk.last.ino); - scoutfs_key_init(&last_key, &last_ikey, sizeof(last_ikey)); + scoutfs_inode_init_index_key(&key, type, walk.first.major, + walk.first.minor, walk.first.ino); + scoutfs_inode_init_index_key(&last_key, type, walk.last.major, + walk.last.minor, walk.last.ino); /* cap nr to the max the ioctl can return to a compat task */ walk.nr_entries = min_t(u64, walk.nr_entries, INT_MAX); @@ -121,21 +106,21 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg) for (nr = 0; nr < walk.nr_entries; ) { - ret = scoutfs_item_next_same(sb, &key, &last_key, NULL, lock); + ret = scoutfs_item_next(sb, &key, &last_key, NULL, lock); if (ret < 0 && ret != -ENOENT) break; if (ret == -ENOENT) { /* done if lock covers last iteration key */ - if (scoutfs_key_compare(&last_key, lock->end) <= 0) { + if (scoutfs_key_compare(&last_key, &lock->end) <= 0) { ret = 0; break; } /* continue iterating after locked empty region */ - scoutfs_key_copy(&key, lock->end); - scoutfs_key_inc_cur_len(&key); + key = lock->end; + scoutfs_key_inc(&key); scoutfs_unlock(sb, lock, DLM_LOCK_PR); @@ -146,37 +131,32 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg) * It'd mean adding a lock to the inode index * items which isn't quite there yet. */ - ret = scoutfs_manifest_next_key(sb, &key, next_key); + ret = scoutfs_manifest_next_key(sb, &key, &next_key); if (ret < 0 && ret != -ENOENT) goto out; if (ret == -ENOENT || - scoutfs_key_compare(next_key, &last_key) > 0) { + scoutfs_key_compare(&next_key, &last_key) > 0) { ret = 0; goto out; } - /* if it's within last it should be same size */ - if (next_key->key_len != key.key_len) { - ret = -EIO; - goto out; - } + key = next_key; - scoutfs_key_copy(&key, next_key); - - ret = scoutfs_lock_inode_index(sb, DLM_LOCK_PR, ikey.type, - be64_to_cpu(ikey.major), - be64_to_cpu(ikey.ino), - &lock); + ret = scoutfs_lock_inode_index(sb, DLM_LOCK_PR, + key.sk_type, + le64_to_cpu(key.skii_major), + le64_to_cpu(key.skii_ino), + &lock); if (ret < 0) goto out; continue; } - ent.major = be64_to_cpu(ikey.major); - ent.minor = be32_to_cpu(ikey.minor); - ent.ino = be64_to_cpu(ikey.ino); + ent.major = le64_to_cpu(key.skii_major); + ent.minor = 0; + ent.ino = le64_to_cpu(key.skii_ino); if (copy_to_user((void __user *)walk.entries_ptr, &ent, sizeof(ent))) { @@ -187,14 +167,12 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg) nr++; walk.entries_ptr += sizeof(ent); - scoutfs_key_inc_cur_len(&key); + scoutfs_key_inc(&key); } scoutfs_unlock(sb, lock, DLM_LOCK_PR); out: - scoutfs_key_free(sb, next_key); - if (nr > 0) ret = nr; @@ -499,66 +477,47 @@ static long scoutfs_ioc_item_cache_keys(struct file *file, unsigned long arg) { struct super_block *sb = file_inode(file)->i_sb; struct scoutfs_ioctl_item_cache_keys ick; - struct scoutfs_key_buf *key; - struct page *page; - unsigned bytes; - void *buf; + struct scoutfs_key __user *ukeys; + struct scoutfs_key keys[16]; + unsigned int nr; int total; int ret; if (copy_from_user(&ick, (void __user *)arg, sizeof(ick))) return -EFAULT; - if ((!!ick.key_ptr != !!ick.key_len) || - ick.key_len > SCOUTFS_MAX_KEY_SIZE || - ick.which > SCOUTFS_IOC_ITEM_CACHE_KEYS_RANGES) + if (ick.which > SCOUTFS_IOC_ITEM_CACHE_KEYS_RANGES) return -EINVAL; - /* don't overflow signed 32bit syscall return longs */ - ick.buf_len = min_t(u64, ick.buf_len, S32_MAX); - - key = scoutfs_key_alloc(sb, SCOUTFS_MAX_KEY_SIZE); - page = alloc_page(GFP_KERNEL); - if (!key || !page) { - ret = -ENOMEM; - goto out; - } - - if (copy_from_user(key->data, (void __user *)ick.key_ptr, ick.key_len)) { - ret = -EFAULT; - goto out; - } - scoutfs_key_init_buf_len(key, key->data, ick.key_len, - SCOUTFS_MAX_KEY_SIZE); - scoutfs_key_inc(key); - - buf = page_address(page); + ukeys = (void __user *)(long)ick.buf_ptr; total = 0; ret = 0; - while (ick.buf_len) { - bytes = min_t(u64, ick.buf_len, PAGE_SIZE); + while (ick.buf_nr) { + nr = min_t(size_t, ick.buf_nr, ARRAY_SIZE(keys)); if (ick.which == SCOUTFS_IOC_ITEM_CACHE_KEYS_ITEMS) - ret = scoutfs_item_copy_keys(sb, key, buf, bytes); + ret = scoutfs_item_copy_keys(sb, &ick.key, keys, nr); else - ret = scoutfs_item_copy_range_keys(sb, key, buf, bytes); - - if (ret > 0 && copy_to_user((void __user *)ick.buf_ptr, buf, ret)) - ret = -EFAULT; + ret = scoutfs_item_copy_range_keys(sb, &ick.key, keys, + nr); + BUG_ON(ret > nr); /* stack overflow \o/ */ if (ret <= 0) break; - ick.buf_len -= ret; - ick.buf_ptr += ret; + if (copy_to_user(ukeys, keys, ret * sizeof(keys[0]))) { + ret = -EFAULT; + break; + } + + ick.key = keys[ret - 1]; + scoutfs_key_inc(&ick.key); + + ukeys += ret; + ick.buf_nr -= ret; total += ret; ret = 0; } -out: - scoutfs_key_free(sb, key); - if (page) - __free_page(page); - return ret ?: total; } diff --git a/kmod/src/ioctl.h b/kmod/src/ioctl.h index 721f1cde..915a130b 100644 --- a/kmod/src/ioctl.h +++ b/kmod/src/ioctl.h @@ -208,11 +208,16 @@ struct scoutfs_ioctl_stat_more { #define SCOUTFS_IOC_STAT_MORE _IOW(SCOUTFS_IOCTL_MAGIC, 7, \ struct scoutfs_ioctl_stat_more) +/* + * Fills the buffer with either the keys for the cached items or the + * keys for the cached ranges found starting with the given key. The + * number of keys filled in the buffer is returned. When filling range + * keys the returned number will always be a multiple of two. + */ struct scoutfs_ioctl_item_cache_keys { - __u64 key_ptr; - __u64 key_len; + struct scoutfs_key key; __u64 buf_ptr; - __u64 buf_len; + __u16 buf_nr; __u8 which; } __packed; diff --git a/kmod/src/item.c b/kmod/src/item.c index af78d0f2..86697a31 100644 --- a/kmod/src/item.c +++ b/kmod/src/item.c @@ -41,10 +41,9 @@ * clobber them in creation and skip them in lookups. */ -static bool invalid_key_val(struct scoutfs_key_buf *key, struct kvec *val) +static bool invalid_key_val(struct scoutfs_key *key, struct kvec *val) { - return WARN_ON_ONCE(key->key_len > SCOUTFS_MAX_KEY_SIZE || - (val && (val->iov_len > SCOUTFS_MAX_VAL_SIZE))); + return WARN_ON_ONCE(val && (val->iov_len > SCOUTFS_MAX_VAL_SIZE)); } struct item_cache { @@ -55,7 +54,6 @@ struct item_cache { struct rb_root ranges; long nr_dirty_items; - long dirty_key_bytes; long dirty_val_bytes; struct shrinker shrinker; @@ -78,7 +76,7 @@ struct cached_item { long dirty; unsigned deletion:1; - struct scoutfs_key_buf *key; + struct scoutfs_key key; void *val; unsigned int val_len; }; @@ -86,12 +84,12 @@ struct cached_item { struct cached_range { struct rb_node node; - struct scoutfs_key_buf *start; - struct scoutfs_key_buf *end; + struct scoutfs_key start; + struct scoutfs_key end; }; #define trace_range(which, sb, rng) \ - trace_scoutfs_item_range_##which(sb, (rng), (rng)->start, (rng)->end) + trace_scoutfs_item_range_##which(sb, (rng), &(rng)->start, &(rng)->end) static u8 item_flags(struct cached_item *item) { @@ -104,7 +102,6 @@ static void free_item(struct super_block *sb, struct cached_item *item) scoutfs_inc_counter(sb, item_free); WARN_ON_ONCE(!list_empty(&item->entry)); WARN_ON_ONCE(!RB_EMPTY_NODE(&item->node)); - scoutfs_key_free(sb, item->key); kfree(item->val); kfree(item); } @@ -116,33 +113,32 @@ static void free_item(struct super_block *sb, struct cached_item *item) * them in place when updating items. */ static struct cached_item *alloc_item(struct super_block *sb, - struct scoutfs_key_buf *key, + struct scoutfs_key *key, struct kvec *val) { struct cached_item *item; item = kzalloc(sizeof(struct cached_item), GFP_NOFS); - if (item) { - RB_CLEAR_NODE(&item->node); - INIT_LIST_HEAD(&item->entry); + if (!item) + goto out; - item->key = scoutfs_key_dup(sb, key); - if (val) { - item->val = kmalloc(val->iov_len, GFP_NOFS); - item->val_len = val->iov_len; - if (item->val) - memcpy(item->val, val->iov_base, val->iov_len); - } + item->key = *key; + RB_CLEAR_NODE(&item->node); + INIT_LIST_HEAD(&item->entry); - if (!item->key || (val && !item->val)) { + if (val) { + item->val = kmalloc(val->iov_len, GFP_NOFS); + if (!item->val) { free_item(sb, item); item = NULL; + goto out; } + item->val_len = val->iov_len; + memcpy(item->val, val->iov_base, val->iov_len); } - if (item) - scoutfs_inc_counter(sb, item_alloc); - + scoutfs_inc_counter(sb, item_alloc); +out: return item; } @@ -170,7 +166,7 @@ static int copy_item_val(struct kvec *val, struct cached_item *item) * prev items. */ static struct cached_item *walk_items(struct rb_root *root, - struct scoutfs_key_buf *key, + struct scoutfs_key *key, struct cached_item **prev, struct cached_item **next) { @@ -184,7 +180,7 @@ static struct cached_item *walk_items(struct rb_root *root, while (node) { item = container_of(node, struct cached_item, node); - cmp = scoutfs_key_compare(key, item->key); + cmp = scoutfs_key_compare(key, &item->key); if (cmp < 0) { *next = item; node = node->rb_left; @@ -209,7 +205,7 @@ static struct cached_item *walk_items(struct rb_root *root, */ static struct cached_item *find_item(struct super_block *sb, struct rb_root *root, - struct scoutfs_key_buf *key) + struct scoutfs_key *key) { struct cached_item *prev; struct cached_item *next; @@ -229,7 +225,7 @@ static struct cached_item *find_item(struct super_block *sb, } static struct cached_item *next_item(struct rb_root *root, - struct scoutfs_key_buf *key) + struct scoutfs_key *key) { struct cached_item *prev; struct cached_item *next; @@ -342,16 +338,15 @@ static void update_dirty_parents(struct cached_item *item) } static void update_dirty_item_counts(struct super_block *sb, signed items, - signed keys, signed vals) + signed vals) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; cac->nr_dirty_items += items; - cac->dirty_key_bytes += keys; cac->dirty_val_bytes += vals; - scoutfs_trans_track_item(sb, items, keys, vals); + scoutfs_trans_track_item(sb, items, vals); } static void mark_item_dirty(struct super_block *sb, struct item_cache *cac, @@ -367,7 +362,7 @@ static void mark_item_dirty(struct super_block *sb, struct item_cache *cac, list_del_init(&item->entry); cac->lru_nr--; - update_dirty_item_counts(sb, 1, item->key->key_len, item->val_len); + update_dirty_item_counts(sb, 1, item->val_len); update_dirty_parents(item); } @@ -384,10 +379,9 @@ static void clear_item_dirty(struct super_block *sb, struct item_cache *cac, list_add_tail(&item->entry, &cac->lru_list); cac->lru_nr++; - update_dirty_item_counts(sb, -1, -item->key->key_len, -item->val_len); + update_dirty_item_counts(sb, -1, -item->val_len); - WARN_ON_ONCE(cac->nr_dirty_items < 0 || cac->dirty_key_bytes < 0 || - cac->dirty_val_bytes < 0); + WARN_ON_ONCE(cac->nr_dirty_items < 0 || cac->dirty_val_bytes < 0); update_dirty_parents(item); } @@ -477,7 +471,7 @@ restart: parent = *node; item = container_of(*node, struct cached_item, node); - cmp = scoutfs_key_compare(ins->key, item->key); + cmp = scoutfs_key_compare(&ins->key, &item->key); if (cmp < 0) { if (ins->dirty) item->dirty |= LEFT_DIRTY; @@ -497,7 +491,7 @@ restart: } } - trace_scoutfs_item_insertion(sb, ins->key); + trace_scoutfs_item_insertion(sb, &ins->key); rb_link_node(&ins->node, parent, node); rb_insert_augmented(&ins->node, root, &scoutfs_item_rb_cb); @@ -530,7 +524,7 @@ static struct cached_range *rb_next_rng(struct cached_range *rng) } static struct cached_range *walk_ranges(struct rb_root *root, - struct scoutfs_key_buf *key, + struct scoutfs_key *key, struct cached_range **prev, struct cached_range **next) { @@ -547,7 +541,7 @@ static struct cached_range *walk_ranges(struct rb_root *root, rng = container_of(node, struct cached_range, node); cmp = scoutfs_key_compare_ranges(key, key, - rng->start, rng->end); + &rng->start, &rng->end); if (cmp < 0) { if (next) *next = rng; @@ -573,8 +567,8 @@ static struct cached_range *walk_ranges(struct rb_root *root, * cached range. */ static bool check_range(struct super_block *sb, struct rb_root *root, - struct scoutfs_key_buf *key, - struct scoutfs_key_buf *end) + struct scoutfs_key *key, + struct scoutfs_key *end) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; @@ -585,15 +579,15 @@ static bool check_range(struct super_block *sb, struct rb_root *root, if (rng) { scoutfs_inc_counter(sb, item_range_hit); if (end) - scoutfs_key_copy(end, rng->end); + *end = rng->end; return true; } if (end) { if (next) - scoutfs_key_copy(end, next->start); + *end = next->start; else - scoutfs_key_set_max(end); + scoutfs_key_set_ones(end); } scoutfs_inc_counter(sb, item_range_miss); @@ -605,8 +599,6 @@ static void free_range(struct super_block *sb, struct cached_range *rng) if (!IS_ERR_OR_NULL(rng)) { scoutfs_inc_counter(sb, item_range_free); trace_range(free, sb, rng); - scoutfs_key_free(sb, rng->start); - scoutfs_key_free(sb, rng->end); kfree(rng); } } @@ -638,8 +630,8 @@ restart: parent = *node; rng = container_of(*node, struct cached_range, node); - cmp = scoutfs_key_compare_ranges(ins->start, ins->end, - rng->start, rng->end); + cmp = scoutfs_key_compare_ranges(&ins->start, &ins->end, + &rng->start, &rng->end); /* simple iteration until we overlap */ if (cmp < 0) { node = &(*node)->rb_left; @@ -649,8 +641,8 @@ restart: continue; } - start_cmp = scoutfs_key_compare(ins->start, rng->start); - end_cmp = scoutfs_key_compare(ins->end, rng->end); + start_cmp = scoutfs_key_compare(&ins->start, &rng->start); + end_cmp = scoutfs_key_compare(&ins->end, &rng->end); /* free our insertion if we're entirely within an existing */ if (start_cmp >= 0 && end_cmp <= 0) { @@ -709,8 +701,8 @@ restart: parent = *node; rng = container_of(*node, struct cached_range, node); - cmp = scoutfs_key_compare_ranges(rem->start, rem->end, - rng->start, rng->end); + cmp = scoutfs_key_compare_ranges(&rem->start, &rem->end, + &rng->start, &rng->end); /* simple iteration until we overlap */ if (cmp < 0) { node = &(*node)->rb_left; @@ -720,17 +712,17 @@ restart: continue; } - start_cmp = scoutfs_key_compare(rem->start, rng->start); - end_cmp = scoutfs_key_compare(rem->end, rng->end); + start_cmp = scoutfs_key_compare(&rem->start, &rng->start); + end_cmp = scoutfs_key_compare(&rem->end, &rng->end); /* remove the middle of an existing range, insert other half */ if (start_cmp > 0 && end_cmp < 0) { swap(rng->end, rem->start); - scoutfs_key_dec(rng->end); + scoutfs_key_dec(&rng->end); trace_range(remove_mid_left, sb, rng); swap(rem->start, rem->end); - scoutfs_key_inc(rem->start); + scoutfs_key_inc(&rem->start); insert = true; goto restart; } @@ -738,14 +730,14 @@ restart: /* remove partial overlap from existing */ if (start_cmp < 0 && end_cmp < 0) { swap(rem->end, rng->start); - scoutfs_key_inc(rng->start); + scoutfs_key_inc(&rng->start); trace_range(remove_start, sb, rng); continue; } if (start_cmp > 0 && end_cmp > 0) { swap(rem->start, rng->end); - scoutfs_key_dec(rng->end); + scoutfs_key_dec(&rng->end); trace_range(remove_end, sb, rng); continue; } @@ -765,26 +757,16 @@ restart: } } -/* - * Return true if the lock protects the use of the key. Some locks not - * intended for item use don't have a key range and we want to safely - * detect that. The lock mode dereference is racy but the field always - * contains a single non-zero byte. - */ +/* Return true if the lock protects the use of the key. */ static bool lock_coverage(struct scoutfs_lock *lock, - struct scoutfs_key_buf *key, int op_mode) + struct scoutfs_key *key, int op_mode) { - signed char mode; - - if (!lock || !lock->start || !lock->end) - return false; - - mode = ACCESS_ONCE(lock->granted_mode); + signed char mode = ACCESS_ONCE(lock->granted_mode); return ((op_mode == mode) || (op_mode == DLM_LOCK_PR && mode == DLM_LOCK_EX)) && scoutfs_key_compare_ranges(key, key, - lock->start, lock->end) == 0; + &lock->start, &lock->end) == 0; } /* @@ -795,7 +777,7 @@ static bool lock_coverage(struct scoutfs_lock *lock, * The end key limits how many keys after the search key can be read * and inserted into the cache. */ -int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key_buf *key, +int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key *key, struct kvec *val, struct scoutfs_lock *lock) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); @@ -828,8 +810,8 @@ int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key_buf *key, spin_unlock_irqrestore(&cac->lock, flags); } while (ret == -ENODATA && - (ret = scoutfs_manifest_read_items(sb, key, lock->start, - lock->end)) == 0); + (ret = scoutfs_manifest_read_items(sb, key, &lock->start, + &lock->end)) == 0); trace_scoutfs_item_lookup_ret(sb, ret); return ret; @@ -849,7 +831,7 @@ int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key_buf *key, * Returns 0 or -errno. */ int scoutfs_item_lookup_exact(struct super_block *sb, - struct scoutfs_key_buf *key, struct kvec *val, + struct scoutfs_key *key, struct kvec *val, struct scoutfs_lock *lock) { int ret; @@ -869,7 +851,7 @@ int scoutfs_item_lookup_exact(struct super_block *sb, */ static struct cached_item *next_item_node(struct rb_root *root, struct cached_item *item, - struct scoutfs_key_buf *last) + struct scoutfs_key *last) { struct rb_node *node; @@ -882,7 +864,7 @@ static struct cached_item *next_item_node(struct rb_root *root, item = container_of(node, struct cached_item, node); - if (scoutfs_key_compare(item->key, last) > 0) { + if (scoutfs_key_compare(&item->key, last) > 0) { item = NULL; break; } @@ -900,9 +882,9 @@ static struct cached_item *next_item_node(struct rb_root *root, * bounds of the end of the cache and the caller's last key. */ static struct cached_item *item_for_next(struct rb_root *root, - struct scoutfs_key_buf *key, - struct scoutfs_key_buf *range_end, - struct scoutfs_key_buf *last) + struct scoutfs_key *key, + struct scoutfs_key *range_end, + struct scoutfs_key *last) { struct cached_item *item; @@ -912,7 +894,7 @@ static struct cached_item *item_for_next(struct rb_root *root, item = next_item(root, key); if (item) { - if (scoutfs_key_compare(item->key, last) > 0) + if (scoutfs_key_compare(&item->key, last) > 0) item = NULL; else if (item->deletion) item = next_item_node(root, item, last); @@ -941,22 +923,22 @@ static struct cached_item *item_for_next(struct rb_root *root, * of value bytes copied is returned. The copied value can be truncated * by the caller's value buffer length. */ -int scoutfs_item_next(struct super_block *sb, struct scoutfs_key_buf *key, - struct scoutfs_key_buf *last, struct kvec *val, +int scoutfs_item_next(struct super_block *sb, struct scoutfs_key *key, + struct scoutfs_key *last, struct kvec *val, struct scoutfs_lock *lock) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; - struct scoutfs_key_buf *pos = NULL; - struct scoutfs_key_buf *range_end = NULL; + struct scoutfs_key pos; + struct scoutfs_key range_end; struct cached_item *item; unsigned long flags; bool cached; int ret; /* use the end key as the last key if it's closer to reduce compares */ - if (scoutfs_key_compare(lock->end, last) < 0) - last = lock->end; + if (scoutfs_key_compare(&lock->end, last) < 0) + last = &lock->end; /* convenience to avoid searching if caller iterates past their last */ if (scoutfs_key_compare(key, last) > 0) { @@ -969,31 +951,25 @@ int scoutfs_item_next(struct super_block *sb, struct scoutfs_key_buf *key, goto out; } - pos = scoutfs_key_alloc(sb, SCOUTFS_MAX_KEY_SIZE); - range_end = scoutfs_key_alloc(sb, SCOUTFS_MAX_KEY_SIZE); - if (!pos || !range_end) { - ret = -ENOMEM; - goto out; - } - - scoutfs_key_copy(pos, key); + pos = *key; spin_lock_irqsave(&cac->lock, flags); for(;;) { /* see if we have cache coverage of our iterator pos */ - cached = check_range(sb, &cac->ranges, pos, range_end); + cached = check_range(sb, &cac->ranges, &pos, &range_end); trace_scoutfs_item_next_range_check(sb, !!cached, key, - pos, last, lock->end, - range_end); + &pos, last, &lock->end, + &range_end); if (!cached) { /* populate missing cached range starting at pos */ spin_unlock_irqrestore(&cac->lock, flags); - ret = scoutfs_manifest_read_items(sb, pos, lock->start, - lock->end); + ret = scoutfs_manifest_read_items(sb, &pos, + &lock->start, + &lock->end); spin_lock_irqsave(&cac->lock, flags); if (ret) @@ -1003,12 +979,12 @@ int scoutfs_item_next(struct super_block *sb, struct scoutfs_key_buf *key, } /* see if there's an item in the cached range from pos */ - item = item_for_next(&cac->items, pos, range_end, last); + item = item_for_next(&cac->items, &pos, &range_end, last); if (!item) { - if (scoutfs_key_compare(range_end, last) < 0) { + if (scoutfs_key_compare(&range_end, last) < 0) { /* keep searching after empty cached range */ - scoutfs_key_copy(pos, range_end); - scoutfs_key_inc(pos); + pos = range_end; + scoutfs_key_inc(&pos); continue; } @@ -1018,7 +994,7 @@ int scoutfs_item_next(struct super_block *sb, struct scoutfs_key_buf *key, } /* we have a next item inside the cached range, done */ - scoutfs_key_copy(key, item->key); + *key = item->key; if (val) { item_referenced(cac, item); ret = copy_item_val(val, item); @@ -1030,71 +1006,17 @@ int scoutfs_item_next(struct super_block *sb, struct scoutfs_key_buf *key, spin_unlock_irqrestore(&cac->lock, flags); out: - scoutfs_key_free(sb, pos); - scoutfs_key_free(sb, range_end); trace_scoutfs_item_next_ret(sb, ret); return ret; } -/* - * Like _next but requires that the found keys be the same length as the - * search key and that values be of at least a minimum size. It treats - * size mismatches as a sign of corruption and returns -EIO. - */ -int scoutfs_item_next_same_min(struct super_block *sb, - struct scoutfs_key_buf *key, - struct scoutfs_key_buf *last, - struct kvec *val, int len, - struct scoutfs_lock *lock) -{ - int key_len = key->key_len; - int ret; - - trace_scoutfs_item_next_same_min(sb, key_len, len); - - if (WARN_ON_ONCE(!val || val->iov_len < len)) - return -EINVAL; - - ret = scoutfs_item_next(sb, key, last, val, lock); - if (ret >= 0 && (key->key_len != key_len || ret < len)) - ret = -EIO; - - trace_scoutfs_item_next_same_min_ret(sb, ret); - - return ret; -} - -/* - * Like _next but requires that the found keys be the same length as the - * search key. It treats size mismatches as a sign of corruption. - */ -int scoutfs_item_next_same(struct super_block *sb, struct scoutfs_key_buf *key, - struct scoutfs_key_buf *last, struct kvec *val, - struct scoutfs_lock *lock) -{ - int key_len = key->key_len; - int ret; - - trace_scoutfs_item_next_same(sb, key_len); - - ret = scoutfs_item_next(sb, key, last, val, lock); - if (ret >= 0 && (key->key_len != key_len)) - ret = -EIO; - - trace_scoutfs_item_next_same_ret(sb, ret); - - return ret; -} - /* * Create a new dirty item in the cache. Returns -EEXIST if an item * already exists with the given key. - * - * XXX but it doesn't read.. is that weird? Seems weird. */ -int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key, - struct kvec *val, struct scoutfs_lock *lock) +int scoutfs_item_create(struct super_block *sb, struct scoutfs_key *key, + struct kvec *val, struct scoutfs_lock *lock) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; @@ -1128,8 +1050,8 @@ int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key, spin_unlock_irqrestore(&cac->lock, flags); } while (ret == -ENODATA && - (ret = scoutfs_manifest_read_items(sb, key, lock->start, - lock->end)) == 0); + (ret = scoutfs_manifest_read_items(sb, key, &lock->start, + &lock->end)) == 0); if (ret) free_item(sb, item); @@ -1138,7 +1060,7 @@ int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key, } int scoutfs_item_create_force(struct super_block *sb, - struct scoutfs_key_buf *key, + struct scoutfs_key *key, struct kvec *val, struct scoutfs_lock *lock) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); @@ -1161,10 +1083,9 @@ int scoutfs_item_create_force(struct super_block *sb, ret = insert_item(sb, cac, item, true, false); if (ret) { - SK_PRINTK(KERN_EMERG "Scoutfs: corrupted item cache found while" - " creating item "SK_FMT" on fs %llu\n", - SK_ARG(key), - le64_to_cpu(SCOUTFS_SB(sb)->super.hdr.fsid)); + printk(KERN_EMERG "Scoutfs: corrupted item cache found while" + " creating item "SK_FMT" on fs %llu\n", SK_ARG(key), + le64_to_cpu(SCOUTFS_SB(sb)->super.hdr.fsid)); BUG_ON(ret); } scoutfs_inc_counter(sb, item_create); @@ -1184,7 +1105,7 @@ int scoutfs_item_create_force(struct super_block *sb, * and we add with _tail to maintain that order. */ int scoutfs_item_add_batch(struct super_block *sb, struct list_head *list, - struct scoutfs_key_buf *key, struct kvec *val) + struct scoutfs_key *key, struct kvec *val) { struct cached_item *item; int ret; @@ -1220,8 +1141,8 @@ int scoutfs_item_add_batch(struct super_block *sb, struct list_head *list, * that will be inserted. */ int scoutfs_item_insert_batch(struct super_block *sb, struct list_head *list, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end) + struct scoutfs_key *start, + struct scoutfs_key *end) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; @@ -1238,16 +1159,15 @@ int scoutfs_item_insert_batch(struct super_block *sb, struct list_head *list, scoutfs_inc_counter(sb, item_range_alloc); rng = kzalloc(sizeof(struct cached_range), GFP_NOFS); - if (rng) { - rng->start = scoutfs_key_dup(sb, start); - rng->end = scoutfs_key_dup(sb, end); - } - if (!rng || !rng->start || !rng->end) { + if (!rng) { free_range(sb, rng); ret = -ENOMEM; goto out; } + rng->start = *start; + rng->end = *end; + spin_lock_irqsave(&cac->lock, flags); insert_range(sb, &cac->ranges, rng); @@ -1286,7 +1206,7 @@ void scoutfs_item_free_batch(struct super_block *sb, struct list_head *list) * If the item exists make sure it's dirty and pinned. It can be read * if it wasn't cached. -ENOENT is returned if the item doesn't exist. */ -int scoutfs_item_dirty(struct super_block *sb, struct scoutfs_key_buf *key, +int scoutfs_item_dirty(struct super_block *sb, struct scoutfs_key *key, struct scoutfs_lock *lock) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); @@ -1314,8 +1234,8 @@ int scoutfs_item_dirty(struct super_block *sb, struct scoutfs_key_buf *key, spin_unlock_irqrestore(&cac->lock, flags); } while (ret == -ENODATA && - (ret = scoutfs_manifest_read_items(sb, key, lock->start, - lock->end)) == 0); + (ret = scoutfs_manifest_read_items(sb, key, &lock->start, + &lock->end)) == 0); trace_scoutfs_item_dirty_ret(sb, ret); return ret; @@ -1327,7 +1247,7 @@ int scoutfs_item_dirty(struct super_block *sb, struct scoutfs_key_buf *key, * * Returns -ENOENT if the item doesn't exist. */ -int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key, +int scoutfs_item_update(struct super_block *sb, struct scoutfs_key *key, struct kvec *val, struct scoutfs_lock *lock) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); @@ -1371,8 +1291,8 @@ int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key, spin_unlock_irqrestore(&cac->lock, flags); } while (ret == -ENODATA && - (ret = scoutfs_manifest_read_items(sb, key, lock->start, - lock->end)) == 0); + (ret = scoutfs_manifest_read_items(sb, key, &lock->start, + &lock->end)) == 0); out: kfree(up_val); @@ -1392,7 +1312,7 @@ out: * there are any ways for userspace to overwhelm the system with * deletion items for items that didn't exist in the first place. */ -int scoutfs_item_delete(struct super_block *sb, struct scoutfs_key_buf *key, +int scoutfs_item_delete(struct super_block *sb, struct scoutfs_key *key, struct scoutfs_lock *lock) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); @@ -1420,15 +1340,15 @@ int scoutfs_item_delete(struct super_block *sb, struct scoutfs_key_buf *key, spin_unlock_irqrestore(&cac->lock, flags); } while (ret == -ENODATA && - (ret = scoutfs_manifest_read_items(sb, key, lock->start, - lock->end)) == 0); + (ret = scoutfs_manifest_read_items(sb, key, &lock->start, + &lock->end)) == 0); trace_scoutfs_item_delete_ret(sb, ret); return ret; } int scoutfs_item_delete_force(struct super_block *sb, - struct scoutfs_key_buf *key, + struct scoutfs_key *key, struct scoutfs_lock *lock) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); @@ -1447,10 +1367,9 @@ int scoutfs_item_delete_force(struct super_block *sb, spin_lock_irqsave(&cac->lock, flags); ret = insert_item(sb, cac, item, true, false); if (ret) { - SK_PRINTK(KERN_EMERG "Scoutfs: corrupted item cache found while" - " deleting item "SK_FMT" on fs %llu\n", - SK_ARG(key), - le64_to_cpu(SCOUTFS_SB(sb)->super.hdr.fsid)); + printk(KERN_EMERG "Scoutfs: corrupted item cache found while" + " deleting item "SK_FMT" on fs %llu\n", SK_ARG(key), + le64_to_cpu(SCOUTFS_SB(sb)->super.hdr.fsid)); BUG_ON(ret); } scoutfs_inc_counter(sb, item_create); @@ -1473,7 +1392,7 @@ int scoutfs_item_delete_force(struct super_block *sb, * Returns -ENOENT if the item didn't exist and couldn't be deleted. */ int scoutfs_item_delete_save(struct super_block *sb, - struct scoutfs_key_buf *key, + struct scoutfs_key *key, struct list_head *list, struct scoutfs_lock *lock) { @@ -1517,8 +1436,8 @@ int scoutfs_item_delete_save(struct super_block *sb, spin_unlock_irqrestore(&cac->lock, flags); } while (ret == -ENODATA && - (ret = scoutfs_manifest_read_items(sb, key, lock->start, - lock->end)) == 0); + (ret = scoutfs_manifest_read_items(sb, key, &lock->start, + &lock->end)) == 0); free_item(sb, del); @@ -1554,8 +1473,8 @@ int scoutfs_item_restore(struct super_block *sb, struct list_head *list, /* make sure all the items are locked and cached */ list_for_each_entry(item, list, entry) { mode = item_is_dirty(item) ? DLM_LOCK_EX : DLM_LOCK_PR; - if (WARN_ON_ONCE(!lock_coverage(lock, item->key, mode)) || - WARN_ON_ONCE(!check_range(sb, &cac->ranges, item->key, + if (WARN_ON_ONCE(!lock_coverage(lock, &item->key, mode)) || + WARN_ON_ONCE(!check_range(sb, &cac->ranges, &item->key, NULL))) { ret = -EINVAL; goto out; @@ -1567,7 +1486,7 @@ int scoutfs_item_restore(struct super_block *sb, struct list_head *list, item->dirty &= ~ITEM_DIRTY; list_del_init(&item->entry); - existing = find_item(sb, &cac->items, item->key); + existing = find_item(sb, &cac->items, &item->key); if (existing) erase_item(sb, cac, existing); insert_item(sb, cac, item, false, false); @@ -1588,7 +1507,7 @@ out: * fail. */ void scoutfs_item_delete_dirty(struct super_block *sb, - struct scoutfs_key_buf *key) + struct scoutfs_key *key) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; @@ -1612,7 +1531,7 @@ void scoutfs_item_delete_dirty(struct super_block *sb, * value is eventually freed along with the item. */ void scoutfs_item_update_dirty(struct super_block *sb, - struct scoutfs_key_buf *key, struct kvec *val) + struct scoutfs_key *key, struct kvec *val) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; @@ -1631,7 +1550,7 @@ void scoutfs_item_update_dirty(struct super_block *sb, if (val) memcpy(item->val, val->iov_base, new_len); item->val_len = new_len; - update_dirty_item_counts(sb, 0, 0, delta); + update_dirty_item_counts(sb, 0, delta); spin_unlock_irqrestore(&cac->lock, flags); } @@ -1697,8 +1616,8 @@ static struct cached_item *next_dirty(struct cached_item *item) } static bool dirty_item_within(struct rb_root *root, - struct scoutfs_key_buf *from, - struct scoutfs_key_buf *end) + struct scoutfs_key *from, + struct scoutfs_key *end) { struct cached_item *item; @@ -1706,7 +1625,7 @@ static bool dirty_item_within(struct rb_root *root, if (item && !item_is_dirty(item)) item = next_dirty(item); - return item && scoutfs_key_compare(item->key, end) <= 0; + return item && scoutfs_key_compare(&item->key, end) <= 0; } bool scoutfs_item_has_dirty(struct super_block *sb) @@ -1732,8 +1651,8 @@ bool scoutfs_item_has_dirty(struct super_block *sb) * we see if the next cached range starts before the end of the query range. */ bool scoutfs_item_range_cached(struct super_block *sb, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end, bool dirty) + struct scoutfs_key *start, + struct scoutfs_key *end, bool dirty) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; @@ -1749,7 +1668,8 @@ bool scoutfs_item_range_cached(struct super_block *sb, cached = true; } else { rng = walk_ranges(&cac->ranges, start, NULL, &next); - if (rng || (next && scoutfs_key_compare(next->start, end) <= 0)) + if (rng || + (next && scoutfs_key_compare(&next->start, end) <= 0)) cached = true; } @@ -1763,7 +1683,7 @@ bool scoutfs_item_range_cached(struct super_block *sb, * still fits in a single item along with the current dirty items. */ bool scoutfs_item_dirty_fits_single(struct super_block *sb, u32 nr_items, - u32 key_bytes, u32 val_bytes) + u32 val_bytes) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; @@ -1772,7 +1692,6 @@ bool scoutfs_item_dirty_fits_single(struct super_block *sb, u32 nr_items, spin_lock_irqsave(&cac->lock, flags); fits = scoutfs_seg_fits_single(nr_items + cac->nr_dirty_items, - key_bytes + cac->dirty_key_bytes, val_bytes + cac->dirty_val_bytes); spin_unlock_irqrestore(&cac->lock, flags); @@ -1805,7 +1724,7 @@ int scoutfs_item_dirty_seg(struct super_block *sb, struct scoutfs_segment *seg) item = first_dirty(cac->items.rb_node); while (item) { kvec_init(&val, item->val, item->val_len); - appended = scoutfs_seg_append_item(sb, seg, item->key, &val, + appended = scoutfs_seg_append_item(sb, seg, &item->key, &val, item_flags(item), links); /* trans reservation should have limited dirty */ BUG_ON(!appended); @@ -1832,8 +1751,8 @@ int scoutfs_item_dirty_seg(struct super_block *sb, struct scoutfs_segment *seg) * Returns a sync error or the number of dirty items written. */ int scoutfs_item_writeback(struct super_block *sb, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end) + struct scoutfs_key *start, + struct scoutfs_key *end) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; @@ -1868,8 +1787,8 @@ int scoutfs_item_writeback(struct super_block *sb, * Returns errors or the count of the items invalidated. */ int scoutfs_item_invalidate(struct super_block *sb, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end) + struct scoutfs_key *start, + struct scoutfs_key *end) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; @@ -1887,23 +1806,19 @@ int scoutfs_item_invalidate(struct super_block *sb, scoutfs_inc_counter(sb, item_range_alloc); rng = kzalloc(sizeof(struct cached_range), GFP_NOFS); - if (rng) { - rng->start = scoutfs_key_alloc(sb, SCOUTFS_MAX_KEY_SIZE); - rng->end = scoutfs_key_alloc(sb, SCOUTFS_MAX_KEY_SIZE); - } - if (!rng || !rng->start || !rng->end) { + if (!rng) { free_range(sb, rng); ret = -ENOMEM; goto out; } - scoutfs_key_copy(rng->start, start); - scoutfs_key_copy(rng->end, end); + rng->start = *start; + rng->end = *end; spin_lock_irqsave(&cac->lock, flags); for (item = next_item(&cac->items, start); - item && scoutfs_key_compare(item->key, end) <= 0; + item && scoutfs_key_compare(&item->key, end) <= 0; item = next) { /* XXX seems like this should be a helper? */ @@ -1967,7 +1882,7 @@ static struct cached_item *rb_prev_item(struct cached_item *item) static struct cached_item *shrink_boundary(struct super_block *sb, struct cached_item *item, struct cached_item **next_ret, - struct scoutfs_key_buf *end, + struct scoutfs_key *end, bool right) { struct cached_item *found = NULL; @@ -1985,9 +1900,9 @@ static struct cached_item *shrink_boundary(struct super_block *sb, if (next) { if (right) - cmp = scoutfs_key_compare(next->key, end) > 0; + cmp = scoutfs_key_compare(&next->key, end) > 0; else - cmp = scoutfs_key_compare(next->key, end) < 0; + cmp = scoutfs_key_compare(&next->key, end) < 0; } else { cmp = true; } @@ -1999,13 +1914,13 @@ static struct cached_item *shrink_boundary(struct super_block *sb, } if (right) { - scoutfs_key_inc_cur_len(item->key); - cmp = scoutfs_key_compare(item->key, next->key) <= 0; - scoutfs_key_dec_cur_len(item->key); + scoutfs_key_inc(&item->key); + cmp = scoutfs_key_compare(&item->key, &next->key) <= 0; + scoutfs_key_dec(&item->key); } else { - scoutfs_key_dec_cur_len(item->key); - cmp = scoutfs_key_compare(item->key, next->key) >= 0; - scoutfs_key_inc_cur_len(item->key); + scoutfs_key_dec(&item->key); + cmp = scoutfs_key_compare(&item->key, &next->key) >= 0; + scoutfs_key_inc(&item->key); } if (cmp) { found = item; @@ -2038,8 +1953,8 @@ static int shrink_around(struct super_block *sb, struct cached_range *rng, struct cached_item *item) { struct item_cache *cac = SCOUTFS_SB(sb)->item_cache; - struct scoutfs_key_buf *rng_end = NULL; - struct scoutfs_key_buf *key; + struct scoutfs_key rng_end; + struct scoutfs_key key; struct cached_range *new_rng; struct cached_item *first; struct cached_item *last; @@ -2050,14 +1965,14 @@ static int shrink_around(struct super_block *sb, struct cached_range *rng, /* we're re-using item memory as ranges :P */ BUILD_BUG_ON(sizeof(struct cached_item) < sizeof(struct cached_range)); - first = shrink_boundary(sb, item, &prev, rng->start, false); - last = shrink_boundary(sb, item, &next, rng->end, true); + first = shrink_boundary(sb, item, &prev, &rng->start, false); + last = shrink_boundary(sb, item, &next, &rng->end, true); - trace_scoutfs_item_shrink_around(sb, rng->start, rng->end, item->key, - prev ? prev->key : NULL, - first ? first->key : NULL, - last ? last->key : NULL, - next ? next->key : NULL); + trace_scoutfs_item_shrink_around(sb, &rng->start, &rng->end, &item->key, + prev ? &prev->key : NULL, + first ? &first->key : NULL, + last ? &last->key : NULL, + next ? &next->key : NULL); /* can't shrink if we can't use neighbours */ if (!first || !last) { @@ -2075,17 +1990,14 @@ static int shrink_around(struct super_block *sb, struct cached_range *rng, if (prev) { rng_end = rng->end; rng->end = first->key; - first->key = NULL; - scoutfs_key_dec_cur_len(rng->end); + scoutfs_key_dec(&rng->end); trace_range(shrink_end, sb, rng); } /* set start of remaining existing range */ if (next && !prev) { - scoutfs_key_free(sb, rng->start); rng->start = last->key; - last->key = NULL; - scoutfs_key_inc_cur_len(rng->start); + scoutfs_key_inc(&rng->start); trace_range(shrink_start, sb, rng); } @@ -2104,9 +2016,8 @@ static int shrink_around(struct super_block *sb, struct cached_range *rng, memset(new_rng, 0, sizeof(struct cached_range)); new_rng->end = rng_end; - rng_end = NULL; new_rng->start = key; - scoutfs_key_inc_cur_len(new_rng->start); + scoutfs_key_inc(&new_rng->start); insert_range(sb, &cac->ranges, new_rng); scoutfs_inc_counter(sb, item_shrink_split_range); @@ -2122,15 +2033,12 @@ static int shrink_around(struct super_block *sb, struct cached_range *rng, for (item = first; item && (next = item == last ? NULL : rb_next_item(item), 1); item = next) { - if (item->key) - trace_scoutfs_item_shrink(sb, item->key); + trace_scoutfs_item_shrink(sb, &item->key); scoutfs_inc_counter(sb, item_shrink); erase_item(sb, cac, item); nr++; } - scoutfs_key_free(sb, rng_end); - return nr; } @@ -2173,7 +2081,7 @@ static int item_lru_shrink(struct shrinker *shrink, struct shrink_control *sc) BUG_ON(item_is_dirty(item)); /* if we're not in a range just shrink the item */ - rng = walk_ranges(&cac->ranges, item->key, NULL, NULL); + rng = walk_ranges(&cac->ranges, &item->key, NULL, NULL); if (!rng) { scoutfs_inc_counter(sb, item_shrink_outside); erase_item(sb, cac, item); @@ -2210,37 +2118,21 @@ out: return ret; } -static void *copy_key_with_len(void *data, struct scoutfs_key_buf *key) -{ - u16 len = key->key_len; - - memcpy(data, &len, sizeof(len)); - data += sizeof(len); - memcpy(data, key->data, len); - - return data + len; -} - /* - * Copy the next cached ranges starting with the key into the caller's - * buffer. Each range copied by storing each keys size in a u16 - * followed by the binary key data. The number of bytes of full copied - * ranges is returned. The caller's key is incremented past the last - * key returned so that they can iterate without worrying about - * examining the returned keys. + * Copy the keys of the sorted cached ranges starting with the search + * key into the caller's key array. The number of copied range keys is + * returned which will always be a multiple of two. */ int scoutfs_item_copy_range_keys(struct super_block *sb, - struct scoutfs_key_buf *key, void *data, - unsigned len) + struct scoutfs_key *key, + struct scoutfs_key *keys, unsigned nr) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; struct rb_node *node = cac->ranges.rb_node; struct cached_range *next = NULL; - struct scoutfs_key_buf *last = NULL; struct cached_range *rng; unsigned long flags; - unsigned bytes; int ret = 0; int cmp; @@ -2250,7 +2142,7 @@ int scoutfs_item_copy_range_keys(struct super_block *sb, rng = container_of(node, struct cached_range, node); cmp = scoutfs_key_compare_ranges(key, key, - rng->start, rng->end); + &rng->start, &rng->end); if (cmp < 0) { next = rng; node = node->rb_left; @@ -2263,21 +2155,11 @@ int scoutfs_item_copy_range_keys(struct super_block *sb, } for (rng = next; rng; rng = rb_next_rng(rng)) { - bytes = 2 + rng->start->key_len + 2 + rng->end->key_len; - if (len < bytes) + if (ret + 2 > nr) break; - data = copy_key_with_len(data, rng->start); - data = copy_key_with_len(data, rng->end); - len -= bytes; - ret += bytes; - - last = rng->end; - } - - if (last) { - scoutfs_key_copy(key, last); - scoutfs_key_inc(key); + keys[ret++] = rng->start; + keys[ret++] = rng->end; } spin_unlock_irqrestore(&cac->lock, flags); @@ -2285,38 +2167,31 @@ int scoutfs_item_copy_range_keys(struct super_block *sb, return ret; } -/* like copy_range_keys, but for present items */ -int scoutfs_item_copy_keys(struct super_block *sb, struct scoutfs_key_buf *key, - void *data, unsigned len) +/* + * Copy keys for the sorted cached items starting with the search key + * into the caller's key array. The number of copied keys is returned. + */ +int scoutfs_item_copy_keys(struct super_block *sb, struct scoutfs_key *key, + struct scoutfs_key *keys, unsigned nr) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct item_cache *cac = sbi->item_cache; - struct scoutfs_key_buf *last = NULL; struct cached_item *item = NULL; unsigned long flags; - unsigned bytes; int ret = 0; spin_lock_irqsave(&cac->lock, flags); - for (item = next_item(&cac->items, key); item; item = rb_next_item(item)) { + for (item = next_item(&cac->items, key); item; + item = rb_next_item(item)) { + + if (ret == nr) + break; + if (item->deletion) continue; - bytes = 2 + item->key->key_len; - if (len < bytes) - break; - - data = copy_key_with_len(data, item->key); - len -= bytes; - ret += bytes; - - last = item->key; - } - - if (last) { - scoutfs_key_copy(key, last); - scoutfs_key_inc(key); + keys[ret++] = item->key; } spin_unlock_irqrestore(&cac->lock, flags); diff --git a/kmod/src/item.h b/kmod/src/item.h index 6507d85a..328345b9 100644 --- a/kmod/src/item.h +++ b/kmod/src/item.h @@ -4,75 +4,67 @@ #include struct scoutfs_segment; -struct scoutfs_key_buf; +struct scoutfs_key; -int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key_buf *key, +int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key *key, struct kvec *val, struct scoutfs_lock *lock); int scoutfs_item_lookup_exact(struct super_block *sb, - struct scoutfs_key_buf *key, struct kvec *val, + struct scoutfs_key *key, struct kvec *val, struct scoutfs_lock *lock); -int scoutfs_item_next(struct super_block *sb, struct scoutfs_key_buf *key, - struct scoutfs_key_buf *last, struct kvec *val, +int scoutfs_item_next(struct super_block *sb, struct scoutfs_key *key, + struct scoutfs_key *last, struct kvec *val, struct scoutfs_lock *lock); -int scoutfs_item_next_same_min(struct super_block *sb, - struct scoutfs_key_buf *key, - struct scoutfs_key_buf *last, - struct kvec *val, int len, - struct scoutfs_lock *lock); -int scoutfs_item_next_same(struct super_block *sb, struct scoutfs_key_buf *key, - struct scoutfs_key_buf *last, struct kvec *val, - struct scoutfs_lock *lock); -int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key, +int scoutfs_item_create(struct super_block *sb, struct scoutfs_key *key, struct kvec *val, struct scoutfs_lock *lock); int scoutfs_item_create_force(struct super_block *sb, - struct scoutfs_key_buf *key, + struct scoutfs_key *key, struct kvec *val, struct scoutfs_lock *lock); -int scoutfs_item_dirty(struct super_block *sb, struct scoutfs_key_buf *key, +int scoutfs_item_dirty(struct super_block *sb, struct scoutfs_key *key, struct scoutfs_lock *lock); -int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key, +int scoutfs_item_update(struct super_block *sb, struct scoutfs_key *key, struct kvec *val, struct scoutfs_lock *lock); void scoutfs_item_delete_dirty(struct super_block *sb, - struct scoutfs_key_buf *key); + struct scoutfs_key *key); void scoutfs_item_update_dirty(struct super_block *sb, - struct scoutfs_key_buf *key, struct kvec *val); -int scoutfs_item_delete(struct super_block *sb, struct scoutfs_key_buf *key, + struct scoutfs_key *key, struct kvec *val); +int scoutfs_item_delete(struct super_block *sb, struct scoutfs_key *key, struct scoutfs_lock *lock); int scoutfs_item_delete_force(struct super_block *sb, - struct scoutfs_key_buf *key, + struct scoutfs_key *key, struct scoutfs_lock *lock); int scoutfs_item_delete_save(struct super_block *sb, - struct scoutfs_key_buf *key, + struct scoutfs_key *key, struct list_head *list, struct scoutfs_lock *lock); int scoutfs_item_restore(struct super_block *sb, struct list_head *list, struct scoutfs_lock *lock); int scoutfs_item_add_batch(struct super_block *sb, struct list_head *list, - struct scoutfs_key_buf *key, struct kvec *val); + struct scoutfs_key *key, struct kvec *val); int scoutfs_item_insert_batch(struct super_block *sb, struct list_head *list, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end); + struct scoutfs_key *start, + struct scoutfs_key *end); void scoutfs_item_free_batch(struct super_block *sb, struct list_head *list); bool scoutfs_item_has_dirty(struct super_block *sb); bool scoutfs_item_range_cached(struct super_block *sb, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end, bool dirty); + struct scoutfs_key *start, + struct scoutfs_key *end, bool dirty); bool scoutfs_item_dirty_fits_single(struct super_block *sb, u32 nr_items, - u32 key_bytes, u32 val_bytes); + u32 val_bytes); int scoutfs_item_dirty_seg(struct super_block *sb, struct scoutfs_segment *seg); int scoutfs_item_writeback(struct super_block *sb, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end); + struct scoutfs_key *start, + struct scoutfs_key *end); int scoutfs_item_invalidate(struct super_block *sb, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end); + struct scoutfs_key *start, + struct scoutfs_key *end); int scoutfs_item_copy_range_keys(struct super_block *sb, - struct scoutfs_key_buf *key, void *data, - unsigned len); -int scoutfs_item_copy_keys(struct super_block *sb, struct scoutfs_key_buf *key, - void *data, unsigned len); + struct scoutfs_key *key, + struct scoutfs_key *keys, unsigned nr); +int scoutfs_item_copy_keys(struct super_block *sb, struct scoutfs_key *key, + struct scoutfs_key *keys, unsigned nr); int scoutfs_item_setup(struct super_block *sb); void scoutfs_item_destroy(struct super_block *sb); diff --git a/kmod/src/key.c b/kmod/src/key.c index 9e8bb5cc..23aa8265 100644 --- a/kmod/src/key.c +++ b/kmod/src/key.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Versity Software, Inc. All rights reserved. + * Copyright (C) 2018 Versity Software, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public @@ -11,422 +11,48 @@ * General Public License for more details. */ #include -#include -#include +#include +#include +#include "format.h" #include "key.h" -struct scoutfs_key_buf *scoutfs_key_alloc(struct super_block *sb, u16 len) +char *scoutfs_zone_strings[SCOUTFS_MAX_ZONE] = { + [SCOUTFS_INODE_INDEX_ZONE] = "ind", + [SCOUTFS_NODE_ZONE] = "nod", + [SCOUTFS_FS_ZONE] = "fs", +}; + +char *scoutfs_type_strings[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE] = { + [SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_META_SEQ_TYPE] = "msq", + [SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] = "dsq", + [SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_SEGNO_TYPE] = "fsg", + [SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_BLKNO_TYPE] = "fbk", + [SCOUTFS_NODE_ZONE][SCOUTFS_ORPHAN_TYPE] = "orp", + [SCOUTFS_FS_ZONE][SCOUTFS_INODE_TYPE] = "ino", + [SCOUTFS_FS_ZONE][SCOUTFS_XATTR_TYPE] = "xat", + [SCOUTFS_FS_ZONE][SCOUTFS_DIRENT_TYPE] = "dnt", + [SCOUTFS_FS_ZONE][SCOUTFS_READDIR_TYPE] = "rdr", + [SCOUTFS_FS_ZONE][SCOUTFS_LINK_BACKREF_TYPE] = "lbr", + [SCOUTFS_FS_ZONE][SCOUTFS_SYMLINK_TYPE] = "sym", + [SCOUTFS_FS_ZONE][SCOUTFS_BLOCK_MAPPING_TYPE] = "bmp", +}; + +char scoutfs_unknown_u8_strings[U8_MAX][U8_STR_MAX]; + +int __init scoutfs_key_init(void) { - struct scoutfs_key_buf *key; - - if (WARN_ON_ONCE(len > SCOUTFS_MAX_KEY_SIZE)) - return NULL; - - key = kmalloc(sizeof(struct scoutfs_key_buf) + len, GFP_NOFS); - if (key) { - key->data = key + 1; - key->key_len = len; - key->buf_len = len; - } - - return key; -} - -struct scoutfs_key_buf *scoutfs_key_dup(struct super_block *sb, - struct scoutfs_key_buf *key) -{ - struct scoutfs_key_buf *dup; - - dup = scoutfs_key_alloc(sb, key->key_len); - if (dup) - memcpy(dup->data, key->data, dup->key_len); - return dup; -} - -void scoutfs_key_free(struct super_block *sb, struct scoutfs_key_buf *key) -{ - kfree(key); -} - -/* - * Keys are large multi-byte big-endian values. To correctly increase - * or decrease keys we need to start by extending the key to the full - * precision using the max key size, setting the least significant bytes - * to 0. - */ -static void extend_zeros(struct scoutfs_key_buf *key) -{ - if (key->key_len < SCOUTFS_MAX_KEY_SIZE && - !WARN_ON_ONCE(key->buf_len != SCOUTFS_MAX_KEY_SIZE)) { - memset(key->data + key->key_len, 0, - key->buf_len - key->key_len); - key->key_len = key->buf_len; - } -} - -/* - * There are callers that work with a range of keys of a uniform length - * who know that it's safe to increment their keys that aren't full - * precision. These are exceptional so a specific function variant - * marks them. - */ -void scoutfs_key_inc_cur_len(struct scoutfs_key_buf *key) -{ - u8 *bytes = key->data; - int i; - - for (i = key->key_len - 1; i >= 0; i--) { - if (++bytes[i] != 0) - break; - } -} - -void scoutfs_key_inc(struct scoutfs_key_buf *key) -{ - extend_zeros(key); - scoutfs_key_inc_cur_len(key); -} - -void scoutfs_key_dec_cur_len(struct scoutfs_key_buf *key) -{ - u8 *bytes = key->data; - int i; - - for (i = key->key_len - 1; i >= 0; i--) { - if (--bytes[i] != 255) - break; - } -} - -void scoutfs_key_dec(struct scoutfs_key_buf *key) -{ - extend_zeros(key); - scoutfs_key_dec_cur_len(key); -} - -/* return the bytes of the string including the null term */ -#define snprintf_null(buf, size, fmt, args...) \ - (snprintf((buf), (size), fmt, ##args) + 1) - -/* - * Store a formatted string representing the key in the buffer. The key - * must be at least min_len to store the data needed by the format at - * all. fmt_len is the length of data that's used by the format. These - * are different because we have badly designed keys with variable - * length data that isn't described by the key. It's assumed from the - * length of the key. Take dirents -- they need to at least have a - * dirent struct, but the name length is the rest of the key. - * - * (XXX And this goes horribly wrong when we pad out dirent keys to max - * len to increment at high precision. We'll never see these items used - * by real fs code, but temporary keys and range endpoints can be full - * precision and we can try and print them and get very confused. We - * need to rev the format to include explicit lengths.) - * - * If the format doesn't cover the entire key then we append more - * formatting to represent the trailing bytes: runs of zeros compresesd - * to _ and then hex output of non-zero bytes. - */ -static int __printf(6, 7) snprintf_key(char *buf, size_t size, - struct scoutfs_key_buf *key, - unsigned min_len, unsigned fmt_len, - const char *fmt, ...) - -{ - va_list args; - char *data; - char *end; - int left; - int part; int ret; - int nr; + int i; - if (key->key_len < min_len) - return snprintf_null(buf, size, "[trunc len %u < min %u]", - key->key_len, min_len); - - if (fmt_len == 0) - fmt_len = min_len; - - va_start(args, fmt); - ret = vsnprintf(buf, size, fmt, args); - va_end(args); - /* next formatting overwrites null */ - if (buf) { - buf += ret; - size -= min_t(int, size, ret); + for (i = 0; i <= U8_MAX; i++) { + ret = snprintf(scoutfs_unknown_u8_strings[i], U8_STR_MAX, + "u%u", i); + if (WARN_ONCE(ret <= 0 || ret >= U8_STR_MAX, + "snprintf("__stringify(U8_STR_MAX)") ret %d\n", + ret)) + return -EINVAL; } - data = key->data + fmt_len; - left = key->key_len - fmt_len; - - while (left && (!buf || size > 1)) { - /* compress runs of zero bytes to _ */ - end = memchr_inv(data, 0, left); - nr = end ? end - data : left; - if (nr) { - if (buf) { - *(buf++) = '_'; - size--; - } - ret++; - data += nr; - left -= nr; - continue; - } - - /* - * hex print non-zero bytes. %ph is limited to 64 bytes - * and is buggy in that it still tries to print to buf - * past size. (so buf = null, size = 0 crashes instead - * of printing the length of the formatted string.) - */ - end = memchr(data, 0, left); - nr = end ? end - data : left; - nr = min(nr, 64); - - if (buf) - part = snprintf(buf, size, "%*phN", nr, data); - else - part = nr * 2; - if (buf) { - buf += part; - size -= min_t(int, size, part); - } - ret += part; - - data += nr; - left -= nr; - } - - /* always store and include null */ - if (buf) - *buf = '\0'; - return ret + 1; -} - -typedef int (*key_printer_t)(char *buf, struct scoutfs_key_buf *key, - size_t size); - -static int pr_ino_idx(char *buf, struct scoutfs_key_buf *key, size_t size) -{ - static char *type_strings[] = { - [SCOUTFS_INODE_INDEX_META_SEQ_TYPE] = "msq", - [SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] = "dsq", - }; - struct scoutfs_inode_index_key *ikey = key->data; - - return snprintf_key(buf, size, key, - sizeof(struct scoutfs_inode_index_key), 0, - "iin.%s.%llu.%u.%llu", - type_strings[ikey->type], be64_to_cpu(ikey->major), - be32_to_cpu(ikey->minor), be64_to_cpu(ikey->ino)); -} - -static int pr_free_bits(char *buf, struct scoutfs_key_buf *key, size_t size) -{ - static char *type_strings[] = { - [SCOUTFS_FREE_BITS_SEGNO_TYPE] = "fsg", - [SCOUTFS_FREE_BITS_BLKNO_TYPE] = "fbk", - }; - struct scoutfs_free_bits_key *frk = key->data; - - return snprintf_key(buf, size, key, - sizeof(struct scoutfs_block_mapping_key), 0, - "nod.%llu.%s.%llu", - be64_to_cpu(frk->node_id), - type_strings[frk->type], - be64_to_cpu(frk->base)); -} - -static int pr_orphan(char *buf, struct scoutfs_key_buf *key, size_t size) -{ - struct scoutfs_orphan_key *okey = key->data; - - return snprintf_key(buf, size, key, - sizeof(struct scoutfs_orphan_key), 0, - "nod.%llu.orp.%llu", - be64_to_cpu(okey->node_id), - be64_to_cpu(okey->ino)); -} - -static int pr_inode(char *buf, struct scoutfs_key_buf *key, size_t size) -{ - struct scoutfs_inode_key *ikey = key->data; - - return snprintf_key(buf, size, key, - sizeof(struct scoutfs_inode_key), 0, - "fs.%llu.ino", - be64_to_cpu(ikey->ino)); -} - -static int pr_xattr(char *buf, struct scoutfs_key_buf *key, size_t size) -{ - struct scoutfs_xattr_key *xkey = key->data; - - return snprintf_key(buf, size, key, - sizeof(struct scoutfs_xattr_key), key->key_len, - "fs.%llu.xat.%08x.%llu.%u", - be64_to_cpu(xkey->ino), - be32_to_cpu(xkey->name_hash), - be64_to_cpu(xkey->id), xkey->part); -} - -static int pr_dirent(char *buf, struct scoutfs_key_buf *key, size_t size) -{ - struct scoutfs_dirent_key *dkey = key->data; - char *which = dkey->type == SCOUTFS_DIRENT_TYPE ? "dnt" : - dkey->type == SCOUTFS_READDIR_TYPE ? "rdr" : - dkey->type == SCOUTFS_LINK_BACKREF_TYPE ? "lbr" : - "unk"; - - return snprintf_key(buf, size, key, - sizeof(struct scoutfs_dirent_key), key->key_len, - "fs.%llu.%s.%llu.%llu", - be64_to_cpu(dkey->ino), which, - be64_to_cpu(dkey->major), - be64_to_cpu(dkey->minor)); -} - -static int pr_symlink(char *buf, struct scoutfs_key_buf *key, size_t size) -{ - struct scoutfs_symlink_key *skey = key->data; - - return snprintf_key(buf, size, key, - sizeof(struct scoutfs_symlink_key), 0, - "fs.%llu.sym", - be64_to_cpu(skey->ino)); -} - -static int pr_block_mapping(char *buf, struct scoutfs_key_buf *key, size_t size) -{ - struct scoutfs_block_mapping_key *bmk = key->data; - - return snprintf_key(buf, size, key, - sizeof(struct scoutfs_block_mapping_key), 0, - "fs.%llu.bmp.%llu", - be64_to_cpu(bmk->ino), - be64_to_cpu(bmk->base)); -} - -const static key_printer_t key_printers[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE] = { - [SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_META_SEQ_TYPE] = - pr_ino_idx, - [SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] = - pr_ino_idx, - [SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_SEGNO_TYPE] = pr_free_bits, - [SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_BLKNO_TYPE] = pr_free_bits, - [SCOUTFS_NODE_ZONE][SCOUTFS_ORPHAN_TYPE] = pr_orphan, - [SCOUTFS_FS_ZONE][SCOUTFS_INODE_TYPE] = pr_inode, - [SCOUTFS_FS_ZONE][SCOUTFS_XATTR_TYPE] = pr_xattr, - [SCOUTFS_FS_ZONE][SCOUTFS_DIRENT_TYPE] = pr_dirent, - [SCOUTFS_FS_ZONE][SCOUTFS_READDIR_TYPE] = pr_dirent, - [SCOUTFS_FS_ZONE][SCOUTFS_LINK_BACKREF_TYPE] = pr_dirent, - [SCOUTFS_FS_ZONE][SCOUTFS_SYMLINK_TYPE] = pr_symlink, - [SCOUTFS_FS_ZONE][SCOUTFS_BLOCK_MAPPING_TYPE] = pr_block_mapping, -}; - -/* - * Write the null-terminated string that describes the key to the - * buffer. The bytes copied (including the null) is returned. A null - * buffer can be used to find the string size without writing anything. - * - * XXX nonprintable characters in the trace? - */ -int scoutfs_key_str_size(char *buf, struct scoutfs_key_buf *key, size_t size) -{ - u8 zone; - u8 type; - - if (key == NULL || key->data == NULL) - return snprintf_null(buf, size, "[NULL]"); - - /* always at least zone, some id, and type */ - if (key->key_len < (1 + 8 + 1)) - return snprintf_null(buf, size, "[trunc len %u]", key->key_len); - - zone = *(u8 *)key->data; - - /* - * each zone's keys always start with the same fields that let - * us deref any key to get the type. We chose a few representative - * keys from each zone to get the type. - */ - if (zone == SCOUTFS_INODE_INDEX_ZONE) { - struct scoutfs_inode_index_key *ikey = key->data; - type = ikey->type; - } else if (zone == SCOUTFS_NODE_ZONE) { - struct scoutfs_free_bits_key *fkey = key->data; - type = fkey->type; - } else if (zone == SCOUTFS_FS_ZONE) { - struct scoutfs_inode_key *ikey = key->data; - type = ikey->type; - } else { - type = 255; - } - - if (zone > SCOUTFS_MAX_ZONE || type > SCOUTFS_MAX_TYPE || - key_printers[zone][type] == NULL) { - return snprintf_null(buf, size, "[unk zone %u type %u]", - zone, type); - } - - return key_printers[zone][type](buf, key, size); -} - -/* - * Callers never have a pre-existing buffer whose size they need to be - * careful for. For a given static string they're first calling with a - * null buf to find out the formatted length without storing anything. - * Then they're called again with a buffer of that allocation size. As - * long as the formatting is consistent this pattern won't overflow. - */ -int scoutfs_key_str(char *buf, struct scoutfs_key_buf *key) -{ - return scoutfs_key_str_size(buf, key, buf ? INT_MAX : 0); -} - -#define MAX_STR_COUNT 10 - -struct key_strings { - bool started; - int next_str; - char strings[MAX_STR_COUNT][SK_STR_BYTES]; -}; - -static DEFINE_PER_CPU(struct key_strings, percpu_key_strings); - -void scoutfs_key_start_percpu(void) -{ - struct key_strings *ks = this_cpu_ptr(&percpu_key_strings); - - BUG_ON(ks->started); - ks->started = true; - get_cpu(); -} - -char *scoutfs_key_percpu_string(void) -{ - struct key_strings *ks = this_cpu_ptr(&percpu_key_strings); - char *str; - - BUG_ON(!ks->started); - - str = ks->strings[ks->next_str++]; - BUG_ON(ks->next_str >= MAX_STR_COUNT); - - return str; -} - -void scoutfs_key_finish_percpu(void) -{ - struct key_strings *ks = this_cpu_ptr(&percpu_key_strings); - - BUG_ON(!ks->started); - - ks->next_str = 0; - ks->started = false; - - put_cpu(); + return 0; } diff --git a/kmod/src/key.h b/kmod/src/key.h index bdeafb57..eb157279 100644 --- a/kmod/src/key.h +++ b/kmod/src/key.h @@ -3,88 +3,87 @@ #include #include "format.h" +#include "cmp.h" +#include "endian_swap.h" -struct scoutfs_key_buf { - void *data; - u16 key_len; - u16 buf_len; -}; +extern char *scoutfs_zone_strings[SCOUTFS_MAX_ZONE]; +extern char *scoutfs_type_strings[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE]; +#define U8_STR_MAX 5 /* u%3u'\0' */ +extern char scoutfs_unknown_u8_strings[U8_MAX][U8_STR_MAX]; -struct scoutfs_key_buf *scoutfs_key_alloc(struct super_block *sb, u16 len); -struct scoutfs_key_buf *scoutfs_key_dup(struct super_block *sb, - struct scoutfs_key_buf *key); -void scoutfs_key_free(struct super_block *sb, struct scoutfs_key_buf *key); -void scoutfs_key_inc(struct scoutfs_key_buf *key); -void scoutfs_key_inc_cur_len(struct scoutfs_key_buf *key); -void scoutfs_key_dec(struct scoutfs_key_buf *key); -void scoutfs_key_dec_cur_len(struct scoutfs_key_buf *key); +int __init scoutfs_key_init(void); -int scoutfs_key_str_size(char *buf, struct scoutfs_key_buf *key, size_t size); -int scoutfs_key_str(char *buf, struct scoutfs_key_buf *key); -void scoutfs_key_start_percpu(void); -char *scoutfs_key_percpu_string(void); -void scoutfs_key_finish_percpu(void); - -#define SK_PCPU(statements) do { \ - scoutfs_key_start_percpu(); \ - { statements; } \ - scoutfs_key_finish_percpu(); \ -} while (0) - -/* - * The biggest keys are typically a little struct then a large name. The - * string representation will tend to be mostly the name, but some of the - * strict fields can blow up from say 8 bytes to 20 bytes. So we give - * a lot of padding for that. - */ -#define SK_STR_BYTES (100 + SCOUTFS_MAX_KEY_SIZE) - -#define SK_FMT "%s" -#define SK_ARG(k) \ -({ \ - char *__str = scoutfs_key_percpu_string(); \ - scoutfs_key_str_size(__str, k, SK_STR_BYTES); \ - __str; \ -}) - -#define SK_TRACE_PRINTK(args...) SK_PCPU(trace_printk(args)) -#define SK_PRINTK(args...) SK_PCPU(printk(args)) - -/* - * Initialize a small key in a larger allocated buffer. This lets - * callers, for example, search for a small key and get a larger key - * copied in. - */ -static inline void scoutfs_key_init_buf_len(struct scoutfs_key_buf *key, - void *data, u16 key_len, - u16 buf_len) +static inline char *sk_zone_str(u8 zone) { - WARN_ON_ONCE(buf_len > SCOUTFS_MAX_KEY_SIZE); - WARN_ON_ONCE(key_len > buf_len); + if (zone >= SCOUTFS_MAX_ZONE || scoutfs_zone_strings[zone] == NULL) + return scoutfs_unknown_u8_strings[zone]; - key->data = data; - key->key_len = key_len; - key->buf_len = buf_len; + return scoutfs_zone_strings[zone]; +} + +static inline char *sk_type_str(u8 zone, u8 type) +{ + if (zone >= SCOUTFS_MAX_ZONE || type >= SCOUTFS_MAX_TYPE || + scoutfs_type_strings[zone][type] == NULL) + return scoutfs_unknown_u8_strings[type]; + + return scoutfs_type_strings[zone][type]; +} + +#define SK_FMT "%s.%llu.%s.%llu.%llu.%u" +/* This does not support null keys */ +#define SK_ARG(key) sk_zone_str((key)->sk_zone), \ + le64_to_cpu((key)->_sk_first), \ + sk_type_str((key)->sk_zone, (key)->sk_type), \ + le64_to_cpu((key)->_sk_second), \ + le64_to_cpu((key)->_sk_third), \ + (key)->_sk_fourth + +static inline void scoutfs_key_set_zeros(struct scoutfs_key *key) +{ + key->sk_zone = 0; + key->_sk_first = 0; + key->sk_type = 0; + key->_sk_second = 0; + key->_sk_third = 0; + key->_sk_fourth = 0; +} + +static inline void scoutfs_key_copy_or_zeros(struct scoutfs_key *dst, + struct scoutfs_key *src) +{ + if (src) + *dst = *src; + else + scoutfs_key_set_zeros(dst); +} + +static inline void scoutfs_key_set_ones(struct scoutfs_key *key) +{ + key->sk_zone = U8_MAX; + key->_sk_first = cpu_to_le64(U64_MAX); + key->sk_type = U8_MAX; + key->_sk_second = cpu_to_le64(U64_MAX); + key->_sk_third = cpu_to_le64(U64_MAX); + key->_sk_fourth = U8_MAX; } /* - * Point the key buf, usually statically allocated, at an existing - * contiguous key stored elsewhere. + * Return a -1/0/1 comparison of keys. + * + * It turns out that these ternary chains are consistently cheaper than + * other alternatives across keys that first differ in any of the + * values. Say maybe 20% faster than memcmp. */ -static inline void scoutfs_key_init(struct scoutfs_key_buf *key, - void *data, u16 len) +static inline int scoutfs_key_compare(struct scoutfs_key *a, + struct scoutfs_key *b) { - scoutfs_key_init_buf_len(key, data, len, len); -} - -/* - * Compare the fs keys in segment sort order. - */ -static inline int scoutfs_key_compare(struct scoutfs_key_buf *a, - struct scoutfs_key_buf *b) -{ - return memcmp(a->data, b->data, min(a->key_len, b->key_len)) ?: - a->key_len < b->key_len ? -1 : a->key_len > b->key_len ? 1 : 0; + return scoutfs_cmp(a->sk_zone, b->sk_zone) ?: + scoutfs_cmp(le64_to_cpu(a->_sk_first), le64_to_cpu(b->_sk_first)) ?: + scoutfs_cmp(a->sk_type, b->sk_type) ?: + scoutfs_cmp(le64_to_cpu(a->_sk_second), le64_to_cpu(b->_sk_second)) ?: + scoutfs_cmp(le64_to_cpu(a->_sk_third), le64_to_cpu(b->_sk_third)) ?: + scoutfs_cmp(a->_sk_fourth, b->_sk_fourth); } /* @@ -93,68 +92,85 @@ static inline int scoutfs_key_compare(struct scoutfs_key_buf *a, * 1: a_start > b_end * else 0: ranges overlap */ -static inline int scoutfs_key_compare_ranges(struct scoutfs_key_buf *a_start, - struct scoutfs_key_buf *a_end, - struct scoutfs_key_buf *b_start, - struct scoutfs_key_buf *b_end) +static inline int scoutfs_key_compare_ranges(struct scoutfs_key *a_start, + struct scoutfs_key *a_end, + struct scoutfs_key *b_start, + struct scoutfs_key *b_end) { return scoutfs_key_compare(a_end, b_start) < 0 ? -1 : scoutfs_key_compare(a_start, b_end) > 0 ? 1 : 0; } -/* - * Copy as much of the contents of the source buffer that fits into the - * dest buffer. - */ -static inline void scoutfs_key_copy(struct scoutfs_key_buf *dst, - struct scoutfs_key_buf *src) +static inline void scoutfs_key_inc(struct scoutfs_key *key) { - dst->key_len = min(dst->buf_len, src->key_len); - memcpy(dst->data, src->data, dst->key_len); -} - -/* - * Initialize the dst buffer to point to the source buffer in all ways, - * including the buf len. The contents of the buffer are shared by the - * fields describing the buffers are not. - */ -static inline void scoutfs_key_clone(struct scoutfs_key_buf *dst, - struct scoutfs_key_buf *src) -{ - *dst = *src; -} - -/* - * Memset as much of the length as fits in the buffer and set that to - * the new key length. - */ -static inline void scoutfs_key_memset(struct scoutfs_key_buf *key, int c, - u16 len) -{ - if (WARN_ON_ONCE(len > SCOUTFS_MAX_KEY_SIZE)) + if (++key->_sk_fourth != 0) return; - key->key_len = min(key->buf_len, len); - memset(key->data, c, key->key_len); + le64_add_cpu(&key->_sk_third, 1); + if (key->_sk_third != 0) + return; + + le64_add_cpu(&key->_sk_second, 1); + if (key->_sk_second != 0) + return; + + if (++key->sk_type != 0) + return; + + le64_add_cpu(&key->_sk_first, 1); + if (key->_sk_first != 0) + return; + + key->sk_zone++; } -/* - * Set the contents of the buffer to the smallest possible key by sort - * order. It might be truncated if the buffer isn't large enough. - */ -static inline void scoutfs_key_set_min(struct scoutfs_key_buf *key) +static inline void scoutfs_key_dec(struct scoutfs_key *key) { - scoutfs_key_memset(key, 0, sizeof(struct scoutfs_inode_key)); + if (--key->_sk_fourth != U8_MAX) + return; + + le64_add_cpu(&key->_sk_third, -1); + if (key->_sk_third != cpu_to_le64(U64_MAX)) + return; + + le64_add_cpu(&key->_sk_second, -1); + if (key->_sk_second != cpu_to_le64(U64_MAX)) + return; + + if (--key->sk_type != U8_MAX) + return; + + le64_add_cpu(&key->_sk_first, -1); + if (key->_sk_first != cpu_to_le64(U64_MAX)) + return; + + key->sk_zone--; } -/* - * Set the contents of the buffer to the largest possible key by sort - * order. It might be truncated if the buffer isn't large enough. - */ -static inline void scoutfs_key_set_max(struct scoutfs_key_buf *key) +static inline void scoutfs_key_to_be(struct scoutfs_key_be *be, + struct scoutfs_key *key) { - scoutfs_key_memset(key, 0xff, sizeof(struct scoutfs_inode_key)); + BUILD_BUG_ON(sizeof(struct scoutfs_key_be) != + sizeof(struct scoutfs_key)); + + 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) +{ + 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; } #endif diff --git a/kmod/src/lock.c b/kmod/src/lock.c index 0f0c4f13..c6545c19 100644 --- a/kmod/src/lock.c +++ b/kmod/src/lock.c @@ -112,8 +112,8 @@ static void invalidate_inode(struct super_block *sb, u64 ino) static int lock_invalidate(struct super_block *sb, struct scoutfs_lock *lock, int prev, int mode) { - struct scoutfs_key_buf *start = lock->start; - struct scoutfs_key_buf *end = lock->end; + struct scoutfs_key *start = &lock->start; + struct scoutfs_key *end = &lock->end; struct scoutfs_lock_coverage *cov; struct scoutfs_lock_coverage *tmp; u64 ino, last; @@ -191,15 +191,13 @@ static void lock_free(struct lock_info *linfo, struct scoutfs_lock *lock) list_del(&lock->lru_head); linfo->lru_nr--; } - scoutfs_key_free(sb, lock->start); - scoutfs_key_free(sb, lock->end); kfree(lock); } static struct scoutfs_lock *lock_alloc(struct super_block *sb, struct scoutfs_lock_name *name, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end) + struct scoutfs_key *start, + struct scoutfs_key *end) { DECLARE_LOCK_INFO(sb, linfo); @@ -235,12 +233,8 @@ static struct scoutfs_lock *lock_alloc(struct super_block *sb, INIT_LIST_HEAD(&lock->cov_list); if (start) { - lock->start = scoutfs_key_dup(sb, start); - lock->end = scoutfs_key_dup(sb, end); - if (!lock->start || !lock->end) { - lock_free(linfo, lock); - return NULL; - } + lock->start = *start; + lock->end = *end; } lock->sb = sb; @@ -465,14 +459,14 @@ static bool insert_range_node(struct super_block *sb, struct scoutfs_lock *ins) parent = *node; lock = container_of(*node, struct scoutfs_lock, range_node); - cmp = scoutfs_key_compare_ranges(ins->start, ins->end, - lock->start, lock->end); + cmp = scoutfs_key_compare_ranges(&ins->start, &ins->end, + &lock->start, &lock->end); if (WARN_ON_ONCE(cmp == 0)) { - scoutfs_warn_sk(sb, "inserting lock %p name "LN_FMT" start "SK_FMT" end "SK_FMT" overlaps with existing lock %p name "LN_FMT" start "SK_FMT" end "SK_FMT"\n", - ins, LN_ARG(&ins->name), - SK_ARG(ins->start), SK_ARG(ins->end), - lock, LN_ARG(&lock->name), - SK_ARG(lock->start), SK_ARG(lock->end)); + scoutfs_warn(sb, "inserting lock %p name "LN_FMT" start "SK_FMT" end "SK_FMT" overlaps with existing lock %p name "LN_FMT" start "SK_FMT" end "SK_FMT"\n", + ins, LN_ARG(&ins->name), + SK_ARG(&ins->start), SK_ARG(&ins->end), + lock, LN_ARG(&lock->name), + SK_ARG(&lock->start), SK_ARG(&lock->end)); return false; } @@ -544,8 +538,8 @@ static void scoutfs_lock_ast(void *arg) struct super_block *sb = lock->sb; DECLARE_LOCK_INFO(sb, linfo); int status = lock->lksb.sb_status; - bool cached; - bool dirty; + bool cached = false; + bool dirty = false; scoutfs_inc_counter(sb, lock_ast); @@ -584,17 +578,20 @@ static void scoutfs_lock_ast(void *arg) * changing lock modes. We can't have cached items if we're not * in the two modes that allow caching. */ - cached = lock->start && scoutfs_item_range_cached(sb, lock->start, - lock->end, false); - dirty = lock->start && scoutfs_item_range_cached(sb, lock->start, - lock->end, true); + if (!RB_EMPTY_NODE(&lock->range_node)) { + cached = scoutfs_item_range_cached(sb, &lock->start, + &lock->end, false); + dirty = scoutfs_item_range_cached(sb, &lock->start, &lock->end, + true); + } + if (WARN_ON_ONCE(dirty || (cached && lock->granted_mode != DLM_LOCK_PR && lock->granted_mode != DLM_LOCK_EX))) { - scoutfs_err_sk(sb, "lock item cache consistency violation, cached %u dirty %u: name "LN_FMT" start "SK_FMT" end "SK_FMT" refresh_gen %llu error %d granted %d bast %d prev %d work %d waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u dlmlksb: status %d lkid 0x%x flags 0x%x\n", + scoutfs_err(sb, "lock item cache consistency violation, cached %u dirty %u: name "LN_FMT" start "SK_FMT" end "SK_FMT" refresh_gen %llu error %d granted %d bast %d prev %d work %d waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u dlmlksb: status %d lkid 0x%x flags 0x%x\n", cached, dirty, - LN_ARG(&lock->name), SK_ARG(lock->start), - SK_ARG(lock->end), lock->refresh_gen, lock->error, + LN_ARG(&lock->name), SK_ARG(&lock->start), + SK_ARG(&lock->end), lock->refresh_gen, lock->error, lock->granted_mode, lock->bast_mode, lock->work_prev_mode, lock->work_mode, lock->waiters[DLM_LOCK_PR], @@ -674,7 +671,7 @@ static void scoutfs_lock_work(struct work_struct *work) spin_unlock(&linfo->lock); - if (lock->start) { + if (!RB_EMPTY_NODE(&lock->range_node)) { ret = lock_invalidate(sb, lock, prev, mode); BUG_ON(ret); } @@ -793,8 +790,7 @@ static bool lock_wait(struct lock_info *linfo, struct scoutfs_lock *lock, */ static int lock_name_keys(struct super_block *sb, int mode, int flags, struct scoutfs_lock_name *name, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end, + struct scoutfs_key *start, struct scoutfs_key *end, struct scoutfs_lock **ret_lock) { DECLARE_LOCK_INFO(sb, linfo); @@ -873,10 +869,8 @@ int scoutfs_lock_ino(struct super_block *sb, int mode, int flags, u64 ino, struct scoutfs_lock **ret_lock) { struct scoutfs_lock_name name; - struct scoutfs_inode_key start_ikey; - struct scoutfs_inode_key end_ikey; - struct scoutfs_key_buf start; - struct scoutfs_key_buf end; + struct scoutfs_key start; + struct scoutfs_key end; ino &= ~(u64)SCOUTFS_LOCK_INODE_GROUP_MASK; @@ -886,15 +880,17 @@ int scoutfs_lock_ino(struct super_block *sb, int mode, int flags, u64 ino, name.first = cpu_to_le64(ino); name.second = 0; - start_ikey.zone = SCOUTFS_FS_ZONE; - start_ikey.ino = cpu_to_be64(ino); - start_ikey.type = 0; - scoutfs_key_init(&start, &start_ikey, sizeof(start_ikey)); + start = (struct scoutfs_key) { + .sk_zone = SCOUTFS_FS_ZONE, + .ski_ino = cpu_to_le64(ino), + .sk_type = 0, + }; - end_ikey.zone = SCOUTFS_FS_ZONE; - end_ikey.ino = cpu_to_be64(ino + SCOUTFS_LOCK_INODE_GROUP_NR - 1); - end_ikey.type = ~0; - scoutfs_key_init(&end, &end_ikey, sizeof(end_ikey)); + end = (struct scoutfs_key) { + .sk_zone = SCOUTFS_FS_ZONE, + .ski_ino = cpu_to_le64(ino + SCOUTFS_LOCK_INODE_GROUP_NR - 1), + .sk_type = U8_MAX, + }; return lock_name_keys(sb, mode, flags, &name, &start, &end, ret_lock); } @@ -1045,8 +1041,8 @@ int scoutfs_lock_global(struct super_block *sb, int mode, int flags, int type, * because their starting keys are the same. */ void scoutfs_lock_get_index_item_range(u8 type, u64 major, u64 ino, - struct scoutfs_inode_index_key *start, - struct scoutfs_inode_index_key *end) + struct scoutfs_key *start, + struct scoutfs_key *end) { u64 start_major = major & ~SCOUTFS_LOCK_SEQ_GROUP_MASK; u64 end_major = major | SCOUTFS_LOCK_SEQ_GROUP_MASK; @@ -1054,21 +1050,12 @@ void scoutfs_lock_get_index_item_range(u8 type, u64 major, u64 ino, BUG_ON(type != SCOUTFS_INODE_INDEX_META_SEQ_TYPE && type != SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE); - if (start) { - start->zone = SCOUTFS_INODE_INDEX_ZONE; - start->type = type; - start->major = cpu_to_be64(start_major); - start->minor = 0; - start->ino = 0; - } + if (start) + scoutfs_inode_init_index_key(start, type, start_major, 0, 0); - if (end) { - end->zone = SCOUTFS_INODE_INDEX_ZONE; - end->type = type; - end->major = cpu_to_be64(end_major); - end->minor = 0; - end->ino = cpu_to_be64(~0ULL); - } + if (end) + scoutfs_inode_init_index_key(end, type, end_major, U32_MAX, + U64_MAX); } /* @@ -1082,22 +1069,16 @@ int scoutfs_lock_inode_index(struct super_block *sb, int mode, struct scoutfs_lock **ret_lock) { struct scoutfs_lock_name name; - struct scoutfs_inode_index_key start_ikey; - struct scoutfs_inode_index_key end_ikey; - struct scoutfs_key_buf start; - struct scoutfs_key_buf end; + struct scoutfs_key start; + struct scoutfs_key end; - scoutfs_lock_get_index_item_range(type, major, ino, - &start_ikey, &end_ikey); + scoutfs_lock_get_index_item_range(type, major, ino, &start, &end); name.scope = SCOUTFS_LOCK_SCOPE_FS_ITEMS; - name.zone = start_ikey.zone; - name.type = start_ikey.type; - name.first = be64_to_le64(start_ikey.major); - name.second = be64_to_le64(start_ikey.ino); - - scoutfs_key_init(&start, &start_ikey, sizeof(start_ikey)); - scoutfs_key_init(&end, &end_ikey, sizeof(end_ikey)); + name.zone = start.sk_zone; + name.type = start.sk_type; + name.first = start.skii_major; + name.second = start.skii_ino; return lock_name_keys(sb, mode, 0, &name, &start, &end, ret_lock); } @@ -1117,10 +1098,8 @@ int scoutfs_lock_node_id(struct super_block *sb, int mode, int flags, u64 node_id, struct scoutfs_lock **lock) { struct scoutfs_lock_name name; - struct scoutfs_orphan_key start_okey; - struct scoutfs_orphan_key end_okey; - struct scoutfs_key_buf start; - struct scoutfs_key_buf end; + struct scoutfs_key start; + struct scoutfs_key end; name.scope = SCOUTFS_LOCK_SCOPE_FS_ITEMS; name.zone = SCOUTFS_NODE_ZONE; @@ -1128,17 +1107,17 @@ int scoutfs_lock_node_id(struct super_block *sb, int mode, int flags, name.first = cpu_to_le64(node_id); name.second = 0; - start_okey.zone = SCOUTFS_NODE_ZONE; - start_okey.node_id = cpu_to_be64(node_id); - start_okey.type = 0; - start_okey.ino = 0; - scoutfs_key_init(&start, &start_okey, sizeof(start_okey)); + start = (struct scoutfs_key) { + .sk_zone = SCOUTFS_NODE_ZONE, + .sko_node_id = cpu_to_le64(node_id), + .sk_type = 0, + }; - end_okey.zone = SCOUTFS_NODE_ZONE; - end_okey.node_id = cpu_to_be64(node_id); - end_okey.type = ~0; - end_okey.ino = cpu_to_be64(~0ULL); - scoutfs_key_init(&end, &end_okey, sizeof(end_okey)); + end = (struct scoutfs_key) { + .sk_zone = SCOUTFS_NODE_ZONE, + .sko_node_id = cpu_to_le64(node_id), + .sk_type = U8_MAX, + }; return lock_name_keys(sb, mode, flags, &name, &start, &end, lock); } @@ -1330,9 +1309,9 @@ static int scoutfs_debug_locks_seq_show(struct seq_file *m, void *v) { struct scoutfs_lock *lock = v; - SK_PCPU(seq_printf(m, "name "LN_FMT" start "SK_FMT" end "SK_FMT" refresh_gen %llu error %d granted %d bast %d prev %d work %d waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u dlmlksb: status %d lkid 0x%x flags 0x%x\n", - LN_ARG(&lock->name), SK_ARG(lock->start), - SK_ARG(lock->end), lock->refresh_gen, lock->error, + seq_printf(m, "name "LN_FMT" start "SK_FMT" end "SK_FMT" refresh_gen %llu error %d granted %d bast %d prev %d work %d waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u dlmlksb: status %d lkid 0x%x flags 0x%x\n", + LN_ARG(&lock->name), SK_ARG(&lock->start), + SK_ARG(&lock->end), lock->refresh_gen, lock->error, lock->granted_mode, lock->bast_mode, lock->work_prev_mode, lock->work_mode, lock->waiters[DLM_LOCK_PR], @@ -1343,7 +1322,7 @@ static int scoutfs_debug_locks_seq_show(struct seq_file *m, void *v) lock->users[DLM_LOCK_CW], lock->lksb.sb_status, lock->lksb.sb_lkid, - lock->lksb.sb_flags)); + lock->lksb.sb_flags); return 0; } @@ -1437,10 +1416,10 @@ void scoutfs_lock_destroy(struct super_block *sb) for (mode = 0; mode < SCOUTFS_LOCK_NR_MODES; mode++) { if (lock->waiters[mode] || lock->users[mode]) { - scoutfs_warn_sk(sb, "lock name "LN_FMT" start "SK_FMT" end "SK_FMT" has mode %d user after shutdown", + scoutfs_warn(sb, "lock name "LN_FMT" start "SK_FMT" end "SK_FMT" has mode %d user after shutdown", LN_ARG(&lock->name), - SK_ARG(lock->start), - SK_ARG(lock->end), mode); + SK_ARG(&lock->start), + SK_ARG(&lock->end), mode); break; } } diff --git a/kmod/src/lock.h b/kmod/src/lock.h index 12e8c610..1898a6a3 100644 --- a/kmod/src/lock.h +++ b/kmod/src/lock.h @@ -16,8 +16,8 @@ struct scoutfs_lock { struct super_block *sb; struct scoutfs_lock_name name; - struct scoutfs_key_buf *start; - struct scoutfs_key_buf *end; + struct scoutfs_key start; + struct scoutfs_key end; struct rb_node node; struct rb_node range_node; unsigned int debug_locks_id; @@ -53,8 +53,8 @@ int scoutfs_lock_inode(struct super_block *sb, int mode, int flags, int scoutfs_lock_ino(struct super_block *sb, int mode, int flags, u64 ino, struct scoutfs_lock **ret_lock); void scoutfs_lock_get_index_item_range(u8 type, u64 major, u64 ino, - struct scoutfs_inode_index_key *start, - struct scoutfs_inode_index_key *end); + struct scoutfs_key *start, + struct scoutfs_key *end); int scoutfs_lock_inode_index(struct super_block *sb, int mode, u8 type, u64 major, u64 ino, struct scoutfs_lock **ret_lock); diff --git a/kmod/src/manifest.c b/kmod/src/manifest.c index 2f00a7e3..a41ba62a 100644 --- a/kmod/src/manifest.c +++ b/kmod/src/manifest.c @@ -50,7 +50,7 @@ struct manifest { unsigned long flags; - struct scoutfs_key_buf *compact_keys[SCOUTFS_MANIFEST_MAX_LEVEL + 1]; + struct scoutfs_key compact_keys[SCOUTFS_MANIFEST_MAX_LEVEL + 1]; }; #define MANI_FLAG_LEVEL0_FULL (1 << 0) @@ -77,8 +77,8 @@ struct manifest_ref { int off; u8 level; - struct scoutfs_key_buf *first; - struct scoutfs_key_buf *last; + struct scoutfs_key first; + struct scoutfs_key last; }; /* @@ -123,95 +123,29 @@ bool scoutfs_manifest_level0_full(struct super_block *sb) void scoutfs_manifest_init_entry(struct scoutfs_manifest_entry *ment, u64 level, u64 segno, u64 seq, - struct scoutfs_key_buf *first, - struct scoutfs_key_buf *last) + struct scoutfs_key *first, + struct scoutfs_key *last) { ment->level = level; ment->segno = segno; ment->seq = seq; - - if (first) - scoutfs_key_clone(&ment->first, first); - else - scoutfs_key_init(&ment->first, NULL, 0); - - if (last) - scoutfs_key_clone(&ment->last, last); - else - scoutfs_key_init(&ment->last, NULL, 0); + scoutfs_key_copy_or_zeros(&ment->first, first); + scoutfs_key_copy_or_zeros(&ment->last, last); } -/* - * level 0 segments have the extra seq up in the btree key. - */ -static struct scoutfs_manifest_btree_key * -alloc_btree_key_val_lens(unsigned first_len, unsigned last_len) +static void init_btree_key(struct scoutfs_manifest_btree_key *mkey, + u8 level, u64 seq, struct scoutfs_key *first) { - return kmalloc(sizeof(struct scoutfs_manifest_btree_key) + - sizeof(u64) + - sizeof(struct scoutfs_manifest_btree_val) + - first_len + last_len, GFP_NOFS); + mkey->level = level; + scoutfs_key_to_be(&mkey->first_key, first); + mkey->seq = cpu_to_be64(seq); } -/* - * Initialize the btree key and value for a manifest entry in one contiguous - * allocation. - */ -static struct scoutfs_manifest_btree_key * -alloc_btree_key_val(struct scoutfs_manifest_entry *ment, unsigned *mkey_len, - struct scoutfs_manifest_btree_val **mval_ret, - unsigned *mval_len_ret) +static void init_btree_val(struct scoutfs_manifest_btree_val *mval, + u64 segno, struct scoutfs_key *last) { - struct scoutfs_manifest_btree_key *mkey; - struct scoutfs_manifest_btree_val *mval; - struct scoutfs_key_buf b_first; - struct scoutfs_key_buf b_last; - unsigned bkey_len; - unsigned mval_len; - __be64 seq; - - mkey = alloc_btree_key_val_lens(ment->first.key_len, ment->last.key_len); - if (!mkey) - return NULL; - - if (ment->level == 0) { - seq = cpu_to_be64(ment->seq); - bkey_len = sizeof(seq); - memcpy(mkey->bkey, &seq, bkey_len); - } else { - bkey_len = ment->first.key_len; - } - - *mkey_len = offsetof(struct scoutfs_manifest_btree_key, bkey[bkey_len]); - mval = (void *)mkey + *mkey_len; - - if (ment->level == 0) { - scoutfs_key_init(&b_first, mval->keys, ment->first.key_len); - scoutfs_key_init(&b_last, mval->keys + ment->first.key_len, - ment->last.key_len); - mval_len = sizeof(struct scoutfs_manifest_btree_val) + - ment->first.key_len + ment->last.key_len; - } else { - scoutfs_key_init(&b_first, mkey->bkey, ment->first.key_len); - scoutfs_key_init(&b_last, mval->keys, ment->last.key_len); - mval_len = sizeof(struct scoutfs_manifest_btree_val) + - ment->last.key_len; - } - - mkey->level = ment->level; - mval->segno = cpu_to_le64(ment->segno); - mval->seq = cpu_to_le64(ment->seq); - mval->first_key_len = cpu_to_le16(ment->first.key_len); - mval->last_key_len = cpu_to_le16(ment->last.key_len); - - scoutfs_key_copy(&b_first, &ment->first); - scoutfs_key_copy(&b_last, &ment->last); - - if (mval_ret) { - *mval_ret = mval; - *mval_len_ret = mval_len; - } - return mkey; + mval->segno = cpu_to_le64(segno); + mval->last_key = *last; } /* initialize a native manifest entry to point to the btree key and value */ @@ -222,50 +156,12 @@ static void init_ment_iref(struct scoutfs_manifest_entry *ment, struct scoutfs_manifest_btree_val *mval = iref->val; ment->level = mkey->level; + scoutfs_key_from_be(&ment->first, &mkey->first_key); + ment->seq = be64_to_cpu(mkey->seq); ment->segno = le64_to_cpu(mval->segno); - ment->seq = le64_to_cpu(mval->seq); - - if (ment->level == 0) { - scoutfs_key_init(&ment->first, mval->keys, - le16_to_cpu(mval->first_key_len)); - scoutfs_key_init(&ment->last, mval->keys + - le16_to_cpu(mval->first_key_len), - le16_to_cpu(mval->last_key_len)); - } else { - scoutfs_key_init(&ment->first, mkey->bkey, - le16_to_cpu(mval->first_key_len)); - scoutfs_key_init(&ment->last, mval->keys, - le16_to_cpu(mval->last_key_len)); - } + ment->last = mval->last_key; } -/* - * Fill the callers max-size btree key with the given values and return - * its length. - */ -static unsigned init_btree_key(struct scoutfs_manifest_btree_key *mkey, - u8 level, u64 seq, struct scoutfs_key_buf *first) -{ - struct scoutfs_key_buf b_first; - unsigned bkey_len; - __be64 bseq; - - mkey->level = level; - - if (level == 0) { - bseq = cpu_to_be64(seq); - bkey_len = sizeof(bseq); - memcpy(mkey->bkey, &bseq, bkey_len); - } else if (first) { - scoutfs_key_init(&b_first, mkey->bkey, first->key_len); - scoutfs_key_copy(&b_first, first); - bkey_len = first->key_len; - } else { - bkey_len = 0; - } - - return offsetof(struct scoutfs_manifest_btree_key, bkey[bkey_len]); -} /* * Insert a new manifest entry in the ring. The ring allocates a new @@ -279,29 +175,25 @@ int scoutfs_manifest_add(struct super_block *sb, DECLARE_MANIFEST(sb, mani); struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_super_block *super = &sbi->super; - struct scoutfs_manifest_btree_key *mkey; - struct scoutfs_manifest_btree_val *mval; - unsigned mkey_len; - unsigned mval_len; + struct scoutfs_manifest_btree_key mkey; + struct scoutfs_manifest_btree_val mval; int ret; lockdep_assert_held(&mani->rwsem); - mkey = alloc_btree_key_val(ment, &mkey_len, &mval, &mval_len); - if (!mkey) - return -ENOMEM; + init_btree_key(&mkey, ment->level, ment->seq, &ment->first); + init_btree_val(&mval, ment->segno, &ment->last); trace_scoutfs_manifest_add(sb, ment->level, ment->segno, ment->seq, &ment->first, &ment->last); - ret = scoutfs_btree_insert(sb, &super->manifest.root, mkey, mkey_len, - mval, mval_len); + ret = scoutfs_btree_insert(sb, &super->manifest.root, + &mkey, sizeof(mkey), &mval, sizeof(mval)); if (ret == 0) { mani->nr_levels = max_t(u8, mani->nr_levels, ment->level + 1); add_level_count(sb, ment->level, 1); } - kfree(mkey); return ret; } @@ -317,8 +209,7 @@ int scoutfs_manifest_del(struct super_block *sb, DECLARE_MANIFEST(sb, mani); struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_super_block *super = &sbi->super; - struct scoutfs_manifest_btree_key *mkey; - unsigned mkey_len; + struct scoutfs_manifest_btree_key mkey; int ret; trace_scoutfs_manifest_delete(sb, ment->level, ment->segno, ment->seq, @@ -326,15 +217,13 @@ int scoutfs_manifest_del(struct super_block *sb, lockdep_assert_held(&mani->rwsem); - mkey = alloc_btree_key_val(ment, &mkey_len, NULL, NULL); - if (!mkey) - return -ENOMEM; + init_btree_key(&mkey, ment->level, ment->seq, &ment->first); - ret = scoutfs_btree_delete(sb, &super->manifest.root, mkey, mkey_len); + ret = scoutfs_btree_delete(sb, &super->manifest.root, + &mkey, sizeof(mkey)); if (ret == 0) add_level_count(sb, ment->level, -1ULL); - kfree(mkey); return ret; } @@ -367,8 +256,6 @@ static void free_ref(struct super_block *sb, struct manifest_ref *ref) if (!IS_ERR_OR_NULL(ref)) { WARN_ON_ONCE(!list_empty(&ref->entry)); scoutfs_seg_put(ref->seg); - scoutfs_key_free(sb, ref->first); - scoutfs_key_free(sb, ref->last); kfree(ref); } } @@ -383,15 +270,11 @@ static int alloc_manifest_ref(struct super_block *sb, struct list_head *ref_list struct manifest_ref *ref; ref = kzalloc(sizeof(struct manifest_ref), GFP_NOFS); - if (ref) { - ref->first = scoutfs_key_dup(sb, &ment->first); - ref->last = scoutfs_key_dup(sb, &ment->last); - } - if (!ref || !ref->first || !ref->last) { - free_ref(sb, ref); + if (!ref) return -ENOMEM; - } + ref->first = ment->first; + ref->last = ment->last; ref->level = ment->level; ref->segno = ment->segno; ref->seq = ment->seq; @@ -410,7 +293,7 @@ static int alloc_manifest_ref(struct super_block *sb, struct list_head *ref_list static int btree_prev_overlap_or_next(struct super_block *sb, struct scoutfs_btree_root *root, void *key, unsigned key_len, - struct scoutfs_key_buf *start, u8 level, + struct scoutfs_key *start, u8 level, struct scoutfs_btree_item_ref *iref) { struct scoutfs_manifest_entry ment; @@ -436,55 +319,63 @@ static int btree_prev_overlap_or_next(struct super_block *sb, /* * Get references to all the level 0 segments whose item ranges - * intersect with the callers range. We walk the manifest backwards so - * that we end up adding refs to the caller's list reverse sorted by - * sequence, which is what they want to be able to use the segment with - * the newest item. + * intersect with the callers range. The entries are sorted by their + * first key so we can stop searching once our end key can only keep + * being less than the increasing start key. * * This can return -ESTALE if it reads through stale btree blocks. */ static int get_zero_refs(struct super_block *sb, struct scoutfs_btree_root *root, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end, + struct scoutfs_key *start, + struct scoutfs_key *end, struct list_head *ref_list) { - struct scoutfs_manifest_btree_key *mkey; + struct scoutfs_manifest_btree_key mkey; struct scoutfs_manifest_entry ment; SCOUTFS_BTREE_ITEM_REF(iref); - SCOUTFS_BTREE_ITEM_REF(prev); - unsigned mkey_len; + struct scoutfs_key zeros; + int cmp; int ret; - scoutfs_manifest_init_entry(&ment, 0, 0, 0, start, NULL); - mkey = alloc_btree_key_val(&ment, &mkey_len, NULL, NULL); - if (!mkey) - return -ENOMEM; + scoutfs_key_set_zeros(&zeros); + init_btree_key(&mkey, 0, 0, &zeros); + + for (;;) { + ret = scoutfs_btree_next(sb, root, &mkey, sizeof(mkey), &iref); + if (ret < 0) { + if (ret == -ENOENT) + ret = 0; + break; + } - /* get level 0 segments that overlap with the missing range */ - mkey_len = init_btree_key(mkey, 0, ~0ULL, NULL); - ret = scoutfs_btree_prev(sb, root, mkey, mkey_len, &iref); - while (ret == 0) { init_ment_iref(&ment, &iref); + scoutfs_btree_put_iref(&iref); - if (scoutfs_key_compare_ranges(start, end, &ment.first, - &ment.last) == 0) { + /* done if we went past level 0 */ + if (ment.level > 0) { + ret = 0; + break; + } + + cmp = scoutfs_key_compare_ranges(start, end, &ment.first, + &ment.last); + /* done if all the ments will be greater */ + if (cmp < 0) { + ret = 0; + break; + } + + if (cmp == 0) { ret = alloc_manifest_ref(sb, ref_list, &ment); if (ret) break; } - swap(prev, iref); - ret = scoutfs_btree_before(sb, root, prev.key, prev.key_len, - &iref); - scoutfs_btree_put_iref(&prev); + scoutfs_key_inc(&ment.first); + init_btree_key(&mkey, ment.level, ment.seq, &ment.first); } - if (ret == -ENOENT) - ret = 0; - scoutfs_btree_put_iref(&iref); - scoutfs_btree_put_iref(&prev); - kfree(mkey); return ret; } @@ -502,37 +393,29 @@ static int get_zero_refs(struct super_block *sb, */ static int get_nonzero_refs(struct super_block *sb, struct scoutfs_btree_root *root, - struct scoutfs_key_buf *key, - struct scoutfs_key_buf *end, + struct scoutfs_key *key, + struct scoutfs_key *end, struct list_head *ref_list) { - struct scoutfs_manifest_btree_key *mkey; + struct scoutfs_manifest_btree_key mkey; struct scoutfs_manifest_entry ment; SCOUTFS_BTREE_ITEM_REF(iref); - SCOUTFS_BTREE_ITEM_REF(prev); - unsigned mkey_len; int ret; int i; - scoutfs_manifest_init_entry(&ment, 0, 0, 0, key, NULL); - mkey = alloc_btree_key_val(&ment, &mkey_len, NULL, NULL); - if (!mkey) - return -ENOMEM; - - mkey_len = init_btree_key(mkey, 1, 0, key); for (i = 1; ; i++) { - mkey->level = i; + init_btree_key(&mkey, i, 0, key); - scoutfs_btree_put_iref(&iref); - ret = btree_prev_overlap_or_next(sb, root, mkey, mkey_len, key, - i, &iref); + ret = btree_prev_overlap_or_next(sb, root, &mkey, sizeof(mkey), + key, i, &iref); if (ret < 0) { if (ret == -ENOENT) ret = 0; - goto out; + break; } init_ment_iref(&ment, &iref); + scoutfs_btree_put_iref(&iref); if (ment.level != i || scoutfs_key_compare(&ment.first, end) > 0) @@ -540,14 +423,9 @@ static int get_nonzero_refs(struct super_block *sb, ret = alloc_manifest_ref(sb, ref_list, &ment); if (ret) - goto out; + break; } - ret = 0; -out: - scoutfs_btree_put_iref(&iref); - scoutfs_btree_put_iref(&prev); - kfree(mkey); return ret; } @@ -630,15 +508,15 @@ static int cmp_ment_ref_level_seq(void *priv, struct list_head *A, * as long as we hold refs. */ int scoutfs_manifest_read_items(struct super_block *sb, - struct scoutfs_key_buf *key, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end) + struct scoutfs_key *key, + struct scoutfs_key *start, + struct scoutfs_key *end) { - struct scoutfs_key_buf item_key; - struct scoutfs_key_buf found_key; - struct scoutfs_key_buf batch_end; - struct scoutfs_key_buf seg_start; - struct scoutfs_key_buf seg_end; + struct scoutfs_key item_key; + struct scoutfs_key found_key; + struct scoutfs_key batch_end; + struct scoutfs_key seg_start; + struct scoutfs_key seg_end; struct scoutfs_btree_root root; struct scoutfs_segment *seg; struct manifest_ref *ref; @@ -666,8 +544,8 @@ int scoutfs_manifest_read_items(struct super_block *sb, last_root_seq = 0; retry_stale: - scoutfs_key_clone(&seg_start, start); - scoutfs_key_clone(&seg_end, end); + seg_start = *start; + seg_end = *end; ret = scoutfs_client_get_manifest_root(sb, &root); if (ret) @@ -681,13 +559,13 @@ retry_stale: /* clamp start and end to the segment boundaries, including key */ list_for_each_entry(ref, &ref_list, entry) { - if (scoutfs_key_compare(ref->first, &seg_start) > 0 && - scoutfs_key_compare(ref->first, key) <= 0) - scoutfs_key_clone(&seg_start, ref->first); + if (scoutfs_key_compare(&ref->first, &seg_start) > 0 && + scoutfs_key_compare(&ref->first, key) <= 0) + seg_start = ref->first; - if (scoutfs_key_compare(ref->last, &seg_end) < 0 && - scoutfs_key_compare(ref->last, key) >= 0) - scoutfs_key_clone(&seg_end, ref->last); + if (scoutfs_key_compare(&ref->last, &seg_end) < 0 && + scoutfs_key_compare(&ref->last, key) >= 0) + seg_end = ref->last; } trace_scoutfs_read_item_keys(sb, key, start, end, &seg_start, &seg_end); @@ -703,8 +581,9 @@ retry_stale: /* submit reads for all the segments */ list_for_each_entry(ref, &ref_list, entry) { - trace_scoutfs_read_item_segment(sb, ref->level, ref->segno, - ref->seq, ref->first, ref->last); + trace_scoutfs_read_item_segment(sb, ref->level, ref->segno, + ref->seq, &ref->first, + &ref->last); seg = scoutfs_seg_submit_read(sb, ref->segno); if (IS_ERR(seg)) { @@ -752,9 +631,9 @@ retry_stale: * items or if the next item is past the keys * that our segments can see. */ - ret = scoutfs_seg_item_ptrs(ref->seg, ref->off, - &item_key, &item_val, - &item_flags); + ret = scoutfs_seg_get_item(ref->seg, ref->off, + &item_key, &item_val, + &item_flags); if (ret < 0 || scoutfs_key_compare(&item_key, &seg_end) > 0) { ref->off = -1; @@ -773,7 +652,7 @@ retry_stale: } /* remember new least key */ - scoutfs_key_clone(&found_key, &item_key); + found_key = item_key; found_val = item_val; found_flags = item_flags; ref->found_ctr = ++found_ctr; @@ -782,7 +661,7 @@ retry_stale: /* ran out of keys in segs, range extends to seg end */ if (!found) { - scoutfs_key_clone(&batch_end, &seg_end); + batch_end = seg_end; ret = 0; break; } @@ -808,7 +687,7 @@ retry_stale: } /* the last successful key determines range end until run out */ - scoutfs_key_clone(&batch_end, &found_key); + batch_end = found_key; /* if we just saw the end key then we're done */ if (scoutfs_key_compare(&found_key, &seg_end) == 0) { @@ -864,14 +743,12 @@ out: * Returns 0 if it set next_key and -ENOENT if the key was after all the * segments in the manifest. */ -int scoutfs_manifest_next_key(struct super_block *sb, - struct scoutfs_key_buf *key, - struct scoutfs_key_buf *next_key) +int scoutfs_manifest_next_key(struct super_block *sb, struct scoutfs_key *key, + struct scoutfs_key *next_key) { - struct scoutfs_key_buf item_key; - struct scoutfs_key_buf end; + struct scoutfs_key item_key; + struct scoutfs_key end; struct scoutfs_btree_root root; - struct scoutfs_inode_key end_key; struct scoutfs_segment *seg; struct manifest_ref *ref; struct manifest_ref *tmp; @@ -887,8 +764,7 @@ retry_stale: if (ret) goto out; - scoutfs_key_init(&end, &end_key, sizeof(end_key)); - scoutfs_key_set_max(&end); + scoutfs_key_set_ones(&end); ret = get_zero_refs(sb, &root, key, &end, &ref_list) ?: get_nonzero_refs(sb, &root, key, &end, &ref_list); @@ -929,8 +805,9 @@ retry_stale: found = false; list_for_each_entry(ref, &ref_list, entry) { if (ref->level > 0 && - (!found || scoutfs_key_compare(ref->last, next_key) < 0)) { - scoutfs_key_copy(next_key, ref->last); + (!found || + scoutfs_key_compare(&ref->last, next_key) < 0)) { + *next_key = ref->last; found = true; } @@ -942,13 +819,13 @@ retry_stale: if (ref->off < 0) continue; - ret = scoutfs_seg_item_ptrs(ref->seg, ref->off, &item_key, - NULL, NULL); + ret = scoutfs_seg_get_item(ref->seg, ref->off, &item_key, + NULL, NULL); if (ret < 0) continue; if (!found || scoutfs_key_compare(&item_key, next_key) < 0) { - scoutfs_key_copy(next_key, &item_key); + *next_key = item_key; found = true; } } @@ -996,19 +873,23 @@ int scoutfs_manifest_next_compact(struct super_block *sb, void *data) DECLARE_MANIFEST(sb, mani); struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_super_block *super = &sbi->super; + struct scoutfs_manifest_btree_key mkey; + struct scoutfs_manifest_entry next; struct scoutfs_manifest_entry ment; struct scoutfs_manifest_entry over; - struct scoutfs_manifest_btree_key *mkey = NULL; SCOUTFS_BTREE_ITEM_REF(iref); SCOUTFS_BTREE_ITEM_REF(over_iref); SCOUTFS_BTREE_ITEM_REF(prev); - unsigned mkey_len; + struct scoutfs_key zeros; + bool wrapped; bool sticky; int level; int ret; int nr = 0; int i; + scoutfs_key_set_zeros(&zeros); + down_write(&mani->rwsem); for (level = mani->nr_levels - 1; level >= 0; level--) { @@ -1024,45 +905,60 @@ int scoutfs_manifest_next_compact(struct super_block *sb, void *data) goto out; } - /* alloc a full size mkey, fill it with whatever search key */ - - mkey = alloc_btree_key_val_lens(SCOUTFS_MAX_KEY_SIZE, 0); - if (!mkey) { - ret = -ENOMEM; - goto out; - } - - /* find the oldest level 0 or the next higher order level by key */ + /* fill ment and ret == 0 if we find an entry at the level */ if (level == 0) { + /* find the oldest level 0 */ - mkey_len = init_btree_key(mkey, 0, 0, NULL); - ret = scoutfs_btree_next(sb, &super->manifest.root, - mkey, mkey_len, &iref); + init_btree_key(&mkey, 0, 0, &zeros); + ment.seq = U64_MAX; + + for (;;) { + ret = scoutfs_btree_next(sb, &super->manifest.root, + &mkey, sizeof(mkey), &iref); + if (ret < 0) { + if (ret == -ENOENT && ment.seq != U64_MAX) + ret = 0; + break; + } + + init_ment_iref(&next, &iref); + scoutfs_btree_put_iref(&iref); + + if (next.level > 0) { + if (ment.seq == U64_MAX) + ret = -ENOENT; + break; + } + + if (next.seq < ment.seq) + ment = next; + + scoutfs_key_inc(&next.first); + init_btree_key(&mkey, next.level, next.seq, + &next.first); + } + } else { /* find the next segment after the compaction at this level */ - mkey_len = init_btree_key(mkey, level, 0, - mani->compact_keys[level]); - + init_btree_key(&mkey, level, 0, &mani->compact_keys[level]); + wrapped = false; +again: ret = scoutfs_btree_next(sb, &super->manifest.root, - mkey, mkey_len, &iref); + &mkey, sizeof(mkey), &iref); if (ret == 0) { init_ment_iref(&ment, &iref); + scoutfs_btree_put_iref(&iref); if (ment.level != level) ret = -ENOENT; } - if (ret == -ENOENT) { - /* .. possibly wrapping to the first key in level */ - mkey_len = init_btree_key(mkey, level, 0, NULL); - scoutfs_btree_put_iref(&iref); - ret = scoutfs_btree_next(sb, &super->manifest.root, - mkey, mkey_len, &iref); + /* try again if we wrapped */ + if (ret == -ENOENT && !wrapped) { + init_btree_key(&mkey, level, 0, &zeros); + wrapped = true; + goto again; } } - if (ret == 0) { - init_ment_iref(&ment, &iref); - if (ment.level != level) - goto out; - } + if (ret < 0) { if (ret == -ENOENT) ret = 0; @@ -1076,10 +972,10 @@ int scoutfs_manifest_next_compact(struct super_block *sb, void *data) nr++; /* and add a fanout's worth of lower overlapping segments */ - mkey_len = init_btree_key(mkey, level + 1, 0, &ment.first); + init_btree_key(&mkey, level + 1, 0, &ment.first); ret = btree_prev_overlap_or_next(sb, &super->manifest.root, - mkey, mkey_len, - &ment.first, level + 1, &over_iref); + &mkey, sizeof(mkey), &ment.first, + level + 1, &over_iref); sticky = false; for (i = 0; ret == 0 && i < SCOUTFS_MANIFEST_FANOUT + 1; i++) { init_ment_iref(&over, &over_iref); @@ -1112,14 +1008,13 @@ int scoutfs_manifest_next_compact(struct super_block *sb, void *data) scoutfs_compact_describe(sb, data, level, mani->nr_levels - 1, sticky); /* record the next key to start from */ - scoutfs_key_copy(mani->compact_keys[level], &ment.last); - scoutfs_key_inc(mani->compact_keys[level]); + mani->compact_keys[level] = ment.last; + scoutfs_key_inc(&mani->compact_keys[level]); ret = 0; out: up_write(&mani->rwsem); - kfree(mkey); scoutfs_btree_put_iref(&iref); scoutfs_btree_put_iref(&over_iref); scoutfs_btree_put_iref(&prev); @@ -1140,18 +1035,8 @@ int scoutfs_manifest_setup(struct super_block *sb) init_rwsem(&mani->rwsem); - for (i = 0; i < ARRAY_SIZE(mani->compact_keys); i++) { - mani->compact_keys[i] = scoutfs_key_alloc(sb, - SCOUTFS_MAX_KEY_SIZE); - if (!mani->compact_keys[i]) { - while (--i >= 0) - scoutfs_key_free(sb, mani->compact_keys[i]); - kfree(mani); - return -ENOMEM; - } - - scoutfs_key_set_min(mani->compact_keys[i]); - } + for (i = 0; i < ARRAY_SIZE(mani->compact_keys); i++) + scoutfs_key_set_zeros(&mani->compact_keys[i]); for (i = ARRAY_SIZE(super->manifest.level_counts) - 1; i >= 0; i--) { if (super->manifest.level_counts[i]) { @@ -1177,11 +1062,8 @@ void scoutfs_manifest_destroy(struct super_block *sb) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct manifest *mani = sbi->manifest; - int i; if (mani) { - for (i = 0; i < ARRAY_SIZE(mani->compact_keys); i++) - scoutfs_key_free(sb, mani->compact_keys[i]); kfree(mani); sbi->manifest = NULL; } diff --git a/kmod/src/manifest.h b/kmod/src/manifest.h index 020a76fc..cd1a095d 100644 --- a/kmod/src/manifest.h +++ b/kmod/src/manifest.h @@ -15,14 +15,14 @@ struct scoutfs_manifest_entry { u8 level; u64 segno; u64 seq; - struct scoutfs_key_buf first; - struct scoutfs_key_buf last; + struct scoutfs_key first; + struct scoutfs_key last; }; void scoutfs_manifest_init_entry(struct scoutfs_manifest_entry *ment, u64 level, u64 segno, u64 seq, - struct scoutfs_key_buf *first, - struct scoutfs_key_buf *last); + struct scoutfs_key *first, + struct scoutfs_key *last); int scoutfs_manifest_add(struct super_block *sb, struct scoutfs_manifest_entry *ment); int scoutfs_manifest_del(struct super_block *sb, @@ -32,12 +32,11 @@ int scoutfs_manifest_lock(struct super_block *sb); int scoutfs_manifest_unlock(struct super_block *sb); int scoutfs_manifest_read_items(struct super_block *sb, - struct scoutfs_key_buf *key, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end); -int scoutfs_manifest_next_key(struct super_block *sb, - struct scoutfs_key_buf *key, - struct scoutfs_key_buf *next_key); + struct scoutfs_key *key, + struct scoutfs_key *start, + struct scoutfs_key *end); +int scoutfs_manifest_next_key(struct super_block *sb, struct scoutfs_key *key, + struct scoutfs_key *next_key); int scoutfs_manifest_next_compact(struct super_block *sb, void *data); diff --git a/kmod/src/msg.h b/kmod/src/msg.h index 9cde9716..eff34766 100644 --- a/kmod/src/msg.h +++ b/kmod/src/msg.h @@ -6,27 +6,13 @@ void __printf(4, 5) scoutfs_msg(struct super_block *sb, const char *prefix, const char *str, const char *fmt, ...); -/* - * The _sk variants wrap the message in the SK_PCPU calls which safely - * manage the use of per-cpu key buffers in the arguments. - */ - #define scoutfs_err(sb, fmt, args...) \ scoutfs_msg(sb, KERN_ERR, " error", fmt, ##args) -#define scoutfs_err_sk(sb, fmt, args...) \ - SK_PCPU(scoutfs_err(sb, fmt, ##args)) - #define scoutfs_warn(sb, fmt, args...) \ scoutfs_msg(sb, KERN_WARNING, " warning", fmt, ##args) -#define scoutfs_warn_sk(sb, fmt, args...) \ - SK_PCPU(scoutfs_warn(sb, fmt, ##args)) - #define scoutfs_info(sb, fmt, args...) \ scoutfs_msg(sb, KERN_INFO, "", fmt, ##args) -#define scoutfs_info_sk(sb, fmt, args...) \ - SK_PCPU(scoutfs_info(sb, fmt, ##args)) - #endif diff --git a/kmod/src/scoutfs_trace.h b/kmod/src/scoutfs_trace.h index a761f468..20c3a16b 100644 --- a/kmod/src/scoutfs_trace.h +++ b/kmod/src/scoutfs_trace.h @@ -317,45 +317,6 @@ TRACE_EVENT(scoutfs_item_next_same_ret, TP_printk(FSID_FMT" ret %d", __entry->fsid, __entry->ret) ); -TRACE_EVENT(scoutfs_item_next_same_min, - TP_PROTO(struct super_block *sb, int key_len, int len), - - TP_ARGS(sb, key_len, len), - - TP_STRUCT__entry( - __field(__u64, fsid) - __field(int, key_len) - __field(int, len) - ), - - TP_fast_assign( - __entry->fsid = FSID_ARG(sb); - __entry->key_len = key_len; - __entry->len = len; - ), - - TP_printk(FSID_FMT" key len %u min val len %d", __entry->fsid, - __entry->key_len, __entry->len) -); - -TRACE_EVENT(scoutfs_item_next_same_min_ret, - TP_PROTO(struct super_block *sb, int ret), - - TP_ARGS(sb, ret), - - TP_STRUCT__entry( - __field(__u64, fsid) - __field(int, ret) - ), - - TP_fast_assign( - __entry->fsid = FSID_ARG(sb); - __entry->ret = ret; - ), - - TP_printk(FSID_FMT" ret %d", __entry->fsid, __entry->ret) -); - TRACE_EVENT(scoutfs_item_next_ret, TP_PROTO(struct super_block *sb, int ret), @@ -619,25 +580,22 @@ TRACE_EVENT(scoutfs_release_trans, struct scoutfs_item_count *res, struct scoutfs_item_count *act, unsigned int tri_holders, unsigned int tri_writing, unsigned int tri_items, - unsigned int tri_keys, unsigned int tri_vals), + unsigned int tri_vals), TP_ARGS(sb, rsv, rsv_holders, res, act, tri_holders, tri_writing, - tri_items, tri_keys, tri_vals), + tri_items, tri_vals), TP_STRUCT__entry( __field(__u64, fsid) __field(void *, rsv) __field(unsigned int, rsv_holders) __field(int, res_items) - __field(int, res_keys) __field(int, res_vals) __field(int, act_items) - __field(int, act_keys) __field(int, act_vals) __field(unsigned int, tri_holders) __field(unsigned int, tri_writing) __field(unsigned int, tri_items) - __field(unsigned int, tri_keys) __field(unsigned int, tri_vals) ), @@ -646,25 +604,21 @@ TRACE_EVENT(scoutfs_release_trans, __entry->rsv = rsv; __entry->rsv_holders = rsv_holders; __entry->res_items = res->items; - __entry->res_keys = res->keys; __entry->res_vals = res->vals; __entry->act_items = act->items; - __entry->act_keys = act->keys; __entry->act_vals = act->vals; __entry->tri_holders = tri_holders; __entry->tri_writing = tri_writing; __entry->tri_items = tri_items; - __entry->tri_keys = tri_keys; __entry->tri_vals = tri_vals; ), - TP_printk(FSID_FMT" rsv %p holders %u reserved %u.%u.%u actual " - "%d.%d.%d, trans holders %u writing %u reserved " - "%u.%u.%u", __entry->fsid, __entry->rsv, - __entry->rsv_holders, __entry->res_items, __entry->res_keys, - __entry->res_vals, __entry->act_items, __entry->act_keys, + TP_printk(FSID_FMT" rsv %p holders %u reserved %u.%u actual " + "%d.%d, trans holders %u writing %u reserved " + "%u.%u", __entry->fsid, __entry->rsv, __entry->rsv_holders, + __entry->res_items, __entry->res_vals, __entry->act_items, __entry->act_vals, __entry->tri_holders, __entry->tri_writing, - __entry->tri_items, __entry->tri_keys, __entry->tri_vals) + __entry->tri_items, __entry->tri_vals) ); TRACE_EVENT(scoutfs_trans_acquired_hold, @@ -673,59 +627,50 @@ TRACE_EVENT(scoutfs_trans_acquired_hold, struct scoutfs_item_count *res, struct scoutfs_item_count *act, unsigned int tri_holders, unsigned int tri_writing, unsigned int tri_items, - unsigned int tri_keys, unsigned int tri_vals), + unsigned int tri_vals), TP_ARGS(sb, cnt, rsv, rsv_holders, res, act, tri_holders, tri_writing, - tri_items, tri_keys, tri_vals), + tri_items, tri_vals), TP_STRUCT__entry( __field(__u64, fsid) __field(int, cnt_items) - __field(int, cnt_keys) __field(int, cnt_vals) __field(void *, rsv) __field(unsigned int, rsv_holders) __field(int, res_items) - __field(int, res_keys) __field(int, res_vals) __field(int, act_items) - __field(int, act_keys) __field(int, act_vals) __field(unsigned int, tri_holders) __field(unsigned int, tri_writing) __field(unsigned int, tri_items) - __field(unsigned int, tri_keys) __field(unsigned int, tri_vals) ), TP_fast_assign( __entry->fsid = FSID_ARG(sb); __entry->cnt_items = cnt->items; - __entry->cnt_keys = cnt->keys; __entry->cnt_vals = cnt->vals; __entry->rsv = rsv; __entry->rsv_holders = rsv_holders; __entry->res_items = res->items; - __entry->res_keys = res->keys; __entry->res_vals = res->vals; __entry->act_items = act->items; - __entry->act_keys = act->keys; __entry->act_vals = act->vals; __entry->tri_holders = tri_holders; __entry->tri_writing = tri_writing; __entry->tri_items = tri_items; - __entry->tri_keys = tri_keys; __entry->tri_vals = tri_vals; ), - TP_printk(FSID_FMT" cnt %u.%u.%u, rsv %p holders %u reserved %u.%u.%u " - "actual %d.%d.%d, trans holders %u writing %u reserved " - "%u.%u.%u", __entry->fsid, __entry->cnt_items, - __entry->cnt_keys, __entry->cnt_vals, __entry->rsv, - __entry->rsv_holders, __entry->res_items, __entry->res_keys, - __entry->res_vals, __entry->act_items, __entry->act_keys, + TP_printk(FSID_FMT" cnt %u.%u, rsv %p holders %u reserved %u.%u " + "actual %d.%d, trans holders %u writing %u reserved " + "%u.%u", __entry->fsid, __entry->cnt_items, + __entry->cnt_vals, __entry->rsv, __entry->rsv_holders, + __entry->res_items, __entry->res_vals, __entry->act_items, __entry->act_vals, __entry->tri_holders, __entry->tri_writing, - __entry->tri_items, __entry->tri_keys, __entry->tri_vals) + __entry->tri_items, __entry->tri_vals) ); TRACE_EVENT(scoutfs_ioc_release_ret, @@ -1102,30 +1047,30 @@ TRACE_EVENT(scoutfs_advance_dirty_super, ); TRACE_EVENT(scoutfs_dir_add_next_linkref, - TP_PROTO(struct super_block *sb, __u64 ino, __u64 dir_ino, int ret, - unsigned int key_len), + TP_PROTO(struct super_block *sb, __u64 ino, __u64 dir_ino, + __u64 dir_pos, int ret), - TP_ARGS(sb, ino, dir_ino, ret, key_len), + TP_ARGS(sb, ino, dir_ino, dir_pos, ret), TP_STRUCT__entry( __field(__u64, fsid) __field(__u64, ino) __field(__u64, dir_ino) + __field(__u64, dir_pos) __field(int, ret) - __field(unsigned int, key_len) ), TP_fast_assign( __entry->fsid = FSID_ARG(sb); __entry->ino = ino; __entry->dir_ino = dir_ino; + __entry->dir_pos = dir_pos; __entry->ret = ret; - __entry->key_len = key_len; ), - TP_printk(FSID_FMT" ino %llu dir_ino %llu ret %d key_len %u", - __entry->fsid, __entry->ino, __entry->dir_ino, __entry->ret, - __entry->key_len) + TP_printk(FSID_FMT" ino %llu dir_ino %llu dis_pos %llu ret %d", + __entry->fsid, __entry->ino, __entry->dir_ino, + __entry->dir_ino, __entry->ret) ); TRACE_EVENT(scoutfs_compact_func, @@ -1342,98 +1287,97 @@ TRACE_EVENT(scoutfs_scan_orphans, DECLARE_EVENT_CLASS(scoutfs_manifest_class, TP_PROTO(struct super_block *sb, u8 level, u64 segno, u64 seq, - struct scoutfs_key_buf *first, struct scoutfs_key_buf *last), + struct scoutfs_key *first, struct scoutfs_key *last), TP_ARGS(sb, level, segno, seq, first, last), TP_STRUCT__entry( __field(u8, level) __field(u64, segno) __field(u64, seq) - __dynamic_array(char, first, scoutfs_key_str(NULL, first)) - __dynamic_array(char, last, scoutfs_key_str(NULL, last)) + __field_struct(struct scoutfs_key, first) + __field_struct(struct scoutfs_key, last) ), TP_fast_assign( __entry->level = level; __entry->segno = segno; __entry->seq = seq; - scoutfs_key_str(__get_dynamic_array(first), first); - scoutfs_key_str(__get_dynamic_array(last), last); + scoutfs_key_copy_or_zeros(&__entry->first, first); + scoutfs_key_copy_or_zeros(&__entry->last, last); ), - TP_printk("level %u segno %llu seq %llu first %s last %s", + TP_printk("level %u segno %llu seq %llu first "SK_FMT" last "SK_FMT, __entry->level, __entry->segno, __entry->seq, - __get_str(first), __get_str(last)) + SK_ARG(&__entry->first), SK_ARG(&__entry->last)) ); DEFINE_EVENT(scoutfs_manifest_class, scoutfs_manifest_add, TP_PROTO(struct super_block *sb, u8 level, u64 segno, u64 seq, - struct scoutfs_key_buf *first, struct scoutfs_key_buf *last), + struct scoutfs_key *first, struct scoutfs_key *last), TP_ARGS(sb, level, segno, seq, first, last) ); DEFINE_EVENT(scoutfs_manifest_class, scoutfs_manifest_delete, TP_PROTO(struct super_block *sb, u8 level, u64 segno, u64 seq, - struct scoutfs_key_buf *first, struct scoutfs_key_buf *last), + struct scoutfs_key *first, struct scoutfs_key *last), TP_ARGS(sb, level, segno, seq, first, last) ); DEFINE_EVENT(scoutfs_manifest_class, scoutfs_compact_input, TP_PROTO(struct super_block *sb, u8 level, u64 segno, u64 seq, - struct scoutfs_key_buf *first, struct scoutfs_key_buf *last), + struct scoutfs_key *first, struct scoutfs_key *last), TP_ARGS(sb, level, segno, seq, first, last) ); DEFINE_EVENT(scoutfs_manifest_class, scoutfs_read_item_segment, TP_PROTO(struct super_block *sb, u8 level, u64 segno, u64 seq, - struct scoutfs_key_buf *first, struct scoutfs_key_buf *last), + struct scoutfs_key *first, struct scoutfs_key *last), TP_ARGS(sb, level, segno, seq, first, last) ); TRACE_EVENT(scoutfs_read_item_keys, TP_PROTO(struct super_block *sb, - struct scoutfs_key_buf *key, - struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end, - struct scoutfs_key_buf *seg_start, - struct scoutfs_key_buf *seg_end), + struct scoutfs_key *key, + struct scoutfs_key *start, + struct scoutfs_key *end, + struct scoutfs_key *seg_start, + struct scoutfs_key *seg_end), TP_ARGS(sb, key, start, end, seg_start, seg_end), TP_STRUCT__entry( __field(__u64, fsid) - __dynamic_array(char, key, scoutfs_key_str(NULL, key)) - __dynamic_array(char, start, scoutfs_key_str(NULL, start)) - __dynamic_array(char, end, scoutfs_key_str(NULL, end)) - __dynamic_array(char, seg_start, - scoutfs_key_str(NULL, seg_start)) - __dynamic_array(char, seg_end, - scoutfs_key_str(NULL, seg_end)) + __field_struct(struct scoutfs_key, key) + __field_struct(struct scoutfs_key, start) + __field_struct(struct scoutfs_key, end) + __field_struct(struct scoutfs_key, seg_start) + __field_struct(struct scoutfs_key, seg_end) ), TP_fast_assign( __entry->fsid = FSID_ARG(sb); - scoutfs_key_str(__get_dynamic_array(key), key); - scoutfs_key_str(__get_dynamic_array(start), start); - scoutfs_key_str(__get_dynamic_array(end), end); - scoutfs_key_str(__get_dynamic_array(seg_start), seg_start); - scoutfs_key_str(__get_dynamic_array(seg_end), seg_end); + scoutfs_key_copy_or_zeros(&__entry->key, key); + scoutfs_key_copy_or_zeros(&__entry->start, start); + scoutfs_key_copy_or_zeros(&__entry->end, end); + scoutfs_key_copy_or_zeros(&__entry->seg_start, seg_start); + scoutfs_key_copy_or_zeros(&__entry->seg_end, seg_end); ), - TP_printk("fsid "FSID_FMT" key %s start %s end %s seg_start %s seg_end %s", - __entry->fsid, __get_str(key), __get_str(start), - __get_str(end), __get_str(seg_start), __get_str(seg_end)) + TP_printk("fsid "FSID_FMT" key "SK_FMT" start "SK_FMT" end "SK_FMT" seg_start "SK_FMT" seg_end "SK_FMT"", + __entry->fsid, SK_ARG(&__entry->key), SK_ARG(&__entry->start), + SK_ARG(&__entry->end), SK_ARG(&__entry->seg_start), + SK_ARG(&__entry->seg_end)) ); DECLARE_EVENT_CLASS(scoutfs_key_class, - TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *key), + TP_PROTO(struct super_block *sb, struct scoutfs_key *key), TP_ARGS(sb, key), TP_STRUCT__entry( __field(__u64, fsid) - __dynamic_array(char, key, scoutfs_key_str(NULL, key)) + __field_struct(struct scoutfs_key, key) ), TP_fast_assign( __entry->fsid = FSID_ARG(sb); - scoutfs_key_str(__get_dynamic_array(key), key); + scoutfs_key_copy_or_zeros(&__entry->key, key); ), - TP_printk(FSID_FMT" key %s", __entry->fsid, __get_str(key)) + TP_printk(FSID_FMT" key "SK_FMT, __entry->fsid, SK_ARG(&__entry->key)) ); DEFINE_EVENT(scoutfs_key_class, scoutfs_item_lookup, - TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *key), + TP_PROTO(struct super_block *sb, struct scoutfs_key *key), TP_ARGS(sb, key) ); @@ -1456,127 +1400,129 @@ TRACE_EVENT(scoutfs_item_lookup_ret, ); DEFINE_EVENT(scoutfs_key_class, scoutfs_item_insertion, - TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *key), + TP_PROTO(struct super_block *sb, struct scoutfs_key *key), TP_ARGS(sb, key) ); DEFINE_EVENT(scoutfs_key_class, scoutfs_item_shrink, - TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *key), + TP_PROTO(struct super_block *sb, struct scoutfs_key *key), TP_ARGS(sb, key) ); DEFINE_EVENT(scoutfs_key_class, scoutfs_xattr_get_next_key, - TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *key), + TP_PROTO(struct super_block *sb, struct scoutfs_key *key), TP_ARGS(sb, key) ); DECLARE_EVENT_CLASS(scoutfs_range_class, - TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end), + TP_PROTO(struct super_block *sb, struct scoutfs_key *start, + struct scoutfs_key *end), TP_ARGS(sb, start, end), TP_STRUCT__entry( __field(__u64, fsid) - __dynamic_array(char, start, scoutfs_key_str(NULL, start)) - __dynamic_array(char, end, scoutfs_key_str(NULL, end)) + __field_struct(struct scoutfs_key, start) + __field_struct(struct scoutfs_key, end) ), TP_fast_assign( __entry->fsid = FSID_ARG(sb); - scoutfs_key_str(__get_dynamic_array(start), start); - scoutfs_key_str(__get_dynamic_array(end), end); + scoutfs_key_copy_or_zeros(&__entry->start, start); + scoutfs_key_copy_or_zeros(&__entry->end, end); ), - TP_printk("fsid "FSID_FMT" start %s end %s", - __entry->fsid, __get_str(start), __get_str(end)) + TP_printk("fsid "FSID_FMT" start "SK_FMT" end "SK_FMT, + __entry->fsid, SK_ARG(&__entry->start), + SK_ARG(&__entry->end)) ); DEFINE_EVENT(scoutfs_range_class, scoutfs_item_insert_batch, - TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end), + TP_PROTO(struct super_block *sb, struct scoutfs_key *start, + struct scoutfs_key *end), TP_ARGS(sb, start, end) ); DEFINE_EVENT(scoutfs_range_class, scoutfs_item_invalidate_range, - TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end), + TP_PROTO(struct super_block *sb, struct scoutfs_key *start, + struct scoutfs_key *end), TP_ARGS(sb, start, end) ); DEFINE_EVENT(scoutfs_range_class, scoutfs_item_shrink_range, - TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *start, - struct scoutfs_key_buf *end), + TP_PROTO(struct super_block *sb, struct scoutfs_key *start, + struct scoutfs_key *end), TP_ARGS(sb, start, end) ); DECLARE_EVENT_CLASS(scoutfs_cached_range_class, TP_PROTO(struct super_block *sb, void *rng, - struct scoutfs_key_buf *start, struct scoutfs_key_buf *end), + struct scoutfs_key *start, struct scoutfs_key *end), TP_ARGS(sb, rng, start, end), TP_STRUCT__entry( __field(__u64, fsid) __field(void *, rng) - __dynamic_array(char, start, scoutfs_key_str(NULL, start)) - __dynamic_array(char, end, scoutfs_key_str(NULL, end)) + __field_struct(struct scoutfs_key, start) + __field_struct(struct scoutfs_key, end) ), TP_fast_assign( __entry->fsid = FSID_ARG(sb); __entry->rng = rng; - scoutfs_key_str(__get_dynamic_array(start), start); - scoutfs_key_str(__get_dynamic_array(end), end); + scoutfs_key_copy_or_zeros(&__entry->start, start); + scoutfs_key_copy_or_zeros(&__entry->end, end); ), - TP_printk("fsid "FSID_FMT" rng %p start %s end %s", - __entry->fsid, __entry->rng, __get_str(start), __get_str(end)) + TP_printk("fsid "FSID_FMT" rng %p start "SK_FMT" end "SK_FMT, + __entry->fsid, __entry->rng, SK_ARG(&__entry->start), + SK_ARG(&__entry->end)) ); DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_free, TP_PROTO(struct super_block *sb, void *rng, - struct scoutfs_key_buf *start, struct scoutfs_key_buf *end), + struct scoutfs_key *start, struct scoutfs_key *end), TP_ARGS(sb, rng, start, end) ); DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_ins_rb_insert, TP_PROTO(struct super_block *sb, void *rng, - struct scoutfs_key_buf *start, struct scoutfs_key_buf *end), + struct scoutfs_key *start, struct scoutfs_key *end), TP_ARGS(sb, rng, start, end) ); DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_remove_mid_left, TP_PROTO(struct super_block *sb, void *rng, - struct scoutfs_key_buf *start, struct scoutfs_key_buf *end), + struct scoutfs_key *start, struct scoutfs_key *end), TP_ARGS(sb, rng, start, end) ); DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_remove_start, TP_PROTO(struct super_block *sb, void *rng, - struct scoutfs_key_buf *start, struct scoutfs_key_buf *end), + struct scoutfs_key *start, struct scoutfs_key *end), TP_ARGS(sb, rng, start, end) ); DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_remove_end, TP_PROTO(struct super_block *sb, void *rng, - struct scoutfs_key_buf *start, struct scoutfs_key_buf *end), + struct scoutfs_key *start, struct scoutfs_key *end), TP_ARGS(sb, rng, start, end) ); DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_rem_rb_insert, TP_PROTO(struct super_block *sb, void *rng, - struct scoutfs_key_buf *start, struct scoutfs_key_buf *end), + struct scoutfs_key *start, struct scoutfs_key *end), TP_ARGS(sb, rng, start, end) ); DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_delete_enoent, TP_PROTO(struct super_block *sb, void *rng, - struct scoutfs_key_buf *start, struct scoutfs_key_buf *end), + struct scoutfs_key *start, struct scoutfs_key *end), TP_ARGS(sb, rng, start, end) ); DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_shrink_start, TP_PROTO(struct super_block *sb, void *rng, - struct scoutfs_key_buf *start, struct scoutfs_key_buf *end), + struct scoutfs_key *start, struct scoutfs_key *end), TP_ARGS(sb, rng, start, end) ); DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_shrink_end, TP_PROTO(struct super_block *sb, void *rng, - struct scoutfs_key_buf *start, struct scoutfs_key_buf *end), + struct scoutfs_key *start, struct scoutfs_key *end), TP_ARGS(sb, rng, start, end) ); @@ -1784,32 +1730,32 @@ DEFINE_EVENT(scoutfs_net_class, scoutfs_client_recv_reply, TRACE_EVENT(scoutfs_item_next_range_check, TP_PROTO(struct super_block *sb, int cached, - struct scoutfs_key_buf *key, struct scoutfs_key_buf *pos, - struct scoutfs_key_buf *last, struct scoutfs_key_buf *end, - struct scoutfs_key_buf *range_end), + struct scoutfs_key *key, struct scoutfs_key *pos, + struct scoutfs_key *last, struct scoutfs_key *end, + struct scoutfs_key *range_end), TP_ARGS(sb, cached, key, pos, last, end, range_end), TP_STRUCT__entry( __field(void *, sb) __field(int, cached) - __dynamic_array(char, key, scoutfs_key_str(NULL, key)) - __dynamic_array(char, pos, scoutfs_key_str(NULL, pos)) - __dynamic_array(char, last, scoutfs_key_str(NULL, last)) - __dynamic_array(char, end, scoutfs_key_str(NULL, end)) - __dynamic_array(char, range_end, - scoutfs_key_str(NULL, range_end)) + __field_struct(struct scoutfs_key, key) + __field_struct(struct scoutfs_key, pos) + __field_struct(struct scoutfs_key, last) + __field_struct(struct scoutfs_key, end) + __field_struct(struct scoutfs_key, range_end) ), TP_fast_assign( __entry->sb = sb; __entry->cached = cached; - scoutfs_key_str(__get_dynamic_array(key), key); - scoutfs_key_str(__get_dynamic_array(pos), pos); - scoutfs_key_str(__get_dynamic_array(last), last); - scoutfs_key_str(__get_dynamic_array(end), end); - scoutfs_key_str(__get_dynamic_array(range_end), range_end); + scoutfs_key_copy_or_zeros(&__entry->key, key); + scoutfs_key_copy_or_zeros(&__entry->pos, pos); + scoutfs_key_copy_or_zeros(&__entry->last, last); + scoutfs_key_copy_or_zeros(&__entry->end, end); + scoutfs_key_copy_or_zeros(&__entry->range_end, range_end); ), - TP_printk("sb %p cached %d key %s pos %s last %s end %s range_end %s", - __entry->sb, __entry->cached, __get_str(key), __get_str(pos), - __get_str(last), __get_str(end), __get_str(range_end)) + TP_printk("sb %p cached %d key "SK_FMT" pos "SK_FMT" last "SK_FMT" end "SK_FMT" range_end "SK_FMT, + __entry->sb, __entry->cached, SK_ARG(&__entry->key), + SK_ARG(&__entry->pos), SK_ARG(&__entry->last), + SK_ARG(&__entry->end), SK_ARG(&__entry->range_end)) ); DECLARE_EVENT_CLASS(scoutfs_shrink_exit_class, @@ -1846,37 +1792,36 @@ DEFINE_EVENT(scoutfs_shrink_exit_class, scoutfs_item_shrink_exit, TRACE_EVENT(scoutfs_item_shrink_around, TP_PROTO(struct super_block *sb, - struct scoutfs_key_buf *rng_start, - struct scoutfs_key_buf *rng_end, struct scoutfs_key_buf *item, - struct scoutfs_key_buf *prev, struct scoutfs_key_buf *first, - struct scoutfs_key_buf *last, struct scoutfs_key_buf *next), + struct scoutfs_key *rng_start, + struct scoutfs_key *rng_end, struct scoutfs_key *item, + struct scoutfs_key *prev, struct scoutfs_key *first, + struct scoutfs_key *last, struct scoutfs_key *next), TP_ARGS(sb, rng_start, rng_end, item, prev, first, last, next), TP_STRUCT__entry( __field(void *, sb) - __dynamic_array(char, rng_start, - scoutfs_key_str(NULL, rng_start)) - __dynamic_array(char, rng_end, - scoutfs_key_str(NULL, rng_end)) - __dynamic_array(char, item, scoutfs_key_str(NULL, item)) - __dynamic_array(char, prev, scoutfs_key_str(NULL, prev)) - __dynamic_array(char, first, scoutfs_key_str(NULL, first)) - __dynamic_array(char, last, scoutfs_key_str(NULL, last)) - __dynamic_array(char, next, scoutfs_key_str(NULL, next)) + __field_struct(struct scoutfs_key, rng_start) + __field_struct(struct scoutfs_key, rng_end) + __field_struct(struct scoutfs_key, item) + __field_struct(struct scoutfs_key, prev) + __field_struct(struct scoutfs_key, first) + __field_struct(struct scoutfs_key, last) + __field_struct(struct scoutfs_key, next) ), TP_fast_assign( __entry->sb = sb; - scoutfs_key_str(__get_dynamic_array(rng_start), rng_start); - scoutfs_key_str(__get_dynamic_array(rng_end), rng_end); - scoutfs_key_str(__get_dynamic_array(item), item); - scoutfs_key_str(__get_dynamic_array(prev), prev); - scoutfs_key_str(__get_dynamic_array(first), first); - scoutfs_key_str(__get_dynamic_array(last), last); - scoutfs_key_str(__get_dynamic_array(next), next); + scoutfs_key_copy_or_zeros(&__entry->rng_start, rng_start); + scoutfs_key_copy_or_zeros(&__entry->rng_end, rng_end); + scoutfs_key_copy_or_zeros(&__entry->item, item); + scoutfs_key_copy_or_zeros(&__entry->prev, prev); + scoutfs_key_copy_or_zeros(&__entry->first, first); + scoutfs_key_copy_or_zeros(&__entry->last, last); + scoutfs_key_copy_or_zeros(&__entry->next, next); ), - TP_printk("sb %p rng_start %s rng_end %s item %s prev %s first %s last %s next %s", - __entry->sb, __get_str(rng_start), __get_str(rng_end), - __get_str(item), __get_str(prev), __get_str(first), - __get_str(last), __get_str(next)) + TP_printk("sb %p rng_start "SK_FMT" rng_end "SK_FMT" item "SK_FMT" prev "SK_FMT" first "SK_FMT" last "SK_FMT" next "SK_FMT, + __entry->sb, SK_ARG(&__entry->rng_start), + SK_ARG(&__entry->rng_end), SK_ARG(&__entry->item), + SK_ARG(&__entry->prev), SK_ARG(&__entry->first), + SK_ARG(&__entry->last), SK_ARG(&__entry->next)) ); TRACE_EVENT(scoutfs_rename, diff --git a/kmod/src/seg.c b/kmod/src/seg.c index 6e116d11..80ccdacd 100644 --- a/kmod/src/seg.c +++ b/kmod/src/seg.c @@ -410,49 +410,39 @@ out: return ret; } -static u32 item_bytes(u8 nr_links, u16 key_len, u16 val_len) +static u32 item_bytes(u8 nr_links, u16 val_len) { return offsetof(struct scoutfs_segment_item, skip_links[nr_links]) + - key_len + val_len; -} - -static inline int item_key_off(struct scoutfs_segment_item *item, int item_off) -{ - return item_off + item_bytes(item->nr_links, 0, 0); -} - -static inline void *item_key_ptr(struct scoutfs_segment_item *item) -{ - return (void *)item + item_bytes(item->nr_links, 0, 0); + val_len; } static inline void *item_val_ptr(struct scoutfs_segment_item *item) { - return item_key_ptr(item) + le16_to_cpu(item->key_len); + return (void *)item + item_bytes(item->nr_links, 0); } -static void item_ptrs(struct scoutfs_segment *seg, int off, - struct scoutfs_key_buf *key, struct kvec *val) +/* copy the item key into the caller's key and init their val to ref the val */ +static void get_item_key_val(struct scoutfs_segment *seg, int off, + struct scoutfs_key *key, struct kvec *val) { struct scoutfs_segment_item *item = off_ptr(seg, off); if (key) - scoutfs_key_init(key, item_key_ptr(item), - le16_to_cpu(item->key_len)); - if (val) { - val->iov_base = item_val_ptr(item); - val->iov_len = le16_to_cpu(item->val_len); - } + *key = item->key; + + if (val) + kvec_init(val, item_val_ptr(item), le16_to_cpu(item->val_len)); } static void first_last_keys(struct scoutfs_segment *seg, - struct scoutfs_key_buf *first, - struct scoutfs_key_buf *last) + struct scoutfs_key *first, + struct scoutfs_key *last) { struct scoutfs_segment_block *sblk = off_ptr(seg, 0); - item_ptrs(seg, sizeof(struct scoutfs_segment_block), first, NULL); - item_ptrs(seg, le32_to_cpu(sblk->last_item_off), last, NULL); + get_item_key_val(seg, sizeof(struct scoutfs_segment_block), + first, NULL); + get_item_key_val(seg, le32_to_cpu(sblk->last_item_off), last, NULL); } static int check_caller_off(struct scoutfs_segment_block *sblk, int off) @@ -475,9 +465,8 @@ static int check_caller_off(struct scoutfs_segment_block *sblk, int off) * All other offsets must be initial values less than the segment header * size, notably including 0, or returned from _next_off(). */ -int scoutfs_seg_item_ptrs(struct scoutfs_segment *seg, int off, - struct scoutfs_key_buf *key, struct kvec *val, - u8 *flags) +int scoutfs_seg_get_item(struct scoutfs_segment *seg, int off, + struct scoutfs_key *key, struct kvec *val,u8 *flags) { struct scoutfs_segment_block *sblk = off_ptr(seg, 0); struct scoutfs_segment_item *item; @@ -486,7 +475,7 @@ int scoutfs_seg_item_ptrs(struct scoutfs_segment *seg, int off, if (off < 0) return off; - item_ptrs(seg, off, key, val); + get_item_key_val(seg, off, key, val); if (flags) { item = off_ptr(seg, off); @@ -524,12 +513,10 @@ static u8 skip_most_nr(u32 nr_items) * than the items and descend down to lower more frequent links when the * search key is less. */ -int scoutfs_seg_find_off(struct scoutfs_segment *seg, - struct scoutfs_key_buf *key) +int scoutfs_seg_find_off(struct scoutfs_segment *seg, struct scoutfs_key *key) { struct scoutfs_segment_block *sblk = off_ptr(seg, 0); struct scoutfs_segment_item *item; - struct scoutfs_key_buf item_key; __le32 *links; int cmp; int ret; @@ -544,10 +531,8 @@ int scoutfs_seg_find_off(struct scoutfs_segment *seg, off = le32_to_cpu(links[i]); item = off_ptr(seg, off); - scoutfs_key_init(&item_key, item_key_ptr(item), - le16_to_cpu(item->key_len)); - cmp = scoutfs_key_compare(key, &item_key); + cmp = scoutfs_key_compare(key, &item->key); if (cmp == 0) { ret = off; break; @@ -607,16 +592,15 @@ u32 scoutfs_seg_total_bytes(struct scoutfs_segment *seg) * than two links per item. We assume the worst case items have the * max number of links. */ -bool scoutfs_seg_fits_single(u32 nr_items, u32 key_bytes, u32 val_bytes) +bool scoutfs_seg_fits_single(u32 nr_items, u32 val_bytes) { u32 header = sizeof(struct scoutfs_segment_block); - u32 items = nr_items * item_bytes(2, 0, 0); - u32 item_pad = item_bytes(skip_most_nr(nr_items), SCOUTFS_MAX_KEY_SIZE, + u32 items = nr_items * item_bytes(2, 0); + u32 item_pad = item_bytes(skip_most_nr(nr_items), SCOUTFS_MAX_VAL_SIZE) - 1; u32 padding = (SCOUTFS_SEGMENT_SIZE / SCOUTFS_BLOCK_SIZE) * item_pad; - return (header + items + key_bytes + val_bytes + padding) - <= SCOUTFS_SEGMENT_SIZE; + return (header + items + val_bytes + padding) <= SCOUTFS_SEGMENT_SIZE; } static u32 align_item_off(struct scoutfs_segment *seg, u32 item_off, u32 bytes) @@ -638,14 +622,13 @@ static u32 align_item_off(struct scoutfs_segment *seg, u32 item_off, u32 bytes) * We return true if we appended and false if the segment was full. */ bool scoutfs_seg_append_item(struct super_block *sb, struct scoutfs_segment *seg, - struct scoutfs_key_buf *key, struct kvec *val, + struct scoutfs_key *key, struct kvec *val, u8 flags, __le32 **links) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_super_block *super = &sbi->super; struct scoutfs_segment_block *sblk = off_ptr(seg, 0); struct scoutfs_segment_item *item; - struct scoutfs_key_buf item_key; struct kvec item_val; u8 nr_links; u32 val_len; @@ -674,12 +657,12 @@ bool scoutfs_seg_append_item(struct super_block *sb, struct scoutfs_segment *seg */ off = le32_to_cpu(sblk->last_item_off); if (off) { - item_ptrs(seg, off, &item_key, NULL); - BUG_ON(scoutfs_key_compare(key, &item_key) <= 0); + item = off_ptr(seg, off); + BUG_ON(scoutfs_key_compare(key, &item->key) <= 0); } nr_links = skip_next_nr(le32_to_cpu(sblk->nr_items)); - bytes = item_bytes(nr_links, key->key_len, val_len); + bytes = item_bytes(nr_links, val_len); off = align_item_off(seg, le32_to_cpu(sblk->total_bytes), bytes); if ((off + bytes) > SCOUTFS_SEGMENT_SIZE) @@ -690,7 +673,7 @@ bool scoutfs_seg_append_item(struct super_block *sb, struct scoutfs_segment *seg le32_add_cpu(&sblk->nr_items, 1); item = off_ptr(seg, off); - item->key_len = cpu_to_le16(key->key_len); + item->key = *key; item->val_len = cpu_to_le16(val_len); item->flags = flags; @@ -702,8 +685,7 @@ bool scoutfs_seg_append_item(struct super_block *sb, struct scoutfs_segment *seg links[i] = &item->skip_links[i]; } - item_ptrs(seg, off, &item_key, &item_val); - scoutfs_key_copy(&item_key, key); + get_item_key_val(seg, off, NULL, &item_val); if (val_len) memcpy(item_val.iov_base, val->iov_base, val_len); @@ -714,8 +696,8 @@ void scoutfs_seg_init_ment(struct scoutfs_manifest_entry *ment, int level, struct scoutfs_segment *seg) { struct scoutfs_segment_block *sblk = off_ptr(seg, 0); - struct scoutfs_key_buf first; - struct scoutfs_key_buf last; + struct scoutfs_key first; + struct scoutfs_key last; first_last_keys(seg, &first, &last); diff --git a/kmod/src/seg.h b/kmod/src/seg.h index 4f151490..74f7f961 100644 --- a/kmod/src/seg.h +++ b/kmod/src/seg.h @@ -2,7 +2,7 @@ #define _SCOUTFS_SEG_H_ struct scoutfs_bio_completion; -struct scoutfs_key_buf; +struct scoutfs_key; struct scoutfs_manifest_entry; struct kvec; @@ -23,24 +23,21 @@ struct scoutfs_segment *scoutfs_seg_submit_read(struct super_block *sb, int scoutfs_seg_wait(struct super_block *sb, struct scoutfs_segment *seg, u64 segno, u64 seq); -int scoutfs_seg_find_off(struct scoutfs_segment *seg, - struct scoutfs_key_buf *key); +int scoutfs_seg_find_off(struct scoutfs_segment *seg, struct scoutfs_key *key); int scoutfs_seg_next_off(struct scoutfs_segment *seg, int off); u32 scoutfs_seg_total_bytes(struct scoutfs_segment *seg); -int scoutfs_seg_item_ptrs(struct scoutfs_segment *seg, int off, - struct scoutfs_key_buf *key, struct kvec *val, - u8 *flags); +int scoutfs_seg_get_item(struct scoutfs_segment *seg, int off, + struct scoutfs_key *key, struct kvec *val, u8 *flags); void scoutfs_seg_get(struct scoutfs_segment *seg); void scoutfs_seg_put(struct scoutfs_segment *seg); int scoutfs_seg_alloc(struct super_block *sb, u64 segno, struct scoutfs_segment **seg_ret); -int scoutfs_seg_free_segno(struct super_block *sb, - struct scoutfs_segment *seg); -bool scoutfs_seg_fits_single(u32 nr_items, u32 key_bytes, u32 val_bytes); +int scoutfs_seg_free_segno(struct super_block *sb, struct scoutfs_segment *seg); +bool scoutfs_seg_fits_single(u32 nr_items, u32 val_bytes); bool scoutfs_seg_append_item(struct super_block *sb, struct scoutfs_segment *seg, - struct scoutfs_key_buf *key, struct kvec *val, + struct scoutfs_key *key, struct kvec *val, u8 flags, __le32 **links); void scoutfs_seg_init_ment(struct scoutfs_manifest_entry *ment, int level, struct scoutfs_segment *seg); diff --git a/kmod/src/server.c b/kmod/src/server.c index ff1ccc69..7482e4bd 100644 --- a/kmod/src/server.c +++ b/kmod/src/server.c @@ -232,67 +232,24 @@ static int send_reply(struct server_connection *conn, u64 id, return ret; } -void scoutfs_init_net_ment_keys(struct scoutfs_net_manifest_entry *net_ment, - struct scoutfs_key_buf *first, - struct scoutfs_key_buf *last) +void scoutfs_init_ment_to_net(struct scoutfs_net_manifest_entry *net_ment, + struct scoutfs_manifest_entry *ment) { - scoutfs_key_init(first, net_ment->keys, - le16_to_cpu(net_ment->first_key_len)); - scoutfs_key_init(last, net_ment->keys + - le16_to_cpu(net_ment->first_key_len), - le16_to_cpu(net_ment->last_key_len)); -} - -/* - * Allocate a contiguous manifest entry for communication over the network. - */ -struct scoutfs_net_manifest_entry * -scoutfs_alloc_net_ment(struct scoutfs_manifest_entry *ment) -{ - struct scoutfs_net_manifest_entry *net_ment; - struct scoutfs_key_buf first; - struct scoutfs_key_buf last; - - net_ment = kmalloc(offsetof(struct scoutfs_net_manifest_entry, - keys[ment->first.key_len + - ment->last.key_len]), GFP_NOFS); - if (!net_ment) - return NULL; - net_ment->segno = cpu_to_le64(ment->segno); net_ment->seq = cpu_to_le64(ment->seq); - net_ment->first_key_len = cpu_to_le16(ment->first.key_len); - net_ment->last_key_len = cpu_to_le16(ment->last.key_len); + net_ment->first = ment->first; + net_ment->last = ment->last; net_ment->level = ment->level; - - scoutfs_init_net_ment_keys(net_ment, &first, &last); - scoutfs_key_copy(&first, &ment->first); - scoutfs_key_copy(&last, &ment->last); - - return net_ment; } -/* point a native manifest entry at a contiguous net manifest */ -void scoutfs_init_ment_net_ment(struct scoutfs_manifest_entry *ment, +void scoutfs_init_ment_from_net(struct scoutfs_manifest_entry *ment, struct scoutfs_net_manifest_entry *net_ment) { - struct scoutfs_key_buf first; - struct scoutfs_key_buf last; - - scoutfs_init_net_ment_keys(net_ment, &first, &last); - scoutfs_key_clone(&ment->first, &first); - scoutfs_key_clone(&ment->last, &last); - ment->segno = le64_to_cpu(net_ment->segno); ment->seq = le64_to_cpu(net_ment->seq); ment->level = net_ment->level; -} - -unsigned scoutfs_net_ment_bytes(struct scoutfs_net_manifest_entry *net_ment) -{ - return offsetof(struct scoutfs_net_manifest_entry, - keys[le16_to_cpu(net_ment->first_key_len) + - le16_to_cpu(net_ment->last_key_len)]); + ment->first = net_ment->first; + ment->last = net_ment->last; } static int process_alloc_inodes(struct server_connection *conn, @@ -381,7 +338,7 @@ static int process_record_segment(struct server_connection *conn, u64 id, net_ment = data; - if (data_len != scoutfs_net_ment_bytes(net_ment)) { + if (data_len != sizeof(*net_ment)) { ret = -EINVAL; goto out; } @@ -399,7 +356,7 @@ retry: goto retry; } - scoutfs_init_ment_net_ment(&ment, net_ment); + scoutfs_init_ment_from_net(&ment, net_ment); ret = scoutfs_manifest_add(sb, &ment); scoutfs_manifest_unlock(sb); diff --git a/kmod/src/server.h b/kmod/src/server.h index 8cb7c05c..f6e076db 100644 --- a/kmod/src/server.h +++ b/kmod/src/server.h @@ -1,14 +1,10 @@ #ifndef _SCOUTFS_SERVER_H_ #define _SCOUTFS_SERVER_H_ -void scoutfs_init_net_ment_keys(struct scoutfs_net_manifest_entry *net_ment, - struct scoutfs_key_buf *first, - struct scoutfs_key_buf *last); -struct scoutfs_net_manifest_entry * -scoutfs_alloc_net_ment(struct scoutfs_manifest_entry *ment); -void scoutfs_init_ment_net_ment(struct scoutfs_manifest_entry *ment, +void scoutfs_init_ment_to_net(struct scoutfs_net_manifest_entry *net_ment, + struct scoutfs_manifest_entry *ment); +void scoutfs_init_ment_from_net(struct scoutfs_manifest_entry *ment, struct scoutfs_net_manifest_entry *net_ment); -unsigned scoutfs_net_ment_bytes(struct scoutfs_net_manifest_entry *net_ment); int scoutfs_client_get_compaction(struct super_block *sb, void *curs); int scoutfs_client_finish_compaction(struct super_block *sb, void *curs, diff --git a/kmod/src/super.c b/kmod/src/super.c index f9d5b80e..9d97e578 100644 --- a/kmod/src/super.c +++ b/kmod/src/super.c @@ -419,6 +419,7 @@ static int __init scoutfs_module_init(void) ".string \""SCOUTFS_GIT_DESCRIBE"\\n\"\n" ".previous\n"); + scoutfs_key_init(); scoutfs_init_counters(); ret = scoutfs_data_test(); diff --git a/kmod/src/trans.c b/kmod/src/trans.c index 712ac1f6..2c39951f 100644 --- a/kmod/src/trans.c +++ b/kmod/src/trans.c @@ -60,7 +60,6 @@ struct trans_info { spinlock_t lock; unsigned reserved_items; - unsigned reserved_keys; unsigned reserved_vals; unsigned holders; bool writing; @@ -295,7 +294,6 @@ static bool acquired_hold(struct super_block *sb, DECLARE_TRANS_INFO(sb, tri); bool acquired = false; unsigned items; - unsigned keys; unsigned vals; bool fits; @@ -305,7 +303,6 @@ static bool acquired_hold(struct super_block *sb, &rsv->reserved, &rsv->actual, tri->holders, tri->writing, tri->reserved_items, - tri->reserved_keys, tri->reserved_vals); /* use a caller's existing reservation */ @@ -318,9 +315,8 @@ static bool acquired_hold(struct super_block *sb, /* see if we can reserve space for our item count */ items = tri->reserved_items + cnt->items; - keys = tri->reserved_keys + cnt->keys; vals = tri->reserved_vals + cnt->vals; - fits = scoutfs_item_dirty_fits_single(sb, items, keys, vals); + fits = scoutfs_item_dirty_fits_single(sb, items, vals); if (!fits) { scoutfs_inc_counter(sb, trans_commit_full); queue_trans_work(sbi); @@ -328,11 +324,9 @@ static bool acquired_hold(struct super_block *sb, } tri->reserved_items = items; - tri->reserved_keys = keys; tri->reserved_vals = vals; rsv->reserved.items = cnt->items; - rsv->reserved.keys = cnt->keys; rsv->reserved.vals = cnt->vals; hold: @@ -358,9 +352,8 @@ int scoutfs_hold_trans(struct super_block *sb, * Caller shouldn't provide garbage counts, nor counts that * can't fit in segments by themselves. */ - if (WARN_ON_ONCE(cnt.items <= 0 || cnt.keys < 0 || cnt.vals < 0) || - WARN_ON_ONCE(!scoutfs_seg_fits_single(cnt.items, cnt.keys, - cnt.vals))) + if (WARN_ON_ONCE(cnt.items <= 0 || cnt.vals < 0) || + WARN_ON_ONCE(!scoutfs_seg_fits_single(cnt.items, cnt.vals))) return -EINVAL; if (current == sbi->trans_task) @@ -400,7 +393,7 @@ bool scoutfs_trans_held(void) } void scoutfs_trans_track_item(struct super_block *sb, signed items, - signed keys, signed vals) + signed vals) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_reservation *rsv = current->journal_info; @@ -411,11 +404,9 @@ void scoutfs_trans_track_item(struct super_block *sb, signed items, BUG_ON(!rsv || rsv->magic != SCOUTFS_RESERVATION_MAGIC); rsv->actual.items += items; - rsv->actual.keys += keys; rsv->actual.vals += vals; WARN_ON_ONCE(rsv->actual.items > rsv->reserved.items); - WARN_ON_ONCE(rsv->actual.keys > rsv->reserved.keys); WARN_ON_ONCE(rsv->actual.vals > rsv->reserved.vals); } @@ -442,15 +433,13 @@ void scoutfs_release_trans(struct super_block *sb) trace_scoutfs_release_trans(sb, rsv, rsv->holders, &rsv->reserved, &rsv->actual, tri->holders, tri->writing, - tri->reserved_items, tri->reserved_keys, - tri->reserved_vals); + tri->reserved_items, tri->reserved_vals); BUG_ON(rsv->holders <= 0); BUG_ON(tri->holders <= 0); if (--rsv->holders == 0) { tri->reserved_items -= rsv->reserved.items; - tri->reserved_keys -= rsv->reserved.keys; tri->reserved_vals -= rsv->reserved.vals; current->journal_info = NULL; kfree(rsv); diff --git a/kmod/src/trans.h b/kmod/src/trans.h index 0df05ff3..04e28f9c 100644 --- a/kmod/src/trans.h +++ b/kmod/src/trans.h @@ -14,7 +14,7 @@ int scoutfs_hold_trans(struct super_block *sb, bool scoutfs_trans_held(void); void scoutfs_release_trans(struct super_block *sb); void scoutfs_trans_track_item(struct super_block *sb, signed items, - signed keys, signed vals); + signed vals); int scoutfs_setup_trans(struct super_block *sb); void scoutfs_shutdown_trans(struct super_block *sb); diff --git a/kmod/src/xattr.c b/kmod/src/xattr.c index cd6df413..d2e57277 100644 --- a/kmod/src/xattr.c +++ b/kmod/src/xattr.c @@ -68,19 +68,17 @@ static unsigned int xattr_nr_parts(struct scoutfs_xattr *xat) le16_to_cpu(xat->val_len)); } -/* If no name is provided then the hash arg is used, caller can modify part */ -static void init_xattr_key(struct scoutfs_key_buf *key, - struct scoutfs_xattr_key *xak, u64 ino, - u32 name_hash, u64 id) +static void init_xattr_key(struct scoutfs_key *key, u64 ino, u32 name_hash, + u64 id) { - xak->zone = SCOUTFS_FS_ZONE; - xak->ino = cpu_to_be64(ino); - xak->type = SCOUTFS_XATTR_TYPE; - xak->name_hash = cpu_to_be32(name_hash); - xak->id = cpu_to_be64(id); - xak->part = 0; - - scoutfs_key_init(key, xak, sizeof(struct scoutfs_xattr_key)); + *key = (struct scoutfs_key) { + .sk_zone = SCOUTFS_FS_ZONE, + .skx_ino = cpu_to_le64(ino), + .sk_type = SCOUTFS_XATTR_TYPE, + .skx_name_hash = cpu_to_le64(name_hash), + .skx_id = cpu_to_le64(id), + .skx_part = 0, + }; } static int unknown_prefix(const char *name) @@ -108,15 +106,13 @@ static int unknown_prefix(const char *name) * * Returns -ENOENT if it didn't find a next item. */ -static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak, +static int get_next_xattr(struct inode *inode, struct scoutfs_key *key, struct scoutfs_xattr *xat, unsigned int bytes, const char *name, unsigned int name_len, u64 name_hash, u64 id, struct scoutfs_lock *lock) { struct super_block *sb = inode->i_sb; - struct scoutfs_xattr_key last_xak; - struct scoutfs_key_buf last; - struct scoutfs_key_buf key; + struct scoutfs_key last; struct kvec val; u8 last_part; int total; @@ -131,17 +127,17 @@ static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak, if (name_len) name_hash = xattr_name_hash(name, name_len); - init_xattr_key(&key, xak, scoutfs_ino(inode), name_hash, id); - init_xattr_key(&last, &last_xak, scoutfs_ino(inode), U32_MAX, U64_MAX); + init_xattr_key(key, scoutfs_ino(inode), name_hash, id); + init_xattr_key(&last, scoutfs_ino(inode), U32_MAX, U64_MAX); last_part = 0; part = 0; total = 0; for (;;) { - xak->part = part; + key->skx_part = part; kvec_init(&val, (void *)xat + total, bytes - total); - ret = scoutfs_item_next(sb, &key, &last, &val, lock); + ret = scoutfs_item_next(sb, key, &last, &val, lock); if (ret < 0) { /* XXX corruption, ran out of parts */ if (ret == -ENOENT && part > 0) @@ -149,10 +145,10 @@ static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak, break; } - trace_scoutfs_xattr_get_next_key(sb, &key); + trace_scoutfs_xattr_get_next_key(sb, key); /* XXX corruption */ - if (xak->part != part) { + if (key->skx_part != part) { ret = -EIO; break; } @@ -175,7 +171,7 @@ static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak, if (part == 0 && name_len) { /* ran out of names that could match */ - if (be32_to_cpu(xak->name_hash) != name_hash) { + if (le64_to_cpu(key->skx_name_hash) != name_hash) { ret = -ENOENT; break; } @@ -184,7 +180,7 @@ static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak, if (!xattr_names_equal(name, name_len, xat->name, xat->name_len)) { part = 0; - be64_add_cpu(&xak->id, 1); + le64_add_cpu(&key->skx_id, 1); continue; } @@ -214,14 +210,13 @@ static int create_xattr_items(struct inode *inode, u64 id, struct scoutfs_lock *lock) { struct super_block *sb = inode->i_sb; - struct scoutfs_xattr_key xak; - struct scoutfs_key_buf key; + struct scoutfs_key key; unsigned int part_bytes; struct kvec val; int total; int ret; - init_xattr_key(&key, &xak, scoutfs_ino(inode), + init_xattr_key(&key, scoutfs_ino(inode), xattr_name_hash(xat->name, xat->name_len), id); total = 0; @@ -232,13 +227,13 @@ static int create_xattr_items(struct inode *inode, u64 id, ret = scoutfs_item_create(sb, &key, &val, lock); if (ret) { - while (xak.part-- > 0) + while (key.skx_part-- > 0) scoutfs_item_delete_dirty(sb, &key); break; } total += part_bytes; - xak.part++; + key.skx_part++; } return ret; @@ -249,20 +244,19 @@ static int create_xattr_items(struct inode *inode, u64 id, * returns an error then the deleted and saved items are left on the * list for the caller to restore. */ -static int delete_xattr_items(struct inode *inode, u64 name_hash, u64 id, +static int delete_xattr_items(struct inode *inode, u32 name_hash, u64 id, u8 nr_parts, struct list_head *list, struct scoutfs_lock *lock) { struct super_block *sb = inode->i_sb; - struct scoutfs_xattr_key xak; - struct scoutfs_key_buf key; + struct scoutfs_key key; int ret; - init_xattr_key(&key, &xak, scoutfs_ino(inode), name_hash, id); + init_xattr_key(&key, scoutfs_ino(inode), name_hash, id); do { ret = scoutfs_item_delete_save(sb, &key, list, lock); - } while (ret == 0 && ++xak.part < nr_parts); + } while (ret == 0 && ++key.skx_part < nr_parts); return ret; } @@ -279,7 +273,7 @@ ssize_t scoutfs_getxattr(struct dentry *dentry, const char *name, void *buffer, struct super_block *sb = inode->i_sb; struct scoutfs_xattr *xat = NULL; struct scoutfs_lock *lck = NULL; - struct scoutfs_xattr_key xak; + struct scoutfs_key key; unsigned int bytes; size_t name_len; int ret; @@ -303,7 +297,7 @@ ssize_t scoutfs_getxattr(struct dentry *dentry, const char *name, void *buffer, down_read(&si->xattr_rwsem); - ret = get_next_xattr(inode, &xak, xat, bytes, + ret = get_next_xattr(inode, &key, xat, bytes, name, name_len, 0, 0, lck); up_read(&si->xattr_rwsem); @@ -360,7 +354,7 @@ static int scoutfs_xattr_set(struct dentry *dentry, const char *name, struct scoutfs_xattr *xat = NULL; struct scoutfs_lock *lck = NULL; size_t name_len = strlen(name); - struct scoutfs_xattr_key xak; + struct scoutfs_key key; LIST_HEAD(ind_locks); LIST_HEAD(saved); u8 found_parts; @@ -399,7 +393,7 @@ static int scoutfs_xattr_set(struct dentry *dentry, const char *name, down_write(&si->xattr_rwsem); /* find an existing xattr to delete */ - ret = get_next_xattr(inode, &xak, xat, + ret = get_next_xattr(inode, &key, xat, sizeof(struct scoutfs_xattr) + name_len, name, name_len, 0, 0, lck); if (ret < 0 && ret != -ENOENT) @@ -420,7 +414,7 @@ static int scoutfs_xattr_set(struct dentry *dentry, const char *name, goto unlock; } - /* found fields in xak will also be used */ + /* found fields in key will also be used */ found_parts = ret >= 0 ? xattr_nr_parts(xat) : 0; /* prepare our xattr */ @@ -450,8 +444,8 @@ retry: ret = 0; if (found_parts) - ret = delete_xattr_items(inode, be32_to_cpu(xak.name_hash), - be64_to_cpu(xak.id), found_parts, + ret = delete_xattr_items(inode, le64_to_cpu(key.skx_name_hash), + le64_to_cpu(key.skx_id), found_parts, &saved, lck); if (value && ret == 0) ret = create_xattr_items(inode, id, xat, bytes, lck); @@ -500,7 +494,7 @@ ssize_t scoutfs_listxattr(struct dentry *dentry, char *buffer, size_t size) struct super_block *sb = inode->i_sb; struct scoutfs_xattr *xat = NULL; struct scoutfs_lock *lck = NULL; - struct scoutfs_xattr_key xak; + struct scoutfs_key key; unsigned int bytes; ssize_t total; u32 name_hash; @@ -526,7 +520,7 @@ ssize_t scoutfs_listxattr(struct dentry *dentry, char *buffer, size_t size) total = 0; for (;;) { - ret = get_next_xattr(inode, &xak, xat, bytes, + ret = get_next_xattr(inode, &key, xat, bytes, NULL, 0, name_hash, id, lck); if (ret < 0) { if (ret == -ENOENT) @@ -547,8 +541,8 @@ ssize_t scoutfs_listxattr(struct dentry *dentry, char *buffer, size_t size) *(buffer++) = '\0'; } - name_hash = be32_to_cpu(xak.name_hash); - id = be64_to_cpu(xak.id) + 1; + name_hash = le64_to_cpu(key.skx_name_hash); + id = le64_to_cpu(key.skx_id) + 1; } up_read(&si->xattr_rwsem); @@ -571,15 +565,13 @@ out: */ int scoutfs_xattr_drop(struct super_block *sb, u64 ino) { - struct scoutfs_xattr_key last_xak; - struct scoutfs_xattr_key xak; - struct scoutfs_key_buf last; - struct scoutfs_key_buf key; + struct scoutfs_key last; + struct scoutfs_key key; struct scoutfs_lock *lck; int ret; - init_xattr_key(&key, &xak, ino, 0, 0); - init_xattr_key(&last, &last_xak, ino, U32_MAX, U64_MAX); + init_xattr_key(&key, ino, 0, 0); + init_xattr_key(&last, ino, U32_MAX, U64_MAX); /* while we read to delete we need to writeback others */ ret = scoutfs_lock_ino(sb, DLM_LOCK_EX, 0, ino, &lck); @@ -598,7 +590,7 @@ int scoutfs_xattr_drop(struct super_block *sb, u64 ino) if (ret) break; - xak.part++; + key.skx_part++; } scoutfs_unlock(sb, lck, DLM_LOCK_EX);