From: Timothy Arceri Date: Wed, 3 Mar 2021 04:12:09 +0000 (+1100) Subject: util/disk_cache: separate file reads from cache item validation X-Git-Tag: upstream/21.2.3~6442 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=16b2b4342b5d561e0c56c47c4fffed22cfe1721c;p=platform%2Fupstream%2Fmesa.git util/disk_cache: separate file reads from cache item validation This will allow us to share validation between the single file cache and the multifile cache. It also reduces the number of malloc() calls. Reviewed-By: Mike Blumenkrantz Part-of: --- diff --git a/src/util/disk_cache_os.c b/src/util/disk_cache_os.c index c4a0324..aeed1c9 100644 --- a/src/util/disk_cache_os.c +++ b/src/util/disk_cache_os.c @@ -57,6 +57,7 @@ struct cache_entry_file_data { #include #include +#include "util/blob.h" #include "util/crc32.h" #include "util/debug.h" #include "util/disk_cache.h" @@ -373,55 +374,33 @@ disk_cache_evict_item(struct disk_cache *cache, char *filename) p_atomic_add(cache->size, - (uint64_t)sb.st_blocks * 512); } -void * -disk_cache_load_item(struct disk_cache *cache, char *filename, size_t *size) +static void * +parse_and_validate_cache_item(struct disk_cache *cache, void *cache_item, + size_t cache_item_size, size_t *size) { - int fd = -1, ret; - struct stat sb; - uint8_t *data = NULL; uint8_t *uncompressed_data = NULL; - uint8_t *file_header = NULL; - - fd = open(filename, O_RDONLY | O_CLOEXEC); - if (fd == -1) - goto fail; - - if (fstat(fd, &sb) == -1) - goto fail; - - data = malloc(sb.st_size); - if (data == NULL) - goto fail; - - size_t ck_size = cache->driver_keys_blob_size; - file_header = malloc(ck_size); - if (!file_header) - goto fail; - if (sb.st_size < ck_size) - goto fail; + struct blob_reader ci_blob_reader; + blob_reader_init(&ci_blob_reader, cache_item, cache_item_size); - ret = read_all(fd, file_header, ck_size); - if (ret == -1) + size_t header_size = cache->driver_keys_blob_size; + const void *keys_blob = blob_read_bytes(&ci_blob_reader, header_size); + if (ci_blob_reader.overrun) goto fail; /* Check for extremely unlikely hash collisions */ - if (memcmp(cache->driver_keys_blob, file_header, ck_size) != 0) { + if (memcmp(cache->driver_keys_blob, keys_blob, header_size) != 0) { assert(!"Mesa cache keys mismatch!"); goto fail; } - size_t cache_item_md_size = sizeof(uint32_t); - uint32_t md_type; - ret = read_all(fd, &md_type, cache_item_md_size); - if (ret == -1) + uint32_t md_type = blob_read_uint32(&ci_blob_reader); + if (ci_blob_reader.overrun) goto fail; if (md_type == CACHE_ITEM_TYPE_GLSL) { - uint32_t num_keys; - cache_item_md_size += sizeof(uint32_t); - ret = read_all(fd, &num_keys, sizeof(uint32_t)); - if (ret == -1) + uint32_t num_keys = blob_read_uint32(&ci_blob_reader); + if (ci_blob_reader.overrun) goto fail; /* The cache item metadata is currently just used for distributing @@ -430,44 +409,75 @@ disk_cache_load_item(struct disk_cache *cache, char *filename, size_t *size) * TODO: pass the metadata back to the caller and do some basic * validation. */ - cache_item_md_size += num_keys * sizeof(cache_key); - ret = lseek(fd, num_keys * sizeof(cache_key), SEEK_CUR); - if (ret == -1) + const void UNUSED *metadata = + blob_read_bytes(&ci_blob_reader, num_keys * sizeof(cache_key)); + if (ci_blob_reader.overrun) goto fail; } /* Load the CRC that was created when the file was written. */ - struct cache_entry_file_data cf_data; - size_t cf_data_size = sizeof(cf_data); - ret = read_all(fd, &cf_data, cf_data_size); - if (ret == -1) + struct cache_entry_file_data *cf_data = + (struct cache_entry_file_data *) + blob_read_bytes(&ci_blob_reader, sizeof(struct cache_entry_file_data)); + if (ci_blob_reader.overrun) goto fail; - /* Load the actual cache data. */ - size_t cache_data_size = - sb.st_size - cf_data_size - ck_size - cache_item_md_size; - ret = read_all(fd, data, cache_data_size); - if (ret == -1) - goto fail; + size_t cache_data_size = ci_blob_reader.end - ci_blob_reader.current; + const uint8_t *data = (uint8_t *) blob_read_bytes(&ci_blob_reader, cache_data_size); /* Check the data for corruption */ - if (cf_data.crc32 != util_hash_crc32(data, cache_data_size)) + if (cf_data->crc32 != util_hash_crc32(data, cache_data_size)) goto fail; /* Uncompress the cache data */ - uncompressed_data = malloc(cf_data.uncompressed_size); + uncompressed_data = malloc(cf_data->uncompressed_size); if (!util_compress_inflate(data, cache_data_size, uncompressed_data, - cf_data.uncompressed_size)) + cf_data->uncompressed_size)) + goto fail; + + if (size) + *size = cf_data->uncompressed_size; + + return uncompressed_data; + + fail: + if (uncompressed_data) + free(uncompressed_data); + + return NULL; +} + +void * +disk_cache_load_item(struct disk_cache *cache, char *filename, size_t *size) +{ + uint8_t *data = NULL; + + int fd = open(filename, O_RDONLY | O_CLOEXEC); + if (fd == -1) + goto fail; + + struct stat sb; + if (fstat(fd, &sb) == -1) + goto fail; + + data = malloc(sb.st_size); + if (data == NULL) + goto fail; + + /* Read entire file into memory */ + int ret = read_all(fd, data, sb.st_size); + if (ret == -1) + goto fail; + + uint8_t *uncompressed_data = + parse_and_validate_cache_item(cache, data, sb.st_size, size); + if (!uncompressed_data) goto fail; free(data); free(filename); - free(file_header); close(fd); - if (size) - *size = cf_data.uncompressed_size; - return uncompressed_data; fail: @@ -475,10 +485,6 @@ disk_cache_load_item(struct disk_cache *cache, char *filename, size_t *size) free(data); if (filename) free(filename); - if (uncompressed_data) - free(uncompressed_data); - if (file_header) - free(file_header); if (fd != -1) close(fd);