}
void CInode::validate_disk_state(CInode::validated_data *results,
- MDRequestRef &mdr)
+ MDRequestRef &mdr, MDSInternalContext *fin)
{
class ValidationContinuation : public MDSContinuation {
public:
MDRequestRef mdr;
+ MDSInternalContext *fin;
CInode *in;
CInode::validated_data *results;
bufferlist bl;
DIRFRAGS
};
+ /**
+ * May set either mdr or fin, depending on whether caller is doing
+ * validation in a single MDRequest (i.e. asok) or caller is doing
+ * their own thing (i.e. ScrubStack)
+ */
ValidationContinuation(CInode *i,
CInode::validated_data *data_r,
- MDRequestRef &_mdr) :
+ MDRequestRef &_mdr,
+ MDSInternalContext *fin_) :
MDSContinuation(i->mdcache->mds->server),
mdr(_mdr),
+ fin(fin_),
in(i),
results(data_r),
shadow_in(NULL) {
}
void _done() {
- server->respond_to_request(mdr, get_rval());
+ if (mdr) {
+ server->respond_to_request(mdr, get_rval());
+ } else if (fin) {
+ fin->complete(get_rval());
+ }
}
};
ValidationContinuation *vc = new ValidationContinuation(this,
results,
- mdr);
+ mdr,
+ fin);
vc->begin();
}
* @param results A freshly-created validated_data struct, with values set
* as described in the struct documentation.
* @param mdr The request to be responeded upon the completion of the
- * validation.
+ * validation (or NULL)
+ * @param fin Context to call back on completion (or NULL)
*/
void validate_disk_state(validated_data *results,
- MDRequestRef& mdr);
+ MDRequestRef& mdr,
+ MDSInternalContext *fin);
static void dump_validation_results(const validated_data& results,
Formatter *f);
private:
CInode::validated_data *vr =
static_cast<CInode::validated_data*>(mdr->internal_op_private);
- in->validate_disk_state(vr, mdr);
+ in->validate_disk_state(vr, mdr, NULL);
return;
}
}
}
+class C_InodeValidated : public MDSInternalContext
+{
+ public:
+ ScrubStack *stack;
+ CInode::validated_data result;
+ CDentry *target;
+
+ C_InodeValidated(MDSRank *mds, ScrubStack *stack_, CDentry *target_)
+ : MDSInternalContext(mds), stack(stack_), target(target_)
+ {}
+
+ void finish(int r)
+ {
+ stack->_scrub_file_dentry_done(target, r, result);
+ }
+};
+
void ScrubStack::scrub_file_dentry(CDentry *dn)
{
- // No-op:
- // TODO: hook into validate_disk_state
+ assert(dn->get_linkage()->get_inode() != NULL);
+
+ CInode *in = dn->get_linkage()->get_inode();
+ C_InodeValidated *fin = new C_InodeValidated(mdcache->mds, this, dn);
+
+ // At this stage the DN is already past scrub_initialize, so
+ // it's in the cache, it has PIN_SCRUBQUEUE and it is authpinned
+ MDRequestRef null_mdr;
+ in->validate_disk_state(&fin->result, null_mdr, fin);
+}
+
+void ScrubStack::_scrub_file_dentry_done(CDentry *dn, int r,
+ const CInode::validated_data &result)
+{
+ // FIXME: do something real with result! DamageTable! Spamming
+ // the cluster log for debugging purposes
+ LogChannelRef clog = mdcache->mds->clog;
+ clog->info() << " scrubbed file dentry " << dn->name << " r=" << r;
+
Context *c = NULL;
dn->scrub_finished(&c);
if (c) {
- // FIXME: pass some error code in?
finisher->queue(new MDSIOContextWrapper(mdcache->mds, c), 0);
}
}
* @pre dn->get_projected_inode()->is_file()==true;
*/
void scrub_file_dentry(CDentry *dn);
+
+ /**
+ * Callback from completion of CInode::validate_disk_state
+ * @param dn The dentry owning the inode we were validating
+ * @param r The return status from validate_disk_state
+ * @param result Populated results from validate_disk_state
+ */
+ void _scrub_file_dentry_done(CDentry *dn, int r,
+ const CInode::validated_data &result);
+ friend class C_InodeValidated;
+
/**
* Make progress on scrubbing a directory-representing dirfrag and
* its children..