ANDROID: Incremental fs: Truncate file when complete

Bug: 182185202
Test: incfs_test passes
Signed-off-by: Paul Lawrence <paullawrence@google.com>
Change-Id: I96a192011f19efa1c597275dafc6c216f8ed0b56
This commit is contained in:
Paul Lawrence 2021-03-17 13:35:44 -07:00
parent 38d8cfc0bd
commit 16ce7f9c5e
2 changed files with 60 additions and 0 deletions

View File

@ -648,6 +648,7 @@ static void notify_unlink(struct dentry *dentry, const char *file_id_str,
static void maybe_delete_incomplete_file(struct file *f,
struct data_file *df)
{
struct backing_file_context *bfc;
struct mount_info *mi = df->df_mount_info;
char *file_id_str = NULL;
struct dentry *incomplete_file_dentry = NULL;
@ -657,6 +658,22 @@ static void maybe_delete_incomplete_file(struct file *f,
if (atomic_read(&df->df_data_blocks_written) < df->df_data_block_count)
goto out;
/* Truncate file to remove any preallocated space */
bfc = df->df_backing_file_context;
if (bfc) {
struct file *f = bfc->bc_file;
if (f) {
loff_t size = i_size_read(file_inode(f));
error = vfs_truncate(&f->f_path, size);
if (error)
/* No useful action on failure */
pr_warn("incfs: Failed to truncate complete file: %d\n",
error);
}
}
/* This is best effort - there is no useful action to take on failure */
file_id_str = file_id_to_str(df->df_id);
if (!file_id_str)

View File

@ -2,6 +2,8 @@
/*
* Copyright 2018 Google LLC
*/
#define _GNU_SOURCE
#include <alloca.h>
#include <dirent.h>
#include <errno.h>
@ -4116,6 +4118,46 @@ static int mmap_test(const char *mount_dir)
return result;
}
static int truncate_test(const char *mount_dir)
{
int result = TEST_FAILURE;
char *backing_dir = NULL;
int cmd_fd = -1;
struct test_file file = {
.name = "file",
.size = INCFS_DATA_FILE_BLOCK_SIZE,
};
char *backing_file = NULL;
int fd = -1;
struct stat st;
TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0);
TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
TESTEQUAL(emit_file(cmd_fd, NULL, file.name, &file.id, file.size, NULL),
0);
TEST(backing_file = concat_file_name(backing_dir, file.name),
backing_file);
TEST(fd = open(backing_file, O_RDWR | O_CLOEXEC), fd != -1);
TESTEQUAL(stat(backing_file, &st), 0);
TESTCOND(st.st_blocks < 128);
TESTEQUAL(fallocate(fd, FALLOC_FL_KEEP_SIZE, 0, 1 << 24), 0);
TESTEQUAL(stat(backing_file, &st), 0);
TESTCOND(st.st_blocks > 32768);
TESTEQUAL(emit_test_file_data(mount_dir, &file), 0);
TESTEQUAL(stat(backing_file, &st), 0);
TESTCOND(st.st_blocks < 128);
result = TEST_SUCCESS;
out:
close(fd);
free(backing_file);
close(cmd_fd);
umount(mount_dir);
free(backing_dir);
return result;
}
static char *setup_mount_dir()
{
struct stat st;
@ -4233,6 +4275,7 @@ int main(int argc, char *argv[])
MAKE_TEST(verity_test),
MAKE_TEST(enable_verity_test),
MAKE_TEST(mmap_test),
MAKE_TEST(truncate_test),
};
#undef MAKE_TEST