blob: ae6684313ebb3befe3a7fcb024bf8c4932ad5151 [file] [log] [blame]
// Copyright 2020 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/minfs/lazy_buffer.h"
namespace minfs {
zx::status<std::unique_ptr<LazyBuffer>> LazyBuffer::Create(Bcache* bcache, const char* name,
uint32_t block_size) {
std::unique_ptr<LazyBuffer> buffer(new LazyBuffer(block_size));
zx_status_t status = buffer->buffer_.Attach(name, bcache);
if (status != ZX_OK)
return zx::error(status);
return zx::ok(std::move(buffer));
}
void LazyBuffer::Shrink(size_t block_count) {
lazy_reader_.SetLoaded(BlockRange(block_count, std::numeric_limits<uint64_t>::max()), false);
// ResizeableVmoBuffer has a minimum block size of 1.
if (block_count < 1)
block_count = 1;
if (block_count < buffer_.capacity()) {
zx_status_t status = buffer_.Shrink(block_count);
ZX_DEBUG_ASSERT(status == ZX_OK);
}
}
zx_status_t LazyBuffer::Read(ByteRange range, Reader* reader) {
if (range.Length() == 0)
return ZX_OK;
uint64_t required_blocks = BytesToBlocks(range, buffer_.BlockSize()).End();
if (required_blocks > buffer_.capacity()) {
zx_status_t status = Grow(required_blocks);
if (status != ZX_OK)
return status;
}
return lazy_reader_.Read(range, reader);
}
zx_status_t LazyBuffer::Flush(PendingWork* transaction, MapperInterface* mapper,
BaseBufferView* view, const Writer& writer) {
// TODO(fxbug.dev/50606): If this or the transaction fails, this will leave memory in an
// indeterminate state. For now, this is no worse than it has been for some time.
view->set_dirty(false);
return EnumerateBlocks(
view->GetByteRange(), buffer_.BlockSize(),
[this, transaction, mapper, &writer](BlockRange range) -> zx::status<uint64_t> {
bool allocated;
zx::status<DeviceBlockRange> device_range =
mapper->MapForWrite(transaction, range, &allocated);
if (device_range.is_error())
return device_range.take_error();
zx_status_t status = writer(
&buffer_, BlockRange(range.Start(), range.Start() + device_range.value().count()),
device_range.value().block());
if (status != ZX_OK)
return zx::error(status);
return zx::ok(device_range.value().count());
});
}
} // namespace minfs