From ab822d3050f2a35e9749315eff43c87205b450d5 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Thu, 2 Jan 2025 11:07:33 +0300 Subject: [PATCH] Support consistent listings in client (rm-data, merge and etc) --- src/client/cluster_client_list.cpp | 31 +++++++++++++++++++++++++++--- src/client/osd_ops.h | 2 +- src/cmd/cli_rm_data.cpp | 1 + 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/client/cluster_client_list.cpp b/src/client/cluster_client_list.cpp index 51acf4f0..5d7f4fb6 100644 --- a/src/client/cluster_client_list.cpp +++ b/src/client/cluster_client_list.cpp @@ -48,6 +48,7 @@ struct inode_list_t uint64_t max_offset = 0; int max_parallel_pgs = 16; + bool fallback = false; int inflight_pgs = 0; std::map inflight_per_osd; int done_pgs = 0; @@ -259,7 +260,7 @@ int cluster_client_t::start_pg_listing(inode_list_pg_t *pg) std::set all_peers; if (pg_it->second.cur_state != PG_ACTIVE) { - // Not clean + // Not clean and OSDs don't support listing from primary for (osd_num_t pg_osd: pg_it->second.target_set) all_peers.insert(pg_osd); for (osd_num_t pg_osd: pg_it->second.all_peers) @@ -282,9 +283,10 @@ int cluster_client_t::start_pg_listing(inode_list_pg_t *pg) peer_it++; } } - else + if (pg_it->second.cur_state == PG_ACTIVE || !pg->lst->fallback) { // Clean + all_peers.clear(); all_peers.insert(pg_it->second.cur_primary); } // Check that we're connected to all PG OSDs @@ -351,6 +353,7 @@ void cluster_client_t::send_list(inode_list_osd_t *cur_list) .max_inode = cur_list->pg->lst->inode, .min_stripe = cur_list->pg->lst->min_offset, .max_stripe = cur_list->pg->lst->max_offset, + .flags = (uint64_t)(cur_list->pg->lst->fallback ? 0 : OSD_LIST_PRIMARY), }, }; op->callback = [this, cur_list](osd_op_t *op) @@ -359,7 +362,29 @@ void cluster_client_t::send_list(inode_list_osd_t *cur_list) { fprintf(stderr, "Failed to get PG %u/%u object list from OSD %ju (retval=%jd), skipping\n", cur_list->pg->lst->pool_id, cur_list->pg->pg_num, cur_list->osd_num, op->reply.hdr.retval); - cur_list->pg->errcode = op->reply.hdr.retval; + if (!cur_list->pg->errcode || + cur_list->pg->errcode == -EPIPE || + op->reply.hdr.retval != -EPIPE) + { + cur_list->pg->errcode = op->reply.hdr.retval; + } + } + else if ((op->req.sec_list.flags & OSD_LIST_PRIMARY) && + !(op->reply.sec_list.flags & OSD_LIST_PRIMARY)) + { + // OSD is old and doesn't support listing from primary + if (log_level > 0) + { + fprintf( + stderr, "[PG %u/%u] Primary OSD doesn't support consistent listings, falling back to listings from all peers\n", + cur_list->pg->lst->pool_id, cur_list->pg->pg_num + ); + } + cur_list->pg->lst->fallback = true; + if (!cur_list->pg->errcode) + { + cur_list->pg->errcode = -EPIPE; + } } else { diff --git a/src/client/osd_ops.h b/src/client/osd_ops.h index e67ed8b6..941ed34f 100644 --- a/src/client/osd_ops.h +++ b/src/client/osd_ops.h @@ -213,7 +213,7 @@ struct __attribute__((__packed__)) osd_reply_sec_list_t uint64_t flags; }; -// read or write to the primary OSD (must be within individual stripe) +// read, write or delete command for the primary OSD (must be within individual stripe) struct __attribute__((__packed__)) osd_op_rw_t { osd_op_header_t header; diff --git a/src/cmd/cli_rm_data.cpp b/src/cmd/cli_rm_data.cpp index d76256cc..ad89d10d 100644 --- a/src/cmd/cli_rm_data.cpp +++ b/src/cmd/cli_rm_data.cpp @@ -182,6 +182,7 @@ struct rm_inode_t { fprintf(stderr, "\n"); } + // FIXME: for 100% correctness inactive_osds should be taken from OSD_OP_DELETE reply, not from the listing if (inactive_osds.size() && !parent->json_output) { fprintf(stderr, "Some data may remain after delete on OSDs which are currently down: ");