1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <lk/reflist.h> 20 #include <stdbool.h> 21 #include <stdint.h> 22 23 #include "block_device.h" 24 #include "crypt.h" 25 26 #ifdef APP_STORAGE_BLOCK_CACHE_SIZE 27 #define BLOCK_CACHE_SIZE (APP_STORAGE_BLOCK_CACHE_SIZE) 28 #else 29 #define BLOCK_CACHE_SIZE (64) 30 #endif 31 #ifdef APP_STORAGE_MAIN_BLOCK_SIZE 32 #define MAX_BLOCK_SIZE (APP_STORAGE_MAIN_BLOCK_SIZE) 33 #else 34 #define MAX_BLOCK_SIZE (2048) 35 #endif 36 37 /** 38 * enum block_cache_entry_data_state - State of a block cache entry's data 39 * @BLOCK_ENTRY_DATA_INVALID: Block entry does not contain valid data. 40 * @BLOCK_ENTRY_DATA_LOADING: Block entry data load is pending. State will 41 * be updated when the load operation completes. 42 * @BLOCK_ENTRY_DATA_LOAD_FAILED: Block data could not be loaded from the disk. 43 * This may be caused by a transient I/O error. 44 * @BLOCK_ENTRY_DATA_NOT_FOUND: Block does not exist on disk. 45 * @BLOCK_ENTRY_DATA_CLEAN_DECRYPTED: Block entry contains valid plaintext data 46 * that is either on disk or queued to be 47 * written to disk 48 * @BLOCK_ENTRY_DATA_CLEAN_ENCRYPTED: Block entry contains valid ciphertext data 49 * that is either on disk or queued to be 50 * written to disk. 51 * @BLOCK_ENTRY_DATA_DIRTY_DECRYPTED: Block entry contains valid plaintext data 52 * that has not yet been queued for write 53 * back to disk. Data must be encrypted and 54 * written back or discarded before the cache 55 * entry can be reused. 56 * @BLOCK_ENTRY_DATA_DIRTY_ENCRYPTED: Block entry contains valid ciphertext data 57 * that has not yet been queued for write 58 * back to disk. Data must be written back or 59 * discarded before the cache entry can be 60 * reused. 61 */ 62 enum block_cache_entry_data_state { 63 BLOCK_ENTRY_DATA_INVALID = 0, 64 BLOCK_ENTRY_DATA_LOADING, 65 BLOCK_ENTRY_DATA_LOAD_FAILED, 66 BLOCK_ENTRY_DATA_NOT_FOUND, 67 BLOCK_ENTRY_DATA_CLEAN_DECRYPTED, 68 BLOCK_ENTRY_DATA_CLEAN_ENCRYPTED, 69 BLOCK_ENTRY_DATA_DIRTY_DECRYPTED, 70 BLOCK_ENTRY_DATA_DIRTY_ENCRYPTED, 71 }; 72 73 /** 74 * struct block_cache_entry - block cache entry 75 * @guard1: Set to BLOCK_CACHE_GUARD_1 to detect out of bound 76 * writes to data. 77 * @data: Decrypted block data. 78 * @guard2: Set to BLOCK_CACHE_GUARD_2 to detect out of bound 79 * writes to data. 80 * @key: Key to use for encrypt, decrypt and calculate_mac. 81 * @dev: Device that block was read from and will be written 82 * to. 83 * @block: Block number in dev. 84 * @block_size: Size of block, but match dev->block_size. 85 * @mac: Last calculated mac of encrypted block data. 86 * @state: Current state of @data, indicating if data has been 87 * loaded from disk or written into this cache entry. 88 * This state is reset to %BLOCK_ENTRY_INVALID when a 89 * cache entry previously containing a different block 90 * is selected for reuse. See &enum 91 * block_cache_entry_state for details. 92 * @encrypted: %true if @data is currently encrypted. 93 * @dirty_ref: Data is currently being modified. Only a single 94 * reference should be allowed. 95 * @dirty_mac: Data has been modified. Mac needs to be updated 96 * after encrypting block. 97 * @dirty_tmp: Data can be discarded by 98 * block_cache_discard_transaction. 99 * @pinned: Block cannot be reused if it fails to write. 100 * @is_superblock: Block is used as a superblock and files should be 101 * synced before it is written. 102 * @dirty_tr: Transaction that modified block. 103 * @obj: Reference tracking struct. 104 * @lru_node: List node for tracking least recently used cache 105 * entries. 106 * @io_op_node: List node for tracking active read and write 107 * operations. 108 * @io_op: Currently active io operation. 109 * 110 * @dirty_ref, @dirty_mac, @dirty_tmp, and @dirty_tr are only relevant if @state 111 * is %BLOCK_ENTRY_DATA_DIRTY, i.e. @data has been modified and not yet queued 112 * for write or discarded. 113 */ 114 struct block_cache_entry { 115 uint64_t guard1; 116 uint8_t data[MAX_BLOCK_SIZE]; 117 uint64_t guard2; 118 119 const struct key* key; 120 struct block_device* dev; 121 data_block_t block; 122 size_t block_size; 123 struct mac mac; 124 enum block_cache_entry_data_state state; 125 bool dirty_ref; 126 bool dirty_mac; 127 bool dirty_tmp; 128 bool pinned; 129 bool is_superblock; 130 struct transaction* dirty_tr; 131 132 struct obj obj; 133 struct list_node lru_node; 134 struct list_node io_op_node; 135 enum { 136 BLOCK_CACHE_IO_OP_NONE, 137 BLOCK_CACHE_IO_OP_READ, 138 BLOCK_CACHE_IO_OP_WRITE, 139 } io_op; 140 }; 141 142 #define BLOCK_CACHE_SIZE_BYTES \ 143 (sizeof(struct block_cache_entry[BLOCK_CACHE_SIZE])) 144