// 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 #include #include "kprivate/ndm.h" #include "posix.h" namespace ftl { const char* VolumeImpl::Init(std::unique_ptr driver) { ZX_DEBUG_ASSERT(!driver_); driver_ = std::move(driver); if (!InitModules()) { return "Module initialization failed"; } const char* error = driver_->Init(); if (error) { return error; } return Attach(); } const char* VolumeImpl::ReAttach() { if (!driver_->Detach()) { return "Failed to remove volume"; } name_ = nullptr; return Attach(); } zx_status_t VolumeImpl::Read(uint32_t first_page, int num_pages, void* buffer) { if (read_pages_(buffer, first_page, num_pages, vol_) != 0) { return ZX_ERR_IO; } return ZX_OK; } zx_status_t VolumeImpl::Write(uint32_t first_page, int num_pages, const void* buffer) { if (write_pages_(const_cast(buffer), first_page, num_pages, vol_) != 0) { return ZX_ERR_IO; } return ZX_OK; } zx_status_t VolumeImpl::Format() { if (report_(vol_, FS_FORMAT) != 0) { return ZX_ERR_BAD_STATE; } return ZX_OK; } zx_status_t VolumeImpl::Mount() { if (report_(vol_, FS_MOUNT) != 0) { return ZX_ERR_BAD_STATE; } return ZX_OK; } zx_status_t VolumeImpl::Unmount() { if (report_(vol_, FS_UNMOUNT) != 0) { return ZX_ERR_BAD_STATE; } return ZX_OK; } zx_status_t VolumeImpl::Flush() { if (report_(vol_, FS_SYNC) != 0) { return ZX_ERR_BAD_STATE; } return ZX_OK; } zx_status_t VolumeImpl::Trim(uint32_t first_page, uint32_t num_pages) { if (report_(vol_, FS_MARK_UNUSED, first_page, num_pages) != 0) { return ZX_ERR_BAD_STATE; } return ZX_OK; } zx_status_t VolumeImpl::GarbageCollect() { int result = report_(vol_, FS_VCLEAN); if (result < 0) { return ZX_ERR_BAD_STATE; } if (result == 0) { return ZX_ERR_STOP; } return ZX_OK; } zx_status_t VolumeImpl::GetStats(Stats* stats) { union vstat buffer; if (report_(vol_, FS_VSTAT, &buffer) != 0) { return ZX_ERR_BAD_STATE; } stats->ram_used = buffer.fat.drvr_stats.ftl.ndm.ram_used; stats->wear_count = buffer.fat.drvr_stats.ftl.ndm.wear_count; stats->garbage_level = buffer.fat.garbage_level; return ZX_OK; } bool VolumeImpl::OnVolumeAdded(const XfsVol* ftl) { ZX_DEBUG_ASSERT(!Created()); vol_ = ftl->vol; name_ = ftl->name; report_ = ftl->report; write_pages_ = ftl->write_pages; read_pages_ = ftl->read_pages; return owner_->OnVolumeAdded(ftl->page_size, ftl->num_pages); } bool VolumeImpl::Created() const { return name_; } const char* VolumeImpl::Attach() { const char* error = driver_->Attach(this); if (error) { return error; } if (!Created()) { return "No volume added"; } if (Mount() != ZX_OK) { return "Mount failed"; } return nullptr; } } // namespace ftl // Callback from the FTL. int XfsAddVol(XfsVol* ftl) { ftl::VolumeImpl* volume = reinterpret_cast(ftl->ftl_volume); if (volume && !volume->OnVolumeAdded(ftl)) { return -1; } return 0; } // Callback from the FTL. int XfsDelVol(const char* name) { return 0; }