From 96f280b652fbede5b28a28ee65b91fac449216c2 Mon Sep 17 00:00:00 2001 From: Lumir Sliva <61183145+lumir-sliva@users.noreply.github.com> Date: Sat, 11 Apr 2026 23:18:45 +0200 Subject: [PATCH] crimson/os/seastore: handle enoent in SeaStore::Shard::stat MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit stat() aborts via assert_all when get_onode() returns ENOENT for a non-existent object. But get_onode() explicitly declares enoent as a valid error (onode_manager.h:36-40), and replicated_recovery_backend calls stat() during push-based recovery on objects that haven't been pulled yet. Handle enoent by returning an empty struct stat — same pattern as exists() (line 1207) and the !store_active early return (line 1384). The recovery code in replicated_recovery_backend.cc:831-840 already handles st_size=0 correctly. Add a unit test that stats a non-existent object to verify it returns an empty struct instead of aborting. Fixes: https://tracker.ceph.com/issues/75814 Signed-off-by: Lumir Sliva <61183145+lumir-sliva@users.noreply.github.com> --- src/crimson/os/seastore/seastore.cc | 3 +++ src/test/crimson/seastore/test_seastore.cc | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/crimson/os/seastore/seastore.cc b/src/crimson/os/seastore/seastore.cc index 0189d840b8f7..3e12c13161b3 100644 --- a/src/crimson/os/seastore/seastore.cc +++ b/src/crimson/os/seastore/seastore.cc @@ -1435,6 +1435,9 @@ seastar::future SeaStore::Shard::stat( [this, oid](auto &t, auto &onode) { return _stat(t, onode, oid); }).handle_error( + crimson::ct_error::enoent::handle([] { + return seastar::make_ready_future(); + }), crimson::ct_error::assert_all{ "Invalid error in SeaStoreS::stat" } diff --git a/src/test/crimson/seastore/test_seastore.cc b/src/test/crimson/seastore/test_seastore.cc index 166ad7b3de3e..2034d620f61a 100644 --- a/src/test/crimson/seastore/test_seastore.cc +++ b/src/test/crimson/seastore/test_seastore.cc @@ -926,6 +926,16 @@ TEST_P(seastore_test_t, touch_stat_list_remove) }); } +TEST_P(seastore_test_t, stat_nonexistent) +{ + run_async([this] { + auto st = sharded_seastore->stat( + coll, + make_oid(99)).get(); + EXPECT_EQ(st.st_size, 0); + }); +} + using bound_t = seastore_test_t::bound_t; constexpr unsigned MAX_LIMIT = std::numeric_limits::max(); static const seastore_test_t::list_test_cases_t temp_list_cases{ -- 2.47.3