OPTION(osd_min_pg_log_entries, OPT_U32) // number of entries to keep in the pg log when trimming it
OPTION(osd_max_pg_log_entries, OPT_U32) // max entries, say when degraded, before we trim
OPTION(osd_pg_log_dups_tracked, OPT_U32) // how many versions back to track combined in both pglog's regular + dup logs
+OPTION(osd_object_clean_region_max_num_intervals, OPT_INT) // number of intervals in clean_offsets
OPTION(osd_force_recovery_pg_log_entries_factor, OPT_FLOAT) // max entries factor before force recovery
OPTION(osd_pg_log_trim_min, OPT_U32)
OPTION(osd_pg_log_trim_max, OPT_U32)
.add_see_also("osd_min_pg_log_entries")
.add_see_also("osd_max_pg_log_entries"),
+ Option("osd_object_clean_region_max_num_intervals", Option::TYPE_INT, Option::LEVEL_ADVANCED)
+ .set_default(10)
+ .set_description("number of intervals in clean_offsets")
+ .set_long_description("partial recovery uses multiple intervals to record the clean part of the object"
+ "when the number of intervals is greater than osd_object_clean_region_max_num_intervals, minimum interval will be trimmed"
+ "(0 will recovery the entire object data interval)")
+ .add_service("osd"),
+
Option("osd_force_recovery_pg_log_entries_factor", Option::TYPE_FLOAT, Option::LEVEL_ADVANCED)
.set_default(1.3)
.set_description(""),
cct->_conf->osd_op_history_duration);
op_tracker.set_history_slow_op_size_and_threshold(cct->_conf->osd_op_history_slow_op_size,
cct->_conf->osd_op_history_slow_op_threshold);
+ ObjectCleanRegions::set_max_num_intervals(cct->_conf->osd_object_clean_region_max_num_intervals);
#ifdef WITH_BLKIN
std::stringstream ss;
ss << "osd." << whoami;
"osd_client_message_cap",
"osd_heartbeat_min_size",
"osd_heartbeat_interval",
+ "osd_object_clean_region_max_num_intervals",
NULL
};
return KEYS;
pol.throttler_bytes->reset_max(newval);
}
}
+ if (changed.count("osd_object_clean_region_max_num_intervals")) {
+ ObjectCleanRegions::set_max_num_intervals(cct->_conf->osd_object_clean_region_max_num_intervals);
+ }
check_config();
}
<< " is not > osd_pg_epoch_persisted_max_stale ("
<< cct->_conf->osd_pg_epoch_persisted_max_stale << ")";
}
+ if (cct->_conf->osd_object_clean_region_max_num_intervals < 0) {
+ clog->warn() << "osd_object_clean_region_max_num_intervals ("
+ << cct->_conf->osd_object_clean_region_max_num_intervals
+ << ") is < 0";
+ }
}
// --------------------------------
}
#include "common/Formatter.h"
-
#include "OSDMap.h"
#include "osd_types.h"
DECODE_FINISH(_bl);
}
+std::atomic<int32_t> ObjectCleanRegions::max_num_intervals = {10};
+
+void ObjectCleanRegions::set_max_num_intervals(int32_t num)
+{
+ max_num_intervals = num;
+}
+
void ObjectCleanRegions::trim()
{
while(clean_offsets.num_intervals() > max_num_intervals) {
/// 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<int, int> max_prio_map = {
{OSD_BACKFILL_PRIORITY_BASE, OSD_BACKFILL_DEGRADED_PRIORITY_BASE - 1},
{OSD_BACKFILL_DEGRADED_PRIORITY_BASE, OSD_RECOVERY_PRIORITY_BASE - 1},
class ObjectCleanRegions {
private:
- interval_set<uint64_t> clean_offsets;
- bool clean_omap;
bool new_object;
- int32_t max_num_intervals;
+ bool clean_omap;
+ interval_set<uint64_t> clean_offsets;
+ static std::atomic<int32_t> max_num_intervals;
/**
* trim the number of intervals if clean_offsets.num_intervals()
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) {
+ ObjectCleanRegions() : new_object(false), clean_omap(true) {
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) {
+ ObjectCleanRegions(uint64_t offset, uint64_t len, bool co)
+ : new_object(false), clean_omap(co) {
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 && new_object == orc.new_object;
+ return new_object == orc.new_object && clean_omap == orc.clean_omap && clean_offsets == orc.clean_offsets;
}
-
+ static void set_max_num_intervals(int32_t num);
void merge(const ObjectCleanRegions &other);
void mark_data_region_dirty(uint64_t offset, uint64_t len);
void mark_omap_dirty();
void encode(bufferlist &bl) const;
void decode(bufferlist::const_iterator &bl);
void dump(Formatter *f) const;
- static void generate_test_instances(list<ObjectCleanRegions*>& o);
+ static void generate_test_instances(list<ObjectCleanRegions*>& o);
};
WRITE_CLASS_ENCODER(ObjectCleanRegions)
ostream& operator<<(ostream& out, const ObjectCleanRegions& ocr);
#include "common/Thread.h"
#include "include/stringify.h"
#include "osd/ReplicatedBackend.h"
-
#include <sstream>
TEST(hobject, prefixes0)
TEST(ObjectCleanRegions, merge)
{
- ObjectCleanRegions cr1(2), cr2(4);
+ ObjectCleanRegions cr1, cr2;
interval_set<uint64_t> cr1_expect;
interval_set<uint64_t> cr2_expect;
ASSERT_EQ(cr1_expect, cr1.get_dirty_regions());