Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ project(llfs CXX)
include(${COR_CMAKE_INCLUDE_DIR}/common.cmake)
include(${CMAKE_BINARY_DIR}/conan_find_requirements.cmake)

#==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - -
# Disable link-time optimization. (Breaks Apple Silicon and Windows builds)
#
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE)

#==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - -
# Do not attempt to set/fix rpath for binaries.
#
Expand Down
4 changes: 2 additions & 2 deletions conan.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"version": "0.5",
"requires": [
"batteries/0.63.0",
"batteries/0.70.1",
"boost/1.88.0",
"bzip2/1.0.8",
"cli11/2.5.0",
Expand All @@ -26,7 +26,7 @@
"ninja/1.13.2"
],
"python_requires": [
"cor_recipe_utils/0.18.2"
"cor_recipe_utils/0.19.1"
],
"overrides": {
"boost/[>=1.88.0 <2]": [
Expand Down
18 changes: 11 additions & 7 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
# See https://www.apache.org/licenses/LICENSE-2.0 for license information.
# SPDX short identifier: Apache-2.0
#
#+++++++++++-+-+--+----- --- -- - - - -
import io, os, platform, shlex, subprocess, sys

from conan import ConanFile
from conan.errors import ConanInvalidConfiguration

import io, os, platform, shlex, subprocess
from conan.tools.scm import Version


class LlfsConan(ConanFile):
Expand Down Expand Up @@ -37,7 +36,7 @@ class LlfsConan(ConanFile):
"shared": False,
}

python_requires = "cor_recipe_utils/0.18.2"
python_requires = "cor_recipe_utils/0.19.1"
python_requires_extend = "cor_recipe_utils.ConanFileBase"

tool_requires = [
Expand Down Expand Up @@ -119,20 +118,25 @@ def package_info(self):
def package_id(self):
return self.cor.package_id_lib_default(self)

#+++++++++++-+-+--+----- --- -- - - - -

def validate_build(self):
if self.settings.compiler == "gcc":
out_capture = io.StringIO()
from_conf = self.conf.get('tools.build:compiler_executables')
cc_name = (
self.buildenv.vars(self).get('CC') or
self.buildenv.vars(self).get('CXX') or
os.getenv('CC') or
os.getenv('CXX') or
(from_conf and from_conf.get('cpp')) or
'gcc'
)
self.run(shlex.join([cc_name, '-dumpversion']), stdout=out_capture, shell=True)
actual_compiler_version = out_capture.getvalue().strip()
profile_compiler_version = str(self.settings.compiler.version)
if profile_compiler_version != actual_compiler_version:
actual_compiler_version = Version(out_capture.getvalue().strip())
profile_compiler_version = Version(str(self.settings.compiler.version))

if profile_compiler_version.major != actual_compiler_version.major:
raise ConanInvalidConfiguration(f"Compiler version mismatch: actual={actual_compiler_version}"
f", expected={profile_compiler_version}")

Expand Down
2 changes: 1 addition & 1 deletion cor.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
cor:
cli:
version: 0.18.2
version: 0.19.1
8 changes: 8 additions & 0 deletions src/llfs/api_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,18 @@ BATT_STRONG_TYPEDEF(bool, UseParallelCopy);
*/
BATT_STRONG_TYPEDEF(u64, TrimDelayByteCount);

/** \brief A number of bytes at the scale of file sizes.
*/
BATT_STRONG_TYPEDEF(i64, FileByteCount);

/** \brief Wrapper for off_t used as an offset.
*/
BATT_STRONG_TYPEDEF(i64, FileOffset);

/** \brief A file size or number of bytes at the scale of file sizes.
*/
BATT_STRONG_TYPEDEF(i64, FileSize);

/** \brief Wrapper for off_t used as a dirent offset.
*/
BATT_STRONG_TYPEDEF(off_t, DirentOffset);
Expand Down
2 changes: 2 additions & 0 deletions src/llfs/page_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include <boost/range/irange.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <chrono>

namespace llfs {

u64 PageAllocator::calculate_log_size(u64 physical_page_count, u64 max_attachments)
Expand Down
44 changes: 40 additions & 4 deletions src/llfs/page_cache_slot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,21 @@ auto PageCacheSlot::fill(PageId key, PageSize page_size, i64 lru_priority, Exter
this->page_size_ = page_size;
this->update_latest_use(lru_priority);

auto observed_state = this->state_.fetch_add(kPinCountDelta) + kPinCountDelta;
BATT_CHECK_EQ(observed_state & Self::kOverflowMask, 0);
BATT_CHECK(Self::is_pinned(observed_state));
if (PageCacheSlot::eviction_pause() == false) {
auto observed_state = this->state_.fetch_add(kPinCountDelta) + kPinCountDelta;
BATT_CHECK_EQ(observed_state & Self::kOverflowMask, 0);
BATT_CHECK(Self::is_pinned(observed_state));
}

this->pool_.metrics().admit_count.add(1);
this->pool_.metrics().admit_byte_count.add(page_size);

claim.absorb();

this->add_pinned_bytes(page_size);
if (PageCacheSlot::eviction_pause() == false) {
this->add_pinned_bytes(page_size);
PageCacheSlot::add_pin_count();
}
this->add_ref();
this->set_valid();

Expand Down Expand Up @@ -91,6 +96,10 @@ void PageCacheSlot::clear()
//
bool PageCacheSlot::evict()
{
if (PageCacheSlot::eviction_pause()) {
return false;
}

// Use a CAS loop here to guarantee an atomic transition from Valid + Filled (unpinned) state to
// Invalid.
//
Expand All @@ -116,6 +125,10 @@ bool PageCacheSlot::evict_if_key_equals(PageId key)
{
static_assert(std::is_same_v<decltype(this->state_)::value_type, u64>);

if (PageCacheSlot::eviction_pause()) {
return false;
}

// The slot must be pinned in order to read the key, so increase the pin count.
//
const u64 old_state = this->state_.fetch_add(kPinCountDelta, std::memory_order_acquire);
Expand All @@ -126,6 +139,7 @@ bool PageCacheSlot::evict_if_key_equals(PageId key)
this->add_pinned_bytes(this->page_size_);
this->add_ref();
}
PageCacheSlot::add_pin_count();

BATT_CHECK_EQ(observed_state & Self::kOverflowMask, 0);

Expand Down Expand Up @@ -156,6 +170,8 @@ bool PageCacheSlot::evict_if_key_equals(PageId key)
this->add_unpinned_bytes(saved_page_size);
this->on_evict_success(nullptr);

PageCacheSlot::add_unpin_count();

// At this point, we always expect to be going from pinned to unpinned.
// In order to successfully evict the slot, we must be holding the only pin,
// as guarenteed by the first if statement in the for loop.
Expand All @@ -172,6 +188,10 @@ bool PageCacheSlot::evict_and_release_pin(ExternalAllocation* reclaim)
{
static_assert(std::is_same_v<decltype(this->state_)::value_type, u64>);

if (PageCacheSlot::eviction_pause()) {
return false;
}

u64 observed_state = this->state_.load(std::memory_order_acquire);

BATT_CHECK(Self::is_pinned(observed_state));
Expand Down Expand Up @@ -203,6 +223,8 @@ bool PageCacheSlot::evict_and_release_pin(ExternalAllocation* reclaim)
this->add_unpinned_bytes(saved_page_size);
this->on_evict_success(reclaim);

PageCacheSlot::add_unpin_count();

// At this point, we always expect to be going from pinned to unpinned.
// In order to successfully evict the slot, we must be holding the only pin,
// as guarenteed by the first if statement in the for loop.
Expand Down Expand Up @@ -267,6 +289,20 @@ void PageCacheSlot::notify_last_ref_released()

#endif // LLFS_PAGE_CACHE_SLOT_UPDATE_POOL_REF_COUNT

//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - -
//
/*static*/ void PageCacheSlot::add_pin_count()
{
Pool::Metrics::instance().pin_count.add(1);
}

//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - -
//
/*static*/ void PageCacheSlot::add_unpin_count()
{
Pool::Metrics::instance().unpin_count.add(1);
}

//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - -
//
void PageCacheSlot::ExternalAllocation::release() noexcept
Expand Down
33 changes: 33 additions & 0 deletions src/llfs/page_cache_slot.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,17 @@ class PageCacheSlot

//+++++++++++-+-+--+----- --- -- - - - -

/** \brief When set to true, no evictions are allowed. Any pins that happen while evictions are
* paused do nothing.
*/
static std::atomic<bool>& eviction_pause() noexcept
{
static std::atomic<bool> b_{false};
return b_;
}

//+++++++++++-+-+--+----- --- -- - - - -

PageCacheSlot(const PageCacheSlot&) = delete;
PageCacheSlot& operator=(const PageCacheSlot&) = delete;

Expand Down Expand Up @@ -426,6 +437,11 @@ class PageCacheSlot

//+++++++++++-+-+--+----- --- -- - - - -
private:
static void add_pin_count();
static void add_unpin_count();

//+++++++++++-+-+--+----- --- -- - - - -

/** \brief The implementation of acquire_pin; returns true iff successful.
*/
bool acquire_pin_impl(PageId key);
Expand Down Expand Up @@ -561,6 +577,10 @@ BATT_ALWAYS_INLINE inline void PageCacheSlot::remove_ref()
//
BATT_ALWAYS_INLINE inline void PageCacheSlot::extend_pin()
{
if (PageCacheSlot::eviction_pause()) {
return;
}

const auto old_state = this->state_.fetch_add(kPinCountDelta, std::memory_order_relaxed);
const auto new_state = old_state + kPinCountDelta;

Expand All @@ -569,6 +589,8 @@ BATT_ALWAYS_INLINE inline void PageCacheSlot::extend_pin()
LLFS_PAGE_CACHE_ASSERT(Self::is_pinned(old_state))
<< "This method should never be called in cases where the current pin count might be 0; "
"use acquire_pin() instead.";

PageCacheSlot::add_pin_count();
}

//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - -
Expand Down Expand Up @@ -608,6 +630,10 @@ BATT_ALWAYS_INLINE inline i64 PageCacheSlot::get_latest_use() const
//
BATT_ALWAYS_INLINE inline void PageCacheSlot::release_pin()
{
if (PageCacheSlot::eviction_pause()) {
return;
}

// Save the page size while the slot is pinned, so we can update metrics below if necessary.
//
const usize saved_page_size = this->page_size_;
Expand Down Expand Up @@ -635,6 +661,8 @@ BATT_ALWAYS_INLINE inline void PageCacheSlot::release_pin()

this->remove_ref();
}

PageCacheSlot::add_unpin_count();
}

//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - -
Expand Down Expand Up @@ -686,6 +714,10 @@ BATT_ALWAYS_INLINE inline auto PageCacheSlot::acquire_pin(PageId key, IgnoreKey
IgnoreGeneration ignore_generation)
-> PinnedRef
{
if (PageCacheSlot::eviction_pause()) {
return PinnedRef{this, CallerPromisesTheyAcquiredPinCount{}};
}

// Increment the pin count.
//
const auto old_state = this->state_.fetch_add(kPinCountDelta, std::memory_order_acquire);
Expand All @@ -704,6 +736,7 @@ BATT_ALWAYS_INLINE inline auto PageCacheSlot::acquire_pin(PageId key, IgnoreKey
this->add_pinned_bytes(this->page_size_);
this->add_ref();
}
PageCacheSlot::add_pin_count();

// If the pin_count > 1 (because of the fetch_add above) and the slot is valid, it is safe to read
// the key. If the key doesn't match, release the ref and return failure.
Expand Down
2 changes: 1 addition & 1 deletion src/llfs/page_cache_slot_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ namespace llfs {
, name_{std::move(name)}
, slot_storage_{new SlotStorage[n_slots]}
{
LLFS_LOG_INFO_FIRST_N(10) << "PageCacheSlot::Pool created, n_slots=" << this->n_slots_;
LLFS_VLOG(1) << "PageCacheSlot::Pool created, n_slots=" << this->n_slots_;
this->metrics_.total_capacity_allocated.add(this->max_byte_size_.load());
}

Expand Down
2 changes: 2 additions & 0 deletions src/llfs/page_cache_slot_pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,12 @@ class PageCacheSlot::Pool : public boost::intrusive_ref_counter<Pool>
/** \brief The total size of all pages that have ever been pinned to the cache.
*/
FastCountMetric<i64> pinned_byte_count{0};
FastCountMetric<i64> pin_count{0};

/** \brief The total size of all pages that have ever been unpinned from the cache.
*/
FastCountMetric<i64> unpinned_byte_count{0};
FastCountMetric<i64> unpin_count{0};

CountMetric<i64> total_capacity_allocated{0};
CountMetric<i64> total_capacity_freed{0};
Expand Down
10 changes: 6 additions & 4 deletions src/llfs/page_recycler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,12 +361,13 @@ StatusOr<slot_offset_type> PageRecycler::recycle_pages_depth_0(
const Slice<const PageId>& page_ids_in, llfs::slot_offset_type volume_trim_slot) noexcept
{
constexpr i32 depth = 0;

// Check to make sure request was never seen before.
//
std::vector<PageId> page_ids_list(page_ids_in.begin(), page_ids_in.end());
{
auto locked_state = this->state_.lock();
if (!is_page_recycling_allowed(page_ids_in, volume_trim_slot)) {
if (!this->is_page_recycling_allowed(page_ids_in, volume_trim_slot)) {
return this->wal_device_->slot_range(LogReadMode::kDurable).upper_bound;
}
}
Expand All @@ -388,7 +389,8 @@ StatusOr<slot_offset_type> PageRecycler::recycle_pages_depth_0(
const usize needed_size = options.insert_grant_size();

BATT_DEBUG_INFO("[PageRecycler::recycle_page_depth_0] waiting for log space; "
<< BATT_INSPECT(needed_size) << BATT_INSPECT(this->insert_grant_pool_.size())
<< BATT_INSPECT(this->stop_requested_.load()) << BATT_INSPECT(needed_size)
<< BATT_INSPECT(this->insert_grant_pool_.size())
<< BATT_INSPECT(options.total_grant_size_for_depth(depth))
<< BATT_INSPECT(this->slot_writer_.in_use_size())
<< BATT_INSPECT(this->slot_writer_.log_capacity())
Expand Down Expand Up @@ -473,9 +475,9 @@ StatusOr<slot_offset_type> PageRecycler::recycle_pages(const Slice<const PageId>
"specify depth == 0 and grant == nullptr; other values are "
"for PageRecycler internal use only.";

return recycle_pages_depth_0(page_ids, volume_trim_slot);
return this->recycle_pages_depth_0(page_ids, volume_trim_slot);
} else {
return recycle_pages_depth_n(page_ids, *grant, depth);
return this->recycle_pages_depth_n(page_ids, *grant, depth);
}
}

Expand Down
Loading