out.append(ss);
} else if (command == "bluefs files list") {
const char* devnames[3] = {"wal","db","slow"};
- std::lock_guard l(bluefs->dirs_lock);
+ std::lock_guard l(bluefs->nodes.lock);
f->open_array_section("files");
- for (auto &d : bluefs->dir_map) {
+ for (auto &d : bluefs->nodes.dir_map) {
std::string dir = d.first;
for (auto &r : d.second->file_map) {
f->open_object_section("file");
void BlueFS::_update_logger_stats()
{
// we must be holding the lock
- logger->set(l_bluefs_num_files, file_map.size());
- logger->set(l_bluefs_log_bytes, log_writer->file->fnode.size);
+ logger->set(l_bluefs_num_files, nodes.file_map.size());
+ logger->set(l_bluefs_log_bytes, log.writer->file->fnode.size);
if (alloc[BDEV_WAL]) {
logger->set(l_bluefs_wal_total_bytes, _get_total(BDEV_WAL));
int BlueFS::get_block_extents(unsigned id, interval_set<uint64_t> *extents)
{
- std::lock_guard dirl(dirs_lock);
+ std::lock_guard dirl(nodes.lock);
dout(10) << __func__ << " bdev " << id << dendl;
ceph_assert(id < alloc.size());
- for (auto& p : file_map) {
+ for (auto& p : nodes.file_map) {
for (auto& q : p.second->fnode.extents) {
if (q.bdev == id) {
extents->insert(q.offset, q.length);
&log_file->fnode);
vselector->add_usage(log_file->vselector_hint, log_file->fnode);
ceph_assert(r == 0);
- log_writer = _create_writer(log_file);
+ log.writer = _create_writer(log_file);
// initial txn
- log_t.op_init();
+ log.t.op_init();
flush_and_sync_log();
// write supers
// clean up
super = bluefs_super_t();
- _close_writer(log_writer);
- log_writer = NULL;
+ _close_writer(log.writer);
+ log.writer = NULL;
vselector.reset(nullptr);
_stop_alloc();
_shutdown_logger();
}
// init freelist
- for (auto& p : file_map) {
+ for (auto& p : nodes.file_map) {
dout(30) << __func__ << " noting alloc for " << p.second->fnode << dendl;
for (auto& q : p.second->fnode.extents) {
bool is_shared = is_shared_alloc(q.bdev);
}
// set up the log for future writes
- log_writer = _create_writer(_get_file(1));
- ceph_assert(log_writer->file->fnode.ino == 1);
- log_writer->pos = log_writer->file->fnode.size;
- log_writer->file->fnode.reset_delta();
+ log.writer = _create_writer(_get_file(1));
+ ceph_assert(log.writer->file->fnode.ino == 1);
+ log.writer->pos = log.writer->file->fnode.size;
+ log.writer->file->fnode.reset_delta();
dout(10) << __func__ << " log write pos set to 0x"
- << std::hex << log_writer->pos << std::dec
+ << std::hex << log.writer->pos << std::dec
<< dendl;
return 0;
sync_metadata(avoid_compact);
- _close_writer(log_writer);
- log_writer = NULL;
+ _close_writer(log.writer);
+ log.writer = NULL;
vselector.reset(nullptr);
_stop_alloc();
- file_map.clear();
- dir_map.clear();
+ nodes.file_map.clear();
+ nodes.dir_map.clear();
super = bluefs_super_t();
- log_t.clear();
+ log.t.clear();
_shutdown_logger();
}
{
dout(10) << __func__ << (noop ? " NO-OP" : "") << dendl;
ino_last = 1; // by the log
- log_seq = 0;
+ uint64_t log_seq = 0;
FileRef log_file;
log_file = _get_file(1);
if (!noop) {
FileRef file = _get_file(ino);
ceph_assert(file->fnode.ino);
- map<string,DirRef>::iterator q = dir_map.find(dirname);
- ceph_assert(q != dir_map.end());
+ map<string,DirRef>::iterator q = nodes.dir_map.find(dirname);
+ ceph_assert(q != nodes.dir_map.end());
map<string,FileRef>::iterator r = q->second->file_map.find(filename);
ceph_assert(r == q->second->file_map.end());
}
if (!noop) {
- map<string,DirRef>::iterator q = dir_map.find(dirname);
- ceph_assert(q != dir_map.end());
+ map<string,DirRef>::iterator q = nodes.dir_map.find(dirname);
+ ceph_assert(q != nodes.dir_map.end());
map<string,FileRef>::iterator r = q->second->file_map.find(filename);
ceph_assert(r != q->second->file_map.end());
ceph_assert(r->second->refs > 0);
}
if (!noop) {
- map<string,DirRef>::iterator q = dir_map.find(dirname);
- ceph_assert(q == dir_map.end());
- dir_map[dirname] = ceph::make_ref<Dir>();
+ map<string,DirRef>::iterator q = nodes.dir_map.find(dirname);
+ ceph_assert(q == nodes.dir_map.end());
+ nodes.dir_map[dirname] = ceph::make_ref<Dir>();
}
}
break;
}
if (!noop) {
- map<string,DirRef>::iterator q = dir_map.find(dirname);
- ceph_assert(q != dir_map.end());
+ map<string,DirRef>::iterator q = nodes.dir_map.find(dirname);
+ ceph_assert(q != nodes.dir_map.end());
ceph_assert(q->second->file_map.empty());
- dir_map.erase(q);
+ nodes.dir_map.erase(q);
}
}
break;
}
if (!noop) {
- auto p = file_map.find(ino);
- ceph_assert(p != file_map.end());
+ auto p = nodes.file_map.find(ino);
+ ceph_assert(p != nodes.file_map.end());
vselector->sub_usage(p->second->vselector_hint, p->second->fnode);
if (cct->_conf->bluefs_log_replay_check_allocations) {
int r = _check_allocations(p->second->fnode,
return r;
}
}
- file_map.erase(p);
+ nodes.file_map.erase(p);
}
}
break;
}
if (!noop) {
vselector->add_usage(log_file->vselector_hint, log_file->fnode);
+ log.seq_live = log_seq;
+ dirty.seq_next = log_seq + 1;
+ dirty.seq_stable = log_seq;
}
dout(10) << __func__ << " log file size was 0x"
if (!noop) {
// verify file link counts are all >0
- for (auto& p : file_map) {
+ for (auto& p : nodes.file_map) {
if (p.second->refs == 0 &&
p.second->fnode.ino > 1) {
derr << __func__ << " file with link count 0: " << p.second->fnode
int BlueFS::log_dump()
{
// only dump log file's content
+<<<<<<< HEAD
ceph_assert(log_writer == nullptr && "cannot log_dump on mounted BlueFS");
+=======
+ ceph_assert(log.writer == nullptr && "cannot log_dump on mounted BlueFS");
+ _init_logger();
+>>>>>>> b661fa2fbcd (os/bluestore/bluefs: Reorganize BlueFS state variables)
int r = _open_super();
if (r < 0) {
derr << __func__ << " failed to open super: " << cpp_strerror(r) << dendl;
dout(0) << __func__ << " super to be written to " << dev_target << dendl;
}
- for (auto& [ino, file_ref] : file_map) {
+ for (auto& [ino, file_ref] : nodes.file_map) {
//do not copy log
if (file_ref->fnode.ino == 1) {
continue;
flags |= devs_source.count(BDEV_WAL) ? REMOVE_WAL : 0;
int dev_target_new = dev_target; //FIXME: remove, makes no sense
- for (auto& p : file_map) {
+ for (auto& p : nodes.file_map) {
//do not copy log
if (p.second->fnode.ino == 1) {
continue;
BlueFS::FileRef BlueFS::_get_file(uint64_t ino)
{
- auto p = file_map.find(ino);
- if (p == file_map.end()) {
+ auto p = nodes.file_map.find(ino);
+ if (p == nodes.file_map.end()) {
FileRef f = ceph::make_ref<File>();
- file_map[ino] = f;
+ nodes.file_map[ino] = f;
dout(30) << __func__ << " ino " << ino << " = " << f
<< " (new)" << dendl;
return f;
dout(20) << __func__ << " had refs " << file->refs
<< " on " << file->fnode << dendl;
ceph_assert(file->refs > 0);
- ceph_assert(ceph_mutex_is_locked(log_lock));
+ ceph_assert(ceph_mutex_is_locked(log.lock));
--file->refs;
if (file->refs == 0) {
dout(20) << __func__ << " destroying " << file->fnode << dendl;
ceph_assert(file->num_reading.load() == 0);
vselector->sub_usage(file->vselector_hint, file->fnode);
- log_t.op_file_remove(file->fnode.ino);
+ log.t.op_file_remove(file->fnode.ino);
- std::lock_guard dl(dirty_lock);
+ std::lock_guard dl(dirty.lock);
for (auto& r : file->fnode.extents) {
pending_release[r.bdev].insert(r.offset, r.length);
}
- file_map.erase(file->fnode.ino);
+ nodes.file_map.erase(file->fnode.ino);
file->deleted = true;
if (file->dirty_seq) {
// retract request to serialize changes
- ceph_assert(file->dirty_seq > log_seq_stable);
- ceph_assert(dirty_files.count(file->dirty_seq));
- auto it = dirty_files[file->dirty_seq].iterator_to(*file);
- dirty_files[file->dirty_seq].erase(it);
+ ceph_assert(file->dirty_seq > dirty.seq_stable);
+ ceph_assert(dirty.files.count(file->dirty_seq));
+ auto it = dirty.files[file->dirty_seq].iterator_to(*file);
+ dirty.files[file->dirty_seq].erase(it);
file->dirty_seq = 0;
}
}
uint64_t BlueFS::estimate_log_size()
{
- std::lock_guard dirl(dirs_lock);
+ std::lock_guard dirl(nodes.lock);
int avg_dir_size = 40; // fixme
int avg_file_size = 12;
uint64_t size = 4096 * 2;
- size += file_map.size() * (1 + sizeof(bluefs_fnode_t));
- size += dir_map.size() + (1 + avg_dir_size);
- size += file_map.size() * (1 + avg_dir_size + avg_file_size);
+ size += nodes.file_map.size() * (1 + sizeof(bluefs_fnode_t));
+ size += nodes.dir_map.size() + (1 + avg_dir_size);
+ size += nodes.file_map.size() * (1 + avg_dir_size + avg_file_size);
return round_up_to(size, super.block_size);
}
}
uint64_t current;
{
- std::lock_guard dirl(log_lock);
- current = log_writer->file->fnode.size;
+ std::lock_guard dirl(log.lock);
+ current = log.writer->file->fnode.size;
}
uint64_t expected = estimate_log_size();
float ratio = (float)current / (float)expected;
void BlueFS::compact_log_dump_metadata(bluefs_transaction_t *t,
int flags)
{
- std::lock_guard dirl(dirs_lock);
+ std::lock_guard dirl(nodes.lock);
t->seq = 1;
t->uuid = super.uuid;
dout(20) << __func__ << " op_init" << dendl;
t->op_init();
- for (auto& [ino, file_ref] : file_map) {
+ for (auto& [ino, file_ref] : nodes.file_map) {
if (ino == 1)
continue;
ceph_assert(ino > 1);
dout(20) << __func__ << " op_file_update " << file_ref->fnode << dendl;
t->op_file_update(file_ref->fnode);
}
- for (auto& [path, dir_ref] : dir_map) {
+ for (auto& [path, dir_ref] : nodes.dir_map) {
dout(20) << __func__ << " op_dir_create " << path << dendl;
t->op_dir_create(path);
for (auto& [fname, file_ref] : dir_ref->file_map) {
{
dout(10) << __func__ << dendl;
auto prefer_bdev =
- vselector->select_prefer_bdev(log_writer->file->vselector_hint);
+ vselector->select_prefer_bdev(log.writer->file->vselector_hint);
rewrite_log_and_layout_sync(true,
BDEV_DB,
prefer_bdev,
int flags,
std::optional<bluefs_layout_t> layout)
{
- //ceph_assert(ceph_mutex_is_notlocked(log_lock));
- std::lock_guard ll(log_lock);
+ //ceph_assert(ceph_mutex_is_notlocked(log.lock));
+ std::lock_guard ll(log.lock);
- File *log_file = log_writer->file.get();
+ File *log_file = log.writer->file.get();
// clear out log (be careful who calls us!!!)
- log_t.clear();
+ log.t.clear();
dout(20) << __func__ << " super_dev:" << super_dev
<< " log_dev:" << log_dev
bluefs_transaction_t t;
compact_log_dump_metadata(&t, flags);
- dout(20) << __func__ << " op_jump_seq " << log_seq << dendl;
- t.op_jump_seq(log_seq);
+ dout(20) << __func__ << " op_jump_seq " << log.seq_live << dendl;
+ t.op_jump_seq(log.seq_live);
bufferlist bl;
encode(t, bl);
}
}
- _close_writer(log_writer);
+ _close_writer(log.writer);
// we will write it to super
log_file->fnode.reset_delta();
vselector->sub_usage(log_file->vselector_hint, old_fnode);
vselector->add_usage(log_file->vselector_hint, log_file->fnode);
- log_writer = _create_writer(log_file);
- log_writer->append(bl);
- r = _flush_special(log_writer);
+ log.writer = _create_writer(log_file);
+ log.writer->append(bl);
+ r = _flush_special(log.writer);
ceph_assert(r == 0);
#ifdef HAVE_LIBAIO
if (!cct->_conf->bluefs_sync_write) {
list<aio_t> completed_ios;
- _claim_completed_aios(log_writer, &completed_ios);
- wait_for_aio(log_writer);
+ _claim_completed_aios(log.writer, &completed_ios);
+ wait_for_aio(log.writer);
completed_ios.clear();
}
#endif
flush_bdev();
dout(10) << __func__ << " release old log extents " << old_fnode.extents << dendl;
- std::lock_guard dl(dirty_lock);
+ std::lock_guard dl(dirty.lock);
for (auto& r : old_fnode.extents) {
pending_release[r.bdev].insert(r.offset, r.length);
}
return;
}
- log_lock.lock();
- File *log_file = log_writer->file.get();
+ log.lock.lock();
+ File *log_file = log.writer->file.get();
FileWriter *new_log_writer = nullptr;
FileRef new_log = nullptr;
uint64_t new_log_jump_to = 0;
// 1.1 allocate new log space and jump to it.
old_log_jump_to = log_file->fnode.get_allocated();
- uint64_t runway = log_file->fnode.get_allocated() - log_writer->get_effective_write_pos();
+ uint64_t runway = log_file->fnode.get_allocated() - log.writer->get_effective_write_pos();
dout(10) << __func__ << " old_log_jump_to 0x" << std::hex << old_log_jump_to
<< " need 0x" << (old_log_jump_to + cct->_conf->bluefs_max_log_runway) << std::dec << dendl;
int r = _allocate(vselector->select_prefer_bdev(log_file->vselector_hint),
// update the log file change and log a jump to the offset where we want to
// write the new entries
- log_t.op_file_update(log_file->fnode); // 1.2
- log_t.op_jump(log_seq, old_log_jump_to); // 1.3
+ log.t.op_file_update(log_file->fnode); // 1.2
+ log.t.op_jump(log.seq_live, old_log_jump_to); // 1.3
// we need to flush all bdev because we will be streaming all dirty files to log
// TODO - think - if _flush_and_sync_log_jump will not add dirty files nor release pending allocations
flush_bdev();
_flush_and_sync_log_jump(old_log_jump_to, runway);
- log_lock.unlock();
+ log.lock.unlock();
// out of jump section - now log can be used to write to
// 2. prepare compacted log
// conservative estimate for final encoded size
new_log_jump_to = round_up_to(t.op_bl.length() + super.block_size * 2,
max_alloc_size);
- t.op_jump(log_seq, new_log_jump_to);
+ t.op_jump(log.seq_live, new_log_jump_to);
// allocate
//FIXME: check if we want DB here?
// swap the log files. New log file is the log file now.
new_log->fnode.swap_extents(log_file->fnode);
- log_writer->pos = log_writer->file->fnode.size =
- log_writer->pos - old_log_jump_to + new_log_jump_to;
+ log.writer->pos = log.writer->file->fnode.size =
+ log.writer->pos - old_log_jump_to + new_log_jump_to;
vselector->add_usage(log_file->vselector_hint, log_file->fnode);
// 7. release old space
dout(10) << __func__ << " release old log extents " << old_extents << dendl;
{
- std::lock_guard dl(dirty_lock);
+ std::lock_guard dl(dirty.lock);
for (auto& r : old_extents) {
pending_release[r.bdev].insert(r.offset, r.length);
}
// flush_special does not dirty files
/*
if (new_log->dirty_seq) {
- std::lock_guard dl(dirty_lock);
- ceph_assert(dirty_files.count(new_log->dirty_seq));
- auto it = dirty_files[new_log->dirty_seq].iterator_to(*new_log);
- dirty_files[new_log->dirty_seq].erase(it);
+ std::lock_guard dl(dirty.lock);
+ ceph_assert(dirty.files.count(new_log->dirty_seq));
+ auto it = dirty.files[new_log->dirty_seq].iterator_to(*new_log);
+ dirty.files[new_log->dirty_seq].erase(it);
}
*/
new_log_writer = nullptr;
}
/**
- * Adds file modifications from `dirty_files` to bluefs transactions
- * already stored in `log_t`. Writes them to disk and waits until are stable.
+ * Adds file modifications from `dirty.files` to bluefs transactions
+ * already stored in `log.t`. Writes them to disk and waits until are stable.
* Guarantees that file modifications with `want_seq` are already stable on disk.
* In addition may insert jump forward transaction to log write position `jump_to`.
*
* it should lock ability to:
- * 1) add to log_t
- * 2) modify dirty_files
+ * 1) add to log.t
+ * 2) modify dirty.files
* 3) add to pending_release
*
- * pending_release and log_t go with same lock
+ * pending_release and log.t go with same lock
*/
-// Adds to log_t file modifications mentioned in `dirty_files`.
-// Note: some bluefs ops may have already been stored in log_t transaction.
+// Adds to log.t file modifications mentioned in `dirty.files`.
+// Note: some bluefs ops may have already been stored in log.t transaction.
uint64_t BlueFS::_consume_dirty()
{
- ceph_assert(ceph_mutex_is_locked(dirty_lock));
- ceph_assert(ceph_mutex_is_locked(log_lock));
+ ceph_assert(ceph_mutex_is_locked(dirty.lock));
+ ceph_assert(ceph_mutex_is_locked(log.lock));
//acquire new seq
- // this will became log_seq_stable once we write
- uint64_t seq = log_t.seq = ++log_seq;
- log_t.uuid = super.uuid;
+ // this will became seq_stable once we write
+ ++dirty.seq_next;
+ ++log.seq_live;
+ ceph_assert(dirty.seq_next == log.seq_live + 1);
+ uint64_t seq = log.t.seq = log.seq_live;
+ log.t.uuid = super.uuid;
// log dirty files
- // we just incremented log_seq. It is now illegal to add to dirty_files[log_seq]
- auto lsi = dirty_files.find(seq);
- if (lsi != dirty_files.end()) {
- dout(20) << __func__ << " " << lsi->second.size() << " dirty_files" << dendl;
+ // we just incremented log_seq. It is now illegal to add to dirty.files[log_seq]
+ auto lsi = dirty.files.find(seq);
+ if (lsi != dirty.files.end()) {
+ dout(20) << __func__ << " " << lsi->second.size() << " dirty.files" << dendl;
for (auto &f : lsi->second) {
dout(20) << __func__ << " op_file_update_inc " << f.fnode << dendl;
- log_t.op_file_update_inc(f.fnode);
+ log.t.op_file_update_inc(f.fnode);
}
}
return seq;
// Returns space available *BEFORE* adding new space. Signed for additional <0 detection.
int64_t BlueFS::_maybe_extend_log()
{
- ceph_assert(ceph_mutex_is_locked(log_lock));
+ ceph_assert(ceph_mutex_is_locked(log.lock));
// allocate some more space (before we run out)?
- // BTW: this triggers `flush()` in the `page_aligned_appender` of `log_writer`.
- int64_t runway = log_writer->file->fnode.get_allocated() -
- log_writer->get_effective_write_pos();
+ // BTW: this triggers `flush()` in the `page_aligned_appender` of `log.writer`.
+ int64_t runway = log.writer->file->fnode.get_allocated() -
+ log.writer->get_effective_write_pos();
if (runway < (int64_t)cct->_conf->bluefs_min_log_runway) {
dout(10) << __func__ << " allocating more log runway (0x"
<< std::hex << runway << std::dec << " remaining)" << dendl;
if (log_forbidden_to_expand.load() == true) {
return -EWOULDBLOCK;
}
- vselector->sub_usage(log_writer->file->vselector_hint, log_writer->file->fnode);
+ vselector->sub_usage(log.writer->file->vselector_hint, log.writer->file->fnode);
int r = _allocate(
- vselector->select_prefer_bdev(log_writer->file->vselector_hint),
+ vselector->select_prefer_bdev(log.writer->file->vselector_hint),
cct->_conf->bluefs_max_log_runway,
- &log_writer->file->fnode);
+ &log.writer->file->fnode);
ceph_assert(r == 0);
- vselector->add_usage(log_writer->file->vselector_hint, log_writer->file->fnode);
- log_t.op_file_update_inc(log_writer->file->fnode);
+ vselector->add_usage(log.writer->file->vselector_hint, log.writer->file->fnode);
+ log.t.op_file_update_inc(log.writer->file->fnode);
}
return runway;
}
void BlueFS::_flush_and_sync_log_core(int64_t runway)
{
- ceph_assert(ceph_mutex_is_locked(log_lock));
- dout(10) << __func__ << " " << log_t << dendl;
+ ceph_assert(ceph_mutex_is_locked(log.lock));
+ dout(10) << __func__ << " " << log.t << dendl;
bufferlist bl;
bl.reserve(super.block_size);
- encode(log_t, bl);
+ encode(log.t, bl);
// pad to block boundary
size_t realign = super.block_size - (bl.length() % super.block_size);
if (realign && realign != super.block_size)
// transaction will not fit extents before growth -> data loss on _replay
}
- log_writer->append(bl);
+ log.writer->append(bl);
- log_t.clear();
- log_t.seq = 0; // just so debug output is less confusing
+ log.t.clear();
+ log.t.seq = 0; // just so debug output is less confusing
- int r = _flush_special(log_writer);
+ int r = _flush_special(log.writer);
ceph_assert(r == 0);
}
-// Clears dirty_files up to (including) seq_stable.
+// Clears dirty.files up to (including) seq_stable.
void BlueFS::_clear_dirty_set_stable(uint64_t seq)
{
- std::lock_guard lg(dirty_lock);
+ std::lock_guard lg(dirty.lock);
// clean dirty files
- if (seq > log_seq_stable) {
- log_seq_stable = seq;
- dout(20) << __func__ << " log_seq_stable " << log_seq_stable << dendl;
+ if (seq > dirty.seq_stable) {
+ dirty.seq_stable = seq;
+ dout(20) << __func__ << " seq_stable " << dirty.seq_stable << dendl;
// undirty all files that were already streamed to log
- auto p = dirty_files.begin();
- while (p != dirty_files.end()) {
- if (p->first > log_seq_stable) {
+ auto p = dirty.files.begin();
+ while (p != dirty.files.end()) {
+ if (p->first > dirty.seq_stable) {
dout(20) << __func__ << " done cleaning up dirty files" << dendl;
break;
}
while (l != p->second.end()) {
File *file = &*l;
ceph_assert(file->dirty_seq > 0);
- ceph_assert(file->dirty_seq <= log_seq_stable);
+ ceph_assert(file->dirty_seq <= dirty.seq_stable);
dout(20) << __func__ << " cleaned file " << file->fnode << dendl;
file->dirty_seq = 0;
p->second.erase(l++);
}
ceph_assert(p->second.empty());
- dirty_files.erase(p++);
+ dirty.files.erase(p++);
}
} else {
- dout(20) << __func__ << " log_seq_stable " << log_seq_stable
+ dout(20) << __func__ << " seq_stable " << dirty.seq_stable
<< " already >= out seq " << seq
<< ", we lost a race against another log flush, done" << dendl;
}
// we synchronize writing to log, by lock to log_lock
int64_t available_runway;
do {
- log_lock.lock();
- dirty_lock.lock();
- if (want_seq && want_seq <= log_seq_stable) {
- dout(10) << __func__ << " want_seq " << want_seq << " <= log_seq_stable "
- << log_seq_stable << ", done" << dendl;
- dirty_lock.unlock();
- log_lock.unlock();
+ log.lock.lock();
+ dirty.lock.lock();
+ if (want_seq && want_seq <= dirty.seq_stable) {
+ dout(10) << __func__ << " want_seq " << want_seq << " <= seq_stable "
+ << dirty.seq_stable << ", done" << dendl;
+ dirty.lock.unlock();
+ log.lock.unlock();
return 0;
}
available_runway = _maybe_extend_log();
if (available_runway == -EWOULDBLOCK) {
// we are in need of adding runway, but we are during log-switch from compaction
- dirty_lock.unlock();
- //instead log_lock_unlock() do move ownership
- std::unique_lock<ceph::mutex> ll(log_lock, std::adopt_lock);
+ dirty.lock.unlock();
+ //instead log.lock_unlock() do move ownership
+ std::unique_lock<ceph::mutex> ll(log.lock, std::adopt_lock);
while (log_forbidden_to_expand.load()) {
log_cond.wait(ll);
}
}
} while (available_runway < 0);
- ceph_assert(want_seq == 0 || want_seq <= log_seq + 1); // illegal to request seq that was not created yet
+ ceph_assert(want_seq == 0 || want_seq <= log.seq_live); // illegal to request seq that was not created yet
uint64_t seq = _consume_dirty();
vector<interval_set<uint64_t>> to_release(pending_release.size());
to_release.swap(pending_release);
- dirty_lock.unlock();
+ dirty.lock.unlock();
_flush_and_sync_log_core(available_runway);
- _flush_bdev(log_writer);
- //now log_lock is no longer needed
- log_lock.unlock();
+ _flush_bdev(log.writer);
+ //now log.lock is no longer needed
+ log.lock.unlock();
_clear_dirty_set_stable(seq);
_release_pending_allocations(to_release);
int BlueFS::_flush_and_sync_log_jump(uint64_t jump_to,
int64_t available_runway)
{
- ceph_assert(ceph_mutex_is_locked(log_lock));
+ ceph_assert(ceph_mutex_is_locked(log.lock));
ceph_assert(jump_to);
// we synchronize writing to log, by lock to log_lock
- dirty_lock.lock();
+ dirty.lock.lock();
uint64_t seq = _consume_dirty();
vector<interval_set<uint64_t>> to_release(pending_release.size());
to_release.swap(pending_release);
- dirty_lock.unlock();
+ dirty.lock.unlock();
_flush_and_sync_log_core(available_runway);
dout(10) << __func__ << " jumping log offset from 0x" << std::hex
- << log_writer->pos << " -> 0x" << jump_to << std::dec << dendl;
- log_writer->pos = jump_to;
- vselector->sub_usage(log_writer->file->vselector_hint, log_writer->file->fnode.size);
- log_writer->file->fnode.size = jump_to;
- vselector->add_usage(log_writer->file->vselector_hint, log_writer->file->fnode.size);
+ << log.writer->pos << " -> 0x" << jump_to << std::dec << dendl;
+ log.writer->pos = jump_to;
+ vselector->sub_usage(log.writer->file->vselector_hint, log.writer->file->fnode.size);
+ log.writer->file->fnode.size = jump_to;
+ vselector->add_usage(log.writer->file->vselector_hint, log.writer->file->fnode.size);
- _flush_bdev(log_writer);
+ _flush_bdev(log.writer);
_clear_dirty_set_stable(seq);
_release_pending_allocations(to_release);
int BlueFS::_signal_dirty_to_log(FileWriter *h)
{
ceph_assert(ceph_mutex_is_locked(h->lock));
- std::lock_guard dl(dirty_lock);
+ std::lock_guard dl(dirty.lock);
if (h->file->deleted) {
dout(10) << __func__ << " deleted, no-op" << dendl;
return 0;
h->file->fnode.mtime = ceph_clock_now();
ceph_assert(h->file->fnode.ino >= 1);
if (h->file->dirty_seq == 0) {
- h->file->dirty_seq = log_seq + 1;
- dirty_files[h->file->dirty_seq].push_back(*h->file);
- dout(20) << __func__ << " dirty_seq = " << log_seq + 1
+ h->file->dirty_seq = dirty.seq_next;
+ dirty.files[h->file->dirty_seq].push_back(*h->file);
+ dout(20) << __func__ << " dirty_seq = " << dirty.seq_next
<< " (was clean)" << dendl;
} else {
- if (h->file->dirty_seq != log_seq + 1) {
+ if (h->file->dirty_seq != dirty.seq_next) {
// need re-dirty, erase from list first
- ceph_assert(dirty_files.count(h->file->dirty_seq));
- auto it = dirty_files[h->file->dirty_seq].iterator_to(*h->file);
- dirty_files[h->file->dirty_seq].erase(it);
- h->file->dirty_seq = log_seq + 1;
- dirty_files[h->file->dirty_seq].push_back(*h->file);
- dout(20) << __func__ << " dirty_seq = " << log_seq + 1
+ ceph_assert(dirty.files.count(h->file->dirty_seq));
+ auto it = dirty.files[h->file->dirty_seq].iterator_to(*h->file);
+ dirty.files[h->file->dirty_seq].erase(it);
+ h->file->dirty_seq = dirty.seq_next;
+ dirty.files[h->file->dirty_seq].push_back(*h->file);
+ dout(20) << __func__ << " dirty_seq = " << dirty.seq_next
<< " (was " << h->file->dirty_seq << ")" << dendl;
} else {
- dout(20) << __func__ << " dirty_seq = " << log_seq + 1
+ dout(20) << __func__ << " dirty_seq = " << dirty.seq_next
<< " (unchanged, do nothing) " << dendl;
}
}
h->file->fnode.size = offset;
vselector->add_usage(h->file->vselector_hint, h->file->fnode.size);
- std::lock_guard ll(log_lock);
- log_t.op_file_update_inc(h->file->fnode);
+ std::lock_guard ll(log.lock);
+ log.t.op_file_update_inc(h->file->fnode);
return 0;
}
_flush_bdev(h);
if (old_dirty_seq) {
- uint64_t s = log_seq;
+ uint64_t s = log.seq_live; // AKAK !!! locks!
dout(20) << __func__ << " file metadata was dirty (" << old_dirty_seq
<< ") on " << h->file->fnode << ", flushing log" << dendl;
flush_and_sync_log(old_dirty_seq);
return 0;
}
-// be careful - either h->file->lock or log_lock must be taken
+// be careful - either h->file->lock or log.lock must be taken
void BlueFS::_flush_bdev(FileWriter *h)
{
if (h->file->fnode.ino != 1) {
ceph_assert(ceph_mutex_is_locked(h->lock));
} else {
- ceph_assert(ceph_mutex_is_locked(log_lock));
+ ceph_assert(ceph_mutex_is_locked(log.lock));
}
std::array<bool, MAX_BDEV> flush_devs = h->dirty_devs;
h->dirty_devs.fill(false);
vselector->add_usage(f->vselector_hint, f->fnode);
if (r < 0)
return r;
- std::lock_guard ll(log_lock);
- log_t.op_file_update_inc(f->fnode);
+ std::lock_guard ll(log.lock);
+ log.t.op_file_update_inc(f->fnode);
}
return 0;
}
{
bool can_skip_flush;
{
- std::lock_guard ll(log_lock);
- std::lock_guard dl(dirty_lock);
- can_skip_flush = log_t.empty() && dirty_files.empty();
+ std::lock_guard ll(log.lock);
+ std::lock_guard dl(dirty.lock);
+ can_skip_flush = log.t.empty() && dirty.files.empty();
}
if (can_skip_flush) {
dout(10) << __func__ << " - no pending log events" << dendl;
FileWriter **h,
bool overwrite)
{
- std::lock_guard dirl(dirs_lock);
+ std::lock_guard dirl(nodes.lock);
dout(10) << __func__ << " " << dirname << "/" << filename << dendl;
- map<string,DirRef>::iterator p = dir_map.find(dirname);
+ map<string,DirRef>::iterator p = nodes.dir_map.find(dirname);
DirRef dir;
- if (p == dir_map.end()) {
+ if (p == nodes.dir_map.end()) {
// implicitly create the dir
dout(20) << __func__ << " dir " << dirname
<< " does not exist" << dendl;
}
file = ceph::make_ref<File>();
file->fnode.ino = ++ino_last;
- file_map[ino_last] = file;
+ nodes.file_map[ino_last] = file;
dir->file_map[string{filename}] = file;
++file->refs;
create = true;
<< " vsel_hint " << file->vselector_hint
<< dendl;
{
- std::lock_guard ll(log_lock);
- log_t.op_file_update(file->fnode);
+ 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);
+ log.t.op_dir_link(dirname, filename, file->fnode.ino);
}
*h = _create_writer(file);
FileReader **h,
bool random)
{
- std::lock_guard dirl(dirs_lock);
+ std::lock_guard dirl(nodes.lock);
dout(10) << __func__ << " " << dirname << "/" << filename
<< (random ? " (random)":" (sequential)") << dendl;
- map<string,DirRef>::iterator p = dir_map.find(dirname);
- if (p == dir_map.end()) {
+ map<string,DirRef>::iterator p = nodes.dir_map.find(dirname);
+ if (p == nodes.dir_map.end()) {
dout(20) << __func__ << " dir " << dirname << " not found" << dendl;
return -ENOENT;
}
std::string_view old_dirname, std::string_view old_filename,
std::string_view new_dirname, std::string_view new_filename)
{
- std::lock_guard dirl(dirs_lock);
- std::lock_guard ll(log_lock);
+ std::lock_guard dirl(nodes.lock);
+ std::lock_guard ll(log.lock);
dout(10) << __func__ << " " << old_dirname << "/" << old_filename
<< " -> " << new_dirname << "/" << new_filename << dendl;
- map<string,DirRef>::iterator p = dir_map.find(old_dirname);
- if (p == dir_map.end()) {
+ map<string,DirRef>::iterator p = nodes.dir_map.find(old_dirname);
+ if (p == nodes.dir_map.end()) {
dout(20) << __func__ << " dir " << old_dirname << " not found" << dendl;
return -ENOENT;
}
}
FileRef file = q->second;
- p = dir_map.find(new_dirname);
- if (p == dir_map.end()) {
+ p = nodes.dir_map.find(new_dirname);
+ if (p == nodes.dir_map.end()) {
dout(20) << __func__ << " dir " << new_dirname << " not found" << dendl;
return -ENOENT;
}
<< ") file " << new_filename
<< " already exists, unlinking" << dendl;
ceph_assert(q->second != file);
- log_t.op_dir_unlink(new_dirname, new_filename);
+ log.t.op_dir_unlink(new_dirname, new_filename);
_drop_link(q->second);
}
new_dir->file_map[string{new_filename}] = file;
old_dir->file_map.erase(string{old_filename});
- log_t.op_dir_link(new_dirname, new_filename, file->fnode.ino);
- log_t.op_dir_unlink(old_dirname, old_filename);
+ log.t.op_dir_link(new_dirname, new_filename, file->fnode.ino);
+ log.t.op_dir_unlink(old_dirname, old_filename);
return 0;
}
int BlueFS::mkdir(std::string_view dirname)
{
- std::lock_guard dirl(dirs_lock);
- std::lock_guard ll(log_lock);
+ std::lock_guard dirl(nodes.lock);
+ std::lock_guard ll(log.lock);
dout(10) << __func__ << " " << dirname << dendl;
- map<string,DirRef>::iterator p = dir_map.find(dirname);
- if (p != dir_map.end()) {
+ map<string,DirRef>::iterator p = nodes.dir_map.find(dirname);
+ if (p != nodes.dir_map.end()) {
dout(20) << __func__ << " dir " << dirname << " exists" << dendl;
return -EEXIST;
}
- dir_map[string{dirname}] = ceph::make_ref<Dir>();
- log_t.op_dir_create(dirname);
+ nodes.dir_map[string{dirname}] = ceph::make_ref<Dir>();
+ log.t.op_dir_create(dirname);
return 0;
}
int BlueFS::rmdir(std::string_view dirname)
{
- std::lock_guard dirl(dirs_lock);
- std::lock_guard ll(log_lock);
+ std::lock_guard dirl(nodes.lock);
+ std::lock_guard ll(log.lock);
dout(10) << __func__ << " " << dirname << dendl;
- auto p = dir_map.find(dirname);
- if (p == dir_map.end()) {
+ auto p = nodes.dir_map.find(dirname);
+ if (p == nodes.dir_map.end()) {
dout(20) << __func__ << " dir " << dirname << " does not exist" << dendl;
return -ENOENT;
}
dout(20) << __func__ << " dir " << dirname << " not empty" << dendl;
return -ENOTEMPTY;
}
- dir_map.erase(string{dirname});
- log_t.op_dir_remove(dirname);
+ nodes.dir_map.erase(string{dirname});
+ log.t.op_dir_remove(dirname);
return 0;
}
bool BlueFS::dir_exists(std::string_view dirname)
{
- std::lock_guard dirl(dirs_lock);
- map<string,DirRef>::iterator p = dir_map.find(dirname);
- bool exists = p != dir_map.end();
+ std::lock_guard dirl(nodes.lock);
+ map<string,DirRef>::iterator p = nodes.dir_map.find(dirname);
+ bool exists = p != nodes.dir_map.end();
dout(10) << __func__ << " " << dirname << " = " << (int)exists << dendl;
return exists;
}
int BlueFS::stat(std::string_view dirname, std::string_view filename,
uint64_t *size, utime_t *mtime)
{
- std::lock_guard dirl(dirs_lock);
+ std::lock_guard dirl(nodes.lock);
dout(10) << __func__ << " " << dirname << "/" << filename << dendl;
- map<string,DirRef>::iterator p = dir_map.find(dirname);
- if (p == dir_map.end()) {
+ map<string,DirRef>::iterator p = nodes.dir_map.find(dirname);
+ if (p == nodes.dir_map.end()) {
dout(20) << __func__ << " dir " << dirname << " not found" << dendl;
return -ENOENT;
}
int BlueFS::lock_file(std::string_view dirname, std::string_view filename,
FileLock **plock)
{
- std::lock_guard dirl(dirs_lock);
+ std::lock_guard dirl(nodes.lock);
dout(10) << __func__ << " " << dirname << "/" << filename << dendl;
- map<string,DirRef>::iterator p = dir_map.find(dirname);
- if (p == dir_map.end()) {
+ map<string,DirRef>::iterator p = nodes.dir_map.find(dirname);
+ if (p == nodes.dir_map.end()) {
dout(20) << __func__ << " dir " << dirname << " not found" << dendl;
return -ENOENT;
}
file = ceph::make_ref<File>();
file->fnode.ino = ++ino_last;
file->fnode.mtime = ceph_clock_now();
- file_map[ino_last] = file;
+ nodes.file_map[ino_last] = file;
dir->file_map[string{filename}] = file;
++file->refs;
- std::lock_guard ll(log_lock);
- log_t.op_file_update(file->fnode);
- log_t.op_dir_link(dirname, filename, file->fnode.ino);
+ std::lock_guard ll(log.lock);
+ log.t.op_file_update(file->fnode);
+ log.t.op_dir_link(dirname, filename, file->fnode.ino);
} else {
file = q->second;
if (file->locked) {
int BlueFS::unlock_file(FileLock *fl)
{
- std::lock_guard dirl(dirs_lock);
+ std::lock_guard dirl(nodes.lock);
dout(10) << __func__ << " " << fl << " on " << fl->file->fnode << dendl;
ceph_assert(fl->file->locked);
fl->file->locked = false;
if (!dirname.empty() && dirname.back() == '/') {
dirname.remove_suffix(1);
}
- std::lock_guard dirl(dirs_lock);
+ std::lock_guard dirl(nodes.lock);
dout(10) << __func__ << " " << dirname << dendl;
if (dirname.empty()) {
// list dirs
- ls->reserve(dir_map.size() + 2);
- for (auto& q : dir_map) {
+ ls->reserve(nodes.dir_map.size() + 2);
+ for (auto& q : nodes.dir_map) {
ls->push_back(q.first);
}
} else {
// list files in dir
- map<string,DirRef>::iterator p = dir_map.find(dirname);
- if (p == dir_map.end()) {
+ map<string,DirRef>::iterator p = nodes.dir_map.find(dirname);
+ if (p == nodes.dir_map.end()) {
dout(20) << __func__ << " dir " << dirname << " not found" << dendl;
return -ENOENT;
}
int BlueFS::unlink(std::string_view dirname, std::string_view filename)
{
- std::lock_guard dirl(dirs_lock);
- std::lock_guard ll(log_lock);
+ std::lock_guard dirl(nodes.lock);
+ std::lock_guard ll(log.lock);
dout(10) << __func__ << " " << dirname << "/" << filename << dendl;
- map<string,DirRef>::iterator p = dir_map.find(dirname);
- if (p == dir_map.end()) {
+ map<string,DirRef>::iterator p = nodes.dir_map.find(dirname);
+ if (p == nodes.dir_map.end()) {
dout(20) << __func__ << " dir " << dirname << " not found" << dendl;
return -ENOENT;
}
return -EBUSY;
}
dir->file_map.erase(string{filename});
- log_t.op_dir_unlink(dirname, filename);
+ log.t.op_dir_unlink(dirname, filename);
_drop_link(file);
return 0;
}
dout(2) << __func__ << " processing " << get_device_name(dev) << dendl;
interval_set<uint64_t> disk_regions;
disk_regions.insert(0, bdev[dev]->get_size());
- for (auto f : file_map) {
+ for (auto f : nodes.file_map) {
auto& e = f.second->fnode.extents;
for (auto& p : e) {
if (p.bdev == dev) {