Merge pull request #50185 from ethanwu-syno/bluefs_tracker_56210

os/bluestore/bluefs: fix dir_link might add link that already exists in compact log

Reviewed-by: Igor Fedotov <ifedotov@suse.com>
Reviewed-by: Adam Kupczyk <akupczyk@redhat.com>
This commit is contained in:
Yuri Weinstein 2023-04-10 11:54:59 -07:00 committed by GitHub
commit a182bc7eb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 81 additions and 12 deletions

View File

@ -3929,7 +3929,7 @@ int BlueFS::open_for_write(
std::string_view dirname,
std::string_view filename,
FileWriter **h,
bool overwrite)/*_N_LD*/
bool overwrite)/*_LND*/
{
_maybe_check_vselector_LNF();
FileRef file;
@ -3937,7 +3937,8 @@ int BlueFS::open_for_write(
bool truncate = false;
mempool::bluefs::vector<bluefs_extent_t> pending_release_extents;
{
std::unique_lock nl(nodes.lock);
std::lock_guard ll(log.lock);
std::lock_guard nl(nodes.lock);
dout(10) << __func__ << " " << dirname << "/" << filename << dendl;
map<string,DirRef>::iterator p = nodes.dir_map.find(dirname);
DirRef dir;
@ -3995,17 +3996,15 @@ int BlueFS::open_for_write(
dout(20) << __func__ << " mapping " << dirname << "/" << filename
<< " vsel_hint " << file->vselector_hint
<< dendl;
}
{
std::lock_guard ll(log.lock);
log.t.op_file_update(file->fnode);
if (create)
log.t.op_dir_link(dirname, filename, file->fnode.ino);
std::lock_guard dl(dirty.lock);
for (auto& p : pending_release_extents) {
dirty.pending_release[p.bdev].insert(p.offset, p.length);
}
log.t.op_file_update(file->fnode);
if (create)
log.t.op_dir_link(dirname, filename, file->fnode.ino);
std::lock_guard dl(dirty.lock);
for (auto& p : pending_release_extents) {
dirty.pending_release[p.bdev].insert(p.offset, p.length);
}
}
*h = _create_writer(file);

View File

@ -1331,6 +1331,76 @@ TEST(BlueFS, test_4k_shared_alloc) {
fs.umount();
}
void create_files(BlueFS &fs,
atomic_bool& stop_creating,
atomic_bool& started_creating)
{
uint32_t i = 0;
stringstream ss;
string dir = "dir.";
ss << std::this_thread::get_id();
dir.append(ss.str());
dir.append(".");
dir.append(to_string(i));
ASSERT_EQ(0, fs.mkdir(dir));
while (!stop_creating.load()) {
string file = "file.";
file.append(to_string(i));
BlueFS::FileWriter *h;
ASSERT_EQ(0, fs.open_for_write(dir, file, &h, false));
ASSERT_NE(nullptr, h);
fs.close_writer(h);
i++;
started_creating = true;
}
}
TEST(BlueFS, test_concurrent_dir_link_and_compact_log_56210) {
uint64_t size = 1048576 * 128;
TempBdev bdev{size};
ConfSaver conf(g_ceph_context->_conf);
conf.SetVal("bluefs_alloc_size", "65536");
conf.SetVal("bluefs_compact_log_sync", "false");
// make sure fsync always trigger log compact
conf.SetVal("bluefs_log_compact_min_ratio", "0");
conf.SetVal("bluefs_log_compact_min_size", "0");
conf.ApplyChanges();
for (int i=0; i<10; ++i) {
BlueFS fs(g_ceph_context);
ASSERT_EQ(0, fs.add_block_device(BlueFS::BDEV_DB, bdev.path, false, 1048576));
uuid_d fsid;
ASSERT_EQ(0, fs.mkfs(fsid, { BlueFS::BDEV_DB, false, false }));
ASSERT_EQ(0, fs.mount());
ASSERT_EQ(0, fs.maybe_verify_layout({ BlueFS::BDEV_DB, false, false }));
{
atomic_bool stop_creating{false};
atomic_bool started_creating{false};
std::thread create_thread;
create_thread = std::thread(create_files,
std::ref(fs),
std::ref(stop_creating),
std::ref(started_creating));
while (!started_creating.load()) {
}
BlueFS::FileWriter *h;
ASSERT_EQ(0, fs.mkdir("foo"));
ASSERT_EQ(0, fs.open_for_write("foo", "bar", &h, false));
fs.fsync(h);
fs.close_writer(h);
stop_creating = true;
do_join(create_thread);
fs.umount(true); //do not compact on exit!
ASSERT_EQ(0, fs.mount());
fs.umount();
}
}
}
int main(int argc, char **argv) {
auto args = argv_to_vec(argc, argv);
map<string,string> defaults = {