From 2665d243f2cd543e74f670ad32aea23bf63d906c Mon Sep 17 00:00:00 2001 From: Matan Breizman Date: Sun, 19 May 2024 13:30:50 +0000 Subject: [PATCH] mon/OSDMonitor: Add force-remove-snap mon command ``` * Forces removal of snapshots in the range of * [lower_snapid_bound, upper_snapid_bound) on pool * in order to cause OSDs to re-trim them. * The command has two mutually exclusive variants: * * Default: All the snapids in the given range which are not * marked as purged in the Monitor will be removed. Mostly useful * for cases in which the snapid is leaked in the client side. * See: https://tracker.ceph.com/issues/64646 ``` Fixes: https://tracker.ceph.com/issues/66122 Signed-off-by: Matan Breizman (cherry picked from commit 6855b049fb38bdb5b15bc1429a7c2e23daccd5ca) --- src/mon/MonCommands.h | 9 +++++ src/mon/OSDMonitor.cc | 94 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index 151ddb83d4f..890f378b3e2 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -1096,6 +1096,15 @@ COMMAND("osd pool rmsnap " "name=pool,type=CephPoolname " "name=snap,type=CephString", "remove snapshot from ", "osd", "rw") +COMMAND("osd pool force-remove-snap " + "name=pool,type=CephPoolname " + "name=lower_snapid_bound,type=CephInt,range=0,req=false " + "name=upper_snapid_bound,type=CephInt,range=0,req=false " + "name=dry_run,type=CephBool,req=false ", + "Forces removal of snapshots in the range " + "[lower_snapid_bound, upper_snapid_bound) on pool in " + "order to cause OSDs to re-trim them.", + "osd", "rw") COMMAND("osd pool ls " "name=detail,type=CephChoices,strings=detail,req=false", "list pools", "osd", "r") diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index 6543da85c44..c751bc5fbed 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -13096,6 +13096,100 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, 0, rs, get_last_committed() + 1)); return true; + } else if (prefix == "osd pool force-remove-snap") { + /* + * Forces removal of snapshots in the range of + * [lower_snapid_bound, upper_snapid_bound) on pool + * in order to cause OSDs to re-trim them. + * The command has two mutually exclusive variants: + * * Default: All the snapids in the given range which are not + * marked as purged in the Monitor will be removed. Mostly useful + * for cases in which the snapid is leaked in the client side. + * See: https://tracker.ceph.com/issues/64646 + */ + string poolstr; + cmd_getval(cmdmap, "pool", poolstr); + int64_t pool = osdmap.lookup_pg_pool_name(poolstr.c_str()); + if (pool < 0) { + ss << "unrecognized pool '" << poolstr << "'"; + err = -ENOENT; + goto reply_no_propose; + } + + const pg_pool_t *p = osdmap.get_pg_pool(pool); + pg_pool_t *pp = nullptr; + if (pending_inc.new_pools.count(pool)) + pp = &pending_inc.new_pools[pool]; + if (!pp) { + pp = &pending_inc.new_pools[pool]; + *pp = *p; + } + + if (!p->is_unmanaged_snaps_mode() && !p->is_pool_snaps_mode()) { + ss << "pool " << poolstr << " invalid snaps mode"; + err = -EINVAL; + goto reply_no_propose; + } + + int64_t lower_snapid_bound = + cmd_getval_or(cmdmap, "lower_snapid_bound", 1); + int64_t upper_snapid_bound = + cmd_getval_or(cmdmap, "upper_snapid_bound", + (int64_t)p->get_snap_seq()); + + if (lower_snapid_bound > upper_snapid_bound) { + ss << "error, lower bound can't be higher than higher bound"; + err = -ENOENT; + goto reply_no_propose; + } + + bool dry_run = false; + cmd_getval(cmdmap, "dry_run", dry_run); + + // don't redelete past pool's snap_seq + auto snapid_limit = std::min(upper_snapid_bound, (int64_t)p->get_snap_seq()); + + if (dry_run) { + ss << "Dry run: "; + } + + ss << "force removing snap ids in the range of [" << lower_snapid_bound << "," + << snapid_limit << ") from pool " << pool << ". "; + + std::set force_removed_snapids; + for (auto i = lower_snapid_bound; i < snapid_limit; i++) { + snapid_t before_begin, before_end; + int res = lookup_purged_snap(pool, i, &before_begin, &before_end); + if (res == 0) { + ss << "snapids: " << i << " was already marked as purged. "; + } else { + // Remove non purged_snaps + // See: https://tracker.ceph.com/issues/64646 + force_removed_snapids.insert(i); + } + } + + for (const auto i : force_removed_snapids) { + if (!dry_run) { + pending_inc.new_removed_snaps[pool].insert(snapid_t(i)); + } + } + + if (force_removed_snapids.size()) { + ss << "removed snapids: " << force_removed_snapids; + } else { + ss << "no snapshots were removed"; + } + + if (dry_run) { + err = 0; + goto reply_no_propose; + } + pp->set_snap_epoch(pending_inc.epoch); + getline(ss, rs); + wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, 0, rs, + get_last_committed() + 1)); + return true; } else if (prefix == "osd pool create") { int64_t pg_num = cmd_getval_or(cmdmap, "pg_num", 0); int64_t pg_num_min = cmd_getval_or(cmdmap, "pg_num_min", 0); -- 2.39.5