]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: repair 21089 on freelist init 17734/head
authorSage Weil <sage@redhat.com>
Thu, 14 Sep 2017 14:02:33 +0000 (10:02 -0400)
committerSage Weil <sage@redhat.com>
Thu, 14 Sep 2017 14:03:11 +0000 (10:03 -0400)
Fix up the size inconsistency on freelist init.  This way it will always
happen after an upgrade... and before the user moves to something
post-luminous.

Signed-off-by: Sage Weil <sage@redhat.com>
src/os/bluestore/BitmapFreelistManager.cc
src/os/bluestore/BitmapFreelistManager.h
src/os/bluestore/BlueStore.cc
src/os/bluestore/FreelistManager.h

index 075d3eff6ef18451c6ba04cdd41463ad6cbc0ee6..6366241f651b317073157add5bcde634974d24df 100644 (file)
@@ -105,7 +105,7 @@ int BitmapFreelistManager::create(uint64_t new_size, KeyValueDB::Transaction txn
   return 0;
 }
 
-int BitmapFreelistManager::init()
+int BitmapFreelistManager::init(uint64_t dev_size)
 {
   dout(1) << __func__ << dendl;
 
@@ -153,6 +153,49 @@ int BitmapFreelistManager::init()
           << " blocks_per_key 0x" << blocks_per_key
           << std::dec << dendl;
   _init_misc();
+
+  // check for http://tracker.ceph.com/issues/21089 inconsistency
+  {
+    uint64_t new_size = P2ALIGN(dev_size, bytes_per_block);
+    if (new_size != size) {
+      uint64_t bad_size = new_size & ~bytes_per_block;
+      if (size == bad_size) {
+       derr << __func__ << " size is 0x" << std::hex << size << " should be 0x"
+            << new_size << " and appears to be due to #21089" << std::dec
+            << dendl;
+
+       uint64_t new_blocks = new_size / bytes_per_block;
+       if (new_blocks / blocks_per_key * blocks_per_key != new_blocks) {
+         new_blocks = (new_blocks / blocks_per_key + 1) *
+           blocks_per_key;
+       }
+
+       KeyValueDB::Transaction t = kvdb->get_transaction();
+       {
+         bufferlist sizebl;
+         ::encode(new_size, sizebl);
+         t->set(meta_prefix, "size", sizebl);
+       }
+       if (new_blocks != blocks) {
+         derr << "blocks is 0x" << std::hex << blocks << " should be 0x"
+              << new_blocks << std::dec << dendl;
+         bufferlist bl;
+         ::encode(new_blocks, bl);
+         t->set(meta_prefix, "blocks", bl);
+         _xor(new_size, new_blocks * bytes_per_block - new_size, t);
+       } else {
+         derr << "blocks are ok" << dendl;
+         _xor(bad_size, bytes_per_block, t);
+       }
+       int r = kvdb->submit_transaction_sync(t);
+       assert(r == 0);
+       size = new_size;
+       blocks = new_blocks;
+       derr << __func__ << " fixed inconsistency, size now 0x" << std::hex
+            << size << " blocks 0x" << blocks << std::dec << dendl;
+      }
+    }
+  }
   return 0;
 }
 
index 9ed39ff56534fd0658ae7305b996be133ddd6a42..81b131b4ef8689a3edb2d17c4befed63f88e908b 100644 (file)
@@ -53,7 +53,7 @@ public:
 
   int create(uint64_t size, KeyValueDB::Transaction txn) override;
 
-  int init() override;
+  int init(uint64_t dev_size) override;
   void shutdown() override;
 
   void dump() override;
index b5493388be30798806ddba8852134e28ed96664c..e2fca5c6568570f90a70d64a2a8e1e7364885189 100644 (file)
@@ -4226,7 +4226,7 @@ int BlueStore::_open_fm(bool create)
     db->submit_transaction_sync(t);
   }
 
-  int r = fm->init();
+  int r = fm->init(bdev->get_size());
   if (r < 0) {
     derr << __func__ << " freelist init failed: " << cpp_strerror(r) << dendl;
     delete fm;
index 7f5ad4d79f9b7ab95540d60150ce96f3ff0e9cf6..7eaba19f392bbe945f4415dd3e327e2a6bc2c405 100644 (file)
@@ -26,7 +26,7 @@ public:
 
   virtual int create(uint64_t size, KeyValueDB::Transaction txn) = 0;
 
-  virtual int init() = 0;
+  virtual int init(uint64_t dev_size) = 0;
   virtual void shutdown() = 0;
 
   virtual void dump() = 0;