From: Igor Fedotov Date: Thu, 11 Jan 2024 21:13:36 +0000 (+0300) Subject: tools/ceph-objectstore-tool: open object store's DB in read-only mode X-Git-Tag: v19.2.3~234^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=310c4849c1b57d0fa386532dbfeee4cd2f2a7133;p=ceph.git tools/ceph-objectstore-tool: open object store's DB in read-only mode for operations which permit that. This provides additional chances to access corrupted object store. Signed-off-by: Igor Fedotov (cherry picked from commit d05d0c8ffb868997d8ad8a5e38fc5afb97f855e3) --- diff --git a/src/os/ObjectStore.h b/src/os/ObjectStore.h index f22574f7d82..1d3e138d1be 100644 --- a/src/os/ObjectStore.h +++ b/src/os/ObjectStore.h @@ -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; } diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index 41a72b7b6ce..32cfa23d975 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -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 diff --git a/src/os/bluestore/BlueStore.h b/src/os/bluestore/BlueStore.h index b8d4c35be07..c085c8c3e60 100644 --- a/src/os/bluestore/BlueStore.h +++ b/src/os/bluestore/BlueStore.h @@ -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(); } diff --git a/src/tools/ceph_objectstore_tool.cc b/src/tools/ceph_objectstore_tool.cc index b7fe32319d5..1266bda5a18 100644 --- a/src/tools/ceph_objectstore_tool.cc +++ b/src/tools/ceph_objectstore_tool.cc @@ -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