Fix stale memory access with FSBuffer and tiered sec cache (#12712) · facebook/rocksdb@6c60c8f (original) (raw)

`@@ -873,6 +873,111 @@ TEST_P(DBTieredAdmPolicyTest, CompressedCacheAdmission) {

`

873

873

`Destroy(options);

`

874

874

`}

`

875

875

``

``

876

`+

TEST_F(DBTieredSecondaryCacheTest, FSBufferTest) {

`

``

877

`+

class WrapFS : public FileSystemWrapper {

`

``

878

`+

public:

`

``

879

`+

explicit WrapFS(const std::shared_ptr& _target)

`

``

880

`+

: FileSystemWrapper(_target) {}

`

``

881

`+

~WrapFS() override {}

`

``

882

`+

const char* Name() const override { return "WrapFS"; }

`

``

883

+

``

884

`+

IOStatus NewRandomAccessFile(const std::string& fname,

`

``

885

`+

const FileOptions& opts,

`

``

886

`+

std::unique_ptr* result,

`

``

887

`+

IODebugContext* dbg) override {

`

``

888

`+

class WrappedRandomAccessFile : public FSRandomAccessFileOwnerWrapper {

`

``

889

`+

public:

`

``

890

`+

explicit WrappedRandomAccessFile(

`

``

891

`+

std::unique_ptr& file)

`

``

892

`+

: FSRandomAccessFileOwnerWrapper(std::move(file)) {}

`

``

893

+

``

894

`+

IOStatus MultiRead(FSReadRequest* reqs, size_t num_reqs,

`

``

895

`+

const IOOptions& options,

`

``

896

`+

IODebugContext* dbg) override {

`

``

897

`+

for (size_t i = 0; i < num_reqs; ++i) {

`

``

898

`+

FSReadRequest& req = reqs[i];

`

``

899

`+

FSAllocationPtr buffer(new char[req.len], [](void* ptr) {

`

``

900

`+

delete[] static_cast<char*>(ptr);

`

``

901

`+

});

`

``

902

`+

req.fs_scratch = std::move(buffer);

`

``

903

`+

req.status = Read(req.offset, req.len, options, &req.result,

`

``

904

`+

static_cast<char*>(req.fs_scratch.get()), dbg);

`

``

905

`+

}

`

``

906

`+

return IOStatus::OK();

`

``

907

`+

}

`

``

908

`+

};

`

``

909

+

``

910

`+

std::unique_ptr file;

`

``

911

`+

IOStatus s = target()->NewRandomAccessFile(fname, opts, &file, dbg);

`

``

912

`+

EXPECT_OK(s);

`

``

913

`+

result->reset(new WrappedRandomAccessFile(file));

`

``

914

+

``

915

`+

return s;

`

``

916

`+

}

`

``

917

+

``

918

`+

void SupportedOps(int64_t& supported_ops) override {

`

``

919

`+

supported_ops = 1 << FSSupportedOps::kAsyncIO;

`

``

920

`+

supported_ops |= 1 << FSSupportedOps::kFSBuffer;

`

``

921

`+

}

`

``

922

`+

};

`

``

923

+

``

924

`+

if (!LZ4_Supported()) {

`

``

925

`+

ROCKSDB_GTEST_SKIP("This test requires LZ4 support.");

`

``

926

`+

return;

`

``

927

`+

}

`

``

928

+

``

929

`+

std::shared_ptr wrap_fs =

`

``

930

`+

std::make_shared(env_->GetFileSystem());

`

``

931

`+

std::unique_ptr wrap_env(new CompositeEnvWrapper(env_, wrap_fs));

`

``

932

`+

BlockBasedTableOptions table_options;

`

``

933

`+

table_options.block_cache = NewCache(250 * 1024, 20 * 1024, 256 * 1024,

`

``

934

`+

TieredAdmissionPolicy::kAdmPolicyAuto,

`

``

935

`+

/ready_before_wait=/true);

`

``

936

`+

table_options.block_size = 4 * 1024;

`

``

937

`+

table_options.cache_index_and_filter_blocks = false;

`

``

938

`+

Options options = GetDefaultOptions();

`

``

939

`+

options.create_if_missing = true;

`

``

940

`+

options.table_factory.reset(NewBlockBasedTableFactory(table_options));

`

``

941

`+

options.statistics = CreateDBStatistics();

`

``

942

`+

options.env = wrap_env.get();

`

``

943

+

``

944

`+

options.paranoid_file_checks = false;

`

``

945

`+

DestroyAndReopen(options);

`

``

946

`+

Random rnd(301);

`

``

947

`+

const int N = 256;

`

``

948

`+

for (int i = 0; i < N; i++) {

`

``

949

`+

std::string p_v;

`

``

950

`+

test::CompressibleString(&rnd, 0.5, 1007, &p_v);

`

``

951

`+

ASSERT_OK(Put(Key(i), p_v));

`

``

952

`+

}

`

``

953

+

``

954

`+

ASSERT_OK(Flush());

`

``

955

+

``

956

`+

std::vectorstd::string keys;

`

``

957

`+

std::vectorstd::string values;

`

``

958

+

``

959

`+

keys.push_back(Key(0));

`

``

960

`+

keys.push_back(Key(4));

`

``

961

`+

keys.push_back(Key(8));

`

``

962

`+

values = MultiGet(keys, /snapshot=/nullptr, /async=/true);

`

``

963

`+

ASSERT_EQ(values.size(), keys.size());

`

``

964

`+

for (const auto& value : values) {

`

``

965

`+

ASSERT_EQ(1007, value.size());

`

``

966

`+

}

`

``

967

`+

ASSERT_EQ(nvm_sec_cache()->num_insert_saved(), 3u);

`

``

968

`+

ASSERT_EQ(nvm_sec_cache()->num_misses(), 3u);

`

``

969

`+

ASSERT_EQ(nvm_sec_cache()->num_hits(), 0u);

`

``

970

+

``

971

`+

std::string v = Get(Key(12));

`

``

972

`+

ASSERT_EQ(1007, v.size());

`

``

973

`+

ASSERT_EQ(nvm_sec_cache()->num_insert_saved(), 4u);

`

``

974

`+

ASSERT_EQ(nvm_sec_cache()->num_misses(), 4u);

`

``

975

`+

ASSERT_EQ(options.statistics->getTickerCount(BLOCK_CACHE_MISS), 4u);

`

``

976

+

``

977

`+

Close();

`

``

978

`+

Destroy(options);

`

``

979

`+

}

`

``

980

+

876

981

`INSTANTIATE_TEST_CASE_P(

`

877

982

` DBTieredAdmPolicyTest, DBTieredAdmPolicyTest,

`

878

983

`::testing::Values(TieredAdmissionPolicy::kAdmPolicyAuto,

`