Loading fs/bcachefs/buckets.c +15 −16 Original line number Diff line number Diff line Loading @@ -546,20 +546,19 @@ static int __disk_sectors(struct bch_extent_crc_unpacked crc, unsigned sectors) */ static void bch2_mark_pointer(struct bch_fs *c, struct bkey_s_c_extent e, const struct bch_extent_ptr *ptr, struct bch_extent_crc_unpacked crc, struct extent_ptr_decoded p, s64 sectors, enum bch_data_type data_type, unsigned replicas, struct bch_fs_usage *fs_usage, u64 journal_seq, unsigned flags) { struct bucket_mark old, new; struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev); struct bucket *g = PTR_BUCKET(ca, ptr); struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev); struct bucket *g = PTR_BUCKET(ca, &p.ptr); s64 uncompressed_sectors = sectors; u64 v; if (crc.compression_type) { if (p.crc.compression_type) { unsigned old_sectors, new_sectors; if (sectors > 0) { Loading @@ -570,8 +569,8 @@ static void bch2_mark_pointer(struct bch_fs *c, new_sectors = e.k->size + sectors; } sectors = -__disk_sectors(crc, old_sectors) +__disk_sectors(crc, new_sectors); sectors = -__disk_sectors(p.crc, old_sectors) +__disk_sectors(p.crc, new_sectors); } /* Loading @@ -584,8 +583,8 @@ static void bch2_mark_pointer(struct bch_fs *c, * caller's responsibility to not apply @fs_usage if gc is in progress. */ fs_usage->replicas [!ptr->cached && replicas ? replicas - 1 : 0].data [!ptr->cached ? data_type : BCH_DATA_CACHED] += [!p.ptr.cached && replicas ? replicas - 1 : 0].data [!p.ptr.cached ? data_type : BCH_DATA_CACHED] += uncompressed_sectors; if (flags & BCH_BUCKET_MARK_GC_WILL_VISIT) { Loading @@ -607,14 +606,14 @@ static void bch2_mark_pointer(struct bch_fs *c, * the allocator invalidating a bucket after we've already * checked the gen */ if (gen_after(new.gen, ptr->gen)) { if (gen_after(new.gen, p.ptr.gen)) { BUG_ON(!test_bit(BCH_FS_ALLOC_READ_DONE, &c->flags)); EBUG_ON(!ptr->cached && EBUG_ON(!p.ptr.cached && test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags)); return; } if (!ptr->cached) if (!p.ptr.cached) checked_add(new.dirty_sectors, sectors); else checked_add(new.cached_sectors, sectors); Loading Loading @@ -695,13 +694,13 @@ void bch2_mark_key(struct bch_fs *c, struct bkey_s_c k, case BCH_EXTENT: case BCH_EXTENT_CACHED: { struct bkey_s_c_extent e = bkey_s_c_to_extent(k); const struct bch_extent_ptr *ptr; struct bch_extent_crc_unpacked crc; const union bch_extent_entry *entry; struct extent_ptr_decoded p; BUG_ON(!sectors); extent_for_each_ptr_crc(e, ptr, crc) bch2_mark_pointer(c, e, ptr, crc, sectors, data_type, extent_for_each_ptr_decode(e, p, entry) bch2_mark_pointer(c, e, p, sectors, data_type, replicas, stats, journal_seq, flags); break; } Loading fs/bcachefs/extents.c +38 −38 Original line number Diff line number Diff line Loading @@ -231,21 +231,21 @@ unsigned bch2_extent_durability(struct bch_fs *c, struct bkey_s_c_extent e) unsigned bch2_extent_is_compressed(struct bkey_s_c k) { struct bkey_s_c_extent e; const struct bch_extent_ptr *ptr; struct bch_extent_crc_unpacked crc; unsigned ret = 0; switch (k.k->type) { case BCH_EXTENT: case BCH_EXTENT_CACHED: e = bkey_s_c_to_extent(k); case BCH_EXTENT_CACHED: { struct bkey_s_c_extent e = bkey_s_c_to_extent(k); const union bch_extent_entry *entry; struct extent_ptr_decoded p; extent_for_each_ptr_crc(e, ptr, crc) if (!ptr->cached && crc.compression_type != BCH_COMPRESSION_NONE && crc.compressed_size < crc.live_size) ret = max_t(unsigned, ret, crc.compressed_size); extent_for_each_ptr_decode(e, p, entry) if (!p.ptr.cached && p.crc.compression_type != BCH_COMPRESSION_NONE && p.crc.compressed_size < p.crc.live_size) ret = max_t(unsigned, ret, p.crc.compressed_size); } } return ret; Loading @@ -254,17 +254,17 @@ unsigned bch2_extent_is_compressed(struct bkey_s_c k) bool bch2_extent_matches_ptr(struct bch_fs *c, struct bkey_s_c_extent e, struct bch_extent_ptr m, u64 offset) { const struct bch_extent_ptr *ptr; struct bch_extent_crc_unpacked crc; const union bch_extent_entry *entry; struct extent_ptr_decoded p; extent_for_each_ptr_crc(e, ptr, crc) if (ptr->dev == m.dev && ptr->gen == m.gen && (s64) ptr->offset + crc.offset - bkey_start_offset(e.k) == extent_for_each_ptr_decode(e, p, entry) if (p.ptr.dev == m.dev && p.ptr.gen == m.gen && (s64) p.ptr.offset + p.crc.offset - bkey_start_offset(e.k) == (s64) m.offset - offset) return ptr; return true; return NULL; return false; } /* Doesn't cleanup redundant crcs */ Loading Loading @@ -323,7 +323,7 @@ bool bch2_extent_narrow_crcs(struct bkey_i_extent *e, struct bch_extent_crc_unpacked n) { struct bch_extent_crc_unpacked u; struct bch_extent_ptr *ptr; struct extent_ptr_decoded p; union bch_extent_entry *i; /* Find a checksum entry that covers only live data: */ Loading @@ -345,11 +345,11 @@ bool bch2_extent_narrow_crcs(struct bkey_i_extent *e, bch2_extent_crc_append(e, n); restart_narrow_pointers: extent_for_each_ptr_crc(extent_i_to_s(e), ptr, u) if (can_narrow_crc(u, n)) { ptr->offset += u.offset; extent_ptr_append(e, *ptr); __bch2_extent_drop_ptr(extent_i_to_s(e), ptr); extent_for_each_ptr_decode(extent_i_to_s(e), p, i) if (can_narrow_crc(p.crc, n)) { i->ptr.offset += p.crc.offset; extent_ptr_append(e, i->ptr); __bch2_extent_drop_ptr(extent_i_to_s(e), &i->ptr); goto restart_narrow_pointers; } Loading Loading @@ -475,6 +475,8 @@ void bch2_ptr_swab(const struct bkey_format *f, struct bkey_packed *k) entry < (union bch_extent_entry *) (d + bkeyp_val_u64s(f, k)); entry = extent_entry_next(entry)) { switch (extent_entry_type(entry)) { case BCH_EXTENT_ENTRY_ptr: break; case BCH_EXTENT_ENTRY_crc32: entry->crc32.csum = swab32(entry->crc32.csum); break; Loading @@ -488,8 +490,6 @@ void bch2_ptr_swab(const struct bkey_format *f, struct bkey_packed *k) entry->crc128.csum.lo = (__force __le64) swab64((__force u64) entry->crc128.csum.lo); break; case BCH_EXTENT_ENTRY_ptr: break; } } break; Loading Loading @@ -605,28 +605,28 @@ static int extent_pick_read_device(struct bch_fs *c, struct bch_devs_mask *avoid, struct extent_ptr_decoded *pick) { const struct bch_extent_ptr *ptr; struct bch_extent_crc_unpacked crc; const union bch_extent_entry *entry; struct extent_ptr_decoded p; struct bch_dev *ca; int ret = 0; extent_for_each_ptr_crc(e, ptr, crc) { ca = bch_dev_bkey_exists(c, ptr->dev); extent_for_each_ptr_decode(e, p, entry) { ca = bch_dev_bkey_exists(c, p.ptr.dev); if (ptr->cached && ptr_stale(ca, ptr)) if (p.ptr.cached && ptr_stale(ca, &p.ptr)) continue; if (avoid && test_bit(ptr->dev, avoid->d)) continue; /* * XXX: need to make avoid work correctly for stripe ptrs */ if (ret && !dev_latency_better(c, ptr, &pick->ptr)) if (avoid && test_bit(p.ptr.dev, avoid->d)) continue; *pick = (struct extent_ptr_decoded) { .ptr = *ptr, .crc = crc, }; if (ret && !dev_latency_better(c, &p.ptr, &pick->ptr)) continue; *pick = p; ret = 1; } Loading fs/bcachefs/extents.h +55 −40 Original line number Diff line number Diff line Loading @@ -182,12 +182,24 @@ static inline size_t extent_entry_u64s(const union bch_extent_entry *entry) static inline bool extent_entry_is_ptr(const union bch_extent_entry *e) { return extent_entry_type(e) == BCH_EXTENT_ENTRY_ptr; switch (extent_entry_type(e)) { case BCH_EXTENT_ENTRY_ptr: return true; default: return false; } } static inline bool extent_entry_is_crc(const union bch_extent_entry *e) { return !extent_entry_is_ptr(e); switch (extent_entry_type(e)) { case BCH_EXTENT_ENTRY_crc32: case BCH_EXTENT_ENTRY_crc64: case BCH_EXTENT_ENTRY_crc128: return true; default: return false; } } union bch_extent_crc { Loading Loading @@ -310,23 +322,25 @@ bch2_extent_crc_unpack(const struct bkey *k, const union bch_extent_crc *crc) #define extent_for_each_entry(_e, _entry) \ extent_for_each_entry_from(_e, _entry, (_e).v->start) /* Iterate over crcs only: */ /* Iterate over pointers only: */ #define __extent_crc_next(_e, _p) \ #define extent_ptr_next(_e, _ptr) \ ({ \ typeof(&(_e).v->start[0]) _entry = _p; \ typeof(&(_e).v->start[0]) _entry; \ \ while ((_entry) < extent_entry_last(_e) && \ !extent_entry_is_crc(_entry)) \ (_entry) = extent_entry_next(_entry); \ extent_for_each_entry_from(_e, _entry, to_entry(_ptr)) \ if (extent_entry_is_ptr(_entry)) \ break; \ \ entry_to_crc(_entry < extent_entry_last(_e) ? _entry : NULL); \ _entry < extent_entry_last(_e) ? entry_to_ptr(_entry) : NULL; \ }) #define __extent_for_each_crc(_e, _crc) \ for ((_crc) = __extent_crc_next(_e, (_e).v->start); \ (_crc); \ (_crc) = __extent_crc_next(_e, extent_entry_next(to_entry(_crc)))) #define extent_for_each_ptr(_e, _ptr) \ for ((_ptr) = &(_e).v->start->ptr; \ ((_ptr) = extent_ptr_next(_e, _ptr)); \ (_ptr)++) /* Iterate over crcs only: */ #define extent_crc_next(_e, _crc, _iter) \ ({ \ Loading @@ -347,43 +361,44 @@ bch2_extent_crc_unpack(const struct bkey *k, const union bch_extent_crc *crc) /* Iterate over pointers, with crcs: */ #define extent_ptr_crc_next(_e, _ptr, _crc) \ static inline struct extent_ptr_decoded __extent_ptr_decoded_init(const struct bkey *k) { return (struct extent_ptr_decoded) { .crc = bch2_extent_crc_unpack(k, NULL), }; } #define EXTENT_ITERATE_EC (1 << 0) #define __extent_ptr_next_decode(_e, _ptr, _entry) \ ({ \ __label__ out; \ typeof(&(_e).v->start[0]) _entry; \ \ extent_for_each_entry_from(_e, _entry, to_entry(_ptr)) \ if (extent_entry_is_crc(_entry)) { \ (_crc) = bch2_extent_crc_unpack((_e).k, entry_to_crc(_entry));\ } else { \ _ptr = entry_to_ptr(_entry); \ extent_for_each_entry_from(_e, _entry, _entry) \ switch (extent_entry_type(_entry)) { \ case BCH_EXTENT_ENTRY_ptr: \ (_ptr).ptr = _entry->ptr; \ goto out; \ case BCH_EXTENT_ENTRY_crc32: \ case BCH_EXTENT_ENTRY_crc64: \ case BCH_EXTENT_ENTRY_crc128: \ (_ptr).crc = bch2_extent_crc_unpack((_e).k, \ entry_to_crc(_entry)); \ break; \ } \ \ _ptr = NULL; \ out: \ _ptr; \ _entry < extent_entry_last(_e); \ }) #define extent_for_each_ptr_crc(_e, _ptr, _crc) \ for ((_crc) = bch2_extent_crc_unpack((_e).k, NULL), \ (_ptr) = &(_e).v->start->ptr; \ ((_ptr) = extent_ptr_crc_next(_e, _ptr, _crc)); \ (_ptr)++) /* Iterate over pointers only, and from a given position: */ #define extent_ptr_next(_e, _ptr) \ ({ \ struct bch_extent_crc_unpacked _crc; \ \ extent_ptr_crc_next(_e, _ptr, _crc); \ }) #define extent_for_each_ptr_decode(_e, _ptr, _entry) \ for ((_ptr) = __extent_ptr_decoded_init((_e).k), \ (_entry) = (_e).v->start; \ __extent_ptr_next_decode(_e, _ptr, _entry); \ (_entry) = extent_entry_next(_entry)) #define extent_for_each_ptr(_e, _ptr) \ for ((_ptr) = &(_e).v->start->ptr; \ ((_ptr) = extent_ptr_next(_e, _ptr)); \ (_ptr)++) /* Iterate over pointers backwards: */ #define extent_ptr_prev(_e, _ptr) \ ({ \ Loading fs/bcachefs/fs-io.c +4 −4 Original line number Diff line number Diff line Loading @@ -920,12 +920,12 @@ static void bchfs_read(struct bch_fs *c, struct btree_iter *iter, if (bkey_extent_is_data(k.k)) { struct bkey_s_c_extent e = bkey_s_c_to_extent(k); struct bch_extent_crc_unpacked crc; const union bch_extent_entry *i; struct extent_ptr_decoded p; extent_for_each_crc(e, crc, i) want_full_extent |= ((crc.csum_type != 0) | (crc.compression_type != 0)); extent_for_each_ptr_decode(e, p, i) want_full_extent |= ((p.crc.csum_type != 0) | (p.crc.compression_type != 0)); } readpage_bio_extend(readpages_iter, Loading fs/bcachefs/fs.c +9 −9 Original line number Diff line number Diff line Loading @@ -1053,18 +1053,18 @@ static int bch2_fill_extent(struct fiemap_extent_info *info, { if (bkey_extent_is_data(&k->k)) { struct bkey_s_c_extent e = bkey_i_to_s_c_extent(k); const struct bch_extent_ptr *ptr; struct bch_extent_crc_unpacked crc; const union bch_extent_entry *entry; struct extent_ptr_decoded p; int ret; extent_for_each_ptr_crc(e, ptr, crc) { extent_for_each_ptr_decode(e, p, entry) { int flags2 = 0; u64 offset = ptr->offset; u64 offset = p.ptr.offset; if (crc.compression_type) if (p.crc.compression_type) flags2 |= FIEMAP_EXTENT_ENCODED; else offset += crc.offset; offset += p.crc.offset; if ((offset & (PAGE_SECTORS - 1)) || (e.k->size & (PAGE_SECTORS - 1))) Loading Loading
fs/bcachefs/buckets.c +15 −16 Original line number Diff line number Diff line Loading @@ -546,20 +546,19 @@ static int __disk_sectors(struct bch_extent_crc_unpacked crc, unsigned sectors) */ static void bch2_mark_pointer(struct bch_fs *c, struct bkey_s_c_extent e, const struct bch_extent_ptr *ptr, struct bch_extent_crc_unpacked crc, struct extent_ptr_decoded p, s64 sectors, enum bch_data_type data_type, unsigned replicas, struct bch_fs_usage *fs_usage, u64 journal_seq, unsigned flags) { struct bucket_mark old, new; struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev); struct bucket *g = PTR_BUCKET(ca, ptr); struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev); struct bucket *g = PTR_BUCKET(ca, &p.ptr); s64 uncompressed_sectors = sectors; u64 v; if (crc.compression_type) { if (p.crc.compression_type) { unsigned old_sectors, new_sectors; if (sectors > 0) { Loading @@ -570,8 +569,8 @@ static void bch2_mark_pointer(struct bch_fs *c, new_sectors = e.k->size + sectors; } sectors = -__disk_sectors(crc, old_sectors) +__disk_sectors(crc, new_sectors); sectors = -__disk_sectors(p.crc, old_sectors) +__disk_sectors(p.crc, new_sectors); } /* Loading @@ -584,8 +583,8 @@ static void bch2_mark_pointer(struct bch_fs *c, * caller's responsibility to not apply @fs_usage if gc is in progress. */ fs_usage->replicas [!ptr->cached && replicas ? replicas - 1 : 0].data [!ptr->cached ? data_type : BCH_DATA_CACHED] += [!p.ptr.cached && replicas ? replicas - 1 : 0].data [!p.ptr.cached ? data_type : BCH_DATA_CACHED] += uncompressed_sectors; if (flags & BCH_BUCKET_MARK_GC_WILL_VISIT) { Loading @@ -607,14 +606,14 @@ static void bch2_mark_pointer(struct bch_fs *c, * the allocator invalidating a bucket after we've already * checked the gen */ if (gen_after(new.gen, ptr->gen)) { if (gen_after(new.gen, p.ptr.gen)) { BUG_ON(!test_bit(BCH_FS_ALLOC_READ_DONE, &c->flags)); EBUG_ON(!ptr->cached && EBUG_ON(!p.ptr.cached && test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags)); return; } if (!ptr->cached) if (!p.ptr.cached) checked_add(new.dirty_sectors, sectors); else checked_add(new.cached_sectors, sectors); Loading Loading @@ -695,13 +694,13 @@ void bch2_mark_key(struct bch_fs *c, struct bkey_s_c k, case BCH_EXTENT: case BCH_EXTENT_CACHED: { struct bkey_s_c_extent e = bkey_s_c_to_extent(k); const struct bch_extent_ptr *ptr; struct bch_extent_crc_unpacked crc; const union bch_extent_entry *entry; struct extent_ptr_decoded p; BUG_ON(!sectors); extent_for_each_ptr_crc(e, ptr, crc) bch2_mark_pointer(c, e, ptr, crc, sectors, data_type, extent_for_each_ptr_decode(e, p, entry) bch2_mark_pointer(c, e, p, sectors, data_type, replicas, stats, journal_seq, flags); break; } Loading
fs/bcachefs/extents.c +38 −38 Original line number Diff line number Diff line Loading @@ -231,21 +231,21 @@ unsigned bch2_extent_durability(struct bch_fs *c, struct bkey_s_c_extent e) unsigned bch2_extent_is_compressed(struct bkey_s_c k) { struct bkey_s_c_extent e; const struct bch_extent_ptr *ptr; struct bch_extent_crc_unpacked crc; unsigned ret = 0; switch (k.k->type) { case BCH_EXTENT: case BCH_EXTENT_CACHED: e = bkey_s_c_to_extent(k); case BCH_EXTENT_CACHED: { struct bkey_s_c_extent e = bkey_s_c_to_extent(k); const union bch_extent_entry *entry; struct extent_ptr_decoded p; extent_for_each_ptr_crc(e, ptr, crc) if (!ptr->cached && crc.compression_type != BCH_COMPRESSION_NONE && crc.compressed_size < crc.live_size) ret = max_t(unsigned, ret, crc.compressed_size); extent_for_each_ptr_decode(e, p, entry) if (!p.ptr.cached && p.crc.compression_type != BCH_COMPRESSION_NONE && p.crc.compressed_size < p.crc.live_size) ret = max_t(unsigned, ret, p.crc.compressed_size); } } return ret; Loading @@ -254,17 +254,17 @@ unsigned bch2_extent_is_compressed(struct bkey_s_c k) bool bch2_extent_matches_ptr(struct bch_fs *c, struct bkey_s_c_extent e, struct bch_extent_ptr m, u64 offset) { const struct bch_extent_ptr *ptr; struct bch_extent_crc_unpacked crc; const union bch_extent_entry *entry; struct extent_ptr_decoded p; extent_for_each_ptr_crc(e, ptr, crc) if (ptr->dev == m.dev && ptr->gen == m.gen && (s64) ptr->offset + crc.offset - bkey_start_offset(e.k) == extent_for_each_ptr_decode(e, p, entry) if (p.ptr.dev == m.dev && p.ptr.gen == m.gen && (s64) p.ptr.offset + p.crc.offset - bkey_start_offset(e.k) == (s64) m.offset - offset) return ptr; return true; return NULL; return false; } /* Doesn't cleanup redundant crcs */ Loading Loading @@ -323,7 +323,7 @@ bool bch2_extent_narrow_crcs(struct bkey_i_extent *e, struct bch_extent_crc_unpacked n) { struct bch_extent_crc_unpacked u; struct bch_extent_ptr *ptr; struct extent_ptr_decoded p; union bch_extent_entry *i; /* Find a checksum entry that covers only live data: */ Loading @@ -345,11 +345,11 @@ bool bch2_extent_narrow_crcs(struct bkey_i_extent *e, bch2_extent_crc_append(e, n); restart_narrow_pointers: extent_for_each_ptr_crc(extent_i_to_s(e), ptr, u) if (can_narrow_crc(u, n)) { ptr->offset += u.offset; extent_ptr_append(e, *ptr); __bch2_extent_drop_ptr(extent_i_to_s(e), ptr); extent_for_each_ptr_decode(extent_i_to_s(e), p, i) if (can_narrow_crc(p.crc, n)) { i->ptr.offset += p.crc.offset; extent_ptr_append(e, i->ptr); __bch2_extent_drop_ptr(extent_i_to_s(e), &i->ptr); goto restart_narrow_pointers; } Loading Loading @@ -475,6 +475,8 @@ void bch2_ptr_swab(const struct bkey_format *f, struct bkey_packed *k) entry < (union bch_extent_entry *) (d + bkeyp_val_u64s(f, k)); entry = extent_entry_next(entry)) { switch (extent_entry_type(entry)) { case BCH_EXTENT_ENTRY_ptr: break; case BCH_EXTENT_ENTRY_crc32: entry->crc32.csum = swab32(entry->crc32.csum); break; Loading @@ -488,8 +490,6 @@ void bch2_ptr_swab(const struct bkey_format *f, struct bkey_packed *k) entry->crc128.csum.lo = (__force __le64) swab64((__force u64) entry->crc128.csum.lo); break; case BCH_EXTENT_ENTRY_ptr: break; } } break; Loading Loading @@ -605,28 +605,28 @@ static int extent_pick_read_device(struct bch_fs *c, struct bch_devs_mask *avoid, struct extent_ptr_decoded *pick) { const struct bch_extent_ptr *ptr; struct bch_extent_crc_unpacked crc; const union bch_extent_entry *entry; struct extent_ptr_decoded p; struct bch_dev *ca; int ret = 0; extent_for_each_ptr_crc(e, ptr, crc) { ca = bch_dev_bkey_exists(c, ptr->dev); extent_for_each_ptr_decode(e, p, entry) { ca = bch_dev_bkey_exists(c, p.ptr.dev); if (ptr->cached && ptr_stale(ca, ptr)) if (p.ptr.cached && ptr_stale(ca, &p.ptr)) continue; if (avoid && test_bit(ptr->dev, avoid->d)) continue; /* * XXX: need to make avoid work correctly for stripe ptrs */ if (ret && !dev_latency_better(c, ptr, &pick->ptr)) if (avoid && test_bit(p.ptr.dev, avoid->d)) continue; *pick = (struct extent_ptr_decoded) { .ptr = *ptr, .crc = crc, }; if (ret && !dev_latency_better(c, &p.ptr, &pick->ptr)) continue; *pick = p; ret = 1; } Loading
fs/bcachefs/extents.h +55 −40 Original line number Diff line number Diff line Loading @@ -182,12 +182,24 @@ static inline size_t extent_entry_u64s(const union bch_extent_entry *entry) static inline bool extent_entry_is_ptr(const union bch_extent_entry *e) { return extent_entry_type(e) == BCH_EXTENT_ENTRY_ptr; switch (extent_entry_type(e)) { case BCH_EXTENT_ENTRY_ptr: return true; default: return false; } } static inline bool extent_entry_is_crc(const union bch_extent_entry *e) { return !extent_entry_is_ptr(e); switch (extent_entry_type(e)) { case BCH_EXTENT_ENTRY_crc32: case BCH_EXTENT_ENTRY_crc64: case BCH_EXTENT_ENTRY_crc128: return true; default: return false; } } union bch_extent_crc { Loading Loading @@ -310,23 +322,25 @@ bch2_extent_crc_unpack(const struct bkey *k, const union bch_extent_crc *crc) #define extent_for_each_entry(_e, _entry) \ extent_for_each_entry_from(_e, _entry, (_e).v->start) /* Iterate over crcs only: */ /* Iterate over pointers only: */ #define __extent_crc_next(_e, _p) \ #define extent_ptr_next(_e, _ptr) \ ({ \ typeof(&(_e).v->start[0]) _entry = _p; \ typeof(&(_e).v->start[0]) _entry; \ \ while ((_entry) < extent_entry_last(_e) && \ !extent_entry_is_crc(_entry)) \ (_entry) = extent_entry_next(_entry); \ extent_for_each_entry_from(_e, _entry, to_entry(_ptr)) \ if (extent_entry_is_ptr(_entry)) \ break; \ \ entry_to_crc(_entry < extent_entry_last(_e) ? _entry : NULL); \ _entry < extent_entry_last(_e) ? entry_to_ptr(_entry) : NULL; \ }) #define __extent_for_each_crc(_e, _crc) \ for ((_crc) = __extent_crc_next(_e, (_e).v->start); \ (_crc); \ (_crc) = __extent_crc_next(_e, extent_entry_next(to_entry(_crc)))) #define extent_for_each_ptr(_e, _ptr) \ for ((_ptr) = &(_e).v->start->ptr; \ ((_ptr) = extent_ptr_next(_e, _ptr)); \ (_ptr)++) /* Iterate over crcs only: */ #define extent_crc_next(_e, _crc, _iter) \ ({ \ Loading @@ -347,43 +361,44 @@ bch2_extent_crc_unpack(const struct bkey *k, const union bch_extent_crc *crc) /* Iterate over pointers, with crcs: */ #define extent_ptr_crc_next(_e, _ptr, _crc) \ static inline struct extent_ptr_decoded __extent_ptr_decoded_init(const struct bkey *k) { return (struct extent_ptr_decoded) { .crc = bch2_extent_crc_unpack(k, NULL), }; } #define EXTENT_ITERATE_EC (1 << 0) #define __extent_ptr_next_decode(_e, _ptr, _entry) \ ({ \ __label__ out; \ typeof(&(_e).v->start[0]) _entry; \ \ extent_for_each_entry_from(_e, _entry, to_entry(_ptr)) \ if (extent_entry_is_crc(_entry)) { \ (_crc) = bch2_extent_crc_unpack((_e).k, entry_to_crc(_entry));\ } else { \ _ptr = entry_to_ptr(_entry); \ extent_for_each_entry_from(_e, _entry, _entry) \ switch (extent_entry_type(_entry)) { \ case BCH_EXTENT_ENTRY_ptr: \ (_ptr).ptr = _entry->ptr; \ goto out; \ case BCH_EXTENT_ENTRY_crc32: \ case BCH_EXTENT_ENTRY_crc64: \ case BCH_EXTENT_ENTRY_crc128: \ (_ptr).crc = bch2_extent_crc_unpack((_e).k, \ entry_to_crc(_entry)); \ break; \ } \ \ _ptr = NULL; \ out: \ _ptr; \ _entry < extent_entry_last(_e); \ }) #define extent_for_each_ptr_crc(_e, _ptr, _crc) \ for ((_crc) = bch2_extent_crc_unpack((_e).k, NULL), \ (_ptr) = &(_e).v->start->ptr; \ ((_ptr) = extent_ptr_crc_next(_e, _ptr, _crc)); \ (_ptr)++) /* Iterate over pointers only, and from a given position: */ #define extent_ptr_next(_e, _ptr) \ ({ \ struct bch_extent_crc_unpacked _crc; \ \ extent_ptr_crc_next(_e, _ptr, _crc); \ }) #define extent_for_each_ptr_decode(_e, _ptr, _entry) \ for ((_ptr) = __extent_ptr_decoded_init((_e).k), \ (_entry) = (_e).v->start; \ __extent_ptr_next_decode(_e, _ptr, _entry); \ (_entry) = extent_entry_next(_entry)) #define extent_for_each_ptr(_e, _ptr) \ for ((_ptr) = &(_e).v->start->ptr; \ ((_ptr) = extent_ptr_next(_e, _ptr)); \ (_ptr)++) /* Iterate over pointers backwards: */ #define extent_ptr_prev(_e, _ptr) \ ({ \ Loading
fs/bcachefs/fs-io.c +4 −4 Original line number Diff line number Diff line Loading @@ -920,12 +920,12 @@ static void bchfs_read(struct bch_fs *c, struct btree_iter *iter, if (bkey_extent_is_data(k.k)) { struct bkey_s_c_extent e = bkey_s_c_to_extent(k); struct bch_extent_crc_unpacked crc; const union bch_extent_entry *i; struct extent_ptr_decoded p; extent_for_each_crc(e, crc, i) want_full_extent |= ((crc.csum_type != 0) | (crc.compression_type != 0)); extent_for_each_ptr_decode(e, p, i) want_full_extent |= ((p.crc.csum_type != 0) | (p.crc.compression_type != 0)); } readpage_bio_extend(readpages_iter, Loading
fs/bcachefs/fs.c +9 −9 Original line number Diff line number Diff line Loading @@ -1053,18 +1053,18 @@ static int bch2_fill_extent(struct fiemap_extent_info *info, { if (bkey_extent_is_data(&k->k)) { struct bkey_s_c_extent e = bkey_i_to_s_c_extent(k); const struct bch_extent_ptr *ptr; struct bch_extent_crc_unpacked crc; const union bch_extent_entry *entry; struct extent_ptr_decoded p; int ret; extent_for_each_ptr_crc(e, ptr, crc) { extent_for_each_ptr_decode(e, p, entry) { int flags2 = 0; u64 offset = ptr->offset; u64 offset = p.ptr.offset; if (crc.compression_type) if (p.crc.compression_type) flags2 |= FIEMAP_EXTENT_ENCODED; else offset += crc.offset; offset += p.crc.offset; if ((offset & (PAGE_SECTORS - 1)) || (e.k->size & (PAGE_SECTORS - 1))) Loading