Merge pull request #7773 from davidsaada/david_fix_init_ref_count

Add some logic related to initialization to various block devices
pull/7895/head
Martin Kojtal 2018-08-27 10:38:15 +02:00 committed by GitHub
commit 928f90a7d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 282 additions and 35 deletions

View File

@ -26,7 +26,7 @@ static inline uint32_t align_down(bd_size_t val, bd_size_t size)
}
BufferedBlockDevice::BufferedBlockDevice(BlockDevice *bd)
: _bd(bd), _bd_program_size(0), _curr_aligned_addr(0), _flushed(true), _cache(0), _init_ref_count(0)
: _bd(bd), _bd_program_size(0), _curr_aligned_addr(0), _flushed(true), _cache(0), _init_ref_count(0), _is_initialized(false)
{
}
@ -57,11 +57,16 @@ int BufferedBlockDevice::init()
_curr_aligned_addr = _bd->size();
_flushed = true;
return 0;
_is_initialized = true;
return BD_ERROR_OK;
}
int BufferedBlockDevice::deinit()
{
if (!_is_initialized) {
return BD_ERROR_OK;
}
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
if (val) {
@ -70,11 +75,16 @@ int BufferedBlockDevice::deinit()
delete[] _cache;
_cache = 0;
_is_initialized = false;
return _bd->deinit();
}
int BufferedBlockDevice::flush()
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
if (!_flushed) {
int ret = _bd->program(_cache, _curr_aligned_addr, _bd_program_size);
if (ret) {
@ -87,6 +97,10 @@ int BufferedBlockDevice::flush()
int BufferedBlockDevice::sync()
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
int ret = flush();
if (ret) {
return ret;
@ -97,6 +111,10 @@ int BufferedBlockDevice::sync()
int BufferedBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(_cache);
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
bool moved_unit = false;
bd_addr_t aligned_addr = align_down(addr, _bd_program_size);
@ -132,7 +150,10 @@ int BufferedBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
int BufferedBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(_cache);
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
int ret;
bool moved_unit = false;
@ -196,12 +217,19 @@ int BufferedBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
int BufferedBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->erase(addr, size);
}
int BufferedBlockDevice::trim(bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
if ((_curr_aligned_addr >= addr) && (_curr_aligned_addr <= addr + size)) {
_flushed = true;
@ -222,20 +250,36 @@ bd_size_t BufferedBlockDevice::get_program_size() const
bd_size_t BufferedBlockDevice::get_erase_size() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size();
}
bd_size_t BufferedBlockDevice::get_erase_size(bd_addr_t addr) const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size(addr);
}
int BufferedBlockDevice::get_erase_value() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_value();
}
bd_size_t BufferedBlockDevice::size() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->size();
}

View File

@ -154,6 +154,7 @@ protected:
bool _flushed;
uint8_t *_cache;
uint32_t _init_ref_count;
bool _is_initialized;
/** Flush data in cache
*

View File

@ -21,7 +21,7 @@
ChainingBlockDevice::ChainingBlockDevice(BlockDevice **bds, size_t bd_count)
: _bds(bds), _bd_count(bd_count)
, _read_size(0), _program_size(0), _erase_size(0), _size(0)
, _erase_value(-1), _init_ref_count(0)
, _erase_value(-1), _init_ref_count(0), _is_initialized(false)
{
}
@ -32,6 +32,7 @@ static bool is_aligned(uint64_t x, uint64_t alignment)
int ChainingBlockDevice::init()
{
int err;
uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
if (val != 1) {
@ -49,9 +50,9 @@ int ChainingBlockDevice::init()
// the constructor since some block devices may need to be
// initialized before they know their block size/count
for (size_t i = 0; i < _bd_count; i++) {
int err = _bds[i]->init();
err = _bds[i]->init();
if (err) {
return err;
goto fail;
}
bd_size_t read = _bds[i]->get_read_size();
@ -85,11 +86,21 @@ int ChainingBlockDevice::init()
_size += _bds[i]->size();
}
return 0;
_is_initialized = true;
return BD_ERROR_OK;
fail:
_is_initialized = false;
_init_ref_count = 0;
return err;
}
int ChainingBlockDevice::deinit()
{
if (!_is_initialized) {
return BD_ERROR_OK;
}
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
if (val) {
@ -103,11 +114,16 @@ int ChainingBlockDevice::deinit()
}
}
return 0;
_is_initialized = false;
return BD_ERROR_OK;
}
int ChainingBlockDevice::sync()
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
for (size_t i = 0; i < _bd_count; i++) {
int err = _bds[i]->sync();
if (err) {
@ -121,6 +137,10 @@ int ChainingBlockDevice::sync()
int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(is_valid_read(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
uint8_t *buffer = static_cast<uint8_t*>(b);
// Find block devices containing blocks, may span multiple block devices
@ -152,6 +172,10 @@ int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
int ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
const uint8_t *buffer = static_cast<const uint8_t*>(b);
// Find block devices containing blocks, may span multiple block devices
@ -183,6 +207,9 @@ int ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
int ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
// Find block devices containing blocks, may span multiple block devices
for (size_t i = 0; i < _bd_count && size > 0; i++) {
@ -226,6 +253,10 @@ bd_size_t ChainingBlockDevice::get_erase_size() const
bd_size_t ChainingBlockDevice::get_erase_size(bd_addr_t addr) const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
bd_addr_t bd_start_addr = 0;
for (size_t i = 0; i < _bd_count; i++) {
bd_size_t bdsize = _bds[i]->size();

View File

@ -176,6 +176,7 @@ protected:
bd_size_t _size;
int _erase_value;
uint32_t _init_ref_count;
bool _is_initialized;
};

View File

@ -20,7 +20,7 @@
ExhaustibleBlockDevice::ExhaustibleBlockDevice(BlockDevice *bd, uint32_t erase_cycles)
: _bd(bd), _erase_array(NULL), _erase_cycles(erase_cycles), _init_ref_count(0)
: _bd(bd), _erase_array(NULL), _erase_cycles(erase_cycles), _init_ref_count(0), _is_initialized(false)
{
}
@ -31,15 +31,16 @@ ExhaustibleBlockDevice::~ExhaustibleBlockDevice()
int ExhaustibleBlockDevice::init()
{
int err;
uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
if (val != 1) {
return BD_ERROR_OK;
}
int err = _bd->init();
err = _bd->init();
if (err) {
return err;
goto fail;
}
if (!_erase_array) {
@ -50,11 +51,21 @@ int ExhaustibleBlockDevice::init()
}
}
return 0;
_is_initialized = true;
return BD_ERROR_OK;
fail:
_is_initialized = false;
_init_ref_count = 0;
return err;
}
int ExhaustibleBlockDevice::deinit()
{
if (!_is_initialized) {
return BD_ERROR_OK;
}
core_util_atomic_decr_u32(&_init_ref_count, 1);
if (_init_ref_count) {
@ -63,16 +74,25 @@ int ExhaustibleBlockDevice::deinit()
// _erase_array is lazily cleaned up in destructor to allow
// data to live across de/reinitialization
_is_initialized = false;
return _bd->deinit();
}
int ExhaustibleBlockDevice::sync()
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->sync();
}
int ExhaustibleBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->read(buffer, addr, size);
}
@ -80,6 +100,10 @@ int ExhaustibleBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_
{
MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
if (_erase_array[addr / get_erase_size()] == 0) {
return 0;
}
@ -90,6 +114,9 @@ int ExhaustibleBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_
int ExhaustibleBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
bd_size_t eu_size = get_erase_size();
while (size) {
@ -114,30 +141,54 @@ int ExhaustibleBlockDevice::erase(bd_addr_t addr, bd_size_t size)
bd_size_t ExhaustibleBlockDevice::get_read_size() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_read_size();
}
bd_size_t ExhaustibleBlockDevice::get_program_size() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_program_size();
}
bd_size_t ExhaustibleBlockDevice::get_erase_size() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size();
}
bd_size_t ExhaustibleBlockDevice::get_erase_size(bd_addr_t addr) const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size(addr);
}
int ExhaustibleBlockDevice::get_erase_value() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_value();
}
bd_size_t ExhaustibleBlockDevice::size() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->size();
}

View File

@ -155,6 +155,7 @@ private:
uint32_t *_erase_array;
uint32_t _erase_cycles;
uint32_t _init_ref_count;
bool _is_initialized;
};

View File

@ -30,7 +30,7 @@ static inline uint32_t align_up(bd_size_t val, bd_size_t size)
FlashSimBlockDevice::FlashSimBlockDevice(BlockDevice *bd, uint8_t erase_value) :
_erase_value(erase_value), _blank_buf_size(0),
_blank_buf(0), _bd(bd), _init_ref_count(0)
_blank_buf(0), _bd(bd), _init_ref_count(0), _is_initialized(false)
{
}
@ -42,73 +42,118 @@ FlashSimBlockDevice::~FlashSimBlockDevice()
int FlashSimBlockDevice::init()
{
int err;
uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
if (val != 1) {
return BD_ERROR_OK;
}
int ret = _bd->init();
if (ret) {
return ret;
err = _bd->init();
if (err) {
goto fail;
}
_blank_buf_size = align_up(min_blank_buf_size, _bd->get_program_size());
if (!_blank_buf) {
_blank_buf = new uint8_t[_blank_buf_size];
MBED_ASSERT(_blank_buf);
}
_is_initialized = true;
return BD_ERROR_OK;
fail:
_is_initialized = false;
_init_ref_count = 0;
return err;
}
int FlashSimBlockDevice::deinit()
{
if (!_is_initialized) {
return BD_ERROR_OK;
}
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
if (val) {
return BD_ERROR_OK;
}
_is_initialized = false;
return _bd->deinit();
}
int FlashSimBlockDevice::sync()
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->sync();
}
bd_size_t FlashSimBlockDevice::get_read_size() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_read_size();
}
bd_size_t FlashSimBlockDevice::get_program_size() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_program_size();
}
bd_size_t FlashSimBlockDevice::get_erase_size() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size();
}
bd_size_t FlashSimBlockDevice::get_erase_size(bd_addr_t addr) const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size(addr);
}
bd_size_t FlashSimBlockDevice::size() const
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->size();
}
int FlashSimBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->read(b, addr, size);
}
int FlashSimBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
bd_addr_t curr_addr = addr;
bd_size_t curr_size = size;
@ -138,6 +183,10 @@ int FlashSimBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
bd_addr_t curr_addr = addr;
bd_size_t curr_size = size;

View File

@ -136,6 +136,7 @@ private:
uint8_t *_blank_buf;
BlockDevice *_bd;
uint32_t _init_ref_count;
bool _is_initialized;
};
#endif

View File

@ -20,14 +20,14 @@
HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t block)
: _read_size(block), _program_size(block), _erase_size(block)
, _count(size / block), _blocks(0), _init_ref_count(0)
, _count(size / block), _blocks(0), _init_ref_count(0), _is_initialized(false)
{
MBED_ASSERT(_count * _erase_size == size);
}
HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t read, bd_size_t program, bd_size_t erase)
: _read_size(read), _program_size(program), _erase_size(erase)
, _count(size / erase), _blocks(0), _init_ref_count(0)
, _count(size / erase), _blocks(0), _init_ref_count(0), _is_initialized(false)
{
MBED_ASSERT(_count * _erase_size == size);
}
@ -59,11 +59,16 @@ int HeapBlockDevice::init()
}
}
_is_initialized = true;
return BD_ERROR_OK;
}
int HeapBlockDevice::deinit()
{
if (!_is_initialized) {
return BD_ERROR_OK;
}
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
if (val) {
@ -73,6 +78,7 @@ int HeapBlockDevice::deinit()
MBED_ASSERT(_blocks != NULL);
// Memory is lazily cleaned up in destructor to allow
// data to live across de/reinitialization
_is_initialized = false;
return BD_ERROR_OK;
}
@ -110,6 +116,10 @@ int HeapBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(_blocks != NULL);
MBED_ASSERT(is_valid_read(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
uint8_t *buffer = static_cast<uint8_t*>(b);
while (size > 0) {
@ -134,6 +144,10 @@ int HeapBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(_blocks != NULL);
MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
const uint8_t *buffer = static_cast<const uint8_t*>(b);
while (size > 0) {

View File

@ -151,6 +151,7 @@ private:
bd_size_t _count;
uint8_t **_blocks;
uint32_t _init_ref_count;
bool _is_initialized;
};

View File

@ -195,40 +195,44 @@ int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type,
}
MBRBlockDevice::MBRBlockDevice(BlockDevice *bd, int part)
: _bd(bd), _part(part), _init_ref_count(0)
: _bd(bd), _offset(0), _size(0), _type(0), _part(part), _init_ref_count(0), _is_initialized(false)
{
MBED_ASSERT(_part >= 1 && _part <= 4);
}
int MBRBlockDevice::init()
{
uint32_t buffer_size;
uint8_t *buffer = 0;
struct mbr_table *table;
bd_size_t sector;
int err;
uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
if (val != 1) {
return BD_ERROR_OK;
}
int err = _bd->init();
err = _bd->init();
if (err) {
return err;
goto fail;
}
// Allocate smallest buffer necessary to write MBR
uint32_t buffer_size = std::max<uint32_t>(_bd->get_read_size(), sizeof(struct mbr_table));
uint8_t *buffer = new uint8_t[buffer_size];
buffer_size = std::max<uint32_t>(_bd->get_read_size(), sizeof(struct mbr_table));
buffer = new uint8_t[buffer_size];
err = _bd->read(buffer, 512-buffer_size, buffer_size);
if (err) {
delete[] buffer;
return err;
goto fail;
}
// Check for valid table
struct mbr_table *table = reinterpret_cast<struct mbr_table*>(
&buffer[buffer_size - sizeof(struct mbr_table)]);
table = reinterpret_cast<struct mbr_table*>(&buffer[buffer_size - sizeof(struct mbr_table)]);
if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) {
delete[] buffer;
return BD_ERROR_INVALID_MBR;
err = BD_ERROR_INVALID_MBR;
goto fail;
}
// Check for valid entry
@ -237,82 +241,130 @@ int MBRBlockDevice::init()
if ((table->entries[_part-1].type == 0x00 ||
table->entries[_part-1].type == 0x05 ||
table->entries[_part-1].type == 0x0f)) {
delete[] buffer;
return BD_ERROR_INVALID_PARTITION;
err = BD_ERROR_INVALID_PARTITION;
goto fail;
}
// Get partition attributes
bd_size_t sector = std::max<uint32_t>(_bd->get_erase_size(), 512);
sector = std::max<uint32_t>(_bd->get_erase_size(), 512);
_type = table->entries[_part-1].type;
_offset = fromle32(table->entries[_part-1].lba_offset) * sector;
_size = fromle32(table->entries[_part-1].lba_size) * sector;
// Check that block addresses are valid
if (!_bd->is_valid_erase(_offset, _size)) {
delete[] buffer;
return BD_ERROR_INVALID_PARTITION;
err = BD_ERROR_INVALID_PARTITION;
goto fail;
}
_is_initialized = true;
delete[] buffer;
return 0;
return BD_ERROR_OK;
fail:
delete[] buffer;
_is_initialized = false;
_init_ref_count = 0;
return err;
}
int MBRBlockDevice::deinit()
{
if (!_is_initialized) {
return BD_ERROR_OK;
}
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
if (val) {
return BD_ERROR_OK;
}
_is_initialized = false;
return _bd->deinit();
}
int MBRBlockDevice::sync()
{
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->sync();
}
int MBRBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(is_valid_read(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->read(b, addr + _offset, size);
}
int MBRBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->program(b, addr + _offset, size);
}
int MBRBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->erase(addr + _offset, size);
}
bd_size_t MBRBlockDevice::get_read_size() const
{
if (!_is_initialized) {
return 0;
}
return _bd->get_read_size();
}
bd_size_t MBRBlockDevice::get_program_size() const
{
if (!_is_initialized) {
return 0;
}
return _bd->get_program_size();
}
bd_size_t MBRBlockDevice::get_erase_size() const
{
if (!_is_initialized) {
return 0;
}
return _bd->get_erase_size();
}
bd_size_t MBRBlockDevice::get_erase_size(bd_addr_t addr) const
{
if (!_is_initialized) {
return 0;
}
return _bd->get_erase_size(_offset + addr);
}
int MBRBlockDevice::get_erase_value() const
{
if (!_is_initialized) {
return 0;
}
return _bd->get_erase_value();
}

View File

@ -253,6 +253,7 @@ protected:
uint8_t _type;
uint8_t _part;
uint32_t _init_ref_count;
bool _is_initialized;
};