- rados bits to do clone+write
/ - cloning
- fix cloning on unlinked file (where snaps=[], but head may have follows_snap attr)
-
-/ - SnapRealm open_parents, get_snap_set need to recursively open/examine parents over given ranges...
-/ - realm split
- - adjust parent/child linkages
-/ - make realm split notifications safe from races from multiple mds's
- - make sense of snap_highwater...
+ - make sense of snap_highwater...
- figure out how to fix up rados logging
- snap collections
void CInode::open_snaprealm()
{
- if (!snaprealm)
+ if (!snaprealm) {
snaprealm = new SnapRealm(mdcache, this);
+
+ snaprealm->open_parent = find_containing_snaprealm();
+ if (snaprealm->open_parent) {
+ snaprealm->open_parent->open_children.insert(snaprealm);
+ dout(10) << " opened snaprealm " << snaprealm
+ << " parent is " << snaprealm->open_parent
+ << " siblings are " << snaprealm->open_parent->open_children
+ << dendl;
+ }
+ }
}
void CInode::close_snaprealm()
{
if (snaprealm) {
+ if (snaprealm->open_parent)
+ snaprealm->open_parent->open_children.erase(snaprealm);
delete snaprealm;
snaprealm = 0;
}
SnapRealm *CInode::find_containing_snaprealm()
{
CInode *cur = this;
- while (1) {
- if (!cur->get_parent_dn()) {
- assert(0); // all base inodes should have realms!
- return 0;
- }
+ while (cur->get_parent_dn()) {
cur = cur->get_parent_dn()->get_dir()->get_inode();
if (cur->snaprealm)
return cur->snaprealm;
}
+ return 0;
}
void CInode::encode_snap(bufferlist &bl)
rdlocks.insert(&trace[i]->lock);
// rdlock ancestor snaps
- CInode *t = diri->get_parent_dn()->get_dir()->get_inode();
- while (t) {
- rdlocks.insert(&t->snaplock);
+ CInode *t = diri;
+ while (t->get_parent_dn()) {
t = t->get_parent_dn()->get_dir()->get_inode();
+ rdlocks.insert(&t->snaplock);
}
// xlock snap
// link them up
// HACK! parent may be on another mds...
- SnapRealm *parent = diri->find_containing_snaprealm();
+ SnapRealm *parent = diri->snaprealm->open_parent;
assert(parent);
+ assert(parent->open_children.count(diri->snaprealm));
snaplink_t link;
link.first = 0;
- link.dirino = diri->ino();
- parent->children.insert(pair<snapid_t,snaplink_t>(CEPH_NOSNAP, link));
link.dirino = parent->inode->ino();
diri->snaprealm->parents.insert(pair<snapid_t,snaplink_t>(CEPH_NOSNAP, link));
mds->send_message_client(update, p->first);
}
- // active children, too.
- for (multimap<snapid_t,snaplink_t>::iterator p = realm->children.find(CEPH_NOSNAP);
- p != realm->children.end();
- p++) {
- CInode *in = mdcache->get_inode(p->second.dirino);
- if (in) {
- assert(in->snaprealm);
- q.push_back(in->snaprealm);
- }
- }
+ // notify for active children, too.
+ dout(10) << " " << realm << " open_children are " << realm->open_children << dendl;
+ for (set<SnapRealm*>::iterator p = realm->open_children.begin();
+ p != realm->open_children.end();
+ p++)
+ q.push_back(*p);
}
// yay
* SnapRealm
*/
-#define dout(x) if (x < g_conf.debug_mds) *_dout << dbeginl << g_clock.now() \
- << " mds" << mdcache->mds->get_nodeid() \
- << ".snaprealm(" << inode->ino() << ") "
+#define dout(x) if (x <= g_conf.debug_mds) *_dout << dbeginl << g_clock.now() \
+ << " mds" << mdcache->mds->get_nodeid() \
+ << ".cache.snaprealm(" << inode->ino() \
+ << " " << this << ") "
bool SnapRealm::open_parents(MDRequest *mdr)
{
void SnapRealm::split_at(SnapRealm *child)
{
- dout(10) << "split_at " << *child << " on " << *child->inode << dendl;
+ dout(10) << "split_at " << *child
+ << " on " << *child->inode << dendl;
+
+ // split children
+ dout(10) << " my children are " << open_children << dendl;
+ for (set<SnapRealm*>::iterator p = open_children.begin();
+ p != open_children.end(); ) {
+ SnapRealm *realm = *p;
+ if (realm != child &&
+ child->inode->is_ancestor_of(realm->inode)) {
+ dout(20) << " child gets child realm " << *realm << " on " << *realm->inode << dendl;
+ realm->open_parent = child;
+ child->open_children.insert(realm);
+ open_children.erase(p++);
+ } else {
+ dout(20) << " keeping child realm " << *realm << " on " << *realm->inode << dendl;
+ p++;
+ }
+ }
+ // split inodes_with_caps
xlist<CInode*>::iterator p = inodes_with_caps.begin();
while (!p.end()) {
CInode *in = *p;
if (t == in)
break;
}
- if (!under_child) {
- dout(20) << " keeping " << *in << dendl;
- continue;
+ if (under_child) {
+ dout(20) << " child gets " << *in << dendl;
+ in->move_to_containing_realm(child);
+ } else {
+ dout(20) << " keeping " << *in << dendl;
}
-
- dout(20) << " child gets " << *in << dendl;
- in->move_to_containing_realm(child);
}
}
// realm state
snapid_t created;
map<snapid_t, SnapInfo> snaps;
- multimap<snapid_t, snaplink_t> parents, children; // key is "last" (or NOSNAP)
+ multimap<snapid_t, snaplink_t> parents; // key is "last" (or NOSNAP)
void encode(bufferlist& bl) const {
::encode(created, bl);
::encode(snaps, bl);
::encode(parents, bl);
- ::encode(children, bl);
}
void decode(bufferlist::iterator& p) {
::decode(created, p);
::decode(snaps, p);
::decode(parents, p);
- ::decode(children, p);
}
// in-memory state
snapid_t highwater; // largest snap this realm has exposed to clients (implicitly or explicitly)
// caches?
+ SnapRealm *open_parent;
+ set<SnapRealm*> open_children; // active children that are currently open
+
//set<snapid_t> cached_snaps;
- //set<SnapRealm*> cached_active_children; // active children that are currently open
xlist<CInode*> inodes_with_caps; // for efficient realm splits
map<int, xlist<Capability*> > client_caps; // to identify clients who need snap notifications
SnapRealm(MDCache *c, CInode *in) :
created(0),
- mdcache(c), inode(in), highwater(0) {}
+ mdcache(c), inode(in), highwater(0),
+ open_parent(0) {}
bool open_parents(MDRequest *mdr);
void get_snap_set(set<snapid_t>& s, snapid_t first=0, snapid_t last=CEPH_NOSNAP);
}
out << ")";
}
- if (realm.children.size()) {
- out << " children=(";
- for (multimap<snapid_t, snaplink_t>::const_iterator p = realm.parents.begin();
- p != realm.parents.end();
- p++) {
- if (p != realm.parents.begin()) out << ",";
- out << p->second.first << "-";
- if (p->first == CEPH_NOSNAP)
- out << "head";
- else
- out << p->first;
- out << "=" << p->second.dirino;
- }
- out << ")";
- }
- out << ")";
+ out << " " << &realm << ")";
return out;
}