Add checkpoint sync flag for TD superblock writes.
Writes to the TD filesystem must not be committed while an uncommitted
checkpoint is pending for userdata. Adds a flag to TD superblock write
messages telling storageproxyd to not perform the write until it is safe
to do so.
Test: Boot with userdata checkpointed and attempt a TD write
Bug: 194313068
Change-Id: Idaf63f1cb773c144914c7d362f092d6245f2c4af
diff --git a/block_device_tipc.c b/block_device_tipc.c
index b9f5b72..209324c 100644
--- a/block_device_tipc.c
+++ b/block_device_tipc.c
@@ -167,7 +167,7 @@
ret = rpmb_write(dev_rpmb->state->rpmb_state, data,
rpmb_block * BLOCK_SIZE_RPMB_BLOCKS,
- BLOCK_SIZE_RPMB_BLOCKS, true);
+ BLOCK_SIZE_RPMB_BLOCKS, true, dev_rpmb->is_userdata);
SS_DBG_IO("%s: block %" PRIu64 ", base %d, rpmb_block %d, ret %d\n",
__func__, block, dev_rpmb->base, rpmb_block, ret);
@@ -207,7 +207,8 @@
assert(data_size == BLOCK_SIZE_MAIN);
ret = ns_write_pos(dev_ns->state->ipc_handle, dev_ns->ns_handle,
- block * BLOCK_SIZE_MAIN, data, data_size);
+ block * BLOCK_SIZE_MAIN, data, data_size,
+ dev_ns->is_userdata);
SS_DBG_IO("%s: block %" PRIu64 ", ret %d\n", __func__, block, ret);
block_cache_complete_write(dev, block, ret != BLOCK_SIZE_MAIN);
}
@@ -219,7 +220,8 @@
static void block_device_tipc_init_dev_rpmb(struct block_device_rpmb* dev_rpmb,
struct block_device_tipc* state,
uint16_t base,
- uint32_t block_count) {
+ uint32_t block_count,
+ bool is_userdata) {
dev_rpmb->dev.start_read = block_device_tipc_rpmb_start_read;
dev_rpmb->dev.start_write = block_device_tipc_rpmb_start_write;
dev_rpmb->dev.wait_for_io = block_device_tipc_rpmb_wait_for_io;
@@ -231,10 +233,12 @@
list_initialize(&dev_rpmb->dev.io_ops);
dev_rpmb->state = state;
dev_rpmb->base = base;
+ dev_rpmb->is_userdata = is_userdata;
}
static void block_device_tipc_init_dev_ns(struct block_device_ns* dev_ns,
- struct block_device_tipc* state) {
+ struct block_device_tipc* state,
+ bool is_userdata) {
dev_ns->dev.start_read = block_device_tipc_ns_start_read;
dev_ns->dev.start_write = block_device_tipc_ns_start_write;
dev_ns->dev.wait_for_io = block_device_tipc_ns_wait_for_io;
@@ -246,6 +250,7 @@
list_initialize(&dev_ns->dev.io_ops);
dev_ns->state = state;
dev_ns->ns_handle = 0; /* Filled in later */
+ dev_ns->is_userdata = is_userdata;
}
/**
@@ -316,7 +321,8 @@
rpmb_set_key(state, &out->rpmb_key);
ret = rpmb_write(state, in->block_data,
- rpmb_key_part_base * BLOCK_SIZE_RPMB_BLOCKS, 1, false);
+ rpmb_key_part_base * BLOCK_SIZE_RPMB_BLOCKS, 1, false,
+ false);
if (ret < 0) {
SS_ERR("%s: rpmb_write failed (%d)\n", __func__, ret);
return ret;
@@ -449,7 +455,7 @@
}
block_device_tipc_init_dev_rpmb(&state->dev_rpmb, state, rpmb_part2_base,
- rpmb_block_count - rpmb_part2_base);
+ rpmb_block_count - rpmb_part2_base, false);
/* TODO: allow non-rpmb based tamper proof storage */
ret = fs_init(&state->tr_state_rpmb, fs_key, &state->dev_rpmb.dev,
@@ -474,7 +480,7 @@
goto err_fs_rpmb_boot_create_port;
}
- block_device_tipc_init_dev_ns(&state->dev_ns, state);
+ block_device_tipc_init_dev_ns(&state->dev_ns, state, true);
ret = ns_open_file(state->ipc_handle, "0", &state->dev_ns.ns_handle, true);
if (ret < 0) {
@@ -484,7 +490,7 @@
}
#if HAS_FS_TDP
- block_device_tipc_init_dev_ns(&state->dev_ns_tdp, state);
+ block_device_tipc_init_dev_ns(&state->dev_ns_tdp, state, false);
ret = ns_open_file(state->ipc_handle, "persist/0",
&state->dev_ns_tdp.ns_handle, true);
@@ -497,7 +503,7 @@
block_device_tipc_init_dev_rpmb(&state->dev_ns_tdp_rpmb, state,
rpmb_part_sb_tdp_base,
- rpmb_part_sb_ns_block_count);
+ rpmb_part_sb_ns_block_count, false);
ret = fs_init(&state->tr_state_ns_tdp, fs_key, &state->dev_ns_tdp.dev,
&state->dev_ns_tdp_rpmb.dev, false /* Don't allow wiping */);
@@ -531,7 +537,7 @@
state->fs_ns.tr_state = &state->tr_state_ns;
block_device_tipc_init_dev_rpmb(&state->dev_ns_rpmb, state, rpmb_part1_base,
- rpmb_part_sb_ns_block_count);
+ rpmb_part_sb_ns_block_count, true);
ret = fs_init(&state->tr_state_ns, fs_key, &state->dev_ns.dev,
&state->dev_ns_rpmb.dev, new_ns_fs);
diff --git a/block_device_tipc.h b/block_device_tipc.h
index 47112fa..c45a16b 100644
--- a/block_device_tipc.h
+++ b/block_device_tipc.h
@@ -28,14 +28,17 @@
/**
* struct block_device_rpmb
- * @state: Pointer to shared state containing ipc_handle and rpmb_state
- * @dev: Block device state
- * @base: First block to use in rpmb partition
+ * @state: Pointer to shared state containing ipc_handle and rpmb_state
+ * @dev: Block device state
+ * @base: First block to use in rpmb partition
+ * @is_userdata: Is this RPMB device tied to the state of the userdata
+ * partition?
*/
struct block_device_rpmb {
struct block_device dev;
struct block_device_tipc* state;
uint16_t base;
+ bool is_userdata;
};
/**
@@ -43,11 +46,14 @@
* @dev: Block device state
* @state: Pointer to shared state containing ipc_handle
* @ns_handle: Handle
+ * @is_userdata: Is the backing file for this device in the (non-persistent)
+ * userdata partition?
*/
struct block_device_ns {
struct block_device dev;
struct block_device_tipc* state;
ns_handle_t ns_handle;
+ bool is_userdata;
};
struct client_port_context {
diff --git a/rpmb.c b/rpmb.c
index 473e26b..f5b1c0f 100644
--- a/rpmb.c
+++ b/rpmb.c
@@ -213,7 +213,7 @@
memcpy(cmd.key_mac.byte, key->byte, sizeof(cmd.key_mac.byte));
ret = rpmb_send(state->mmc_handle, &cmd, sizeof(cmd), &rescmd,
- sizeof(rescmd), &res, sizeof(res), false);
+ sizeof(rescmd), &res, sizeof(res), false, false);
if (ret < 0)
return ret;
@@ -241,7 +241,7 @@
struct rpmb_packet res;
ret = rpmb_send(state->mmc_handle, NULL, 0, &cmd, sizeof(cmd), &res,
- sizeof(res), false);
+ sizeof(res), false, false);
if (ret < 0)
return ret;
@@ -309,7 +309,7 @@
return -EINVAL;
ret = rpmb_send(state->mmc_handle, NULL, 0, &cmd, sizeof(cmd), res,
- sizeof(res[0]) * count, false);
+ sizeof(res[0]) * count, false, false);
if (ret < 0)
return ret;
@@ -387,7 +387,8 @@
const char* buf,
uint16_t addr,
uint16_t count,
- bool sync) {
+ bool sync,
+ bool sync_checkpoint) {
int i;
int ret;
struct rpmb_key mac;
@@ -416,7 +417,7 @@
}
ret = rpmb_send(state->mmc_handle, cmd, sizeof(cmd[0]) * count, &rescmd,
- sizeof(rescmd), &res, sizeof(res), sync);
+ sizeof(rescmd), &res, sizeof(res), sync, sync_checkpoint);
if (ret < 0) {
fprintf(stderr, "rpmb send failed: %d, result: %hu\n", ret,
rpmb_get_u16(res.result));
@@ -514,13 +515,14 @@
const void* buf,
uint16_t addr,
uint16_t count,
- bool sync) {
+ bool sync,
+ bool sync_checkpoint) {
int ret;
if (!state)
return -EINVAL;
- ret = rpmb_write_data(state, buf, addr, count, sync);
+ ret = rpmb_write_data(state, buf, addr, count, sync, sync_checkpoint);
if (ret < 0)
return ret;
diff --git a/rpmb.h b/rpmb.h
index 21c9f8b..647fe0f 100644
--- a/rpmb.h
+++ b/rpmb.h
@@ -51,7 +51,8 @@
const void* buf,
uint16_t addr,
uint16_t count,
- bool sync);
+ bool sync,
+ bool sync_checkpoint);
/* needs */
int rpmb_send(void* mmc_handle,
@@ -61,6 +62,7 @@
size_t write_buf_size,
void* read_buf,
size_t read_buf_size,
- bool sync);
+ bool sync,
+ bool sync_checkpoint);
#endif
diff --git a/tipc_ns.c b/tipc_ns.c
index 6557560..7ba8d69 100644
--- a/tipc_ns.c
+++ b/tipc_ns.c
@@ -66,7 +66,8 @@
size_t write_size,
void* read_buf,
size_t read_size,
- bool sync) {
+ bool sync,
+ bool sync_checkpoint) {
SS_DBG_IO(
"%s: handle %p, rel_write size %zu, write size %zu, read size %zu\n",
__func__, handle_, reliable_write_size, write_size, read_size);
@@ -90,6 +91,10 @@
write_size,
};
+ if (sync_checkpoint) {
+ msg.flags |= STORAGE_MSG_FLAG_PRE_COMMIT_CHECKPOINT;
+ }
+
struct iovec rx_iov[] = {
{.iov_base = &msg, .iov_len = sizeof(msg)},
{.iov_base = read_buf, .iov_len = read_size},
@@ -242,7 +247,8 @@
ns_handle_t handle,
ns_off_t pos,
const void* data,
- int data_size) {
+ int data_size,
+ bool is_userdata) {
SS_DBG_IO("%s: handle %llu, pos %llu, size %d\n", __func__, handle, pos,
data_size);
@@ -253,6 +259,7 @@
struct storage_msg msg = {
.cmd = STORAGE_FILE_WRITE,
+ .flags = is_userdata ? STORAGE_MSG_FLAG_PRE_COMMIT_CHECKPOINT : 0,
.size = sizeof(msg) + sizeof(req) + data_size,
};
diff --git a/tipc_ns.h b/tipc_ns.h
index 9851f2e..c1c3f0d 100644
--- a/tipc_ns.h
+++ b/tipc_ns.h
@@ -36,4 +36,5 @@
ns_handle_t handle,
ns_off_t pos,
const void* data,
- int data_size);
+ int data_size,
+ bool is_userdata);