Merge "storageproxyd: Sync parent dir when creating a file"
diff --git a/trusty/storage/proxy/storage.c b/trusty/storage/proxy/storage.c
index d74a708..c00c399 100644
--- a/trusty/storage/proxy/storage.c
+++ b/trusty/storage/proxy/storage.c
@@ -41,11 +41,9 @@
SS_DIRTY = 1,
};
-static int ssdir_fd = -1;
static const char *ssdir_name;
static enum sync_state fs_state;
-static enum sync_state dir_state;
static enum sync_state fd_state[FD_TBL_SIZE];
static bool alternate_mode;
@@ -59,10 +57,6 @@
{
uint32_t handle = fd;
- if (open_flags & O_CREAT) {
- dir_state = SS_DIRTY;
- }
-
if (handle < FD_TBL_SIZE) {
fd_state[fd] = SS_CLEAN; /* fd clean */
if (open_flags & O_TRUNC) {
@@ -193,7 +187,6 @@
goto err_response;
}
- dir_state = SS_DIRTY;
rc = unlink(path);
if (rc < 0) {
rc = errno;
@@ -217,12 +210,21 @@
return ipc_respond(msg, NULL, 0);
}
+static void sync_parent(const char* path) {
+ int parent_fd;
+ char* parent_path = dirname(path);
+ parent_fd = TEMP_FAILURE_RETRY(open(parent_path, O_RDONLY));
+ if (parent_fd >= 0) {
+ fsync(parent_fd);
+ close(parent_fd);
+ } else {
+ ALOGE("%s: failed to open parent directory \"%s\" for sync: %s\n", __func__, parent_path,
+ strerror(errno));
+ }
+}
-int storage_file_open(struct storage_msg *msg,
- const void *r, size_t req_len)
-{
- char *path = NULL;
- char* parent_path;
+int storage_file_open(struct storage_msg* msg, const void* r, size_t req_len) {
+ char* path = NULL;
const struct storage_file_open_req *req = r;
struct storage_file_open_resp resp = {0};
@@ -271,7 +273,6 @@
if (req->flags & STORAGE_FILE_OPEN_TRUNCATE)
open_flags |= O_TRUNC;
- parent_path = dirname(path);
if (req->flags & STORAGE_FILE_OPEN_CREATE) {
/*
* Create the alternate parent dir if needed & allowed.
@@ -281,8 +282,11 @@
* it has access to the necessary bit of information.
*/
if (strstr(req->name, ALTERNATE_DATA_DIR) == req->name) {
+ char* parent_path = dirname(path);
rc = mkdir(parent_path, S_IRWXU);
- if (rc && errno != EEXIST) {
+ if (rc == 0) {
+ sync_parent(parent_path);
+ } else if (errno != EEXIST) {
ALOGE("%s: Could not create parent directory \"%s\": %s\n", __func__, parent_path,
strerror(errno));
}
@@ -320,6 +324,10 @@
msg->result = translate_errno(rc);
goto err_response;
}
+
+ if (open_flags & O_CREAT) {
+ sync_parent(path);
+ }
free(path);
/* at this point rc contains storage file fd */
@@ -512,16 +520,10 @@
alternate_mode = is_gsi_running();
fs_state = SS_CLEAN;
- dir_state = SS_CLEAN;
for (uint i = 0; i < FD_TBL_SIZE; i++) {
fd_state[i] = SS_UNUSED; /* uninstalled */
}
- ssdir_fd = open(dirname, O_RDONLY);
- if (ssdir_fd < 0) {
- ALOGE("failed to open ss root dir \"%s\": %s\n",
- dirname, strerror(errno));
- }
ssdir_name = dirname;
return 0;
}
@@ -545,25 +547,16 @@
}
}
- /* check if we need to sync the directory */
- if (dir_state == SS_DIRTY) {
- if (fs_state == SS_CLEAN) {
- rc = fsync(ssdir_fd);
- if (rc < 0) {
- ALOGE("fsync for ssdir failed: %s\n", strerror(errno));
- return rc;
- }
- }
- dir_state = SS_CLEAN; /* set to clean */
- }
-
- /* check if we need to sync the whole fs */
+ /* check if we need to sync all filesystems */
if (fs_state == SS_DIRTY) {
- rc = syscall(SYS_syncfs, ssdir_fd);
- if (rc < 0) {
- ALOGE("syncfs failed: %s\n", strerror(errno));
- return rc;
- }
+ /*
+ * We sync all filesystems here because we don't know what filesystem
+ * needs syncing if there happen to be other filesystems symlinked under
+ * the root data directory. This should not happen in the normal case
+ * because our fd table is large enough to handle the few open files we
+ * use.
+ */
+ sync();
fs_state = SS_CLEAN;
}