/*
* we have two snap modes:
- * - pool global snaps
+ * - pool snaps
* - snap existence/non-existence defined by snaps[] and snap_seq
* - user managed snaps
- * - removal governed by removed_snaps
- *
- * we know which mode we're using based on whether removed_snaps is empty.
+ * - existence tracked by librados user
*/
bool pg_pool_t::is_pool_snaps_mode() const
{
- return removed_snaps.empty() && get_snap_seq() > 0;
+ return has_flag(FLAG_POOL_SNAPS);
}
bool pg_pool_t::is_unmanaged_snaps_mode() const
{
- return removed_snaps.size() && get_snap_seq() > 0;
+ return has_flag(FLAG_SELFMANAGED_SNAPS);
}
bool pg_pool_t::is_removed_snap(snapid_t s) const
void pg_pool_t::add_snap(const char *n, utime_t stamp)
{
assert(!is_unmanaged_snaps_mode());
+ flags |= FLAG_POOL_SNAPS;
snapid_t s = get_snap_seq() + 1;
snap_seq = s;
snaps[s].snapid = s;
void pg_pool_t::add_unmanaged_snap(uint64_t& snapid)
{
- if (removed_snaps.empty()) {
- assert(!is_pool_snaps_mode());
+ assert(!is_pool_snaps_mode());
+ if (snap_seq == 0) {
+ // kludge for pre-mimic tracking of pool vs selfmanaged snaps. after
+ // mimic this field is not decoded but our flag is set; pre-mimic, we
+ // have a non-empty removed_snaps to signifiy a non-pool-snaps pool.
removed_snaps.insert(snapid_t(1));
snap_seq = 1;
}
+ flags |= FLAG_SELFMANAGED_SNAPS;
snapid = snap_seq = snap_seq + 1;
}
::encode(snaps, bl, features);
::encode(removed_snaps, bl);
::encode(auid, bl);
- ::encode(flags, bl);
+ if (v >= 27) {
+ ::encode(flags, bl);
+ } else {
+ auto tmp = flags;
+ tmp &= ~(FLAG_SELFMANAGED_SNAPS | FLAG_POOL_SNAPS);
+ ::encode(tmp, bl);
+ }
::encode((uint32_t)0, bl); // crash_replay_interval
::encode(min_size, bl);
::encode(quota_max_bytes, bl);
} else {
flags = 0;
}
+ // upgrade path for selfmanaged vs pool snaps
+ if (snap_seq > 0 && (flags & (FLAG_SELFMANAGED_SNAPS|FLAG_POOL_SNAPS)) == 0) {
+ if (!removed_snaps.empty()) {
+ flags |= FLAG_SELFMANAGED_SNAPS;
+ } else {
+ flags |= FLAG_POOL_SNAPS;
+ }
+ }
if (struct_v >= 7) {
::decode(min_size, bl);
} else {
a.last_force_op_resend_preluminous = 123824;
a.snap_seq = 10;
a.snap_epoch = 11;
+ a.flags = FLAG_POOL_SNAPS;
a.auid = 12;
a.quota_max_bytes = 473;
a.quota_max_objects = 474;
a.snaps[6].stamp = utime_t(23423, 4);
o.push_back(new pg_pool_t(a));
- a.removed_snaps.insert(2); // not quite valid to combine with snaps!
+ a.flags = FLAG_SELFMANAGED_SNAPS;
+ a.snaps.clear();
+ a.removed_snaps.insert(2);
a.quota_max_bytes = 2473;
a.quota_max_objects = 4374;
a.tiers.insert(0);
FLAG_FULL_QUOTA = 1<<10, // pool is currently running out of quota, will set FLAG_FULL too
FLAG_NEARFULL = 1<<11, // pool is nearfull
FLAG_BACKFILLFULL = 1<<12, // pool is backfillfull
+ FLAG_SELFMANAGED_SNAPS = 1<<13, // pool uses selfmanaged snaps
+ FLAG_POOL_SNAPS = 1<<14, // pool has pool snaps
};
static const char *get_flag_name(int f) {
case FLAG_FULL_QUOTA: return "full_quota";
case FLAG_NEARFULL: return "nearfull";
case FLAG_BACKFILLFULL: return "backfillfull";
+ case FLAG_SELFMANAGED_SNAPS: return "selfmanaged_snaps";
+ case FLAG_POOL_SNAPS: return "pool_snaps";
default: return "???";
}
}
return FLAG_NEARFULL;
if (name == "backfillfull")
return FLAG_BACKFILLFULL;
+ if (name == "selfmanaged_snaps")
+ return FLAG_SELFMANAGED_SNAPS;
+ if (name == "pool_snaps")
+ return FLAG_POOL_SNAPS;
return 0;
}