]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
tools/ceph-objectstore-tool: open object store's DB in read-only mode
authorIgor Fedotov <igor.fedotov@croit.io>
Thu, 11 Jan 2024 21:13:36 +0000 (00:13 +0300)
committerIgor Fedotov <igor.fedotov@croit.io>
Wed, 5 Mar 2025 18:42:31 +0000 (21:42 +0300)
for operations which permit that.
This provides additional chances to access corrupted object store.

Signed-off-by: Igor Fedotov <igor.fedotov@croit.io>
(cherry picked from commit d05d0c8ffb868997d8ad8a5e38fc5afb97f855e3)

src/os/ObjectStore.h
src/os/bluestore/BlueStore.cc
src/os/bluestore/BlueStore.h
src/tools/ceph_objectstore_tool.cc

index f22574f7d828b3296e60afa8e002accf174019e7..1d3e138d1be4898e6a77130bb79ed8f061c3cdb2 100644 (file)
@@ -270,6 +270,12 @@ public:
   virtual bool test_mount_in_use() = 0;
   virtual int mount() = 0;
   virtual int umount() = 0;
+  virtual int mount_readonly() {
+    return -EOPNOTSUPP;
+  }
+  virtual int umount_readonly() {
+    return -EOPNOTSUPP;
+  }
   virtual int fsck(bool deep) {
     return -EOPNOTSUPP;
   }
index 41a72b7b6cedbe05b702ee5d5c1384666b9b8af4..32cfa23d9756cc8a00ff5644d34a9f938d12c1ed 100644 (file)
@@ -9031,6 +9031,131 @@ bool BlueStore::has_null_manager() const
   return (fm && fm->is_null_manager());
 }
 
+int BlueStore::mount_readonly()
+{
+  int r = _mount_readonly();
+  if (r < 0) {
+    return r;
+  }
+  r = _open_collections();
+  if (r < 0) {
+    return r;
+  }
+  auto shutdown_cache = make_scope_guard([&] {
+    if (!mounted) {
+      _shutdown_cache();
+    }
+  });
+
+  _kv_start();
+  auto stop_kv = make_scope_guard([&] {
+    if (!mounted) {
+      _kv_stop();
+    }
+  });
+
+  r = _deferred_replay();
+  if (r < 0) {
+    return r;
+  }
+  mempool_thread.init();
+  mounted = true;
+  return r;
+}
+
+int BlueStore::_mount_readonly()
+{
+  dout(5) << __func__ << dendl;
+  {
+    string type;
+    int r = read_meta("type", &type);
+    if (r < 0) {
+      derr << __func__ << " failed to load os-type: " << cpp_strerror(r)
+          << dendl;
+      return r;
+     }
+
+     if (type != "bluestore") {
+       derr << __func__ << " expected bluestore, but type is " << type << dendl;
+       return -EIO;
+     }
+   }
+
+  int r = _open_path();
+  if (r < 0)
+    return r;
+  r = _open_fsid(false);
+  if (r < 0)
+    goto out_path;
+
+  r = _read_fsid(&fsid);
+  if (r < 0)
+    goto out_fsid;
+
+  r = _lock_fsid();
+  if (r < 0)
+    goto out_fsid;
+
+  r = _open_bdev(false);
+  if (r < 0)
+    goto out_fsid;
+
+  r = _open_db(false, false, true);
+  if (r < 0)
+    goto out_bdev;
+
+  r = _open_super_meta();
+  if (r < 0) {
+    goto out_db;
+  }
+  return 0;
+
+out_db:
+  _close_db();
+out_bdev:
+  _close_bdev();
+  out_fsid:
+  _close_fsid();
+out_path:
+  _close_path();
+  return r;
+}
+
+int BlueStore::umount_readonly()
+{
+  ceph_assert(_kv_only || mounted);
+  _osr_drain_all();
+
+  mounted = false;
+
+  if (!_kv_only) {
+    mempool_thread.shutdown();
+    dout(20) << __func__ << " stopping kv thread" << dendl;
+    _kv_stop();
+    // skip cache cleanup step on fast shutdown
+    if (likely(!m_fast_shutdown)) {
+      _shutdown_cache();
+    }
+    dout(20) << __func__ << " closing" << dendl;
+  }
+  return _umount_readonly();
+}
+
+int BlueStore::_umount_readonly()
+{
+  dout(5) << __func__ << dendl;
+  if (db) {
+    _close_db();
+  }
+  if (bluefs) {
+    _close_bluefs();
+  }
+  _close_bdev();
+  _close_fsid();
+  _close_path();
+  return 0;
+}
+
 int BlueStore::_mount()
 {
   dout(5) << __func__ << " path " << path << dendl;
@@ -14290,7 +14415,8 @@ void BlueStore::_txc_release_alloc(TransContext *txc)
   bool discard_queued = false;
   // it's expected we're called with lazy_release_lock already taken!
   if (unlikely(cct->_conf->bluestore_debug_no_reuse_blocks ||
-               txc->released.size() == 0)) {
+               txc->released.size() == 0 ||
+               !alloc)) {
       goto out;
   }
   discard_queued = bdev->try_discard(txc->released);
@@ -14673,7 +14799,8 @@ void BlueStore::_kv_sync_thread()
       auto sync_start = mono_clock::now();
 #endif
       // submit synct synchronously (block and wait for it to commit)
-      int r = cct->_conf->bluestore_debug_omit_kv_commit ? 0 : db->submit_transaction_sync(synct);
+      int r = db_was_opened_read_only || cct->_conf->bluestore_debug_omit_kv_commit ?
+       0 : db->submit_transaction_sync(synct);
       ceph_assert(r == 0);
 
 #ifdef WITH_BLKIN
index b8d4c35be078b6d7f89961473097747854f12a57..c085c8c3e60202d7aaca7dfdfe73376dfcfac76e 100644 (file)
@@ -3002,7 +3002,13 @@ public:
 
 private:
   int _mount();
+  int _mount_readonly();
+  int _umount_readonly();
+
 public:
+  int mount_readonly() override;
+  int umount_readonly() override;
+
   int mount() override {
     return _mount();
   }
index b7fe32319d5fcfb38498b5764da3c161c327a030..1266bda5a186a14b4f08e52bf172a60b3edb03a2 100644 (file)
@@ -3873,7 +3873,28 @@ int main(int argc, char **argv)
     return 0;
   }
 
-  int ret = fs->mount();
+  int ret;
+  bool mount_readonly =
+    op == "export" ||
+    op == "list" ||
+    op == "list-pgs" ||
+    op == "meta-list" ||
+    op == "get-osdmap" ||
+    op == "get-superblock" ||
+    op == "get-inc-osdmap" ||
+    objcmd == "get-bytes" ||
+    objcmd == "get-attrs" ||
+    objcmd == "get-omap" ||
+    objcmd == "get-omaphdr" ||
+    objcmd == "list-attrs" ||
+    objcmd == "list-omap" ||
+    objcmd == "dump";
+  if(mount_readonly) {
+    ret = fs->mount_readonly();
+  } else {
+    ret = fs->mount();
+  }
+
   if (ret < 0) {
     if (ret == -EBUSY) {
       cerr << "OSD has the store locked" << std::endl;
@@ -4761,7 +4782,7 @@ out:
     cout <<  ostr.str() << std::endl;
   }
 
-  int r = fs->umount();
+  int r = mount_readonly ? fs->umount_readonly() : fs->umount();
   if (r < 0) {
     cerr << "umount failed: " << cpp_strerror(r) << std::endl;
     // If no previous error, then use umount() error