From dee1afdd651fad7b62001c5d235cb6efb6c7d7b8 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Wed, 27 May 2020 14:00:12 -0700 Subject: [PATCH] Revert "ANDROID: Incremental fs: Avoid continually recalculating hashes" This reverts commit ab185e45f637ba0b0239268f1130890c8837981d. This change used the PageChecked flag to mark the Merkle tree as checked. However, f2fs uses this internally. This caused file system hangs on devices after installs. Test: incfs_test passes, installs no longer hang Bug: 157589629 Signed-off-by: Paul Lawrence Change-Id: I980a700d65eb4f4a77434715d61dda4b8e80658c --- fs/incfs/data_mgmt.c | 80 ++++++-------------------------------------- 1 file changed, 10 insertions(+), 70 deletions(-) diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c index bf34f57e27a2..6b74a9d0325f 100644 --- a/fs/incfs/data_mgmt.c +++ b/fs/incfs/data_mgmt.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -388,8 +387,7 @@ static void log_block_read(struct mount_info *mi, incfs_uuid_t *id, } static int validate_hash_tree(struct file *bf, struct data_file *df, - int block_index, struct mem_range data, - u8 *tmp_buf) + int block_index, struct mem_range data, u8 *buf) { u8 digest[INCFS_MAX_HASH_SIZE] = {}; struct mtree *tree = NULL; @@ -402,7 +400,6 @@ static int validate_hash_tree(struct file *bf, struct data_file *df, int hash_per_block; int lvl = 0; int res; - struct page *saved_page = NULL; tree = df->df_hash_tree; sig = df->df_signature; @@ -424,39 +421,17 @@ static int validate_hash_tree(struct file *bf, struct data_file *df, INCFS_DATA_FILE_BLOCK_SIZE); size_t hash_off_in_block = hash_block_index * digest_size % INCFS_DATA_FILE_BLOCK_SIZE; - struct mem_range buf_range; - struct page *page = NULL; - bool aligned = (hash_block_off & - (INCFS_DATA_FILE_BLOCK_SIZE - 1)) == 0; - u8 *actual_buf; + struct mem_range buf_range = range(buf, + INCFS_DATA_FILE_BLOCK_SIZE); + ssize_t read_res = incfs_kread(bf, buf, + INCFS_DATA_FILE_BLOCK_SIZE, hash_block_off); - if (aligned) { - page = read_mapping_page( - bf->f_inode->i_mapping, - hash_block_off / INCFS_DATA_FILE_BLOCK_SIZE, - NULL); + if (read_res < 0) + return read_res; + if (read_res != INCFS_DATA_FILE_BLOCK_SIZE) + return -EIO; - if (IS_ERR(page)) - return PTR_ERR(page); - - actual_buf = page_address(page); - } else { - size_t read_res = - incfs_kread(bf, tmp_buf, - INCFS_DATA_FILE_BLOCK_SIZE, - hash_block_off); - - if (read_res < 0) - return read_res; - if (read_res != INCFS_DATA_FILE_BLOCK_SIZE) - return -EIO; - - actual_buf = tmp_buf; - } - - buf_range = range(actual_buf, INCFS_DATA_FILE_BLOCK_SIZE); - saved_digest_rng = - range(actual_buf + hash_off_in_block, digest_size); + saved_digest_rng = range(buf + hash_off_in_block, digest_size); if (!incfs_equal_ranges(calc_digest_rng, saved_digest_rng)) { int i; bool zero = true; @@ -471,37 +446,9 @@ static int validate_hash_tree(struct file *bf, struct data_file *df, if (zero) pr_debug("incfs: Note saved_digest all zero - did you forget to load the hashes?\n"); - - if (saved_page) - put_page(saved_page); - if (page) - put_page(page); return -EBADMSG; } - if (saved_page) { - /* - * This is something of a kludge. The PageChecked flag - * is reserved for the file system, but we are setting - * this on the pages belonging to the underlying file - * system. incfs is only going to be used on f2fs and - * ext4 which only use this flag when fs-verity is being - * used, so this is safe for now, however a better - * mechanism needs to be found. - */ - SetPageChecked(saved_page); - put_page(saved_page); - saved_page = NULL; - } - - if (page && PageChecked(page)) { - put_page(page); - return 0; - } - - saved_page = page; - page = NULL; - res = incfs_calc_digest(tree->alg, buf_range, calc_digest_rng); if (res) return res; @@ -511,15 +458,8 @@ static int validate_hash_tree(struct file *bf, struct data_file *df, root_hash_rng = range(tree->root_hash, digest_size); if (!incfs_equal_ranges(calc_digest_rng, root_hash_rng)) { pr_debug("incfs: Root hash mismatch blk:%d\n", block_index); - if (saved_page) - put_page(saved_page); return -EBADMSG; } - - if (saved_page) { - SetPageChecked(saved_page); - put_page(saved_page); - } return 0; }