Skip to content

Commit ecaae49

Browse files
committed
test/store_test: add tests for deferred ops replay in
mount/mount_readonly. Signed-off-by: Igor Fedotov <[email protected]>
1 parent c0983e9 commit ecaae49

File tree

2 files changed

+201
-0
lines changed

2 files changed

+201
-0
lines changed

src/test/objectstore/store_test.cc

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7101,6 +7101,201 @@ INSTANTIATE_TEST_SUITE_P(
71017101
));
71027102
#endif
71037103

7104+
class DeferredReplayTest : public DeferredWriteTest {
7105+
};
7106+
7107+
TEST_P(DeferredReplayTest, DeferredReplay) {
7108+
const bool print = false;
7109+
deferred_test_t t = GetParam();
7110+
SetVal(g_conf(), "bdev_block_size", stringify(t.bdev_block_size).c_str());
7111+
SetVal(g_conf(), "bluestore_min_alloc_size", stringify(t.min_alloc_size).c_str());
7112+
SetVal(g_conf(), "bluestore_max_blob_size", stringify(t.max_blob_size).c_str());
7113+
SetVal(g_conf(), "bluestore_prefer_deferred_size", stringify(t.prefer_deferred_size).c_str());
7114+
// forbid periodic deferred ops submission to keep them pending
7115+
// until umount.
7116+
SetVal(g_conf(), "bluestore_max_defer_interval", "0");
7117+
g_conf().apply_changes(nullptr);
7118+
DeferredSetup();
7119+
7120+
int r;
7121+
coll_t cid;
7122+
const PerfCounters* logger = store->get_perf_counters();
7123+
ObjectStore::CollectionHandle ch = store->create_new_collection(cid);
7124+
{
7125+
ObjectStore::Transaction t;
7126+
t.create_collection(cid, 0);
7127+
r = queue_transaction(store, ch, std::move(t));
7128+
ASSERT_EQ(r, 0);
7129+
}
7130+
{
7131+
auto offset = offsets[0];
7132+
auto length = lengths[0];
7133+
std::string hname = fmt::format("test-{}-{}", offset, length);
7134+
ghobject_t hoid(hobject_t(hname, "", CEPH_NOSNAP, 0, -1, ""));
7135+
{
7136+
ObjectStore::Transaction t;
7137+
t.touch(cid, hoid);
7138+
r = queue_transaction(store, ch, std::move(t));
7139+
ASSERT_EQ(r, 0);
7140+
}
7141+
if (print)
7142+
std::cout << hname << std::endl;
7143+
7144+
auto w_new = logger->get(l_bluestore_write_new);
7145+
auto i_deferred_w = logger->get(l_bluestore_issued_deferred_writes);
7146+
{
7147+
C_SaferCond c;
7148+
ObjectStore::Transaction t;
7149+
bufferlist bl;
7150+
bl.append(std::string(length, 'x'));
7151+
t.write(cid, hoid, offset, bl.length(), bl,
7152+
CEPH_OSD_OP_FLAG_FADVISE_NOCACHE);
7153+
t.register_on_commit(&c);
7154+
r = queue_transaction(store, ch, std::move(t));
7155+
ASSERT_EQ(r, 0);
7156+
c.wait();
7157+
}
7158+
uint32_t first_db = offset / t.bdev_block_size;
7159+
uint32_t last_db = (offset + length - 1) / t.bdev_block_size;
7160+
7161+
uint32_t write_size = (last_db - first_db + 1) * t.bdev_block_size;
7162+
if (write_size < t.prefer_deferred_size) {
7163+
// expect no direct writes
7164+
ASSERT_EQ(w_new, logger->get(l_bluestore_write_new));
7165+
ASSERT_EQ(i_deferred_w + 1, logger->get(l_bluestore_issued_deferred_writes));
7166+
ASSERT_EQ(0, logger->get(l_bluestore_submitted_deferred_writes));
7167+
}
7168+
}
7169+
auto cct = store->cct;
7170+
// disable DB txc commits during umount,
7171+
// hence deferred op(s) aren't fully committed and
7172+
// are left pending in DB.
7173+
//
7174+
SetVal(g_conf(), "bluestore_debug_omit_kv_commit", "true");
7175+
g_conf().apply_changes(nullptr);
7176+
store->umount();
7177+
SetVal(g_conf(), "bluestore_debug_omit_kv_commit", "false");
7178+
g_conf().apply_changes(nullptr);
7179+
store = ObjectStore::create(cct,
7180+
get_type(),
7181+
get_data_dir(),
7182+
"store_test_temp_journal");
7183+
store->mount();
7184+
logger = store->get_perf_counters();
7185+
// mount performs deferred ops replay and submits pending ones,
7186+
// hence we get a submitted deferred write.
7187+
ASSERT_EQ(1, logger->get(l_bluestore_submitted_deferred_writes));
7188+
}
7189+
7190+
7191+
TEST_P(DeferredReplayTest, DeferredReplayInReadOnly) {
7192+
const bool print = false;
7193+
deferred_test_t t = GetParam();
7194+
SetVal(g_conf(), "bdev_block_size", stringify(t.bdev_block_size).c_str());
7195+
SetVal(g_conf(), "bluestore_min_alloc_size", stringify(t.min_alloc_size).c_str());
7196+
SetVal(g_conf(), "bluestore_max_blob_size", stringify(t.max_blob_size).c_str());
7197+
SetVal(g_conf(), "bluestore_prefer_deferred_size", stringify(t.prefer_deferred_size).c_str());
7198+
// forbid periodic deferred ops submission to keep them pending
7199+
// until umount.
7200+
SetVal(g_conf(), "bluestore_max_defer_interval", "0");
7201+
g_conf().apply_changes(nullptr);
7202+
DeferredSetup();
7203+
7204+
int r;
7205+
coll_t cid;
7206+
const PerfCounters* logger = store->get_perf_counters();
7207+
ObjectStore::CollectionHandle ch = store->create_new_collection(cid);
7208+
{
7209+
ObjectStore::Transaction t;
7210+
t.create_collection(cid, 0);
7211+
r = queue_transaction(store, ch, std::move(t));
7212+
ASSERT_EQ(r, 0);
7213+
}
7214+
{
7215+
auto offset = offsets[0];
7216+
auto length = lengths[0];
7217+
std::string hname = fmt::format("test-{}-{}", offset, length);
7218+
ghobject_t hoid(hobject_t(hname, "", CEPH_NOSNAP, 0, -1, ""));
7219+
{
7220+
ObjectStore::Transaction t;
7221+
t.touch(cid, hoid);
7222+
r = queue_transaction(store, ch, std::move(t));
7223+
ASSERT_EQ(r, 0);
7224+
}
7225+
if (print)
7226+
std::cout << hname << std::endl;
7227+
7228+
auto w_new = logger->get(l_bluestore_write_new);
7229+
auto i_deferred_w = logger->get(l_bluestore_issued_deferred_writes);
7230+
{
7231+
C_SaferCond c;
7232+
ObjectStore::Transaction t;
7233+
bufferlist bl;
7234+
bl.append(std::string(length, 'x'));
7235+
t.write(cid, hoid, offset, bl.length(), bl,
7236+
CEPH_OSD_OP_FLAG_FADVISE_NOCACHE);
7237+
t.register_on_commit(&c);
7238+
r = queue_transaction(store, ch, std::move(t));
7239+
ASSERT_EQ(r, 0);
7240+
c.wait();
7241+
}
7242+
uint32_t first_db = offset / t.bdev_block_size;
7243+
uint32_t last_db = (offset + length - 1) / t.bdev_block_size;
7244+
7245+
uint32_t write_size = (last_db - first_db + 1) * t.bdev_block_size;
7246+
if (write_size < t.prefer_deferred_size) {
7247+
// expect no direct writes
7248+
ASSERT_EQ(w_new, logger->get(l_bluestore_write_new));
7249+
ASSERT_EQ(i_deferred_w + 1, logger->get(l_bluestore_issued_deferred_writes));
7250+
ASSERT_EQ(0, logger->get(l_bluestore_submitted_deferred_writes));
7251+
}
7252+
}
7253+
auto cct = store->cct;
7254+
// disable DB txc commits during umount,
7255+
// hence deferred op(s) aren't fully committed and
7256+
// kept in DB.
7257+
//
7258+
SetVal(g_conf(), "bluestore_debug_omit_kv_commit", "true");
7259+
g_conf().apply_changes(nullptr);
7260+
store->umount();
7261+
SetVal(g_conf(), "bluestore_debug_omit_kv_commit", "false");
7262+
g_conf().apply_changes(nullptr);
7263+
store = ObjectStore::create(cct,
7264+
get_type(),
7265+
get_data_dir(),
7266+
"store_test_temp_journal");
7267+
store->mount_readonly();
7268+
logger = store->get_perf_counters();
7269+
// make sure we don't inherit old perf counters from the previous mount
7270+
ASSERT_EQ(0, logger->get(l_bluestore_issued_deferred_writes));
7271+
// mount_readonly performs deferred ops replay and submits pending ones,
7272+
// hence we get a submitted deferred write.
7273+
// Deferred op isn't removed though - will see that on the next mount.
7274+
ASSERT_EQ(1, logger->get(l_bluestore_submitted_deferred_writes));
7275+
7276+
store->umount_readonly();
7277+
store = ObjectStore::create(cct,
7278+
get_type(),
7279+
get_data_dir(),
7280+
"store_test_temp_journal");
7281+
store->mount();
7282+
logger = store->get_perf_counters();
7283+
// mount performs deferred ops replay and submits pending ones,
7284+
// preceding mount_readonly left deferred op pending, although applied it.
7285+
// Hence we get a submitted deferred write once again.
7286+
ASSERT_EQ(1, logger->get(l_bluestore_submitted_deferred_writes));
7287+
}
7288+
7289+
#if defined(WITH_BLUESTORE)
7290+
INSTANTIATE_TEST_SUITE_P(
7291+
BlueStore,
7292+
DeferredReplayTest,
7293+
::testing::Values(
7294+
// bdev alloc blob deferred
7295+
deferred_test_t{4 * 1024, 4 * 1024, 16 * 1024, 32 * 1024}
7296+
));
7297+
#endif
7298+
71047299
void doMany4KWritesTest(ObjectStore* store,
71057300
unsigned max_objects,
71067301
unsigned max_ops,

src/test/objectstore/store_test_fixture.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,10 @@ class StoreTestFixture : virtual public ::testing::Test {
4141
}
4242
void PopSettings(size_t);
4343
void CloseAndReopen();
44+
const std::string get_type() const {
45+
return type;
46+
}
47+
const std::string get_data_dir() const {
48+
return data_dir;
49+
}
4450
};

0 commit comments

Comments
 (0)