mirror of
https://github.com/ceph/ceph
synced 2026-08-02 07:03:18 +00:00
rgw: Implement support for --shard-id in radosgw-admin's gc process and gc list commands
This allows operators to do targeted GC work against specific shards, instead of working on all of them. Signed-off-by: Nathan Hoad <nhoad@bloomberg.net> AI-Assisted: Used AI to generate the initial implementation.
This commit is contained in:
parent
e317e86c8e
commit
12efa485f5
@ -639,7 +639,7 @@ Options
|
||||
|
||||
.. option:: --shard-id=<shard-id>
|
||||
|
||||
Optional for mdlog list, bi list, data sync status. Required for ``mdlog trim``.
|
||||
Optional for mdlog list, bi list, data sync status, gc list, gc process. Required for ``mdlog trim``.
|
||||
|
||||
.. option:: --max-entries=<entries>
|
||||
|
||||
|
||||
@ -175,13 +175,18 @@ static int gc_list(const DoutPrefixProvider* dpp, optional_yield y, librados::Io
|
||||
return cls_rgw_gc_list_decode(bl, entries, truncated, next_marker);
|
||||
}
|
||||
|
||||
int RGWGC::list(int *index, string& marker, uint32_t max, bool expired_only, std::list<cls_rgw_gc_obj_info>& result, bool *truncated, bool& processing_queue)
|
||||
int RGWGC::list(int *index, string& marker, uint32_t max, bool expired_only, std::list<cls_rgw_gc_obj_info>& result, bool *truncated, bool& processing_queue, std::optional<int> shard_id)
|
||||
{
|
||||
result.clear();
|
||||
string next_marker;
|
||||
bool check_queue = false;
|
||||
|
||||
for (; *index < max_objs && result.size() < max; (*index)++, marker.clear(), check_queue = false) {
|
||||
int max_index = shard_id.has_value() ? (shard_id.value() + 1) : max_objs;
|
||||
if (shard_id.has_value()) {
|
||||
*index = shard_id.value();
|
||||
}
|
||||
|
||||
for (; *index < max_index && result.size() < max; (*index)++, marker.clear(), check_queue = false) {
|
||||
std::list<cls_rgw_gc_obj_info> entries, queue_entries;
|
||||
int ret = 0;
|
||||
|
||||
@ -236,7 +241,7 @@ int RGWGC::list(int *index, string& marker, uint32_t max, bool expired_only, std
|
||||
|
||||
marker = next_marker;
|
||||
|
||||
if (*index == max_objs - 1) {
|
||||
if (*index == max_index - 1) {
|
||||
if (queue_entries.size() > 0 && *truncated) {
|
||||
processing_queue = true;
|
||||
} else {
|
||||
@ -655,19 +660,26 @@ done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RGWGC::process(bool expired_only, optional_yield y)
|
||||
int RGWGC::process(bool expired_only, optional_yield y, std::optional<int> shard_id)
|
||||
{
|
||||
int max_secs = cct->_conf->rgw_gc_processor_max_time;
|
||||
|
||||
const int start = ceph::util::generate_random_number(0, max_objs - 1);
|
||||
|
||||
RGWGCIOManager io_manager(this, store->ctx(), this);
|
||||
|
||||
for (int i = 0; i < max_objs; i++) {
|
||||
int index = (i + start) % max_objs;
|
||||
int ret = process(index, max_secs, expired_only, io_manager, y);
|
||||
if (shard_id.has_value()) {
|
||||
// Process only the specified shard
|
||||
int ret = process(shard_id.value(), max_secs, expired_only, io_manager, y);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
// Process all shards with random start
|
||||
const int start = ceph::util::generate_random_number(0, max_objs - 1);
|
||||
for (int i = 0; i < max_objs; i++) {
|
||||
int index = (i + start) % max_objs;
|
||||
int ret = process(index, max_secs, expired_only, io_manager, y);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (!going_down()) {
|
||||
io_manager.drain();
|
||||
|
||||
@ -59,11 +59,10 @@ public:
|
||||
void initialize(CephContext *_cct, RGWRados *_store, optional_yield y);
|
||||
void finalize();
|
||||
|
||||
int list(int *index, std::string& marker, uint32_t max, bool expired_only, std::list<cls_rgw_gc_obj_info>& result, bool *truncated, bool& processing_queue);
|
||||
void list_init(int *index) { *index = 0; }
|
||||
int list(int *index, std::string& marker, uint32_t max, bool expired_only, std::list<cls_rgw_gc_obj_info>& result, bool *truncated, bool& processing_queue, std::optional<int> shard_id = std::nullopt);
|
||||
int process(int index, int process_max_secs, bool expired_only,
|
||||
RGWGCIOManager& io_manager, optional_yield y);
|
||||
int process(bool expired_only, optional_yield y);
|
||||
int process(bool expired_only, optional_yield y, std::optional<int> shard_id = std::nullopt);
|
||||
|
||||
bool going_down();
|
||||
void start_processor();
|
||||
|
||||
@ -10635,14 +10635,14 @@ int RGWRados::gc_operate(const DoutPrefixProvider *dpp, string& oid, librados::O
|
||||
return rgw_rados_operate(dpp, gc_pool_ctx, oid, std::move(op), pbl, y);
|
||||
}
|
||||
|
||||
int RGWRados::list_gc_objs(int *index, string& marker, uint32_t max, bool expired_only, std::list<cls_rgw_gc_obj_info>& result, bool *truncated, bool& processing_queue)
|
||||
int RGWRados::list_gc_objs(int *index, string& marker, uint32_t max, bool expired_only, std::list<cls_rgw_gc_obj_info>& result, bool *truncated, bool& processing_queue, std::optional<int> shard_id)
|
||||
{
|
||||
return gc->list(index, marker, max, expired_only, result, truncated, processing_queue);
|
||||
return gc->list(index, marker, max, expired_only, result, truncated, processing_queue, shard_id);
|
||||
}
|
||||
|
||||
int RGWRados::process_gc(bool expired_only, optional_yield y)
|
||||
int RGWRados::process_gc(bool expired_only, optional_yield y, std::optional<int> shard_id)
|
||||
{
|
||||
return gc->process(expired_only, y);
|
||||
return gc->process(expired_only, y, shard_id);
|
||||
}
|
||||
|
||||
int RGWRados::process_lc(const std::unique_ptr<rgw::sal::Bucket>& optional_bucket)
|
||||
|
||||
@ -1629,8 +1629,8 @@ public:
|
||||
librados::ObjectWriteOperation *op);
|
||||
int gc_operate(const DoutPrefixProvider *dpp, std::string& oid, librados::ObjectReadOperation&& op, bufferlist *pbl, optional_yield y);
|
||||
|
||||
int list_gc_objs(int *index, std::string& marker, uint32_t max, bool expired_only, std::list<cls_rgw_gc_obj_info>& result, bool *truncated, bool& processing_queue);
|
||||
int process_gc(bool expired_only, optional_yield y);
|
||||
int list_gc_objs(int *index, std::string& marker, uint32_t max, bool expired_only, std::list<cls_rgw_gc_obj_info>& result, bool *truncated, bool& processing_queue, std::optional<int> shard_id = std::nullopt);
|
||||
int process_gc(bool expired_only, optional_yield y, std::optional<int> shard_id = std::nullopt);
|
||||
bool process_expired_objects(const DoutPrefixProvider *dpp, optional_yield y);
|
||||
|
||||
int process_lc(const std::unique_ptr<rgw::sal::Bucket>& optional_bucket);
|
||||
|
||||
@ -420,6 +420,8 @@ void usage()
|
||||
cout << " mdlog list\n";
|
||||
cout << " data sync status\n";
|
||||
cout << " sync error trim\n";
|
||||
cout << " gc list\n";
|
||||
cout << " gc process\n";
|
||||
cout << " required for:\n";
|
||||
cout << " mdlog trim\n";
|
||||
cout << " --gen=<gen-id> optional for:\n";
|
||||
@ -9709,14 +9711,24 @@ next:
|
||||
}
|
||||
|
||||
if (opt_cmd == OPT::GC_LIST) {
|
||||
if (specified_shard_id) {
|
||||
int max_gc_shards = min(static_cast<int>(g_ceph_context->_conf->rgw_gc_max_objs), rgw_shards_max());
|
||||
if (shard_id < 0 || shard_id >= max_gc_shards) {
|
||||
cerr << "ERROR: shard-id must be in the range [0, " << max_gc_shards - 1 << "]" << std::endl;
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
bool truncated;
|
||||
bool processing_queue = false;
|
||||
formatter->open_array_section("entries");
|
||||
|
||||
std::optional<int> gc_shard_id = specified_shard_id ? std::optional<int>(shard_id) : std::nullopt;
|
||||
|
||||
do {
|
||||
list<cls_rgw_gc_obj_info> result;
|
||||
int ret = static_cast<rgw::sal::RadosStore*>(driver)->getRados()->list_gc_objs(&index, marker, 1000, !include_all, result, &truncated, processing_queue);
|
||||
int ret = static_cast<rgw::sal::RadosStore*>(driver)->getRados()->list_gc_objs(&index, marker, 1000, !include_all, result, &truncated, processing_queue, gc_shard_id);
|
||||
if (ret < 0) {
|
||||
cerr << "ERROR: failed to list objs: " << cpp_strerror(-ret) << std::endl;
|
||||
return 1;
|
||||
@ -9743,6 +9755,14 @@ next:
|
||||
}
|
||||
|
||||
if (opt_cmd == OPT::GC_PROCESS) {
|
||||
if (specified_shard_id) {
|
||||
int max_gc_shards = min(static_cast<int>(g_ceph_context->_conf->rgw_gc_max_objs), rgw_shards_max());
|
||||
if (shard_id < 0 || shard_id >= max_gc_shards) {
|
||||
cerr << "ERROR: shard-id must be in the range [0, " << max_gc_shards - 1 << "]" << std::endl;
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
rgw::sal::RadosStore* rados_store = dynamic_cast<rgw::sal::RadosStore*>(driver);
|
||||
if (!rados_store) {
|
||||
cerr <<
|
||||
@ -9752,7 +9772,8 @@ next:
|
||||
}
|
||||
RGWRados* store = rados_store->getRados();
|
||||
|
||||
int ret = store->process_gc(!include_all, null_yield);
|
||||
std::optional<int> gc_shard_id = specified_shard_id ? std::optional<int>(shard_id) : std::nullopt;
|
||||
int ret = store->process_gc(!include_all, null_yield, gc_shard_id);
|
||||
if (ret < 0) {
|
||||
cerr << "ERROR: gc processing returned error: " << cpp_strerror(-ret) << std::endl;
|
||||
return 1;
|
||||
|
||||
@ -269,6 +269,8 @@
|
||||
mdlog list
|
||||
data sync status
|
||||
sync error trim
|
||||
gc list
|
||||
gc process
|
||||
required for:
|
||||
mdlog trim
|
||||
--gen=<gen-id> optional for:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user