* client-facing protocol.
*/
#define CEPH_OSD_PROTOCOL 8 /* cluster internal */
-#define CEPH_MDS_PROTOCOL 9 /* cluster internal */
+#define CEPH_MDS_PROTOCOL 10 /* cluster internal */
#define CEPH_MON_PROTOCOL 5 /* cluster internal */
#define CEPH_OSDC_PROTOCOL 24 /* server/client */
#define CEPH_MDSC_PROTOCOL 32 /* server/client */
lock->decode_locked_state(m->get_data());
lock->set_state(LOCK_SYNC);
lock->finish_waiters(SimpleLock::WAIT_RD|SimpleLock::WAIT_STABLE);
-
- // special case: trim replica no-longer-null dentry?
- if (lock->get_type() == CEPH_LOCK_DN) {
- CDentry *dn = (CDentry*)lock->get_parent();
- if (dn->get_linkage()->is_null() && m->get_data().length() > 0) {
- dout(10) << "handle_simple_lock replica dentry null -> non-null, must trim "
- << *dn << dendl;
- assert(dn->get_num_ref() == 0);
- map<int, MCacheExpire*> expiremap;
- mdcache->trim_dentry(dn, expiremap);
- mdcache->send_expire_messages(expiremap);
- }
- }
break;
case LOCK_AC_LOCK:
#include "messages/MInodeFileCaps.h"
#include "messages/MLock.h"
+#include "messages/MDentryLink.h"
#include "messages/MDentryUnlink.h"
#include "messages/MClientRequest.h"
+ case MSG_MDS_DENTRYLINK:
+ handle_dentry_link((MDentryLink*)m);
+ break;
case MSG_MDS_DENTRYUNLINK:
handle_dentry_unlink((MDentryUnlink*)m);
break;
+// LINK
+
+void MDCache::send_dentry_link(CDentry *dn)
+{
+ dout(7) << "send_dentry_link " << *dn << dendl;
+
+ for (map<int,int>::iterator p = dn->replicas_begin();
+ p != dn->replicas_end();
+ p++) {
+ if (mds->mdsmap->get_state(p->first) < MDSMap::STATE_REJOIN)
+ continue;
+ CDentry::linkage_t *dnl = dn->get_linkage();
+ MDentryLink *m = new MDentryLink(dn->get_dir()->dirfrag(), dn->name,
+ dnl->is_primary());
+ if (dnl->is_primary()) {
+ dout(10) << " primary " << *dnl->get_inode() << dendl;
+ replicate_inode(dnl->get_inode(), p->first, m->bl);
+ } else if (dnl->is_remote()) {
+ inodeno_t ino = dnl->get_remote_ino();
+ __u8 d_type = dnl->get_remote_d_type();
+ dout(10) << " remote " << ino << " " << d_type << dendl;
+ ::encode(ino, m->bl);
+ ::encode(d_type, m->bl);
+ } else
+ assert(0); // aie, bad caller!
+ mds->send_message_mds(m, p->first);
+ }
+}
+
+void MDCache::handle_dentry_link(MDentryLink *m)
+{
+ CDir *dir = get_dirfrag(m->get_dirfrag());
+ assert(dir);
+ CDentry *dn = dir->lookup(m->get_dn());
+ assert(dn);
+
+ dout(7) << "handle_dentry_link on " << *dn << dendl;
+ CDentry::linkage_t *dnl = dn->get_linkage();
+
+ assert(!dn->is_auth());
+ assert(dnl->is_null());
+
+ bufferlist::iterator p = m->bl.begin();
+ list<Context*> finished;
+
+ if (m->get_is_primary()) {
+ // primary link.
+ add_replica_inode(p, dn, finished);
+ } else {
+ // remote link, easy enough.
+ inodeno_t ino;
+ __u8 d_type;
+ ::decode(ino, p);
+ ::decode(d_type, p);
+ dir->link_remote_inode(dn, ino, d_type);
+ }
+
+ if (!finished.empty())
+ mds->queue_waiters(finished);
+
+ delete m;
+ return;
+}
+
// UNLINK
+void MDCache::send_dentry_unlink(CDentry *dn, CDentry *straydn)
+{
+ dout(10) << "send_dentry_unlink " << *dn << dendl;
+ // share unlink news with replicas
+ for (map<int,int>::iterator it = dn->replicas_begin();
+ it != dn->replicas_end();
+ it++) {
+ MDentryUnlink *unlink = new MDentryUnlink(dn->get_dir()->dirfrag(), dn->name);
+ if (straydn) {
+ replicate_inode(get_myin(), it->first, unlink->straybl);
+ replicate_dir(straydn->get_dir()->inode->get_parent_dn()->get_dir(), it->first, unlink->straybl);
+ replicate_dentry(straydn->get_dir()->inode->get_parent_dn(), it->first, unlink->straybl);
+ replicate_inode(straydn->get_dir()->inode, it->first, unlink->straybl);
+ replicate_dir(straydn->get_dir(), it->first, unlink->straybl);
+ replicate_dentry(straydn, it->first, unlink->straybl);
+ }
+ mds->send_message_mds(unlink, it->first);
+ }
+}
+
void MDCache::handle_dentry_unlink(MDentryUnlink *m)
{
CDir *dir = get_dirfrag(m->get_dirfrag());
-
if (!dir) {
dout(7) << "handle_dentry_unlink don't have dirfrag " << m->get_dirfrag() << dendl;
- }
- else {
+ } else {
CDentry *dn = dir->lookup(m->get_dn());
if (!dn) {
dout(7) << "handle_dentry_unlink don't have dentry " << *dir << " dn " << m->get_dn() << dendl;
class MDiscoverReply;
class MCacheExpire;
class MDirUpdate;
+class MDentryLink;
class MDentryUnlink;
class MLock;
CInode *add_replica_inode(bufferlist::iterator& p, CDentry *dn, list<Context*>& finished);
CDentry *add_replica_stray(bufferlist &bl, int from);
-protected:
// -- namespace --
+public:
+ void send_dentry_link(CDentry *dn);
+ void send_dentry_unlink(CDentry *dn, CDentry *straydn);
+protected:
+ void handle_dentry_link(MDentryLink *m);
void handle_dentry_unlink(MDentryUnlink *m);
mdr->apply();
+ mds->mdcache->send_dentry_link(dn);
+
mds->server->reply_request(mdr, 0);
}
};
mdr->apply();
+ mds->mdcache->send_dentry_link(dn);
+
+
// hit pop
mds->balancer->hit_inode(mdr->now, newi, META_POP_IWR);
//mds->balancer->hit_dir(mdr->now, dn->get_dir(), META_POP_DWR);
mdr->apply();
+ mds->mdcache->send_dentry_link(dn);
+
// bump target popularity
mds->balancer->hit_inode(mdr->now, targeti, META_POP_IWR);
//mds->balancer->hit_dir(mdr->now, dn->get_dir(), META_POP_DWR);
}
mdr->apply();
+
+ mds->mdcache->send_dentry_link(dn);
// commit anchor update?
if (mdr->more()->dst_reanchor_atid)
dn->mark_dirty(dnpv, mdr->ls);
mdr->apply();
- // share unlink news with replicas
- for (map<int,int>::iterator it = dn->replicas_begin();
- it != dn->replicas_end();
- it++) {
- dout(7) << "_unlink_local_finish sending MDentryUnlink to mds" << it->first << dendl;
- MDentryUnlink *unlink = new MDentryUnlink(dn->get_dir()->dirfrag(), dn->name);
- if (straydn) {
- mdcache->replicate_inode(mds->mdcache->get_myin(), it->first, unlink->straybl);
- mdcache->replicate_dir(straydn->get_dir()->inode->get_parent_dn()->get_dir(), it->first, unlink->straybl);
- mdcache->replicate_dentry(straydn->get_dir()->inode->get_parent_dn(), it->first, unlink->straybl);
- mdcache->replicate_inode(straydn->get_dir()->inode, it->first, unlink->straybl);
- mdcache->replicate_dir(straydn->get_dir(), it->first, unlink->straybl);
- mdcache->replicate_dentry(straydn, it->first, unlink->straybl);
- }
- mds->send_message_mds(unlink, it->first);
- }
+ mds->mdcache->send_dentry_unlink(dn, straydn);
// commit anchor update?
if (mdr->more()->dst_reanchor_atid)
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+
+#ifndef __MDENTRYLINK_H
+#define __MDENTRYLINK_H
+
+class MDentryLink : public Message {
+ dirfrag_t dirfrag;
+ nstring dn;
+ bool is_primary;
+
+ public:
+ dirfrag_t get_dirfrag() { return dirfrag; }
+ nstring& get_dn() { return dn; }
+ bool get_is_primary() { return is_primary; }
+
+ bufferlist bl;
+
+ MDentryLink() :
+ Message(MSG_MDS_DENTRYLINK) { }
+ MDentryLink(dirfrag_t df, nstring& n, bool p) :
+ Message(MSG_MDS_DENTRYLINK),
+ dirfrag(df),
+ dn(n),
+ is_primary(p) {}
+
+ const char *get_type_name() { return "dentry_link";}
+ void print(ostream& o) {
+ o << "dentry_link(" << dirfrag << " " << dn << ")";
+ }
+
+ void decode_payload() {
+ bufferlist::iterator p = payload.begin();
+ ::decode(dirfrag, p);
+ ::decode(dn, p);
+ ::decode(is_primary, p);
+ ::decode(bl, p);
+ }
+ void encode_payload() {
+ ::encode(dirfrag, payload);
+ ::encode(dn, payload);
+ ::encode(is_primary, payload);
+ ::encode(bl, payload);
+ }
+};
+
+#endif
#include "messages/MDentryUnlink.h"
+#include "messages/MDentryLink.h"
#include "messages/MHeartbeat.h"
case MSG_MDS_DENTRYUNLINK:
- m = new MDentryUnlink();
+ m = new MDentryUnlink;
+ break;
+ case MSG_MDS_DENTRYLINK:
+ m = new MDentryLink;
break;
case MSG_MDS_HEARTBEAT:
#define MSG_MDS_FRAGMENTNOTIFY 0x209
#define MSG_MDS_OFFLOAD_TARGETS 0x20a
#define MSG_MDS_OFFLOAD_COMPLETE 0x20b
+#define MSG_MDS_DENTRYLINK 0x20c
#define MSG_MDS_LOCK 0x300
#define MSG_MDS_INODEFILECAPS 0x301