/** * Constructs a full data block representation from the specified minimal * block entry. However, the resultant block's pointers are set to null, * rather than populated via hash table lookups. This behavior is useful when * the RAM representation has not been fully constructed yet. * * @param out_block On success, this gets populated with the data * block information. * @param block_entry The source block entry to convert. * * @return 0 on success; nonzero on failure. */ int nffs_block_from_hash_entry_no_ptrs(struct nffs_block *out_block, struct nffs_hash_entry *block_entry) { struct nffs_disk_block disk_block; uint32_t area_offset; uint8_t area_idx; int rc; assert(nffs_hash_id_is_block(block_entry->nhe_id)); if (nffs_hash_entry_is_dummy(block_entry)) { /* * We can't read this from disk so we'll be missing filling in anything * not already in inode_entry (e.g., prev_id). */ out_block->nb_hash_entry = block_entry; return FS_ENOENT; /* let caller know it's a partial inode_entry */ } nffs_flash_loc_expand(block_entry->nhe_flash_loc, &area_idx, &area_offset); rc = nffs_block_read_disk(area_idx, area_offset, &disk_block); if (rc != 0) { return rc; } out_block->nb_hash_entry = block_entry; nffs_block_from_disk_no_ptrs(out_block, &disk_block); return 0; }
/** * Checks that each block a chain of data blocks was properly restored. * * @param last_block_entry The entry corresponding to the last block in * the chain. * * @return 0 if the block chain is OK; * FS_ECORRUPT if corruption is detected; * nonzero on other error. */ static int nffs_restore_validate_block_chain(struct nffs_hash_entry *last_block_entry) { struct nffs_disk_block disk_block; struct nffs_hash_entry *cur; struct nffs_block block; uint32_t area_offset; uint8_t area_idx; int rc; cur = last_block_entry; while (cur != NULL) { if (nffs_hash_entry_is_dummy(cur)) { return FS_ENOENT; } nffs_flash_loc_expand(cur->nhe_flash_loc, &area_idx, &area_offset); rc = nffs_block_read_disk(area_idx, area_offset, &disk_block); if (rc != 0) { return rc; } rc = nffs_block_from_hash_entry(&block, cur); if (rc != 0) { return rc; } cur = block.nb_prev; } return 0; }
/** * Deletes the specified block entry from the nffs RAM representation. * * @param block_entry The block entry to delete. * * @return 0 on success; nonzero on failure. */ int nffs_block_delete_from_ram(struct nffs_hash_entry *block_entry) { struct nffs_inode_entry *inode_entry; struct nffs_block block; int rc; if (nffs_hash_entry_is_dummy(block_entry)) { /* * it's very limited to what we can do here as the block doesn't have * any way to get to the inode via hash entry. Just delete the * block and return FS_ECORRUPT */ nffs_hash_remove(block_entry); nffs_block_entry_free(block_entry); return FS_ECORRUPT; } rc = nffs_block_from_hash_entry(&block, block_entry); if (rc == 0 || rc == FS_ECORRUPT) { /* If file system corruption was detected, the resulting block is still * valid and can be removed from RAM. * Note that FS_CORRUPT can occur because the owning inode was not * found in the hash table - this can occur during the sweep where * the inodes were deleted ahead of the blocks. */ inode_entry = block.nb_inode_entry; if (inode_entry != NULL && inode_entry->nie_last_block_entry == block_entry) { inode_entry->nie_last_block_entry = block.nb_prev; } nffs_hash_remove(block_entry); nffs_block_entry_free(block_entry); } return rc; }