]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: use scatter pins for migration instead of rd/wrlocks
authorSage Weil <sage@newdream.net>
Wed, 22 Sep 2010 22:42:52 +0000 (15:42 -0700)
committerSage Weil <sage@newdream.net>
Thu, 23 Sep 2010 23:44:47 +0000 (16:44 -0700)
This is simpler (for the migrator), and wrlocks allow scatter_writebehind,
which is a no-no for a frozen tree.  By pinning the frozen dir's parent
inode, we prevent any scatter or unscatter operations from implicitly
updating metadata within the frozen root dirfrag.

src/mds/Migrator.cc
src/mds/Migrator.h

index cd7f72959218f2f8f1d68d56592681045a960a31..94915d53d0725239879d7a780c431206dbd60c08 100644 (file)
@@ -548,33 +548,6 @@ public:
  * public method to initiate an export.
  * will fail if the directory is freezing, frozen, unpinnable, or root. 
  */
-static void rd_or_wr_lock(ScatterLock *lock, int *rd, int *wr)
-{
-  if (lock->can_rdlock(-1)) {
-    lock->get_rdlock();
-    *rd |= lock->get_type();
-  } else {
-    lock->get_wrlock();
-    *wr |= lock->get_type();
-  }
-}
-
-static void rd_or_wr_unlock(MDS *mds, ScatterLock *lock, int rd, int wr)
-{
-  if (rd & lock->get_type())
-    mds->locker->rdlock_finish(lock, NULL);
-  else
-    mds->locker->wrlock_finish(lock, NULL);
-}
-
-void Migrator::drop_parent_rd_wr_locks(CInode *in, int rd, int wr)
-{
-  rd_or_wr_unlock(mds, &in->filelock, rd, wr);
-  rd_or_wr_unlock(mds, &in->nestlock, rd, wr);
-  rd_or_wr_unlock(mds, &in->dirfragtreelock, rd, wr);
-}
-
-
 void Migrator::export_dir(CDir *dir, int dest)
 {
   dout(7) << "export_dir " << *dir << " to " << dest << dendl;
@@ -616,10 +589,8 @@ void Migrator::export_dir(CDir *dir, int dest)
   }
   // pin parent scatterlocks?
   CInode *diri = dir->inode;
-  if ((!diri->filelock.can_rdlock(-1) && !diri->filelock.can_wrlock(diri->get_loner())) ||
-      (!diri->nestlock.can_rdlock(-1) && !diri->nestlock.can_wrlock(diri->get_loner())) ||
-      (!diri->dirfragtreelock.can_rdlock(-1) && !diri->dirfragtreelock.can_wrlock(diri->get_loner()))) {
-    dout(7) << "export_dir couldn't rd|wrlock parent inode file+nest+dftlock, failing. " << *diri << dendl;
+  if (!diri->can_scatter_pin()) {
+    dout(7) << "export_dir couldn't pin parent inode scatterlocks, failing. " << *diri << dendl;
     return;
   }
 
@@ -689,9 +660,7 @@ void Migrator::export_frozen(CDir *dir)
 
   CInode *diri = dir->inode;
   if (!mds->locker->dentry_can_rdlock_trace(trace) ||
-      (!diri->filelock.can_rdlock(-1) && !diri->filelock.can_wrlock(diri->get_loner())) ||
-      (!diri->nestlock.can_rdlock(-1) && !diri->nestlock.can_wrlock(diri->get_loner())) ||
-      (!diri->dirfragtreelock.can_rdlock(-1) && !diri->dirfragtreelock.can_wrlock(diri->get_loner()))) {
+      !diri->can_scatter_pin()) {
     dout(7) << "export_dir couldn't rdlock path or rd|wrlock parent inode file+nest+dftlock, failing. " 
            << *diri << dendl;
 
@@ -711,16 +680,10 @@ void Migrator::export_frozen(CDir *dir)
   dout(10) << " taking locks on path, parent inode scatterlocks" << dendl;
   // rdlock path
   mds->locker->dentry_anon_rdlock_trace_start(trace);
-
-  // rd or wrlock parent inode scatterlocks
-  //   this prevents accounted_fragstat updates while we are frozen
-  int rdlocked = 0, wrlocked = 0;
-  rd_or_wr_lock(&diri->filelock, &rdlocked, &wrlocked);
-  rd_or_wr_lock(&diri->nestlock, &rdlocked, &wrlocked);
-  rd_or_wr_lock(&diri->dirfragtreelock, &rdlocked, &wrlocked);
-  export_parent_rdlocked[dir] = rdlocked;
-  export_parent_wrlocked[dir] = wrlocked;
-  dout(10) << " dir inode now locked " << *diri << dendl;
+  
+  // pin scatterlocks
+  diri->get_scatter_pin();
+  dout(10) << " dir inode now scatter pinned " << *diri << dendl;
 
 
   cache->show_subtrees();
@@ -1407,9 +1370,10 @@ void Migrator::export_unlock(CDir *dir)
   vector<CDentry*> trace;
   cache->make_trace(trace, dir->inode);
   mds->locker->dentry_anon_rdlock_trace_finish(trace);
-  drop_parent_rd_wr_locks(dir->inode, export_parent_rdlocked[dir], export_parent_wrlocked[dir]);
-  export_parent_rdlocked.erase(dir);
-  export_parent_wrlocked.erase(dir);
+
+  list<Context*> ls;
+  dir->inode->put_scatter_pin(ls);
+  mds->queue_waiters(ls);
 }
 
 void Migrator::export_finish(CDir *dir)
index 40ce4b413ad6293fe15e1b2b874d059933d42412..fa02007765bace19d22689d6d034a1fd7c76ea60 100644 (file)
@@ -81,8 +81,6 @@ protected:
   // export fun
   map<CDir*,int>               export_state;
   map<CDir*,int>               export_peer;
-  map<CDir*,int>               export_parent_rdlocked;  // bit set => rdlocked
-  map<CDir*,int>               export_parent_wrlocked;  // bit set => wrlocked
   //map<CDir*,list<bufferlist> > export_data;   // only during EXPORTING state
   map<CDir*,set<int> >         export_warning_ack_waiting;
   map<CDir*,set<int> >         export_notify_ack_waiting;
@@ -167,8 +165,6 @@ public:
   }
 
 
-  void drop_parent_rd_wr_locks(CInode *in, int rd, int wr);
-
 
   // -- misc --
   void handle_mds_failure_or_stop(int who);