diff --git a/kmod/src/alloc.c b/kmod/src/alloc.c index 530e261f..53965eec 100644 --- a/kmod/src/alloc.c +++ b/kmod/src/alloc.c @@ -358,31 +358,24 @@ static void list_block_sort(struct scoutfs_alloc_list_block *lblk) /* * We're always reading blocks that we own, so we shouldn't see stale - * references. But the cached block can be stale and we can need to - * invalidate it. + * references but we could retry reads after dropping stale cached + * blocks. If we do see a stale error then we've hit persistent + * corruption. */ -static int read_list_block(struct super_block *sb, - struct scoutfs_alloc_list_ref *ref, +static int read_list_block(struct super_block *sb, struct scoutfs_block_ref *ref, struct scoutfs_block **bl_ret) { - struct scoutfs_block *bl = NULL; + int ret; - bl = scoutfs_block_read(sb, le64_to_cpu(ref->blkno)); - if (!IS_ERR_OR_NULL(bl) && - !scoutfs_block_consistent_ref(sb, bl, ref->seq, ref->blkno, - SCOUTFS_BLOCK_MAGIC_ALLOC_LIST)) { - scoutfs_inc_counter(sb, alloc_stale_cached_list_block); - scoutfs_block_invalidate(sb, bl); - scoutfs_block_put(sb, bl); - bl = scoutfs_block_read(sb, le64_to_cpu(ref->blkno)); - } - if (IS_ERR(bl)) { - *bl_ret = NULL; - return PTR_ERR(bl); - } + ret = scoutfs_block_read_ref(sb, ref, SCOUTFS_BLOCK_MAGIC_ALLOC_LIST, bl_ret); + if (ret < 0) { + if (ret == -ESTALE) { + scoutfs_inc_counter(sb, alloc_stale_list_block); + ret = -EIO; + } + }; - *bl_ret = bl; - return 0; + return ret; } /* @@ -396,7 +389,7 @@ static int read_list_block(struct super_block *sb, static int dirty_list_block(struct super_block *sb, struct scoutfs_alloc *alloc, struct scoutfs_block_writer *wri, - struct scoutfs_alloc_list_ref *ref, + struct scoutfs_block_ref *ref, u64 dirty, u64 *old, struct scoutfs_block **bl_ret) { @@ -497,7 +490,7 @@ static int dirty_alloc_blocks(struct super_block *sb, struct scoutfs_alloc *alloc, struct scoutfs_block_writer *wri) { - struct scoutfs_alloc_list_ref orig_freed; + struct scoutfs_block_ref orig_freed; struct scoutfs_alloc_list_block *lblk; struct scoutfs_block *av_bl = NULL; struct scoutfs_block *fr_bl = NULL; @@ -1106,7 +1099,7 @@ int scoutfs_alloc_splice_list(struct super_block *sb, struct scoutfs_alloc_list_head *src) { struct scoutfs_alloc_list_block *lblk; - struct scoutfs_alloc_list_ref *ref; + struct scoutfs_block_ref *ref; struct scoutfs_block *prev = NULL; struct scoutfs_block *bl = NULL; int ret = 0; @@ -1169,8 +1162,8 @@ bool scoutfs_alloc_meta_low(struct super_block *sb, int scoutfs_alloc_foreach(struct super_block *sb, scoutfs_alloc_foreach_cb_t cb, void *arg) { - struct scoutfs_btree_ref stale_refs[2] = {{0,}}; - struct scoutfs_btree_ref refs[2] = {{0,}}; + struct scoutfs_block_ref stale_refs[2] = {{0,}}; + struct scoutfs_block_ref refs[2] = {{0,}}; struct scoutfs_super_block *super = NULL; struct scoutfs_srch_compact *sc; struct scoutfs_log_trees lt; diff --git a/kmod/src/block.c b/kmod/src/block.c index 1c2e4ae8..8e0ed42f 100644 --- a/kmod/src/block.c +++ b/kmod/src/block.c @@ -114,12 +114,7 @@ do { \ #define BLOCK_PRIVATE(_bl) \ container_of((_bl), struct block_private, bl) -/* - * These _block_header helpers are from a previous generation and may - * be refactored away. - */ - -__le32 scoutfs_block_calc_crc(struct scoutfs_block_header *hdr, u32 size) +static __le32 block_calc_crc(struct scoutfs_block_header *hdr, u32 size) { int off = offsetof(struct scoutfs_block_header, crc) + FIELD_SIZEOF(struct scoutfs_block_header, crc); @@ -128,21 +123,6 @@ __le32 scoutfs_block_calc_crc(struct scoutfs_block_header *hdr, u32 size) return cpu_to_le32(calc); } -bool scoutfs_block_valid_crc(struct scoutfs_block_header *hdr, u32 size) -{ - return hdr->crc == scoutfs_block_calc_crc(hdr, size); -} - -bool scoutfs_block_valid_ref(struct super_block *sb, - struct scoutfs_block_header *hdr, - __le64 seq, __le64 blkno) -{ - struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; - - return hdr->fsid == super->hdr.fsid && hdr->seq == seq && - hdr->blkno == blkno; -} - static struct block_private *block_alloc(struct super_block *sb, u64 blkno) { struct block_private *bp; @@ -625,7 +605,7 @@ static bool uptodate_or_error(struct block_private *bp) test_bit(BLOCK_BIT_ERROR, &bp->bits); } -struct scoutfs_block *scoutfs_block_read(struct super_block *sb, u64 blkno) +static struct block_private *block_read(struct super_block *sb, u64 blkno) { DECLARE_BLOCK_INFO(sb, binf); struct block_private *bp = NULL; @@ -654,45 +634,69 @@ out: return ERR_PTR(ret); } - return &bp->bl; + return bp; } /* - * Drop a stale cached read block from the cache. A future read will - * re-read the block from the device. This doesn't drop the caller's reference, - * they still have to call _put. + * Btree blocks don't have rigid cache consistency. We can be following + * block references into cached blocks that are now stale or can be + * following a stale root into blocks that have been overwritten. If we + * hit a block that looks stale we first invalidate the cache and retry, + * returning -ESTALE if it still looks wrong. The caller can retry the + * read from a more current root or decide that this is a persistent + * error. */ -void scoutfs_block_invalidate(struct super_block *sb, struct scoutfs_block *bl) -{ - struct block_private *bp = BLOCK_PRIVATE(bl); - - if (!WARN_ON_ONCE(test_bit(BLOCK_BIT_DIRTY, &bp->bits))) { - scoutfs_inc_counter(sb, block_cache_invalidate); - block_remove(sb, bp); - TRACE_BLOCK(invalidate, bp); - } -} - -/* This is only used for large metadata blocks */ -bool scoutfs_block_consistent_ref(struct super_block *sb, - struct scoutfs_block *bl, - __le64 seq, __le64 blkno, u32 magic) +int scoutfs_block_read_ref(struct super_block *sb, struct scoutfs_block_ref *ref, u32 magic, + struct scoutfs_block **bl_ret) { struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; - struct block_private *bp = BLOCK_PRIVATE(bl); - struct scoutfs_block_header *hdr = bl->data; + struct scoutfs_block_header *hdr; + struct block_private *bp = NULL; + bool retried = false; + int ret; +retry: + bp = block_read(sb, le64_to_cpu(ref->blkno)); + if (IS_ERR(bp)) { + ret = PTR_ERR(bp); + goto out; + } + hdr = bp->bl.data; + + /* corrupted writes might be a sign of a stale reference */ if (!test_bit(BLOCK_BIT_CRC_VALID, &bp->bits)) { - if (hdr->crc != - scoutfs_block_calc_crc(hdr, SCOUTFS_BLOCK_LG_SIZE)) - return false; + if (hdr->crc != block_calc_crc(hdr, SCOUTFS_BLOCK_LG_SIZE)) { + ret = -ESTALE; + goto out; + } + set_bit(BLOCK_BIT_CRC_VALID, &bp->bits); } - return hdr->magic == cpu_to_le32(magic) && - hdr->fsid == super->hdr.fsid && - hdr->seq == seq && - hdr->blkno == blkno; + if (hdr->magic != cpu_to_le32(magic) || hdr->fsid != super->hdr.fsid || + hdr->seq != ref->seq || hdr->blkno != ref->blkno) { + ret = -ESTALE; + goto out; + } + + ret = 0; +out: + if (ret == -ESTALE && !retried) { + retried = true; + scoutfs_inc_counter(sb, block_cache_remove_stale); + block_remove(sb, bp); + block_put(sb, bp); + bp = NULL; + goto retry; + } + + if (ret < 0) { + block_put(sb, bp); + bp = NULL; + } + + *bl_ret = bp ? &bp->bl : NULL; + return ret; } void scoutfs_block_put(struct super_block *sb, struct scoutfs_block *bl) @@ -762,7 +766,7 @@ int scoutfs_block_writer_write(struct super_block *sb, /* checksum everything to reduce time between io submission merging */ list_for_each_entry(bp, &wri->dirty_list, dirty_entry) { hdr = bp->bl.data; - hdr->crc = scoutfs_block_calc_crc(hdr, SCOUTFS_BLOCK_LG_SIZE); + hdr->crc = block_calc_crc(hdr, SCOUTFS_BLOCK_LG_SIZE); } blk_start_plug(&plug); @@ -1013,8 +1017,7 @@ static int sm_block_io(struct block_device *bdev, int rw, u64 blkno, if (len < SCOUTFS_BLOCK_SM_SIZE) memset((char *)pg_hdr + len, 0, SCOUTFS_BLOCK_SM_SIZE - len); - pg_hdr->crc = scoutfs_block_calc_crc(pg_hdr, - SCOUTFS_BLOCK_SM_SIZE); + pg_hdr->crc = block_calc_crc(pg_hdr, SCOUTFS_BLOCK_SM_SIZE); } bio = bio_alloc(GFP_NOFS, 1); @@ -1039,8 +1042,7 @@ static int sm_block_io(struct block_device *bdev, int rw, u64 blkno, if (ret == 0 && !(rw & WRITE)) { memcpy(hdr, pg_hdr, len); - *blk_crc = scoutfs_block_calc_crc(pg_hdr, - SCOUTFS_BLOCK_SM_SIZE); + *blk_crc = block_calc_crc(pg_hdr, SCOUTFS_BLOCK_SM_SIZE); } out: __free_page(page); diff --git a/kmod/src/block.h b/kmod/src/block.h index 79a859d7..7276a61c 100644 --- a/kmod/src/block.h +++ b/kmod/src/block.h @@ -13,18 +13,9 @@ struct scoutfs_block { void *priv; }; -__le32 scoutfs_block_calc_crc(struct scoutfs_block_header *hdr, u32 size); -bool scoutfs_block_valid_crc(struct scoutfs_block_header *hdr, u32 size); -bool scoutfs_block_valid_ref(struct super_block *sb, - struct scoutfs_block_header *hdr, - __le64 seq, __le64 blkno); - struct scoutfs_block *scoutfs_block_create(struct super_block *sb, u64 blkno); -struct scoutfs_block *scoutfs_block_read(struct super_block *sb, u64 blkno); -void scoutfs_block_invalidate(struct super_block *sb, struct scoutfs_block *bl); -bool scoutfs_block_consistent_ref(struct super_block *sb, - struct scoutfs_block *bl, - __le64 seq, __le64 blkno, u32 magic); +int scoutfs_block_read_ref(struct super_block *sb, struct scoutfs_block_ref *ref, u32 magic, + struct scoutfs_block **bl_ret); void scoutfs_block_put(struct super_block *sb, struct scoutfs_block *bl); void scoutfs_block_writer_init(struct super_block *sb, diff --git a/kmod/src/btree.c b/kmod/src/btree.c index d4eee1cc..78643961 100644 --- a/kmod/src/btree.c +++ b/kmod/src/btree.c @@ -619,18 +619,13 @@ static void move_items(struct scoutfs_btree_block *dst, * This is used to lookup cached blocks, read blocks, cow blocks for * dirtying, and allocate new blocks. * - * Btree blocks don't have rigid cache consistency. We can be following - * block references into cached blocks that are now stale or can be - * following a stale root into blocks that have been overwritten. If we - * hit a block that looks stale we first invalidate the cache and retry, - * returning -ESTALE if it still looks wrong. The caller can retry the - * read from a more current root or decide that this is a persistent - * error. + * If we read a stale block we return stale so the caller can retry with + * a newer root or return an error. */ static int get_ref_block(struct super_block *sb, struct scoutfs_alloc *alloc, struct scoutfs_block_writer *wri, int flags, - struct scoutfs_btree_ref *ref, + struct scoutfs_block_ref *ref, struct scoutfs_block **bl_ret) { struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; @@ -638,40 +633,16 @@ static int get_ref_block(struct super_block *sb, struct scoutfs_btree_block *new; struct scoutfs_block *new_bl = NULL; struct scoutfs_block *bl = NULL; - bool retried = false; u64 blkno; u64 seq; int ret; /* always get the current block, either to return or cow from */ if (ref && ref->blkno) { -retry: - - bl = scoutfs_block_read(sb, le64_to_cpu(ref->blkno)); - if (IS_ERR(bl)) { - trace_scoutfs_btree_read_error(sb, ref); - scoutfs_inc_counter(sb, btree_read_error); - ret = PTR_ERR(bl); - goto out; - } - bt = (void *)bl->data; - - if (!scoutfs_block_consistent_ref(sb, bl, ref->seq, ref->blkno, - SCOUTFS_BLOCK_MAGIC_BTREE) || - scoutfs_trigger(sb, BTREE_STALE_READ)) { - - scoutfs_inc_counter(sb, btree_stale_read); - - scoutfs_block_invalidate(sb, bl); - scoutfs_block_put(sb, bl); - bl = NULL; - - if (!retried) { - retried = true; - goto retry; - } - - ret = -ESTALE; + ret = scoutfs_block_read_ref(sb, ref, SCOUTFS_BLOCK_MAGIC_BTREE, &bl); + if (ret < 0) { + if (ret == -ESTALE) + scoutfs_inc_counter(sb, btree_stale_read); goto out; } @@ -766,7 +737,7 @@ static void create_parent_item(struct scoutfs_btree_block *parent, { struct scoutfs_avl_node *par; int cmp; - struct scoutfs_btree_ref ref = { + struct scoutfs_block_ref ref = { .blkno = child->hdr.blkno, .seq = child->hdr.seq, }; @@ -784,7 +755,7 @@ static void update_parent_item(struct scoutfs_btree_block *parent, struct scoutfs_btree_item *par_item, struct scoutfs_btree_block *child) { - struct scoutfs_btree_ref *ref = item_val(parent, par_item); + struct scoutfs_block_ref *ref = item_val(parent, par_item); par_item->key = *item_key(last_item(child)); ref->blkno = child->hdr.blkno; @@ -837,7 +808,7 @@ static int try_split(struct super_block *sb, /* parents need to leave room for child references */ if (right->level) - val_len = sizeof(struct scoutfs_btree_ref); + val_len = sizeof(struct scoutfs_block_ref); /* don't need to split if there's enough space for the item */ if (mid_free_item_room(right, val_len)) @@ -905,7 +876,7 @@ static int try_join(struct super_block *sb, struct scoutfs_btree_item *sib_par_item; struct scoutfs_btree_block *sib; struct scoutfs_block *sib_bl; - struct scoutfs_btree_ref *ref; + struct scoutfs_block_ref *ref; unsigned int sib_tot; bool move_right; int to_move; @@ -1194,7 +1165,7 @@ static int btree_walk(struct super_block *sb, struct scoutfs_btree_item *prev; struct scoutfs_avl_node *next_node; struct scoutfs_avl_node *node; - struct scoutfs_btree_ref *ref; + struct scoutfs_block_ref *ref; unsigned int level; unsigned int nr; int ret; diff --git a/kmod/src/counters.h b/kmod/src/counters.h index 37d08191..7cb5a331 100644 --- a/kmod/src/counters.h +++ b/kmod/src/counters.h @@ -20,7 +20,7 @@ EXPAND_COUNTER(alloc_list_freed_hi) \ EXPAND_COUNTER(alloc_move) \ EXPAND_COUNTER(alloc_moved_extent) \ - EXPAND_COUNTER(alloc_stale_cached_list_block) \ + EXPAND_COUNTER(alloc_stale_list_block) \ EXPAND_COUNTER(block_cache_access_update) \ EXPAND_COUNTER(block_cache_alloc_failure) \ EXPAND_COUNTER(block_cache_alloc_page_order) \ @@ -29,7 +29,7 @@ EXPAND_COUNTER(block_cache_forget) \ EXPAND_COUNTER(block_cache_free) \ EXPAND_COUNTER(block_cache_free_work) \ - EXPAND_COUNTER(block_cache_invalidate) \ + EXPAND_COUNTER(block_cache_remove_stale) \ EXPAND_COUNTER(block_cache_shrink) \ EXPAND_COUNTER(block_cache_shrink_next) \ EXPAND_COUNTER(block_cache_shrink_recent) \ @@ -46,7 +46,6 @@ EXPAND_COUNTER(btree_lookup) \ EXPAND_COUNTER(btree_next) \ EXPAND_COUNTER(btree_prev) \ - EXPAND_COUNTER(btree_read_error) \ EXPAND_COUNTER(btree_split) \ EXPAND_COUNTER(btree_stale_read) \ EXPAND_COUNTER(btree_update) \ @@ -77,6 +76,7 @@ EXPAND_COUNTER(ext_op_remove) \ EXPAND_COUNTER(forest_bloom_fail) \ EXPAND_COUNTER(forest_bloom_pass) \ + EXPAND_COUNTER(forest_bloom_stale) \ EXPAND_COUNTER(forest_read_items) \ EXPAND_COUNTER(forest_roots_next_hint) \ EXPAND_COUNTER(forest_set_bloom_bits) \ @@ -167,7 +167,6 @@ EXPAND_COUNTER(srch_compact_flush) \ EXPAND_COUNTER(srch_compact_log_page) \ EXPAND_COUNTER(srch_compact_removed_entry) \ - EXPAND_COUNTER(srch_inconsistent_ref) \ EXPAND_COUNTER(srch_rotate_log) \ EXPAND_COUNTER(srch_search_log) \ EXPAND_COUNTER(srch_search_log_block) \ diff --git a/kmod/src/forest.c b/kmod/src/forest.c index f5f259c0..a832b2dd 100644 --- a/kmod/src/forest.c +++ b/kmod/src/forest.c @@ -66,8 +66,8 @@ struct forest_info { struct forest_info *name = SCOUTFS_SB(sb)->forest_info struct forest_refs { - struct scoutfs_btree_ref fs_ref; - struct scoutfs_btree_ref logs_ref; + struct scoutfs_block_ref fs_ref; + struct scoutfs_block_ref logs_ref; }; /* initialize some refs that initially aren't equal */ @@ -96,20 +96,16 @@ static void calc_bloom_nrs(struct forest_bloom_nrs *bloom, } } -static struct scoutfs_block *read_bloom_ref(struct super_block *sb, - struct scoutfs_btree_ref *ref) +static struct scoutfs_block *read_bloom_ref(struct super_block *sb, struct scoutfs_block_ref *ref) { struct scoutfs_block *bl; + int ret; - bl = scoutfs_block_read(sb, le64_to_cpu(ref->blkno)); - if (IS_ERR(bl)) - return bl; - - if (!scoutfs_block_consistent_ref(sb, bl, ref->seq, ref->blkno, - SCOUTFS_BLOCK_MAGIC_BLOOM)) { - scoutfs_block_invalidate(sb, bl); - scoutfs_block_put(sb, bl); - return ERR_PTR(-ESTALE); + ret = scoutfs_block_read_ref(sb, ref, SCOUTFS_BLOCK_MAGIC_BLOOM, &bl); + if (ret < 0) { + if (ret == -ESTALE) + scoutfs_inc_counter(sb, forest_bloom_stale); + bl = ERR_PTR(ret); } return bl; @@ -386,7 +382,7 @@ int scoutfs_forest_set_bloom_bits(struct super_block *sb, struct scoutfs_block *new_bl = NULL; struct scoutfs_block *bl = NULL; struct scoutfs_bloom_block *bb; - struct scoutfs_btree_ref *ref; + struct scoutfs_block_ref *ref; struct forest_bloom_nrs bloom; int nr_set = 0; u64 blkno; diff --git a/kmod/src/format.h b/kmod/src/format.h index 9578586f..28a15175 100644 --- a/kmod/src/format.h +++ b/kmod/src/format.h @@ -106,6 +106,15 @@ struct scoutfs_block_header { __le64 blkno; }; +/* + * A reference to a block. The corresponding fields in the block_header + * must match after having read the block contents. + */ +struct scoutfs_block_ref { + __le64 blkno; + __le64 seq; +}; + /* * scoutfs identifies all file system metadata items by a small key * struct. @@ -202,17 +211,12 @@ struct scoutfs_avl_node { */ #define SCOUTFS_BTREE_MAX_HEIGHT 20 -struct scoutfs_btree_ref { - __le64 blkno; - __le64 seq; -}; - /* * A height of X means that the first block read will have level X-1 and * the leaves will have level 0. */ struct scoutfs_btree_root { - struct scoutfs_btree_ref ref; + struct scoutfs_block_ref ref; __u8 height; __u8 __pad[7]; }; @@ -253,18 +257,13 @@ struct scoutfs_btree_block { #define SCOUTFS_BTREE_LEAF_ITEM_HASH_BYTES \ (SCOUTFS_BTREE_LEAF_ITEM_HASH_NR * sizeof(__le16)) -struct scoutfs_alloc_list_ref { - __le64 blkno; - __le64 seq; -}; - /* * first_nr tracks the nr of the first block in the list and is used for * allocation sizing. total_nr is the sum of the nr of all the blocks in * the list and is used for calculating total free block counts. */ struct scoutfs_alloc_list_head { - struct scoutfs_alloc_list_ref ref; + struct scoutfs_block_ref ref; __le64 total_nr; __le32 first_nr; __u8 __pad[4]; @@ -283,7 +282,7 @@ struct scoutfs_alloc_list_head { */ struct scoutfs_alloc_list_block { struct scoutfs_block_header hdr; - struct scoutfs_alloc_list_ref next; + struct scoutfs_block_ref next; __le32 start; __le32 nr; __le64 blknos[0]; /* naturally aligned for sorting */ @@ -329,15 +328,10 @@ struct scoutfs_srch_entry { #define SCOUTFS_SRCH_ENTRY_MAX_BYTES (2 + (sizeof(__u64) * 3)) -struct scoutfs_srch_ref { - __le64 blkno; - __le64 seq; -}; - struct scoutfs_srch_file { struct scoutfs_srch_entry first; struct scoutfs_srch_entry last; - struct scoutfs_srch_ref ref; + struct scoutfs_block_ref ref; __le64 blocks; __le64 entries; __u8 height; @@ -346,13 +340,13 @@ struct scoutfs_srch_file { struct scoutfs_srch_parent { struct scoutfs_block_header hdr; - struct scoutfs_srch_ref refs[0]; + struct scoutfs_block_ref refs[0]; }; #define SCOUTFS_SRCH_PARENT_REFS \ ((SCOUTFS_BLOCK_LG_SIZE - \ offsetof(struct scoutfs_srch_parent, refs)) / \ - sizeof(struct scoutfs_srch_ref)) + sizeof(struct scoutfs_block_ref)) struct scoutfs_srch_block { struct scoutfs_block_header hdr; @@ -423,7 +417,7 @@ struct scoutfs_log_trees { struct scoutfs_alloc_list_head meta_avail; struct scoutfs_alloc_list_head meta_freed; struct scoutfs_btree_root item_root; - struct scoutfs_btree_ref bloom_ref; + struct scoutfs_block_ref bloom_ref; struct scoutfs_alloc_root data_avail; struct scoutfs_alloc_root data_freed; struct scoutfs_srch_file srch_file; diff --git a/kmod/src/scoutfs_trace.h b/kmod/src/scoutfs_trace.h index 563f95e3..ecd2080f 100644 --- a/kmod/src/scoutfs_trace.h +++ b/kmod/src/scoutfs_trace.h @@ -1611,7 +1611,7 @@ TRACE_EVENT(scoutfs_get_name, ); TRACE_EVENT(scoutfs_btree_read_error, - TP_PROTO(struct super_block *sb, struct scoutfs_btree_ref *ref), + TP_PROTO(struct super_block *sb, struct scoutfs_block_ref *ref), TP_ARGS(sb, ref), @@ -1661,7 +1661,7 @@ TRACE_EVENT(scoutfs_btree_dirty_block, TRACE_EVENT(scoutfs_btree_walk, TP_PROTO(struct super_block *sb, struct scoutfs_btree_root *root, struct scoutfs_key *key, int flags, int level, - struct scoutfs_btree_ref *ref), + struct scoutfs_block_ref *ref), TP_ARGS(sb, root, key, flags, level, ref), @@ -1989,8 +1989,8 @@ DEFINE_EVENT(scoutfs_forest_bloom_class, scoutfs_forest_bloom_search, ); TRACE_EVENT(scoutfs_forest_prepare_commit, - TP_PROTO(struct super_block *sb, struct scoutfs_btree_ref *item_ref, - struct scoutfs_btree_ref *bloom_ref), + TP_PROTO(struct super_block *sb, struct scoutfs_block_ref *item_ref, + struct scoutfs_block_ref *bloom_ref), TP_ARGS(sb, item_ref, bloom_ref), TP_STRUCT__entry( SCSB_TRACE_FIELDS diff --git a/kmod/src/srch.c b/kmod/src/srch.c index 00c4f0fd..41cb11b1 100644 --- a/kmod/src/srch.c +++ b/kmod/src/srch.c @@ -284,39 +284,15 @@ static void init_file_block(struct super_block *sb, struct scoutfs_block *bl, */ static int read_srch_block(struct super_block *sb, struct scoutfs_block_writer *wri, int level, - struct scoutfs_srch_ref *ref, + struct scoutfs_block_ref *ref, struct scoutfs_block **bl_ret) { - struct scoutfs_block *bl; - int retries = 0; - int ret = 0; - int mag; + u32 magic = level ? SCOUTFS_BLOCK_MAGIC_SRCH_PARENT : SCOUTFS_BLOCK_MAGIC_SRCH_BLOCK; + int ret; - mag = level ? SCOUTFS_BLOCK_MAGIC_SRCH_PARENT : - SCOUTFS_BLOCK_MAGIC_SRCH_BLOCK; -retry: - bl = scoutfs_block_read(sb, le64_to_cpu(ref->blkno)); - if (!IS_ERR_OR_NULL(bl) && - !scoutfs_block_consistent_ref(sb, bl, ref->seq, ref->blkno, mag)) { - - scoutfs_inc_counter(sb, srch_inconsistent_ref); - scoutfs_block_writer_forget(sb, wri, bl); - scoutfs_block_invalidate(sb, bl); - scoutfs_block_put(sb, bl); - bl = NULL; - - if (retries++ == 0) - goto retry; - - bl = ERR_PTR(-ESTALE); + ret = scoutfs_block_read_ref(sb, ref, magic, bl_ret); + if (ret == -ESTALE) scoutfs_inc_counter(sb, srch_read_stale); - } - if (IS_ERR(bl)) { - ret = PTR_ERR(bl); - bl = NULL; - } - - *bl_ret = bl; return ret; } @@ -333,7 +309,7 @@ static int read_path_block(struct super_block *sb, { struct scoutfs_block *bl = NULL; struct scoutfs_srch_parent *srp; - struct scoutfs_srch_ref ref; + struct scoutfs_block_ref ref; int level; int ind; int ret; @@ -393,7 +369,7 @@ static int get_file_block(struct super_block *sb, struct scoutfs_block *bl = NULL; struct scoutfs_srch_parent *srp; struct scoutfs_block *new_bl; - struct scoutfs_srch_ref *ref; + struct scoutfs_block_ref *ref; u64 blkno = 0; int level; int ind;