From: lishuhao Date: Sun, 14 Apr 2019 00:36:24 +0000 (+0800) Subject: osd: define ObjectCleanRegions for recovery object X-Git-Tag: v15.1.0~2697^2~15 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3a8164ac353f3a9463c06e71b9f38f8a6b59236b;p=ceph.git osd: define ObjectCleanRegions for recovery object Signed-off-by: Ning Yao Signed-off-by: lishuhao --- diff --git a/src/osd/osd_types.cc b/src/osd/osd_types.cc index 5d329b3a40c..1b6971b332b 100644 --- a/src/osd/osd_types.cc +++ b/src/osd/osd_types.cc @@ -4275,6 +4275,118 @@ void ObjectModDesc::decode(ceph::buffer::list::const_iterator &_bl) DECODE_FINISH(_bl); } +void ObjectCleanRegions::trim() +{ + while(clean_offsets.num_intervals() > max_num_intervals) { + typename interval_set::iterator shortest_interval = clean_offsets.begin(); + if (shortest_interval == clean_offsets.end()) + break; + for (typename interval_set::iterator it = clean_offsets.begin(); + it != clean_offsets.end(); + ++it) { + if (it.get_len() < shortest_interval.get_len()) + shortest_interval = it; + } + clean_offsets.erase(shortest_interval); + } +} + +void ObjectCleanRegions::merge(const ObjectCleanRegions &other) +{ + clean_offsets.intersection_of(other.clean_offsets); + clean_omap = clean_omap && other.clean_omap; + trim(); +} + +void ObjectCleanRegions::mark_data_region_dirty(uint64_t offset, uint64_t len) +{ + interval_set clean_region; + clean_region.insert(0, (uint64_t)-1); + clean_region.erase(offset, len); + clean_offsets.intersection_of(clean_region); + trim(); +} + +void ObjectCleanRegions::mark_omap_dirty() +{ + clean_omap = false; +} + +void ObjectCleanRegions::mark_object_new() +{ + new_object = true; +} + +void ObjectCleanRegions::mark_fully_dirty() +{ + mark_data_region_dirty(0, (uint64_t)-1); + mark_omap_dirty(); + mark_object_new(); +} + +interval_set ObjectCleanRegions::get_dirty_regions() const +{ + interval_set dirty_region; + dirty_region.insert(0, (uint64_t)-1); + dirty_region.subtract(clean_offsets); + return dirty_region; +} + +bool ObjectCleanRegions::omap_is_dirty() const +{ + return !clean_omap; +} + +bool ObjectCleanRegions::object_is_exist() const +{ + return !new_object; +} + +void ObjectCleanRegions::encode(bufferlist &bl) const +{ + ENCODE_START(1, 1, bl); + using ceph::encode; + encode(clean_offsets, bl); + encode(clean_omap, bl); + encode(new_object, bl); + ENCODE_FINISH(bl); +} + +void ObjectCleanRegions::decode(bufferlist::const_iterator &bl) +{ + DECODE_START(1, bl); + using ceph::decode; + decode(clean_offsets, bl); + decode(clean_omap, bl); + decode(new_object, bl); + DECODE_FINISH(bl); +} + +void ObjectCleanRegions::dump(Formatter *f) const +{ + f->open_object_section("object_clean_regions"); + f->dump_stream("clean_offsets") << clean_offsets; + f->dump_bool("clean_omap", clean_omap); + f->dump_bool("object_new", new_object); + f->close_section(); +} + +void ObjectCleanRegions::generate_test_instances(list& o) +{ + o.push_back(new ObjectCleanRegions()); + o.push_back(new ObjectCleanRegions()); + o.back()->mark_data_region_dirty(4096, 40960); + o.back()->mark_omap_dirty(); + o.back()->mark_object_new(); +} + +ostream& operator<<(ostream& out, const ObjectCleanRegions& ocr) +{ + return out << "clean_offsets: " << ocr.clean_offsets + << ", clean_omap: " << ocr.clean_omap + << ", object_new: " << ocr.new_object; +} + // -- pg_log_entry_t -- string pg_log_entry_t::get_key_name() const diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h index f856e63101e..83addc9463a 100644 --- a/src/osd/osd_types.h +++ b/src/osd/osd_types.h @@ -108,6 +108,8 @@ /// priority when more full #define OSD_DELETE_PRIORITY_FULL 255 +/// max intervals for clean_offsets in ObjectCleanRegions +#define OSD_CLEAN_OFFSETS_MAX_INTERVALS 10 static std::map max_prio_map = { {OSD_BACKFILL_PRIORITY_BASE, OSD_BACKFILL_DEGRADED_PRIORITY_BASE - 1}, {OSD_BACKFILL_DEGRADED_PRIORITY_BASE, OSD_RECOVERY_PRIORITY_BASE - 1}, @@ -3744,6 +3746,51 @@ public: }; WRITE_CLASS_ENCODER(ObjectModDesc) +class ObjectCleanRegions { +private: + interval_set clean_offsets; + bool clean_omap; + bool new_object; + int32_t max_num_intervals; + + /** + * trim the number of intervals if clean_offsets.num_intervals() + * exceeds the given upbound max_num_intervals + * etc. max_num_intervals=2, clean_offsets:{[5~10], [20~5]} + * then new interval [30~10] will evict out the shortest one [20~5] + * finally, clean_offsets becomes {[5~10], [30~10]} + */ + void trim(); + friend ostream& operator<<(ostream& out, const ObjectCleanRegions& ocr); +public: + ObjectCleanRegions(int32_t max = OSD_CLEAN_OFFSETS_MAX_INTERVALS) : new_object(false), max_num_intervals(max) { + clean_offsets.insert(0, (uint64_t)-1); + clean_omap = true; + } + ObjectCleanRegions(uint64_t offset, uint64_t len, bool co, int32_t max = OSD_CLEAN_OFFSETS_MAX_INTERVALS) + : clean_omap(co), new_object(false), max_num_intervals(max) { + clean_offsets.insert(offset, len); + } + bool operator==(const ObjectCleanRegions &orc) const { + return clean_offsets == orc.clean_offsets && clean_omap == orc.clean_omap && max_num_intervals == orc.max_num_intervals; + } + + void merge(const ObjectCleanRegions &other); + void mark_data_region_dirty(uint64_t offset, uint64_t len); + void mark_omap_dirty(); + void mark_object_new(); + void mark_fully_dirty(); + interval_set get_dirty_regions() const; + bool omap_is_dirty() const; + bool object_is_exist() const; + + void encode(bufferlist &bl) const; + void decode(bufferlist::const_iterator &bl); + void dump(Formatter *f) const; + static void generate_test_instances(list& o); +}; +WRITE_CLASS_ENCODER(ObjectCleanRegions) +ostream& operator<<(ostream& out, const ObjectCleanRegions& ocr); /** * pg_log_entry_t - single entry/event in pg log