blob: cb5dd145ce7918a54fed08bc900e1e34936e272c [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.
#ifndef SRC_DEVICES_BLOCK_DRIVERS_FTL_TESTS_NDM_RAM_DRIVER_H_
#define SRC_DEVICES_BLOCK_DRIVERS_FTL_TESTS_NDM_RAM_DRIVER_H_
#include <inttypes.h>
#include <lib/ftl/ndm-driver.h>
#include <zircon/types.h>
#include <cstdint>
#include <limits>
#include <fbl/array.h>
struct TestOptions {
static constexpr TestOptions NoEccErrors() {
TestOptions options = {};
options.ecc_error_interval = std::numeric_limits<int>::max();
options.save_config_data = false;
return options;
}
// Controls simulation of ECC errors.
int ecc_error_interval = 900;
// Controls simulation of bad block sequence.
int bad_block_interval = 50;
// Controls the size of the sequence of operations that will run
// into a bad block.
int bad_block_burst = 1;
// Makes only half of the space visible.
bool use_half_size = false;
// Save options on the partition info.
bool save_config_data = true;
// Delay before power failure kicks in.
int power_failure_delay = -1;
};
// Ram-backed driver for testing purposes.
class NdmRamDriver final : public ftl::NdmBaseDriver {
public:
explicit NdmRamDriver(const ftl::VolumeOptions& options) : NdmRamDriver(options, {}) {}
NdmRamDriver(const ftl::VolumeOptions& options, const TestOptions& test_options)
: NdmBaseDriver(ftl::DefaultLogger()), options_(options), test_options_(test_options) {}
~NdmRamDriver() final = default;
// Extends the visible volume to the whole size of the storage.
bool DoubleSize();
void save_config_data(bool value) { test_options_.save_config_data = value; }
void set_options(const ftl::VolumeOptions& options) { options_ = options; }
void set_max_bad_blocks(uint32_t value) { options_.max_bad_blocks = value; }
uint32_t num_bad_blocks() const { return num_bad_blocks_; }
void SetPowerFailureDelay(int delay) {
test_options_.power_failure_delay = delay;
power_failure_delay_ = 0;
power_failure_triggered_ = false;
}
// NdmDriver interface:
const char* Init() final;
const char* Attach(const ftl::Volume* ftl_volume) final;
bool Detach() final;
int NandRead(uint32_t start_page, uint32_t page_count, void* page_buffer, void* oob_buffer) final;
int NandWrite(uint32_t start_page, uint32_t page_count, const void* page_buffer,
const void* oob_buffer) final;
int NandErase(uint32_t page_num) final;
int IsBadBlock(uint32_t page_num) final;
bool IsEmptyPage(uint32_t page_num, const uint8_t* data, const uint8_t* spare) final;
uint32_t PageSize() final;
uint8_t SpareSize() final;
private:
// Reads or Writes a single page.
int ReadPage(uint32_t page_num, uint8_t* data, uint8_t* spare);
int WritePage(uint32_t page_num, const uint8_t* data, const uint8_t* spare);
// Returns true for a freshly minted bad block.
bool SimulateBadBlock(uint32_t page_num);
// Returns true if a power failure should be triggered at this point.
bool ShouldTriggerPowerFailure();
// Triggers side-effects of a power failure.
void OnWritePowerFailure(uint64_t page_number, const uint8_t* data, const uint8_t* spare);
void OnErasePowerFailure(uint64_t page_number);
// Access the main data and spare area for a given page.
uint8_t* MainData(uint32_t page_num);
uint8_t* SpareData(uint32_t page_num);
// Access flags for a given page.
bool Written(uint32_t page_num);
bool FailEcc(uint32_t page_num);
bool BadBlock(uint32_t page_num);
void SetWritten(uint32_t page_num, bool value);
void SetFailEcc(uint32_t page_num, bool value);
void SetBadBlock(uint32_t page_num, bool value);
uint32_t PagesPerBlock() const;
fbl::Array<uint8_t> volume_;
fbl::Array<uint8_t> flags_;
ftl::VolumeOptions options_;
TestOptions test_options_;
// Controls simulation of ECC errors.
int ecc_error_interval_ = 0;
// Controls simulation of bad blocks.
int bad_block_interval_ = 0;
// Marks that power failure happened.
bool power_failure_triggered_ = false;
// Controls simulation of bad blocks.
int power_failure_delay_ = 0;
uint32_t num_bad_blocks_ = 0;
};
#endif // SRC_DEVICES_BLOCK_DRIVERS_FTL_TESTS_NDM_RAM_DRIVER_H_