blob: cfe6e01a104f682d067db670644fe92fd1ac8e3a [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/storage/f2fs/storage_buffer.h"
#include "src/storage/f2fs/bcache.h"
#include "src/storage/f2fs/file_cache.h"
namespace f2fs {
StorageBuffer::StorageBuffer(BcacheMapper *bc, size_t num_blocks, std::string_view label)
: allocated_blocks_(num_blocks) {
ZX_ASSERT(num_blocks >= 1);
ZX_ASSERT(buffer_.Initialize(bc, num_blocks, Page::Size(), label.data()) == ZX_OK);
}
zx::result<size_t> StorageBuffer::Reserve(size_t num_blocks) {
if (current_index_ + num_blocks > allocated_blocks_) {
return zx::error(ZX_ERR_UNAVAILABLE);
}
size_t ret = current_index_;
current_index_ += num_blocks;
return zx::ok(ret);
}
void *StorageBuffer::Data(const size_t offset) {
ZX_ASSERT(offset < buffer_.capacity());
return buffer_.Data(offset);
}
StorageBufferPool::StorageBufferPool(BcacheMapper *bcache_mapper, size_t default_size,
size_t large_size, int num_pager_threads)
: buffer_size_(default_size),
large_buffer_size_(large_size),
num_buffers_(num_pager_threads),
bcache_mapper_(bcache_mapper) {
ZX_ASSERT(num_pager_threads > 0);
for (size_t i = 0; i < num_buffers_; ++i) {
std::string str = "StorageBuffer_" + std::to_string(buffer_size_) + "_" + std::to_string(i);
buffers(buffer_size_)
.push_back(std::make_unique<StorageBuffer>(bcache_mapper, buffer_size_, str));
str = "StorageBuffer_" + std::to_string(large_buffer_size_) + "_" + std::to_string(i);
buffers(large_buffer_size_)
.push_back(std::make_unique<StorageBuffer>(bcache_mapper, large_buffer_size_, str));
}
}
StorageBufferPool::~StorageBufferPool() {
for (size_t i = 0; i < num_buffers_; ++i) {
auto buffer = Retrieve(buffer_size_);
auto large_buffer = Retrieve(large_buffer_size_);
}
}
std::unique_ptr<StorageBuffer> StorageBufferPool::Retrieve(size_t size) {
ZX_ASSERT(var_.wait_for(mutex_, std::chrono::seconds(kWriteTimeOut),
[this, &size]()
TA_NO_THREAD_SAFETY_ANALYSIS { return !buffers(size).empty(); }));
auto owned_buffer = std::move(buffers(size).back());
buffers(size).pop_back();
return owned_buffer;
}
OwnedStorageBuffer StorageBufferPool::Get(size_t size) {
std::lock_guard lock(mutex_);
ZX_ASSERT(var_.wait_for(mutex_, std::chrono::seconds(kWriteTimeOut),
[this, &size]()
TA_NO_THREAD_SAFETY_ANALYSIS { return !buffers(size).empty(); }));
auto owned_buffer = std::move(buffers(size).back());
buffers(size).pop_back();
return OwnedStorageBuffer(std::move(owned_buffer),
[this](std::unique_ptr<StorageBuffer> buffer)
__TA_EXCLUDES(mutex_) { Return(std::move(buffer)); });
}
void StorageBufferPool::Return(std::unique_ptr<StorageBuffer> buffer) {
if (buffer) {
std::lock_guard lock(mutex_);
buffers(buffer->Capacity()).push_back(std::move(buffer));
var_.notify_one();
}
}
} // namespace f2fs