]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: check snapset in journal_cow_dentry()
authorYan, Zheng <zyan@redhat.com>
Tue, 10 Mar 2015 04:01:32 +0000 (12:01 +0800)
committerYan, Zheng <zyan@redhat.com>
Wed, 18 Mar 2015 06:25:44 +0000 (14:25 +0800)
Removing snapshot also increases snaprealm's sequence number.
So only using snaprealm's sequence number to decide if we should
COW dentry is too loose. This patch makes journal_cow_dentry()
also check snaprealm's snapset.

Signed-off-by: Yan, Zheng <zyan@redhat.com>
src/mds/MDCache.cc
src/mds/SnapRealm.h

index da4685a8a788ce16c8029f01d7220aacb685c17e..d7dbf219060aaef6f7a79a6df9fd30562b604ad3 100644 (file)
@@ -1567,32 +1567,39 @@ void MDCache::journal_cow_dentry(MutationImpl *mut, EMetaBlob *metablob,
   if (dnl->is_primary() && dnl->get_inode()->is_multiversion()) {
     // multiversion inode.
     CInode *in = dnl->get_inode();
+    SnapRealm *realm = NULL;
 
     if (in->get_projected_parent_dn() != dn) {
       assert(follows == CEPH_NOSNAP);
-      snapid_t dir_follows = dn->dir->inode->find_snaprealm()->get_newest_seq();
+      realm = dn->dir->inode->find_snaprealm();
+      snapid_t dir_follows = realm->get_newest_snap();
 
       if (dir_follows+1 > dn->first) {
        snapid_t oldfirst = dn->first;
        dn->first = dir_follows+1;
-       CDentry *olddn = dn->dir->add_remote_dentry(dn->name, in->ino(),  in->d_type(),
-                                                   oldfirst, dir_follows);
-       olddn->pre_dirty();
-       dout(10) << " olddn " << *olddn << dendl;
-       metablob->add_remote_dentry(olddn, true);
-       mut->add_cow_dentry(olddn);
-       // FIXME: adjust link count here?  hmm.
-
-       if (dir_follows+1 > in->first)
-         in->cow_old_inode(dir_follows, false);
+       if (realm->has_snaps_in_range(oldfirst, dn->last)) {
+         CDentry *olddn = dn->dir->add_remote_dentry(dn->name, in->ino(),  in->d_type(),
+                                                     oldfirst, dir_follows);
+         olddn->pre_dirty();
+         dout(10) << " olddn " << *olddn << dendl;
+         metablob->add_remote_dentry(olddn, true);
+         mut->add_cow_dentry(olddn);
+         // FIXME: adjust link count here?  hmm.
+
+         if (dir_follows+1 > in->first)
+           in->cow_old_inode(dir_follows, false);
+       }
       }
 
-      if (in->snaprealm)
-       follows = in->snaprealm->get_newest_seq();
-      else
+      if (in->snaprealm) {
+       realm = in->snaprealm;
+       follows = realm->get_newest_seq();
+      } else
        follows = dir_follows;
-    } else if (follows == CEPH_NOSNAP) {
-      follows = in->find_snaprealm()->get_newest_seq();
+    } else {
+      realm = in->find_snaprealm();
+      if (follows == CEPH_NOSNAP)
+       follows = realm->get_newest_seq();
     }
 
     // already cloned?
@@ -1601,26 +1608,41 @@ void MDCache::journal_cow_dentry(MutationImpl *mut, EMetaBlob *metablob,
       return;
     }
 
+    if (!realm->has_snaps_in_range(in->first, in->last)) {
+      dout(10) << "journal_cow_dentry no snapshot follows " << follows << " on " << *in << dendl;
+      in->first = follows + 1;
+      return;
+    }
+
     in->cow_old_inode(follows, false);
 
   } else {
+    SnapRealm *realm = dn->dir->inode->find_snaprealm();
     if (follows == CEPH_NOSNAP)
-      follows = dn->dir->inode->find_snaprealm()->get_newest_seq();
-    
+      follows = realm->get_newest_seq();
+
     // already cloned?
     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;
     dn->first = follows+1;
+
+    CInode *in = dnl->is_primary() ? dnl->get_inode() : NULL;
+
+    if (!realm->has_snaps_in_range(oldfirst, dn->last)) {
+      dout(10) << "journal_cow_dentry no snapshot follows " << follows << " on " << *dn << dendl;
+      if (in)
+       in->first = follows+1;
+      return;
+    }
     
     dout(10) << "    dn " << *dn << dendl;
-    if (dnl->is_primary()) {
-      assert(oldfirst == dnl->get_inode()->first);
-      CInode *oldin = cow_inode(dnl->get_inode(), follows);
+    if (in) {
+      CInode *oldin = cow_inode(in, follows);
       mut->add_cow_inode(oldin);
       if (pcow_inode)
        *pcow_inode = oldin;
index 28886240a60fffbc6e3626af2cedba1a8e0197d7..cd0de824d255deac8492419183086838cba07a99 100644 (file)
@@ -119,13 +119,20 @@ struct SnapRealm {
 
   snapid_t get_snap_following(snapid_t follows) {
     check_cache();
-    set<snapid_t> s = get_snaps();
-    set<snapid_t>::iterator p = s.upper_bound(follows);
+    const set<snapid_t>& s = get_snaps();
+    set<snapid_t>::const_iterator p = s.upper_bound(follows);
     if (p != s.end())
       return *p;
     return CEPH_NOSNAP;
   }
 
+  bool has_snaps_in_range(snapid_t first, snapid_t last) {
+    check_cache();
+    const set<snapid_t>& s = get_snaps();
+    set<snapid_t>::const_iterator p = s.lower_bound(first);
+    return (p != s.end() && *p <= last);
+  }
+
   void adjust_parent();
 
   void split_at(SnapRealm *child);