in->dirfragtree.swap(inode_data.dirfragtree);
in->xattrs.swap(inode_data.xattrs);
- in->decode_snap_blob(inode_data.snap_blob);
in->old_inodes.swap(inode_data.old_inodes);
+ in->decode_snap_blob(inode_data.snap_blob);
+ in->oldest_snap = inode_data.oldest_snap;
if (snaps && !in->snaprealm)
in->purge_stale_snap_data(*snaps);
::encode(xattrs, bl);
::encode(snap_blob, bl);
::encode(old_inodes, bl);
+ ::encode(oldest_snap, bl);
}
void InodeStore::encode(bufferlist &bl) const
{
- ENCODE_START(4, 4, bl);
+ ENCODE_START(5, 4, bl);
encode_bare(bl);
ENCODE_FINISH(bl);
}
::decode(inode.layout, bl); // but we only care about the layout portion
}
}
+ if (struct_v >= 5)
+ ::decode(oldest_snap, bl);
}
void InodeStore::decode(bufferlist::iterator &bl)
{
- DECODE_START_LEGACY_COMPAT_LEN(4, 4, 4, bl);
+ DECODE_START_LEGACY_COMPAT_LEN(5, 4, 4, bl);
decode_bare(bl, struct_v);
DECODE_FINISH(bl);
}
snapid_t t = first;
if (!old_inodes.empty())
t = old_inodes.begin()->second.first;
- return MIN(t, first);
+ return MIN(t, oldest_snap);
}
old_inode_t& CInode::cow_old_inode(snapid_t follows, bool cow_head)
old.first = first;
old.inode = *pi;
old.xattrs = *px;
+
+ if (first < oldest_snap)
+ oldest_snap = first;
dout(10) << " " << px->size() << " xattrs cowed, " << *px << dendl;
std::map<snapid_t, old_inode_t> old_inodes; // key = last, value.first = first
bufferlist snap_blob; // Encoded copy of SnapRealm, because we can't
// rehydrate it without full MDCache
+ snapid_t oldest_snap;
+
+ InodeStore() : oldest_snap(CEPH_NOSNAP) { }
/* Helpers */
bool is_file() const { return inode.is_file(); }
oldin->inode.trim_client_ranges(last);
+ if (in->first < in->oldest_snap)
+ in->oldest_snap = in->first;
+
in->first = last+1;
dout(10) << "cow_inode " << *in << " to " << *oldin << dendl;
dnl = dn->get_projected_linkage();
assert(!dnl->is_null());
- if (dnl->is_primary()) {
+ if (dnl->is_primary() && dnl->get_inode()->is_multiversion()) {
// multiversion inode.
CInode *in = dnl->get_inode();
mdcache->predirty_journal_parents(mdr, &le->metablob, in, straydn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
// project snaprealm, too
- if (in->snaprealm || follows + 1 > dn->first)
+ if (in->snaprealm || follows + 1 > in->get_oldest_snap())
in->project_past_snaprealm_parent(straydn->get_dir()->inode->find_snaprealm());
pi->update_backtrace();
if (destdnl->is_primary()) {
if (destdn->is_auth()) {
// project snaprealm, too
- if (oldin->snaprealm || dest_realm->get_newest_seq() + 1 > destdn->first)
+ if (oldin->snaprealm || dest_realm->get_newest_seq() + 1 > oldin->get_oldest_snap())
oldin->project_past_snaprealm_parent(straydn->get_dir()->inode->find_snaprealm());
straydn->first = MAX(oldin->first, next_dest_snap);
metablob->add_primary_dentry(straydn, oldin, true, true);
} else if (srcdnl->is_primary()) {
// project snap parent update?
if (destdn->is_auth() && src_realm != dest_realm &&
- (srci->snaprealm || src_realm->get_newest_seq() + 1 > srcdn->first))
+ (srci->snaprealm || src_realm->get_newest_seq() + 1 > srci->get_oldest_snap()))
srci->project_past_snaprealm_parent(dest_realm);
if (destdn->is_auth() && !destdnl->is_null())
fragtree_t dirfragtree;
map<string,bufferptr> xattrs;
string symlink;
+ snapid_t oldest_snap;
bufferlist snapbl;
__u8 state;
typedef map<snapid_t, old_inode_t> old_inodes_t;
fullbit(const string& d, snapid_t df, snapid_t dl,
version_t v, const inode_t& i, const fragtree_t &dft,
const map<string,bufferptr> &xa, const string& sym,
- const bufferlist &sbl, __u8 st,
+ snapid_t os, const bufferlist &sbl, __u8 st,
const old_inodes_t *oi = NULL) :
- dn(d), dnfirst(df), dnlast(dl), dnv(v), inode(i), xattrs(xa), state(st)
+ dn(d), dnfirst(df), dnlast(dl), dnv(v), inode(i), xattrs(xa),
+ oldest_snap(os), state(st)
{
if (i.is_symlink())
symlink = sym;
sr->encode(snapbl);
lump.nfull++;
- lump.add_dfull(ceph::shared_ptr<fullbit>(new fullbit(dn->get_name(),
- dn->first, dn->last,
- dn->get_projected_version(),
- *pi, in->dirfragtree,
- *in->get_projected_xattrs(),
- in->symlink, snapbl,
- state,
- &in->old_inodes)));
+ lump.add_dfull(ceph::shared_ptr<fullbit>(new fullbit(dn->get_name(),
+ dn->first, dn->last,
+ dn->get_projected_version(),
+ *pi, in->dirfragtree,
+ *in->get_projected_xattrs(),
+ in->symlink,
+ in->oldest_snap, snapbl,
+ state, &in->old_inodes)));
}
// convenience: primary or remote? figure it out.
string empty;
roots.push_back(ceph::shared_ptr<fullbit>(new fullbit(empty, in->first, in->last, 0, *pi,
- *pdft, *px, in->symlink, snapbl,
- dirty ? fullbit::STATE_DIRTY : 0,
- &in->old_inodes)));
+ *pdft, *px, in->symlink,
+ in->oldest_snap, snapbl,
+ dirty ? fullbit::STATE_DIRTY : 0,
+ &in->old_inodes)));
}
dirlump& add_dir(CDir *dir, bool dirty, bool complete=false) {
// EMetaBlob::fullbit
void EMetaBlob::fullbit::encode(bufferlist& bl) const {
- ENCODE_START(7, 5, bl);
+ ENCODE_START(8, 5, bl);
::encode(dn, bl);
::encode(dnfirst, bl);
::encode(dnlast, bl);
}
if (!inode.is_dir())
::encode(snapbl, bl);
+ ::encode(oldest_snap, bl);
ENCODE_FINISH(bl);
}
if (struct_v >= 7)
::decode(snapbl, bl);
}
+ if (struct_v >= 8)
+ ::decode(oldest_snap, bl);
+ else
+ oldest_snap = CEPH_NOSNAP;
+
DECODE_FINISH(bl);
}
map<string,bufferptr> empty_xattrs;
bufferlist empty_snapbl;
fullbit *sample = new fullbit("/testdn", 0, 0, 0,
- inode, fragtree, empty_xattrs, "", empty_snapbl,
+ inode, fragtree, empty_xattrs, "", 0, empty_snapbl,
false, NULL);
ls.push_back(sample);
}
* be a no-op.. we have no children (namely open snaprealms) to
* divy up
*/
+ in->oldest_snap = oldest_snap;
in->decode_snap_blob(snapbl);
}
version_t backtrace_version;
+ snapid_t oldest_snap;
+
inode_t() : ino(0), rdev(0),
mode(0), uid(0), gid(0), nlink(0),
size(0), max_size_ever(0),