From: Yan, Zheng Date: Tue, 20 Jan 2015 12:12:11 +0000 (+0800) Subject: mds: save the oldest snapid of inode X-Git-Tag: v0.93~87^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d62c67ca2041797fc7aa212ae4a37ba91e5620e7;p=ceph.git mds: save the oldest snapid of inode When moving a inode to different snapshot realm, we need to check if the inode is snapshotted. If the inode is snapshotted, we create a snapshot realm for it. The snapshot realm records inode's past snapshot realm. Currently there is no reliable way to check if a inode is snapshotted. So add a new field to CInode the store the oldest snapid, it's used to check if inode is snapshotted. Signed-off-by: Yan, Zheng --- diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index 7c06d91154f6..db6e5567955b 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -1706,8 +1706,9 @@ void CDir::_omap_fetched(bufferlist& hdrbl, map& omap, 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); diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 1313a67c12d1..4f66ba60f7c0 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -1239,11 +1239,12 @@ void InodeStore::encode_bare(bufferlist &bl) const ::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); } @@ -1272,12 +1273,14 @@ void InodeStore::decode_bare(bufferlist::iterator &bl, __u8 struct_v) ::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); } @@ -2375,7 +2378,7 @@ snapid_t CInode::get_oldest_snap() 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) @@ -2389,6 +2392,9 @@ 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; diff --git a/src/mds/CInode.h b/src/mds/CInode.h index e6d159230cda..bcb6da667c47 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -79,6 +79,9 @@ public: std::map 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(); } diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 8696be773e6b..67c8df7f9ca7 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -1499,6 +1499,9 @@ CInode *MDCache::cow_inode(CInode *in, snapid_t last) 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; @@ -1563,7 +1566,7 @@ void MDCache::journal_cow_dentry(MutationImpl *mut, EMetaBlob *metablob, 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(); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 24cf29882a45..eae6b6057d6e 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -5205,7 +5205,7 @@ void Server::_unlink_local(MDRequestRef& mdr, CDentry *dn, CDentry *straydn) 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(); @@ -6406,7 +6406,7 @@ void Server::_rename_prepare(MDRequestRef& mdr, 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); @@ -6453,7 +6453,7 @@ void Server::_rename_prepare(MDRequestRef& mdr, } 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()) diff --git a/src/mds/events/EMetaBlob.h b/src/mds/events/EMetaBlob.h index d8fd4588ee05..60f64f859dbe 100644 --- a/src/mds/events/EMetaBlob.h +++ b/src/mds/events/EMetaBlob.h @@ -69,6 +69,7 @@ public: fragtree_t dirfragtree; map xattrs; string symlink; + snapid_t oldest_snap; bufferlist snapbl; __u8 state; typedef map old_inodes_t; @@ -80,9 +81,10 @@ public: fullbit(const string& d, snapid_t df, snapid_t dl, version_t v, const inode_t& i, const fragtree_t &dft, const map &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; @@ -439,14 +441,14 @@ private: sr->encode(snapbl); lump.nfull++; - lump.add_dfull(ceph::shared_ptr(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(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. @@ -501,9 +503,10 @@ private: string empty; roots.push_back(ceph::shared_ptr(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) { diff --git a/src/mds/journal.cc b/src/mds/journal.cc index ace30bd27e8c..025083fde0a2 100644 --- a/src/mds/journal.cc +++ b/src/mds/journal.cc @@ -397,7 +397,7 @@ void EMetaBlob::update_segment(LogSegment *ls) // 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); @@ -419,6 +419,7 @@ void EMetaBlob::fullbit::encode(bufferlist& bl) const { } if (!inode.is_dir()) ::encode(snapbl, bl); + ::encode(oldest_snap, bl); ENCODE_FINISH(bl); } @@ -464,6 +465,11 @@ void EMetaBlob::fullbit::decode(bufferlist::iterator &bl) { if (struct_v >= 7) ::decode(snapbl, bl); } + if (struct_v >= 8) + ::decode(oldest_snap, bl); + else + oldest_snap = CEPH_NOSNAP; + DECODE_FINISH(bl); } @@ -516,7 +522,7 @@ void EMetaBlob::fullbit::generate_test_instances(list& ls) map 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); } @@ -553,6 +559,7 @@ void EMetaBlob::fullbit::update_inode(MDS *mds, CInode *in) * be a no-op.. we have no children (namely open snaprealms) to * divy up */ + in->oldest_snap = oldest_snap; in->decode_snap_blob(snapbl); } diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index abe923c3003c..95ebf496b229 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -412,6 +412,8 @@ struct inode_t { 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),