From a2e3657e45792224120b7c3ccc162c03e42e3a7a Mon Sep 17 00:00:00 2001 From: Greg Farnum Date: Mon, 19 Jan 2015 16:34:05 -0800 Subject: [PATCH] mds: CDir: implement scrub_local() and call it in CInode::validate_disk_state() Add another set of scrub stamps for the local scrub, which map onto the fnode local scrub members. Use it in CInode::validate_disk_state() instead of the call to check_rstats, because this way we bump the scrub stats, and also in scrub_initialize() because we know we'll have everything we need in memory at that time, while we might not later on. Signed-off-by: Greg Farnum --- src/mds/CDir.cc | 24 ++++++++++++++++++++++++ src/mds/CDir.h | 8 ++++++++ src/mds/CInode.cc | 2 +- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index 930ecb43820e..0cfb0faa670d 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -1264,11 +1264,16 @@ fnode_t *CDir::project_fnode() fnode_t *p = new fnode_t; *p = *get_projected_fnode(); projected_fnode.push_back(p); + if (scrub_infop && scrub_infop->last_scrub_dirty) { + p->localized_scrub_stamp = scrub_infop->last_local.time; + p->localized_scrub_version = scrub_infop->last_local.version; p->recursive_scrub_stamp = scrub_infop->last_recursive.time; p->recursive_scrub_version = scrub_infop->last_recursive.version; scrub_infop->last_scrub_dirty = false; scrub_maybe_delete_info(); + } + dout(10) << "project_fnode " << p << dendl; return p; } @@ -2871,6 +2876,9 @@ void CDir::scrub_info_create() const si->last_recursive.time = si->recursive_start.time = fn->recursive_scrub_stamp; + si->last_local.version = fn->localized_scrub_version; + si->last_local.time = fn->localized_scrub_stamp; + me->scrub_infop = si; } @@ -2908,6 +2916,8 @@ void CDir::scrub_initialize() scrub_infop->others_to_scrub.insert(i->first); } scrub_infop->directory_scrubbing = true; + + assert(scrub_local()); // TODO: handle failure } void CDir::scrub_finished() @@ -3043,3 +3053,17 @@ void CDir::scrub_maybe_delete_info() scrub_infop = NULL; } } + +bool CDir::scrub_local() +{ + assert(is_complete()); + bool rval = check_rstats(); + + if (rval) { + scrub_info(); + scrub_infop->last_local.time = ceph_clock_now(g_ceph_context); + scrub_infop->last_local.version = get_projected_version(); + scrub_infop->last_scrub_dirty = true; + } + return rval; +} diff --git a/src/mds/CDir.h b/src/mds/CDir.h index 6b578892b7f7..e161d5ba9c6d 100644 --- a/src/mds/CDir.h +++ b/src/mds/CDir.h @@ -250,6 +250,8 @@ public: scrub_stamps recursive_start; // when we last started a recursive scrub scrub_stamps last_recursive; // when we last finished a recursive scrub + scrub_stamps last_local; // when we last did a local scrub + bool directory_scrubbing; /// safety check bool last_scrub_dirty; /// is scrub info dirty or is it flushed to fnode? @@ -303,6 +305,12 @@ public: * scrub_dentry_next's listing. It finalizes the scrub statistics. */ void scrub_finished(); + /** + * Tell the CDir to do a local scrub of itself. + * @pre The CDir is_complete(). + * @returns true if the rstats and directory contents match, false otherwise. + */ + bool scrub_local(); private: /** * Create a scrub_info_t struct for the scrub_infop pointer. diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index ae1d521205c4..2e69d6f4b1d5 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -3812,7 +3812,7 @@ void CInode::validate_disk_state(CInode::validated_data *results, results->raw_rstats.error_str << "dirfrag is INCOMPLETE despite fetching; probably too large compared to MDS cache size?\n"; return true; } - assert(p->second->check_rstats()); + assert(p->second->scrub_local()); sub_info.add(p->second->fnode.accounted_rstat); } // ...and that their sum matches our inode settings -- 2.47.3