// internal op
CEPH_MDS_OP_FRAGMENTDIR= 0x01500,
CEPH_MDS_OP_EXPORTDIR = 0x01501,
- CEPH_MDS_OP_VALIDATE = 0x01502
+ CEPH_MDS_OP_VALIDATE = 0x01502,
+ CEPH_MDS_OP_FLUSH = 0x01503
};
extern const char *ceph_mds_op_name(int op);
case CEPH_MDS_OP_VALIDATE:
scrub_dentry_work(mdr);
break;
+ case CEPH_MDS_OP_FLUSH:
+ flush_dentry_work(mdr);
+ break;
default:
assert(0);
}
in->validate_disk_state(vr, mdr->internal_op_finish);
return;
}
+
+void MDCache::flush_dentry(const string& path, Context *fin)
+{
+ dout(10) << "flush_dentry " << path << dendl;
+ MDRequestRef mdr = request_start_internal(CEPH_MDS_OP_FLUSH);
+ filepath fp(path.c_str());
+ mdr->set_filepath(fp);
+ mdr->internal_op_finish = fin;
+ flush_dentry_work(mdr);
+}
+
+void MDCache::flush_dentry_work(MDRequestRef& mdr)
+{
+ set<SimpleLock*> rdlocks, wrlocks, xlocks;
+ CInode *in = mds->server->rdlock_path_pin_ref(mdr, 0, rdlocks, true);
+ if (NULL == in)
+ return;
+
+ // TODO: Is this necessary? Fix it if so
+ assert(in->is_auth());
+ bool locked = mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks);
+ if (!locked)
+ return;
+ in->flush(new MDSInternalContextWrapper(mds,mdr->internal_op_finish));
+}
}
void scrub_dentry(const string& path, Formatter *f, Context *fin);
void scrub_dentry_work(MDRequestRef& mdr);
+ void flush_dentry(const string& path, Context *fin);
+ void flush_dentry_work(MDRequestRef& mdr);
};
class C_MDS_RetryRequest : public MDSInternalContext {
string path;
cmd_getval(g_ceph_context, cmdmap, "path", path);
command_scrub_path(f, path);
+ } else if (command == "flush_path") {
+ string path;
+ cmd_getval(g_ceph_context, cmdmap, "path", path);
+ command_flush_path(f, path);
}
f->flush(ss);
delete f;
// scrub_dentry() finishers will dump the data for us; we're done!
}
+void MDS::command_flush_path(Formatter *f, const string& path)
+{
+ C_SaferCond scond;
+ {
+ Mutex::Locker l(mds_lock);
+ mdcache->flush_dentry(path, &scond);
+ }
+ int r = scond.wait();
+ f->open_object_section("results");
+ f->dump_int("return_code", r);
+ f->close_section(); // results
+}
+
void MDS::set_up_admin_socket()
{
int r;
"scrub_path name=path,type=CephString",
asok_hook,
"scrub an inode and output results");
+ r = admin_socket->register_command("flush_path",
+ "flush_path name=path,type=CephString",
+ asok_hook,
+ "flush an inode (and its dirfrags)");
assert(0 == r);
r = admin_socket->register_command("session evict",
"session evict name=client_id,type=CephString",
void clean_up_admin_socket();
void check_ops_in_flight(); // send off any slow ops to monitor
void command_scrub_path(Formatter *f, const string& path);
+ void command_flush_path(Formatter *f, const string& path);
// config observer bits
virtual const char** get_tracked_conf_keys() const;
virtual void handle_conf_change(const struct md_config_t *conf,