return;
C_MDS_EnqueueScrub *cs = static_cast<C_MDS_EnqueueScrub*>(mdr->internal_op_finish);
- ScrubHeaderRef &header = cs->header;
+ ScrubHeaderRef header = cs->header;
// Cannot scrub same dentry twice at same time
if (in->scrub_infop && in->scrub_infop->scrub_in_progress) {
header->set_origin(in);
- Context *fin = nullptr;
- if (!header->get_recursive()) {
+ Context *fin;
+ if (header->get_recursive()) {
+ header->get_origin()->get(CInode::PIN_SCRUBQUEUE);
+ fin = new MDSInternalContextWrapper(mds,
+ new FunctionContext([this, header](int r) {
+ recursive_scrub_finish(header);
+ header->get_origin()->put(CInode::PIN_SCRUBQUEUE);
+ })
+ );
+ } else {
fin = cs->take_finisher();
}
return;
}
+void MDCache::recursive_scrub_finish(const ScrubHeaderRef& header)
+{
+ if (header->get_origin()->is_base() &&
+ header->get_force() && header->get_repair()) {
+ // notify snapserver that base directory is recursively scrubbed.
+ // After both root and mdsdir are recursively scrubbed, snapserver
+ // knows that all old format snaprealms are converted to the new
+ // format.
+ if (mds->mdsmap->get_num_in_mds() == 1 &&
+ mds->mdsmap->get_num_failed_mds() == 0 &&
+ mds->mdsmap->get_tableserver() == mds->get_nodeid()) {
+ mds->mark_base_recursively_scrubbed(header->get_origin()->ino());
+ }
+ }
+}
+
struct C_MDC_RespondInternalRequest : public MDCacheLogContext {
MDRequestRef mdr;
C_MDC_RespondInternalRequest(MDCache *c, MDRequestRef& m) :
* long time)
*/
void enqueue_scrub_work(MDRequestRef& mdr);
+ void recursive_scrub_finish(const ScrubHeaderRef& header);
void repair_inode_stats_work(MDRequestRef& mdr);
void repair_dirfrag_stats_work(MDRequestRef& mdr);
void upgrade_inode_snaprealm_work(MDRequestRef& mdr);
already_sent = true;
}
+void MDSRank::mark_base_recursively_scrubbed(inodeno_t ino)
+{
+ if (mdsmap->get_tableserver() == whoami)
+ snapserver->mark_base_recursively_scrubbed(ino);
+}
+
void MDSRankDispatcher::tick()
{
heartbeat_reset();
bool evict_client(int64_t session_id, bool wait, bool blacklist,
std::stringstream& ss, Context *on_killed=nullptr);
+ void mark_base_recursively_scrubbed(inodeno_t ino);
+
protected:
void dump_clientreplay_status(Formatter *f) const;
void command_scrub_path(Formatter *f, std::string_view path, vector<string>& scrubop_vec);
bool get_recursive() const { return recursive; }
bool get_repair() const { return repair; }
bool get_force() const { return force; }
- const CInode *get_origin() const { return origin; }
+ CInode *get_origin() const { return origin; }
std::string_view get_tag() const { return tag; }
Formatter &get_formatter() const { return *formatter; }
version_t last_checked_osdmap;
+ bool root_scrubbed = false; // all snaprealms under root are converted?
+ bool mdsdir_scrubbed = false; // all snaprealms under ~mds0 are converted?
+
void encode_server_state(bufferlist& bl) const override {
ENCODE_START(5, 3, bl);
encode(last_snap, bl);
void check_osd_map(bool force);
+ void mark_base_recursively_scrubbed(inodeno_t ino) {
+ if (ino == MDS_INO_ROOT)
+ root_scrubbed = true;
+ else if (ino == MDS_INO_MDSDIR(rank))
+ mdsdir_scrubbed = true;
+ else
+ assert(0);
+ }
bool can_allow_multimds_snaps() const {
- return snaps.empty() || snaps.begin()->first >= snaprealm_v2_since;
+ return (root_scrubbed && mdsdir_scrubbed) ||
+ snaps.empty() || snaps.begin()->first >= snaprealm_v2_since;
}
void encode(bufferlist& bl) const {