From f56decf755972b2e573e1217e8908a0e4d94dcac Mon Sep 17 00:00:00 2001 From: Nikhilkumar Shelke Date: Wed, 2 Feb 2022 17:21:46 +0530 Subject: [PATCH] ceph-fuse: perform cleanup if test_dentry_handling failed If remount failed due to some reason then ceph_abort() is getting called which causes child process termination without cleanup. To fix this issue, ceph_abort() call moved after performing cleanup. Fixes: https://tracker.ceph.com/issues/54049 Signed-off-by: Nikhilkumar Shelke (cherry picked from commit 8c778e79840f1aa9b9731e2ef20881da0d122fda) --- src/ceph_fuse.cc | 7 ++++++- src/client/Client.cc | 31 ++++++++++++++++++++++++------- src/client/Client.h | 4 ++-- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/ceph_fuse.cc b/src/ceph_fuse.cc index b7f8a4d4b9019..de668541b1f3d 100644 --- a/src/ceph_fuse.cc +++ b/src/ceph_fuse.cc @@ -203,7 +203,9 @@ int main(int argc, const char **argv, const char *envp[]) { "client_try_dentry_invalidate"); bool can_invalidate_dentries = client_try_dentry_invalidate && ver < KERNEL_VERSION(3, 18, 0); - int tr = client->test_dentry_handling(can_invalidate_dentries); + auto test_result = client->test_dentry_handling(can_invalidate_dentries); + int tr = test_result.first; + bool abort_on_failure = test_result.second; bool client_die_on_failed_dentry_invalidate = g_conf().get_val( "client_die_on_failed_dentry_invalidate"); if (tr != 0 && client_die_on_failed_dentry_invalidate) { @@ -229,6 +231,9 @@ int main(int argc, const char **argv, const char *envp[]) { } } } + if(abort_on_failure) { + ceph_abort(); + } return reinterpret_cast(tr); #else return reinterpret_cast(0); diff --git a/src/client/Client.cc b/src/client/Client.cc index 86936de67bcb0..0af07b25af07e 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -4395,9 +4395,10 @@ void Client::remove_session_caps(MetaSession *s, int err) sync_cond.notify_all(); } -int Client::_do_remount(bool retry_on_error) +std::pair Client::_do_remount(bool retry_on_error) { uint64_t max_retries = cct->_conf.get_val("mds_max_retries_on_remount_failure"); + bool abort_on_failure = false; errno = 0; int r = remount_cb(callback_handle); @@ -4421,10 +4422,10 @@ int Client::_do_remount(bool retry_on_error) !(retry_on_error && (++retries_on_invalidate < max_retries)); if (should_abort && !is_unmounting()) { lderr(cct) << "failed to remount for kernel dentry trimming; quitting!" << dendl; - ceph_abort(); + abort_on_failure = true; } } - return r; + return std::make_pair(r, abort_on_failure); } class C_Client_Remount : public Context { @@ -11312,20 +11313,36 @@ void Client::ll_register_callbacks(struct ceph_client_callback_args *args) umask_cb = args->umask_cb; } -int Client::test_dentry_handling(bool can_invalidate) +// This is deprecated, use ll_register_callbacks2() instead. +void Client::ll_register_callbacks(struct ceph_client_callback_args *args) { - int r = 0; + ceph_assert(!is_mounting() && !is_mounted() && !is_unmounting()); + + _ll_register_callbacks(args); +} + +int Client::ll_register_callbacks2(struct ceph_client_callback_args *args) +{ + if (is_mounting() || is_mounted() || is_unmounting()) + return -CEPHFS_EBUSY; + + _ll_register_callbacks(args); + return 0; +} + +std::pair Client::test_dentry_handling(bool can_invalidate) +{ + std::pair r(0, false); RWRef_t iref_reader(initialize_state, CLIENT_INITIALIZED); if (!iref_reader.is_state_satisfied()) - return -CEPHFS_ENOTCONN; + return std::make_pair(-CEPHFS_ENOTCONN, false); can_invalidate_dentries = can_invalidate; if (can_invalidate_dentries) { ceph_assert(dentry_invalidate_cb); ldout(cct, 1) << "using dentry_invalidate_cb" << dendl; - r = 0; } else { ceph_assert(remount_cb); ldout(cct, 1) << "using remount_cb" << dendl; diff --git a/src/client/Client.h b/src/client/Client.h index 4a30c1ba772c8..ca103e52ce075 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -654,7 +654,7 @@ public: int ll_osdaddr(int osd, char* buf, size_t size); void ll_register_callbacks(struct ceph_client_callback_args *args); - int test_dentry_handling(bool can_invalidate); + std::pair test_dentry_handling(bool can_invalidate); const char** get_tracked_conf_keys() const override; void handle_conf_change(const ConfigProxy& conf, @@ -1291,7 +1291,7 @@ private: int _release_fh(Fh *fh); void _put_fh(Fh *fh); - int _do_remount(bool retry_on_error); + std::pair _do_remount(bool retry_on_error); int _read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl, bool *checkeof); int _read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl); -- 2.39.5