From: John Spray Date: Thu, 16 Jul 2015 12:45:45 +0000 (+0100) Subject: mds: write scrub tag during validation X-Git-Tag: v10.0.1~51^2~9 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=19300836921265a2becf81a1c35ee95f36bd53a4;p=ceph.git mds: write scrub tag during validation Signed-off-by: John Spray --- diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 4ba3ca4a9ccc..6a0c1e1b3f05 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -3685,6 +3685,40 @@ void CInode::validate_disk_state(CInode::validated_data *results, delete shadow_in; } + /** + * Fetch backtrace and set tag if tag is non-empty + */ + void fetch_backtrace_and_tag(CInode *in, std::string tag, + Context *fin, int *bt_r, bufferlist *bt) + { + int64_t pool; + if (in->is_dir()) + pool = in->mdcache->mds->mdsmap->get_metadata_pool(); + else + pool = in->inode.layout.fl_pg_pool; + + object_t oid = CInode::get_object_name(in->ino(), frag_t(), ""); + + ObjectOperation fetch; + + fetch.getxattr("parent", bt, bt_r); + // We want to tag even if we get ENODATA fetching the backtrace + fetch.set_last_op_flags(CEPH_OSD_OP_FLAG_FAILOK); + if (!tag.empty()) { + bufferlist tag_bl; + ::encode(tag, tag_bl); + fetch.setxattr("scrub_tag", tag_bl); + } + if (tag.empty()) { + in->mdcache->mds->objecter->read(oid, object_locator_t(pool), fetch, CEPH_NOSNAP, + NULL, 0, fin); + } else { + SnapContext snapc; + in->mdcache->mds->objecter->mutate(oid, object_locator_t(pool), fetch, snapc, + ceph_clock_now(g_ceph_context), 0, NULL, fin); + } + } + bool _start(int rval) { if (in->is_dirty()) { MDCache *mdcache = in->mdcache; @@ -3703,7 +3737,12 @@ void CInode::validate_disk_state(CInode::validated_data *results, C_OnFinisher *conf = new C_OnFinisher(get_io_callback(BACKTRACE), in->mdcache->mds->finisher); - in->fetch_backtrace(conf, &bl); + // Rather than using the usual CInode::fetch_backtrace, + // use a special variant that optionally writes a tag in the same + // operation. + const std::string &tag = in->get_parent_dn()->scrub_info()->header->tag; + fetch_backtrace_and_tag(in, tag, conf, + &results->backtrace.ondisk_read_retval, &bl); return false; } @@ -3711,9 +3750,12 @@ void CInode::validate_disk_state(CInode::validated_data *results, // set up basic result reporting and make sure we got the data results->performed_validation = true; // at least, some of it! results->backtrace.checked = true; - results->backtrace.ondisk_read_retval = rval; results->backtrace.passed = false; // we'll set it true if we make it - if (rval != 0) { + + // Ignore rval because it's the result of a FAILOK operation + // from fetch_backtrace_and_tag: the real result is in + // backtrace.ondisk_read_retval + if (results->backtrace.ondisk_read_retval != 0) { results->backtrace.error_str << "failed to read off disk; see retval"; return true; } @@ -3722,9 +3764,10 @@ void CInode::validate_disk_state(CInode::validated_data *results, try { bufferlist::iterator p = bl.begin(); ::decode(results->backtrace.ondisk_value, p); - } catch (buffer::malformed_input&) { + } catch (buffer::error&) { results->backtrace.passed = false; - results->backtrace.error_str << "failed to decode on-disk backtrace!"; + results->backtrace.error_str << "failed to decode on-disk backtrace (" + << bl.length() << " bytes)!"; return true; } int64_t pool;