blob: b93a9851fa71cf07fd9fa6dabe6676d5b6fef805 [file] [log] [blame]
// Copyright 2018 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/allocator/storage.h"
#include <lib/syslog/cpp/macros.h>
#include <cstdint>
#include <utility>
#include <fs/trace.h>
#include "src/storage/minfs/allocator/allocator.h"
#include "src/storage/minfs/format.h"
namespace minfs {
PersistentStorage::PersistentStorage(block_client::BlockDevice* device, SuperblockManager* sb,
size_t unit_size, GrowHandler grow_cb,
AllocatorMetadata metadata, uint32_t block_size)
: device_(device),
unit_size_(unit_size),
sb_(sb),
grow_cb_(std::move(grow_cb)),
metadata_(std::move(metadata)),
block_size_(block_size) {}
zx_status_t PersistentStorage::AttachVmo(const zx::vmo& vmo, storage::OwnedVmoid* out) {
return device_->BlockAttachVmo(vmo, &out->GetReference(device_));
}
zx_status_t PersistentStorage::Extend(PendingWork* write_transaction, WriteData data,
GrowMapCallback grow_map) {
TRACE_DURATION("minfs", "Minfs::PersistentStorage::Extend");
ZX_DEBUG_ASSERT(write_transaction != nullptr);
if (!metadata_.UsingFvm()) {
return ZX_ERR_NO_SPACE;
}
uint32_t data_slices_diff = 1;
// Determine if we will have enough space in the bitmap slice
// to grow |data_slices_diff| data slices.
// How large is the bitmap right now?
uint32_t bitmap_slices = metadata_.Fvm().MetadataSlices();
uint32_t bitmap_blocks = metadata_.Fvm().UnitsPerSlices(bitmap_slices, BlockSize());
// How large does the bitmap need to be?
uint32_t data_slices = metadata_.Fvm().DataSlices();
uint32_t data_slices_new = data_slices + data_slices_diff;
uint32_t pool_size =
metadata_.Fvm().UnitsPerSlices(data_slices_new, static_cast<uint32_t>(unit_size_));
uint32_t bitmap_blocks_new = BitmapBlocksForSize(pool_size);
if (bitmap_blocks_new > bitmap_blocks) {
// TODO(smklein): Grow the bitmap another slice.
// TODO(planders): Once we start growing the [block] bitmap,
// we will need to start growing the journal as well.
FX_LOGS(ERROR) << "Minfs allocator needs to increase bitmap size";
return ZX_ERR_NO_SPACE;
}
// Make the request to the FVM.
extend_request_t request;
request.length = data_slices_diff;
request.offset = metadata_.Fvm().BlocksToSlices(metadata_.DataStartBlock()) + data_slices;
zx_status_t status = device_->VolumeExtend(request.offset, request.length);
if (status != ZX_OK) {
FX_LOGS(ERROR) << ":PersistentStorage::Extend failed to grow (on disk): " << status;
return status;
}
if (grow_cb_) {
if ((status = grow_cb_(pool_size)) != ZX_OK) {
FX_LOGS(ERROR) << ":Allocator grow callback failure: " << status;
return status;
}
}
// Extend the in memory representation of our allocation pool -- it grew!
size_t old_pool_size;
if ((status = grow_map(pool_size, &old_pool_size)) != ZX_OK) {
return status;
}
metadata_.Fvm().SetDataSlices(data_slices_new);
metadata_.SetPoolTotal(pool_size);
sb_->Write(write_transaction, UpdateBackupSuperblock::kUpdate);
// Update the block bitmap.
PersistRange(write_transaction, data, old_pool_size, pool_size - old_pool_size);
return ZX_OK;
}
} // namespace minfs