snaps on mds
- cap release probably needs ack by mds. or, mds needs to possibly initiate recovery on import? no, release should pbly just be acked by mds... like it was way back when... bah!
-- client snap caps
- - NO CAP STATE FOR SNAPPED INODES.
- - mds grants open access (yes/no), but there is no state, since there is no concurrency.
- (mds doesn't grant access until filelock it is readable, i.e., snapped data has flushed)
- - client _should_ only send FLUSHSNAP _after_ data is flushed. this will require much more sophisticated barriers in the client's cache.
- - reconnect should map caps into snaprealms, and include snaprealm state, such that those can be brought in sync w/ the mds.
- - reconnect does _not_ need any per-cap snap-related info.
-
-- mds open within snapshot
-- client snap read
-
- mds server ops
- link rollback
- rename rollback
- build snaprealm for any hardlinked file
- include snaps for all (primary+remote) parents
-- does snap_follows in MClientFileCaps properly handle snap deletion?
-
snaps on osd
-- clean up snap context packaging..
- - seq, not just snap list
- - keep newest object around on osd?
- - hmm, can we eliminate the snap list for reads?
- - fix cloning on unlinked file (where snaps=[], but head may have follows_snap attr)
- figure out how to fix up rados logging
- snap collections
- garbage collection
if (in->inode.anchored + in->nested_anchors)
dn->adjust_nested_anchors(in->nested_anchors + in->inode.anchored);
+
+ // verify open snaprealm parent
+ if (in->snaprealm)
+ in->snaprealm->adjust_parent();
}
void CDir::unlink_inode( CDentry *dn )
{
dout(10) << "adjust_subtree_after_rename " << *diri << " from " << *olddir << dendl;
- // fix up snaprealms
- assert(diri->snaprealm);
- SnapRealm *newparent = diri->parent->dir->inode->find_snaprealm();
- if (newparent != diri->snaprealm->parent)
- diri->snaprealm->change_open_parent_to(newparent);
-
//show_subtrees();
// adjust subtree
// ===================================
// journal and snap/cow helpers
+
/*
* find first inode in cache that follows given snapid. otherwise, return current.
*/
follows = in->find_snaprealm()->get_newest_snap();
// already cloned?
- if (follows < in->first)
+ if (follows < in->first) {
+ dout(10) << "journal_cow_dentry follows " << follows << " < first on " << *in << dendl;
return;
+ }
in->cow_old_inode(follows, in->get_previous_projected_inode());
follows = dn->dir->inode->find_snaprealm()->get_newest_snap();
// already cloned?
- if (follows < dn->first)
+ if (follows < dn->first) {
+ dout(10) << "journal_cow_dentry follows " << follows << " < first on " << *dn << dendl;
return;
+ }
// update dn.first before adding old dentry to cdir's map
snapid_t oldfirst = dn->first;
void request_drop_locks(MDRequest *r);
void request_cleanup(MDRequest *r);
- // journal helpers
+ // journal/snap helpers
CInode *pick_inode_snap(CInode *in, snapid_t follows);
CInode *cow_inode(CInode *in, snapid_t last);
void journal_cow_dentry(Mutation *mut, EMetaBlob *metablob, CDentry *dn, snapid_t follows=CEPH_NOSNAP);
assert(dn->last == p->dnlast);
}
- bool do_snap_split = false;
CInode *in = mds->mdcache->get_inode(p->inode.ino, p->dnlast);
if (!in) {
in = new CInode(mds->mdcache, true, p->dnfirst, p->dnlast);
in->xattrs = p->xattrs;
if (in->inode.is_dir()) {
in->dirfragtree = p->dirfragtree;
- in->decode_snap_blob(p->snapbl);
- if (in->snaprealm)
- do_snap_split = true;
+ /*
+ * we can do this before linking hte inode bc the split_at would
+ * be a no-op.. we have no children (namely open snaprealms) to
+ * divy up
+ */
+ in->decode_snap_blob(p->snapbl);
}
if (in->inode.is_symlink()) in->symlink = p->symlink;
mds->mdcache->add_inode(in);
in->xattrs = p->xattrs;
if (in->inode.is_dir()) {
in->dirfragtree = p->dirfragtree;
- bool had = in->snaprealm ? true:false;
in->decode_snap_blob(p->snapbl);
- if (!had && in->snaprealm)
- do_snap_split = true;
}
if (in->inode.is_symlink()) in->symlink = p->symlink;
if (p->dirty) in->_mark_dirty(logseg);
dout(10) << "EMetaBlob.replay for [" << p->dnfirst << "," << p->dnlast << "] had " << *in << dendl;
}
in->first = p->dnfirst;
-
- // verify open snaprealm parent
- if (in->snaprealm) {
- SnapRealm *actual = in->get_parent_dn()->get_dir()->inode->find_snaprealm();
- if (actual != in->snaprealm->parent) {
- dout(10) << "EMetaBlob.replay fixing snaprealm open parent" << dendl;
- in->snaprealm->change_open_parent_to(actual);
- }
- }
}
}
build_snap_set(cached_snaps, cached_seq, cached_last_created, cached_last_destroyed,
0, CEPH_NOSNAP);
- dout(10) << "check_cache " << cached_snaps
+ dout(10) << "check_cache rebuilt " << cached_snaps
<< " seq " << seq
<< " cached_seq " << cached_seq
<< " cached_last_created " << cached_last_created
}
+void SnapRealm::adjust_parent()
+{
+ SnapRealm *newparent = inode->get_parent_dn()->get_dir()->get_inode()->find_snaprealm();
+ if (newparent != parent) {
+ dout(10) << "adjust_parent " << parent << " -> " << newparent << dendl;
+ if (parent)
+ parent->open_children.erase(this);
+ parent = newparent;
+ if (parent)
+ parent->open_children.insert(this);
+
+ invalidate_cached_snaps();
+ }
+}
void SnapRealm::split_at(SnapRealm *child)
{
}
current_parent_since = MAX(oldlast, newlast) + 1;
dout(10) << "add_past_parent current_parent_since " << current_parent_since << dendl;
+
+ invalidate_cached_snaps();
}
return cached_seq;
}
- void change_open_parent_to(SnapRealm *newp) {
- if (parent)
- parent->open_children.erase(this);
- parent = newp;
- if (parent)
- parent->open_children.insert(this);
- }
+ void adjust_parent();
+
void split_at(SnapRealm *child);
void join(SnapRealm *child);