]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: fix use-after-free in Migrater 33751/head
authorYan, Zheng <zyan@redhat.com>
Fri, 14 Feb 2020 02:45:47 +0000 (10:45 +0800)
committerPatrick Donnelly <pdonnell@redhat.com>
Thu, 5 Mar 2020 15:48:27 +0000 (07:48 -0800)
use PIN_PTRWAITER to pin CDir in MigratorContext. Also pin CDir to
MDRequest because export may get cancelled while acquiring locks.

Fixes: https://tracker.ceph.com/issues/43909
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
(cherry picked from commit 6203c27b1e48438450524b7c40bb036e5897f207)

src/mds/Migrator.cc

index 8823aee8cde363be772505a42a515622b31d227d..98bf78c3b73f32034a854dd08928a357ba8ae553 100644 (file)
@@ -156,9 +156,13 @@ void Migrator::dispatch(const Message::const_ref &m)
 class C_MDC_EmptyImport : public MigratorContext {
   CDir *dir;
 public:
-  C_MDC_EmptyImport(Migrator *m, CDir *d) : MigratorContext(m), dir(d) {}
+  C_MDC_EmptyImport(Migrator *m, CDir *d) :
+    MigratorContext(m), dir(d) {
+    dir->get(CDir::PIN_PTRWAITER);
+  }
   void finish(int r) override {
     mig->export_empty_import(dir);
+    dir->put(CDir::PIN_PTRWAITER);
   }
 };
 
@@ -719,16 +723,17 @@ void Migrator::maybe_do_queued_export()
 
 
 class C_MDC_ExportFreeze : public MigratorContext {
-  CDir *ex;   // dir i'm exporting
+  CDir *dir;   // dir i'm exporting
   uint64_t tid;
 public:
   C_MDC_ExportFreeze(Migrator *m, CDir *e, uint64_t t) :
-       MigratorContext(m), ex(e), tid(t) {
-          ceph_assert(ex != NULL);
-        }
+    MigratorContext(m), dir(e), tid(t) {
+    dir->get(CDir::PIN_PTRWAITER);
+  }
   void finish(int r) override {
     if (r >= 0)
-      mig->export_frozen(ex, tid);
+      mig->export_frozen(dir, tid);
+    dir->put(CDir::PIN_PTRWAITER);
   }
 };
 
@@ -855,6 +860,7 @@ void Migrator::export_dir(CDir *dir, mds_rank_t dest)
 
   MDRequestRef mdr = mds->mdcache->request_start_internal(CEPH_MDS_OP_EXPORTDIR);
   mdr->more()->export_dir = dir;
+  mdr->pin(dir);
 
   ceph_assert(export_state.count(dir) == 0);
   export_state_t& stat = export_state[dir];
@@ -1139,6 +1145,7 @@ void Migrator::dispatch_export_dir(MDRequestRef& mdr, int count)
 
     MDRequestRef _mdr = mds->mdcache->request_start_internal(CEPH_MDS_OP_EXPORTDIR);
     _mdr->more()->export_dir = sub;
+    _mdr->pin(sub);
 
     ceph_assert(export_state.count(sub) == 0);
     auto& stat = export_state[sub];
@@ -1216,12 +1223,13 @@ class C_M_ExportSessionsFlushed : public MigratorContext {
   CDir *dir;
   uint64_t tid;
 public:
-  C_M_ExportSessionsFlushed(Migrator *m, CDir *d, uint64_t t)
-   : MigratorContext(m), dir(d), tid(t) {
-    ceph_assert(dir != NULL);
+  C_M_ExportSessionsFlushed(Migrator *m, CDir *d, uint64_t t) :
+    MigratorContext(m), dir(d), tid(t) {
+    dir->get(CDir::PIN_PTRWAITER);
   }
   void finish(int r) override {
     mig->export_sessions_flushed(dir, tid);
+    dir->put(CDir::PIN_PTRWAITER);
   }
 };
 
@@ -1502,10 +1510,11 @@ class C_M_ExportGo : public MigratorContext {
 public:
   C_M_ExportGo(Migrator *m, CDir *d, uint64_t t) :
     MigratorContext(m), dir(d), tid(t) {
-      ceph_assert(dir != NULL);
-    }
+    dir->get(CDir::PIN_PTRWAITER);
+  }
   void finish(int r) override {
     mig->export_go_synced(dir, tid);
+    dir->put(CDir::PIN_PTRWAITER);
   }
 };
 
@@ -2595,9 +2604,11 @@ public:
 
   C_MDS_ImportDirLoggedStart(Migrator *m, CDir *d, mds_rank_t f) :
     MigratorLogContext(m), df(d->dirfrag()), dir(d), from(f) {
+    dir->get(CDir::PIN_PTRWAITER);
   }
   void finish(int r) override {
     mig->import_logged_start(df, dir, from, imported_session_map);
+    dir->put(CDir::PIN_PTRWAITER);
   }
 };
 
@@ -2957,6 +2968,8 @@ void Migrator::import_reverse_final(CDir *dir)
 void Migrator::import_logged_start(dirfrag_t df, CDir *dir, mds_rank_t from,
                                   map<client_t,pair<Session*,uint64_t> >& imported_session_map)
 {
+  dout(7) << "import_logged " << *dir << dendl;
+
   map<dirfrag_t, import_state_t>::iterator it = import_state.find(dir->dirfrag());
   if (it == import_state.end() ||
       it->second.state != IMPORT_LOGGINGSTART) {
@@ -2965,8 +2978,6 @@ void Migrator::import_logged_start(dirfrag_t df, CDir *dir, mds_rank_t from,
     return;
   }
 
-  dout(7) << "import_logged " << *dir << dendl;
-
   // note state
   it->second.state = IMPORT_ACKING;