]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: avoid double-pinning stray inodes
authorSage Weil <sage@newdream.net>
Tue, 11 Jan 2011 17:50:20 +0000 (09:50 -0800)
committerSage Weil <sage@newdream.net>
Tue, 11 Jan 2011 17:50:20 +0000 (09:50 -0800)
We make multiple iterations through populate_mydir().  Only pin each stray
once.  Fixes #689 and crashes like

mds/CInode.h: In function 'virtual void CInode::bad_get(int)':
mds/CInode.h:1088: FAILED assert(ref_set.count(by) == 0)
ceph version 0.24 (180a4176035521940390f4ce24ee3eb7aa290632)
1: (CInode::bad_put(int)+0) [0x827b090]
2: (MDSCacheObject::get(int)+0x153) [0x813e463]
3: (MDCache::populate_mydir()+0x8a) [0x81a7e5a]
4: (MDCache::_create_system_file_finish(Mutation*, CDentry*,
Context*)+0x181) [0x819f501]
5: (C_MDC_CreateSystemFile::finish(int)+0x29) [0x81d6c29]
6: (finish_contexts(std::list<Context*, std::allocator<Context*> >&,
int)+0x6b) [0x81d663b]
7: (Journaler::_finish_flush(int, long long, utime_t, bool)+0x983) [0x82f2f53]
8: (Journaler::C_Flush::finish(int)+0x3f) [0x82fb24f]
9: (Objecter::handle_osd_op_reply(MOSDOpReply*)+0x801) [0x82d8e31]
10: (MDS::_dispatch(Message*)+0x2ae5) [0x80eaa15]
11: (MDS::ms_dispatch(Message*)+0x62) [0x80eb142]
12: (SimpleMessenger::dispatch_entry()+0x899) [0x80b8649]
13: (SimpleMessenger::DispatchThread::entry()+0x22) [0x80b30f2]

Signed-off-by: Sage Weil <sage@newdream.net>
src/mds/CInode.h
src/mds/MDCache.cc

index 8426478221284507296e4ceb70d79d2002917c6f..51ea61e72c8f9c738ab6c1887f20d5c951a0b086 100644 (file)
@@ -171,6 +171,7 @@ public:
   static const int STATE_PURGING =     (1<<13);
   static const int STATE_DIRTYPARENT =  (1<<14);
   static const int STATE_DIRTYRSTAT =  (1<<15);
+  static const int STATE_STRAYPINNED = (1<<16);
 
   // -- waiters --
   static const uint64_t WAIT_DIR         = (1<<0);
index bb9bc0a5c01933a87bf5561d94613c062c5da876..83968e18d227d17670d2cda20e44f0a5ff5e485b 100644 (file)
@@ -574,7 +574,11 @@ void MDCache::populate_mydir()
     }
     assert(straydn);
     assert(strays[i]);
-    strays[i]->get(CInode::PIN_STRAY);
+    // we make multiple passes through this method; make sure we only pin each stray once.
+    if (!strays[i]->state_test(CInode::STATE_STRAYPINNED)) {
+      strays[i]->get(CInode::PIN_STRAY);
+      strays[i]->state_set(CInode::STATE_STRAYPINNED);
+    }
     dout(20) << " stray num " << i << " is " << *strays[i] << dendl;
   }