[Mesa-dev] [PATCH v2 5/5] util/disk_cache: write cache item metadata to disk
Nicolai Hähnle
nhaehnle at gmail.com
Wed Aug 23 14:00:25 UTC 2017
On 23.08.2017 08:33, Timothy Arceri wrote:
> ---
> src/util/disk_cache.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 88 insertions(+), 1 deletion(-)
>
> diff --git a/src/util/disk_cache.c b/src/util/disk_cache.c
> index c1b7429b92..dd12a09841 100644
> --- a/src/util/disk_cache.c
> +++ b/src/util/disk_cache.c
> @@ -105,20 +105,22 @@ struct disk_cache_put_job {
>
> struct disk_cache *cache;
>
> cache_key key;
>
> /* Copy of cache data to be compressed and written. */
> void *data;
>
> /* Size of data to be compressed and written. */
> size_t size;
> +
> + struct cache_item_metadata cache_item_metadata;
> };
>
> /* Create a directory named 'path' if it does not already exist.
> *
> * Returns: 0 if path already exists as a directory or if created.
> * -1 in all other cases.
> */
> static int
> mkdir_if_needed(const char *path)
> {
> @@ -771,29 +773,60 @@ create_put_job(struct disk_cache *cache, const cache_key key,
> {
> struct disk_cache_put_job *dc_job = (struct disk_cache_put_job *)
> malloc(sizeof(struct disk_cache_put_job) + size);
>
> if (dc_job) {
> dc_job->cache = cache;
> memcpy(dc_job->key, key, sizeof(cache_key));
> dc_job->data = dc_job + 1;
> memcpy(dc_job->data, data, size);
> dc_job->size = size;
> +
> + /* Copy the cache item metadata */
> + if (cache_item_metadata) {
> + dc_job->cache_item_metadata.type = cache_item_metadata->type;
> + if (cache_item_metadata->type == CACHE_ITEM_TYPE_GLSL) {
> + dc_job->cache_item_metadata.num_keys =
> + cache_item_metadata->num_keys;
> + dc_job->cache_item_metadata.keys = (cache_key *)
> + malloc(cache_item_metadata->num_keys * sizeof(cache_key));
> +
> + if (!dc_job->cache_item_metadata.keys)
> + goto fail;
> +
> + for (unsigned i = 0; i < cache_item_metadata->num_keys; i++) {
> + memcpy(dc_job->cache_item_metadata.keys[i],
> + cache_item_metadata->keys[i], sizeof(cache_key));
> + }
You can just use a single memcpy.
With that fixed, patches 2-5 are
Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com>
> + }
> + } else {
> + dc_job->cache_item_metadata.type = CACHE_ITEM_TYPE_UNKNOWN;
> + dc_job->cache_item_metadata.keys = NULL;
> + }
> }
>
> return dc_job;
> +
> +fail:
> + free(dc_job->cache_item_metadata.keys);
> + free(dc_job);
> +
> + return NULL;
> }
>
> static void
> destroy_put_job(void *job, int thread_index)
> {
> if (job) {
> + struct disk_cache_put_job *dc_job = (struct disk_cache_put_job *) job;
> + free(dc_job->cache_item_metadata.keys);
> +
> free(job);
> }
> }
>
> struct cache_entry_file_data {
> uint32_t crc32;
> uint32_t uncompressed_size;
> };
>
> static void
> @@ -868,20 +901,48 @@ cache_put(void *job, int thread_index)
> * mesa version that produced the entry or deal with hash collisions,
> * should that ever become a real problem.
> */
> ret = write_all(fd, dc_job->cache->driver_keys_blob,
> dc_job->cache->driver_keys_blob_size);
> if (ret == -1) {
> unlink(filename_tmp);
> goto done;
> }
>
> + /* Write the cache item metadata. This data can be used to deal with
> + * hash collisions, as well as providing useful information to 3rd party
> + * tools reading the cache files.
> + */
> + ret = write_all(fd, &dc_job->cache_item_metadata.type,
> + sizeof(uint32_t));
> + if (ret == -1) {
> + unlink(filename_tmp);
> + goto done;
> + }
> +
> + if (dc_job->cache_item_metadata.type == CACHE_ITEM_TYPE_GLSL) {
> + ret = write_all(fd, &dc_job->cache_item_metadata.num_keys,
> + sizeof(uint32_t));
> + if (ret == -1) {
> + unlink(filename_tmp);
> + goto done;
> + }
> +
> + ret = write_all(fd, dc_job->cache_item_metadata.keys[0],
> + dc_job->cache_item_metadata.num_keys *
> + sizeof(cache_key));
> + if (ret == -1) {
> + unlink(filename_tmp);
> + goto done;
> + }
> + }
> +
> /* Create CRC of the data. We will read this when restoring the cache and
> * use it to check for corruption.
> */
> struct cache_entry_file_data cf_data;
> cf_data.crc32 = util_hash_crc32(dc_job->data, dc_job->size);
> cf_data.uncompressed_size = dc_job->size;
>
> size_t cf_data_size = sizeof(cf_data);
> ret = write_all(fd, &cf_data, cf_data_size);
> if (ret == -1) {
> @@ -1019,29 +1080,55 @@ disk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size)
> goto fail;
>
> ret = read_all(fd, file_header, ck_size);
> if (ret == -1)
> goto fail;
>
> /* Check for extremely unlikely hash collisions */
> if (memcmp(cache->driver_keys_blob, file_header, ck_size) != 0)
> 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)
> + 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)
> + goto fail;
> +
> + /* The cache item metadata is currently just used for distributing
> + * precompiled shaders, they are not used by Mesa so just skip them for
> + * now.
> + * TODO: pass the metadata back to the caller and do some basic
> + * validation.
> + */
> + cache_item_md_size += sizeof(cache_key);
> + ret = lseek(fd, num_keys * sizeof(cache_key), SEEK_CUR);
> + if (ret == -1)
> + 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)
> goto fail;
>
> /* Load the actual cache data. */
> - size_t cache_data_size = sb.st_size - cf_data_size - ck_size;
> + 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;
>
> /* Uncompress the cache data */
> uncompressed_data = malloc(cf_data.uncompressed_size);
> if (!inflate_cache_data(data, cache_data_size, uncompressed_data,
> cf_data.uncompressed_size))
> goto fail;
>
>
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
More information about the mesa-dev
mailing list