static int _write_errorcheck_bootblock( struct bootconfig * bc, unsigned int block_idx ) { int err, no; char page[ bc->info.min_io_size ]; err = _check_block( bc, block_idx ); if ( 0 != err ) return err; err = _do_write_bootblock( bc, block_idx ); no = errno; if( 1 == err ) { if ( 1 == _check_block( bc, block_idx ) ) { bc_log( LOG_WARNING, "Block #%d went bad while erasing / writing it.\n", block_idx); return 1; } } if (err) bc_log( LOG_ERR, "Error #%d while erasing / writing block %d on %s: %s.\n", no, block_idx, bc->dev, strerror(no)); return err; }
/** * Search number of first block suitable for writing. */ void bnapStorageMount(BnapStorage_t *bsp){ int64_t t0; int64_t t1; uint32_t p0 = 0; uint32_t p1 = bsp->mmcp->capacity - 1; while (p1 > p0 + 1) _search_knee(bsp->mmcp, &p0, &p1, bsp->buf); /* check founded 2 points separately */ t0 = _check_block(bsp->mmcp, p0, bsp->buf); t1 = _check_block(bsp->mmcp, p1, bsp->buf); if (t0 > t1){ bsp->tip = p1; bsp->mtime = t0; } else{ bsp->tip = p0; bsp->mtime = t1; } if (t1 == -1) bsp->used = bsp->tip; /* only blocks before tip used */ else bsp->used = bsp->mmcp->capacity; /* whole card used */ }
/** * Search last record in ring buffer using binary search algorithm. * Function modifies block numbers using poiters to them. * * @param[in] mmcdp pointer to MMC driver * @param[in] p0 pointer to first block number to search * @param[in] p1 pointer to last block number to search * @param[in] mmcbuf temporal working buffer */ static void _search_knee(MMCDriver *mmcp, uint32_t *p0, uint32_t *p1, void *mmcbuf){ int64_t t0; /* timestamp of block */ int64_t t; /* time of mid point */ uint32_t p; /* mid block number */ t0 = _check_block(mmcp, *p0, mmcbuf); p = *p0 + ((*p1 - *p0) / 2); t = _check_block(mmcp, p, mmcbuf); if ((*p0 == 0) && (t0 == -1)){ /* probably storage never used before */ *p1 = *p0; } else{ if (t0 < t) *p0 = p; else *p1 = p; } }
static int _read_bootblock( struct bootconfig * bc, unsigned int block_idx ) { int err; err = _check_block( bc, block_idx ); if ( 0 != err ) return err; err = mtd_read( &bc->info, bc->fd, block_idx, 0, &bc->blocks[ block_idx ], sizeof( *bc->blocks ) ); if ( (err * -1) == EUCLEAN ) { bc_log( LOG_INFO, "Info: Block %d needs cleaningi\n", block_idx ); return 0; } if( err ) { bc_log( LOG_ERR, "Error %d while reading bootinfo block %d from %s: %s.\n", errno, block_idx, bc->dev, strerror( errno )); return -1; } return 0; }
int check_expansion( cg_expansion *cge, chunk_neighborhood* nbh, block_index base, block root_block ) { cell *cl; size_t i; int subresult; block_index oidx; cg_expansion* child; block b; block compare; switch (cge->cmp_strategy) { default: case CGCS_EXACT: case CGCS_CAN_GROW: case CGCS_CANT_GROW: case CGCS_BLOCKS_GROWTH: case CGCS_BLOCK_INFO: compare = cge->compare; break; case CGCS_ROOT: case CGCS_ROOT_CAN_GROW: case CGCS_ROOT_CANT_GROW: compare = root_block; break; case CGCS_ROOT_ID: compare = cge->compare; compare &= ~BM_ID; compare |= (root_block & BM_ID); break; case CGCS_ROOT_SPECIES: compare = cge->compare; compare &= ~BM_SPECIES; compare |= (root_block & BM_SPECIES); break; } switch (cge->type) { default: case CGET_BLOCK_RELATIVE: cge->target = nb_block(nbh, cidx_add(base, cge->offset)); b = *(cge->target); return _check_block(cge->cmp_strategy, b, compare, cge->cmp_mask); case CGET_BLOCK_EXACT: cge->target = &( nb_cell( nbh, cidx_add(base, cge->offset) )->blocks[cge->offset.xyz.w] ); b = *(cge->target); return _check_block(cge->cmp_strategy, b, compare, cge->cmp_mask); case CGET_BLOCK_EITHER: cl = nb_cell(nbh, cidx_add(base, cge->offset)); // Try the first block: cge->target = &(cl->blocks[cge->offset.xyz.w]); b = *(cge->target); if ((b & cge->cmp_mask) == compare) { return 1; } if (_check_block(cge->cmp_strategy, b, compare, cge->cmp_mask)) { return 1; } // Try the other block: cge->target = &(cl->blocks[cge->offset.xyz.w ^ 1]); b = *(cge->target); return _check_block(cge->cmp_strategy, b, compare, cge->cmp_mask); case CGET_LOGICAL_AND: oidx = cidx_add(base, cge->offset); cge->target = nb_block(nbh, oidx); for(i = 0; i < l_get_length(cge->children); ++i) { subresult = check_expansion( (cg_expansion*) l_get_item(cge->children, i), nbh, oidx, root_block ); if (!subresult) { return 0; } } return 1; case CGET_LOGICAL_OR: oidx = cidx_add(base, cge->offset); cge->target = nb_block(nbh, oidx); for(i = 0; i < l_get_length(cge->children); ++i) { child = (cg_expansion*) l_get_item(cge->children, i); subresult = check_expansion( child, nbh, oidx, root_block ); if (subresult) { return 1; } else { child->target = NULL; // mark this child as failed } } return 0; case CGET_LOGICAL_NOT: oidx = cidx_add(base, cge->offset); cge->target = nb_block(nbh, oidx); for(i = 0; i < l_get_length(cge->children); ++i) { child = (cg_expansion*) l_get_item(cge->children, i); subresult = check_expansion( child, nbh, oidx, root_block ); if (subresult) { return 0; } } return 1; } #ifdef DEBUG return 0; // Should be unreachable #endif }