struct {
uint64_t ino; // "file" identifier
uint32_t bno; // "block" in that "file"
- objectrev_t snap; // revision. normally ctime (as epoch).
+ uint64_t snap; // snap revision.
} __attribute__ ((packed));
};
// snaps
-typedef __u64 snapid_t;
+struct snapid_t {
+ __u64 val;
+ snapid_t(__u64 v=0) : val(v) {}
+ snapid_t operator+=(snapid_t o) { val += o.val; return *this; }
+ snapid_t operator++() { ++val; return *this; }
+ operator __u64() const { return val; }
+};
+
+inline void encode(snapid_t i, bufferlist &bl) { encode(i.val, bl); }
+inline void decode(snapid_t &i, bufferlist::iterator &p) { decode(i.val, p); }
+
+inline ostream& operator<<(ostream& out, snapid_t s) {
+ if (s == CEPH_NOSNAP)
+ return out << "head";
+ else
+ return out << s.val;
+}
+
#define MAXSNAP CEPH_MAXSNAP
#define NOSNAP CEPH_NOSNAP
// inode
in = new CInode(cache);
in->inode = inode;
- in->snapid = first;
+ in->first = first;
+ in->last = last;
// symlink?
if (in->is_symlink())
filepath path;
in.make_path(path);
out << "[inode " << in.inode.ino << " " << path << (in.is_dir() ? "/":"");
- if (in.snapid)
- out << " SNAP=" << in.snapid;
+ if (in.is_multiversion())
+ out << " [" << in.first << ",...]";
+ else
+ out << " [" << in.first << "," << in.last << "]";
+
if (in.is_auth()) {
out << " auth";
if (in.is_replicated())
SnapRealm *snaprealm;
SnapRealm *containing_realm;
- snapid_t snapid; // 0 = multiversion OR head
+ snapid_t first, last; // last=0 => multiversion or head.
map<snapid_t, old_inode_t> old_inodes; // key = last, value.first = first
+ bool is_multiversion() { return snaprealm || inode.is_dir(); }
+
loff_t last_journaled; // log offset for the last time i was journaled
loff_t last_open_journaled; // log offset for the last journaled EOpen
CInode(MDCache *c, bool auth=true) :
mdcache(c),
snaprealm(0), containing_realm(0),
- snapid(0),
+ first(1), last(0),
last_journaled(0), last_open_journaled(0),
//hack_accessed(true),
stickydir_ref(0),
inodeno_t ino() const { return inode.ino; }
- vinodeno_t vino() const { return vinodeno_t(inode.ino, snapid); }
+ vinodeno_t vino() const { return vinodeno_t(inode.ino, last); }
inode_t& get_inode() { return inode; }
CDentry* get_parent_dn() { return parent; }
CDentry* get_projected_parent_dn() { return projected_parent ? projected_parent:parent; }
assert(parent->is_auth());
blob->add_dir_context(parent);
blob->add_dir(parent, true);
+ SnapRealm *realm = 0;
for (list<CInode*>::iterator p = lsi.begin();
p != lsi.end();
p++) {
CInode *cur = *p;
- inode_t *pi = cur->get_projected_inode();
- blob->add_primary_dentry(cur->get_projected_parent_dn(), true, 0, pi);
+ if (!realm)
+ realm = cur->find_snaprealm();
+ else if (cur->snaprealm)
+ realm = cur->snaprealm;
+ mds->mdcache->journal_dirty_inode(blob, cur, realm->get_latest_snap());
+ //inode_t *pi = cur->get_projected_inode();
+ //blob->add_primary_dentry(cur->get_projected_parent_dn(), true, 0, pi);
}
}
return in;
}
-CInode *MDCache::cow_inode(CInode *in, snapid_t tosnap)
+CInode *MDCache::cow_inode(CInode *in, snapid_t first, snapid_t last)
{
CInode *oldin = new CInode(this);
oldin->inode = *in->get_previous_projected_inode();
- oldin->snapid = tosnap;
+ oldin->symlink = in->symlink;
+ oldin->xattrs = in->xattrs;
+
+ oldin->first = first;
+ oldin->last = last;
+
dout(10) << " oldin " << *oldin << dendl;
add_inode(oldin);
void MDCache::journal_dirty_inode(EMetaBlob *metablob, CInode *in, snapid_t follows)
{
dout(10) << "journal_dirty_inode follows " << follows << " on " << *in << dendl;
- CDentry *dn = in->parent;
+ CDentry *dn = in->get_projected_parent_dn();
dout(10) << " orig dn " << *dn << dendl;
- if (in->snaprealm || in->inode.is_dir()) {
+ if (follows == CEPH_NOSNAP)
+ follows = in->find_snaprealm()->get_latest_snap();
+
+ if (in->is_multiversion()) {
// multiversion inode.
- assert(0);
+ if (follows < in->first) {
+ metablob->add_primary_dentry(dn, true, in, in->get_projected_inode());
+ } else {
+ old_inode_t &old = in->old_inodes[follows];
+ old.first = in->first;
+ if (in->is_projected())
+ old.inode = *in->get_previous_projected_inode(); // mkdir/mknod/symlink don't bother to project new inodes
+ else
+ old.inode = in->inode;
+ old.xattrs = in->xattrs;
+
+ in->first = follows+1;
+ metablob->add_primary_dentry(dn, true, in, in->get_projected_inode());
+
+ dout(10) << " duped to old_inode [" << old.first << "," << follows << "] "
+ << *in << dendl;
+ }
} else {
// is dn within current snap?
if (follows < dn->first) {
- metablob->add_primary_dentry(dn, true, 0, in->get_projected_inode());
+ metablob->add_primary_dentry(dn, true, in, in->get_projected_inode());
} else {
snapid_t oldfirst = dn->first;
dn->first = follows+1;
dout(10) << " dn " << *dn << dendl;
- CInode *oldin = cow_inode(in, follows);
+ CInode *oldin = cow_inode(in, in->first, follows);
CDentry *olddn = dn->dir->add_primary_dentry(dn->name, oldin, oldfirst, follows);
dout(10) << " olddn " << *olddn << dendl;
metablob->add_primary_dentry(olddn, true);
- metablob->add_primary_dentry(dn, true, 0, in->get_projected_inode());
+ metablob->add_primary_dentry(dn, true, in, in->get_projected_inode());
}
}
}
// journal helpers
CInode *pick_inode_snap(CInode *in, snapid_t follows);
- CInode *cow_inode(CInode *in, snapid_t tosnap);
- void journal_dirty_inode(EMetaBlob *metablob, CInode *in, snapid_t follows);
+ CInode *cow_inode(CInode *in, snapid_t first, snapid_t last);
+ void journal_dirty_inode(EMetaBlob *metablob, CInode *in, snapid_t follows=CEPH_NOSNAP);
// slaves
void add_uncommitted_master(metareqid_t reqid, LogSegment *ls, set<int> &slaves) {
EUpdate *le = new EUpdate(mdlog, "utime");
le->metablob.add_client_req(req->get_reqid());
mds->locker->predirty_nested(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false);
- le->metablob.add_primary_dentry(cur->parent, true, 0, pi);
+ mdcache->journal_dirty_inode(&le->metablob, cur);
mdlog->submit_entry(le, new C_MDS_inode_update_finish(mds, mdr, cur));
}
EUpdate *le = new EUpdate(mdlog, "chmod");
le->metablob.add_client_req(req->get_reqid());
mds->locker->predirty_nested(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false);
- le->metablob.add_primary_dentry(cur->parent, true, 0, pi);
+ mdcache->journal_dirty_inode(&le->metablob, cur);
mdlog->submit_entry(le, new C_MDS_inode_update_finish(mds, mdr, cur));
}
EUpdate *le = new EUpdate(mdlog, "chown");
le->metablob.add_client_req(req->get_reqid());
mds->locker->predirty_nested(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false);
- le->metablob.add_primary_dentry(cur->parent, true, 0, pi);
+ mdcache->journal_dirty_inode(&le->metablob, cur);
mdlog->submit_entry(le, new C_MDS_inode_update_finish(mds, mdr, cur));
}
EUpdate *le = new EUpdate(mdlog, "setxattr");
le->metablob.add_client_req(req->get_reqid());
mds->locker->predirty_nested(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false);
- le->metablob.add_primary_dentry(cur->parent, true, 0, pi);
+ mdcache->journal_dirty_inode(&le->metablob, cur);
mdlog->submit_entry(le, new C_MDS_inode_update_finish(mds, mdr, cur));
}
EUpdate *le = new EUpdate(mdlog, "removexattr");
le->metablob.add_client_req(req->get_reqid());
mds->locker->predirty_nested(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false);
- le->metablob.add_primary_dentry(cur->parent, true, 0, pi);
+ mdcache->journal_dirty_inode(&le->metablob, cur);
mdlog->submit_entry(le, new C_MDS_inode_update_finish(mds, mdr, cur));
}
newi->inode.mode |= S_IFREG;
newi->inode.version = dn->pre_dirty() - 1;
newi->inode.dirstat.rfiles = 1;
+
+ newi->projected_parent = dn;
dout(10) << "mknod mode " << newi->inode.mode << " rdev " << newi->inode.rdev << dendl;
le->metablob.add_allocated_ino(newi->ino(), mds->idalloc->get_version());
mds->locker->predirty_nested(mdr, &le->metablob, newi, dn->dir, PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
-
- le->metablob.add_primary_dentry(dn, true, newi, &newi->inode);
+ mdcache->journal_dirty_inode(&le->metablob, newi, dn->dir->inode->find_snaprealm()->get_latest_snap());
// log + wait
mdlog->submit_entry(le, new C_MDS_mknod_finish(mds, mdr, dn, newi));
le->metablob.add_client_req(req->get_reqid());
le->metablob.add_allocated_ino(newi->ino(), mds->idalloc->get_version());
mds->locker->predirty_nested(mdr, &le->metablob, newi, dn->dir, PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
- le->metablob.add_primary_dentry(dn, true, newi, &newi->inode);
+ //le->metablob.add_primary_dentry(dn, true, newi, &newi->inode);
+ mdcache->journal_dirty_inode(&le->metablob, newi, dn->dir->inode->find_snaprealm()->get_latest_snap());
le->metablob.add_dir(newdir, true, true); // dirty AND complete
// log + wait
le->metablob.add_client_req(req->get_reqid());
le->metablob.add_allocated_ino(newi->ino(), mds->idalloc->get_version());
mds->locker->predirty_nested(mdr, &le->metablob, newi, dn->dir, PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
- le->metablob.add_primary_dentry(dn, true, newi, &newi->inode);
+ mdcache->journal_dirty_inode(&le->metablob, newi, dn->dir->inode->find_snaprealm()->get_latest_snap());
// log + wait
mdlog->submit_entry(le, new C_MDS_mknod_finish(mds, mdr, dn, newi));
struct old_inode_t {
snapid_t first;
- inodeno_t inode;
+ inode_t inode;
map<string,bufferptr> xattrs;
void encode(bufferlist& bl) const {
oldparent->snaprealm->get_snap_set(s,
MAX(first, p->second.first),
thru);
- thru++;
+ ++thru;
}
if (thru <= last && parent)
parent->get_snap_set(s, thru, last);
capseq_t get_mseq() { return h.migrate_seq; }
inodeno_t get_snap_realm() { return inodeno_t(h.snap_realm); }
- snapid_t get_snap_created() { return h.snap_created; }
- snapid_t get_snap_highwater() { return h.snap_highwater; }
+ snapid_t get_snap_created() { return snapid_t(h.snap_created); }
+ snapid_t get_snap_highwater() { return snapid_t(h.snap_highwater); }
vector<snapid_t> &get_snaps() { return snaps; }
inodeno_t get_ino() { return inodeno_t(h.ino); }
int get_result() { return (__s32)(__u32)st.result; }
inodeno_t get_snap_realm() { return inodeno_t((__u64)st.snap_realm); }
- snapid_t get_snap_created() { return st.snap_created; }
- snapid_t get_snap_highwater() { return st.snap_highwater; }
+ snapid_t get_snap_created() { return snapid_t(st.snap_created); }
+ snapid_t get_snap_highwater() { return snapid_t(st.snap_highwater); }
vector<snapid_t> &get_snaps() { return snaps; }
void set_snap_info(inodeno_t r, snapid_t c, snapid_t hw) {