[Mesa-dev] [PATCH] glsl: fix disk cache eviction issue

Emil Velikov emil.l.velikov at gmail.com
Mon Jan 9 15:36:38 UTC 2017


On 9 December 2016 at 05:58, Tapani Pälli <tapani.palli at intel.com> wrote:
> When 'evict_random_item' attempts to remove cache content to make more
> space, it may try to remove from new cache directory it just created
> which only has '.tmp' content at this phase and not proper cache files,
> this will cause eviction to fail and 'test_put_and_get' subtest
> assumptions about cache size and item count won't hold.
>
> Patch fixes this issue by adding 'exception' argument for random file
> matching so that algorithm won't pick the new directory.
>
Hi Tapani,

I've mentioned this over at #android-ia, but adding it here for posterity.


The issue itself is actually quite different - in my experiments with
importing SHA1 implementation to mesa, I've noticed that there bug
lies with a buggy (and/or undefined behaviour) SHA1 implementation
given the input data.

Namely:
As one observes the output of _mesa_sha1_compute they will notice that
it differs across implementations. This in itself combined with the
(afaict) correct assumption in test_put_and_get() that the beginning
for the SHA1blob_key_byte_zero


 above


As mentioned

> Signed-off-by: Tapani Pälli <tapani.palli at intel.com>
> https://bugs.freedesktop.org/show_bug.cgi?id=97967
> ---
>  src/util/disk_cache.c | 33 +++++++++++++++++++++++----------
>  1 file changed, 23 insertions(+), 10 deletions(-)
>
> diff --git a/src/util/disk_cache.c b/src/util/disk_cache.c
> index ac172ef..710c08e 100644
> --- a/src/util/disk_cache.c
> +++ b/src/util/disk_cache.c
> @@ -340,25 +340,30 @@ get_cache_file(struct disk_cache *cache, cache_key key)
>   *
>   * Obviously, the implementation here must closely match
>   * _get_cache_file above.
> + *
> + * returns the created directory name for the particular key
>  */
> -static void
> +static char*
>  make_cache_file_directory(struct disk_cache *cache, cache_key key)
>  {
>     char *dir;
> +   char *ret;
>     char buf[41];
>
>     _mesa_sha1_format(buf, key);
>
>     dir = ralloc_asprintf(cache, "%s/%c%c", cache->path, buf[0], buf[1]);
> +   ret = ralloc_asprintf(cache, "%c%c", buf[0], buf[1]);
>
>     mkdir_if_needed(dir);
>
>     ralloc_free(dir);
> +   return ret;
>  }
>
>  /* Given a directory path and predicate function, count all entries in
>   * that directory for which the predicate returns true. Then choose a
> - * random entry from among those counted.
> + * random entry from among those counted except 'exception' if given.
>   *
>   * Returns: A malloc'ed string for the path to the chosen file, (or
>   * NULL on any error). The caller should free the string when
> @@ -366,7 +371,8 @@ make_cache_file_directory(struct disk_cache *cache, cache_key key)
>   */
>  static char *
>  choose_random_file_matching(const char *dir_path,
> -                            bool (*predicate)(struct dirent *))
> +                            bool (*predicate)(struct dirent *),
> +                            char *exception)
>  {
>     DIR *dir;
>     struct dirent *entry;
> @@ -385,6 +391,8 @@ choose_random_file_matching(const char *dir_path,
>           break;
>        if (! predicate(entry))
>           continue;
> +      if (exception && strcmp(entry->d_name, exception) == 0)
> +         continue;
>
>        count++;
>     }
> @@ -449,7 +457,7 @@ unlink_random_file_from_directory(const char *path)
>     struct stat sb;
>     char *filename;
>
> -   filename = choose_random_file_matching(path, is_regular_non_tmp_file);
> +   filename = choose_random_file_matching(path, is_regular_non_tmp_file, NULL);
>     if (filename == NULL)
>        return 0;
>
> @@ -483,8 +491,11 @@ is_two_character_sub_directory(struct dirent *entry)
>     return true;
>  }
>
> +/*
> + * Evict item from anywhere expect from 'exception' if given.
> + */
>  static void
> -evict_random_item(struct disk_cache *cache)
> +evict_random_item(struct disk_cache *cache, char *exception)
>  {
>     const char hex[] = "0123456789abcde";
>     char *dir_path;
> @@ -517,8 +528,9 @@ evict_random_item(struct disk_cache *cache)
>      * tests to work, (which use an artificially-small cache to be able
>      * to force a single cached item to be evicted).
>      */
> -   dir_path = choose_random_file_matching(cache->path,
> -                                          is_two_character_sub_directory);
> +   dir_path =
> +      choose_random_file_matching(cache->path,
> +                                  is_two_character_sub_directory, exception);
>     if (dir_path == NULL)
>        return;
>
> @@ -540,6 +552,7 @@ disk_cache_put(struct disk_cache *cache,
>     size_t len;
>     char *filename = NULL, *filename_tmp = NULL;
>     const char *p = data;
> +   char *dir_name = NULL;
>
>     filename = get_cache_file(cache, key);
>     if (filename == NULL)
> @@ -560,7 +573,7 @@ disk_cache_put(struct disk_cache *cache,
>        if (errno != ENOENT)
>           goto done;
>
> -      make_cache_file_directory(cache, key);
> +      dir_name = make_cache_file_directory(cache, key);
>
>        fd = open(filename_tmp, O_WRONLY | O_CLOEXEC | O_CREAT, 0644);
>        if (fd == -1)
> @@ -591,10 +604,10 @@ disk_cache_put(struct disk_cache *cache,
>      * by some other process.
>      *
>      * Before we do that, if the cache is too large, evict something
> -    * else first.
> +    * else first (except from the path we just made).
>      */
>     if (*cache->size + size > cache->max_size)
> -      evict_random_item(cache);
> +      evict_random_item(cache, dir_name);
>
>     /* Now, finally, write out the contents to the temporary file, then
>      * rename them atomically to the destination filename, and also
> --
> 2.9.3
>


More information about the mesa-dev mailing list