[Mesa-dev] [PATCH 6/7] glsl/cache.c: Dynamically allocate filenames internal to cache

Carl Worth cworth at cworth.org
Wed Feb 4 13:53:00 PST 2015


The user can put the cache directory anywhere, so it's not safe to use
fixed-size arrays to store filenames. Instead, allocate the cache
pointer itself as a ralloc context and use that to dynamically
allocate all filenames.

While making this change, simplify the error handling in cache_get
with a new "goto FAIL" block so the cleanup code exists in a single
place, rather than being spread throughout the function over and over.
---
 src/glsl/cache.c | 87 +++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 54 insertions(+), 33 deletions(-)

diff --git a/src/glsl/cache.c b/src/glsl/cache.c
index 79e8afb..0bbf659 100644
--- a/src/glsl/cache.c
+++ b/src/glsl/cache.c
@@ -197,14 +197,14 @@ cache_create(void)
       fsync(fd);
    }
 
-   cache = (struct program_cache *) malloc(sizeof *cache);
+   cache = ralloc(NULL, struct program_cache);
    if (cache == NULL) {
       goto done;
    }
 
    cache->path = strdup(path);
    if (cache->path == NULL) {
-      free (cache);
+      ralloc_free (cache);
       cache = NULL;
       goto done;
    }
@@ -214,7 +214,7 @@ cache_create(void)
    cache->index = (unsigned char *)
       mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (cache->index == MAP_FAILED) {
-      free(cache);
+      ralloc_free(cache);
       cache = NULL;
       goto done;
    }
@@ -227,16 +227,18 @@ cache_create(void)
    return cache;
 }
 
+/* Return a filename within the cache's directory corresponding to 'key'. The
+ * returned filename is ralloced with 'cache' as the parent context.
+ *
+ * Returns NULL if out of memory.
+ */
 static char *
-get_cache_file(struct program_cache *cache,
-               char *buffer, size_t size, cache_key key)
+get_cache_file(struct program_cache *cache, cache_key key)
 {
    char buf[41];
 
-   snprintf(buffer, size, "%s/%s",
-            cache->path, _mesa_sha1_format(buf, key));
-
-   return buffer;
+   return ralloc_asprintf(cache, "%s/%s", cache->path,
+                          _mesa_sha1_format(buf, key));
 }
 
 int
@@ -261,59 +263,69 @@ cache_has(struct program_cache *cache, cache_key key)
 uint8_t *
 cache_get(struct program_cache *cache, cache_key key, size_t *size)
 {
-   int fd, ret, len;
+   int fd = -1, ret, len;
    struct stat sb;
-   char filename[256], *data;
+   char *filename = NULL;
+   uint8_t *data = NULL;
 
    if (size)
       *size = 0;
 
    if (!cache_has(cache, key))
-      return NULL;
+      goto fail;
 
-   get_cache_file(cache, filename, sizeof filename, key);
+   filename = get_cache_file(cache, key);
+   if (filename == NULL)
+      goto fail;
 
    fd = open(filename, O_RDONLY | O_CLOEXEC);
    if (fd == -1)
-      return NULL;
+      goto fail;
 
-   if (fstat(fd, &sb) == -1) {
-      close(fd);
-      return NULL;
-   }
+   if (fstat(fd, &sb) == -1)
+      goto fail;
 
-   data = (char *) malloc(sb.st_size);
-   if (data == NULL) {
-      close(fd);
-      return NULL;
-   }
+   data = malloc(sb.st_size);
+   if (data == NULL)
+      goto fail;
 
    for (len = 0; len < sb.st_size; len += ret) {
       ret = read(fd, data + len, sb.st_size - len);
-      if (ret == -1) {
-         free(data);
-         close(fd);
-         return NULL;
-      }
+      if (ret == -1)
+         goto fail;
    }
 
+   ralloc_free(filename);
    close(fd);
 
    if (size)
       *size = sb.st_size;
 
-   return (void *) data;
+   return data;
+
+ fail:
+   if (data)
+      free(data);
+   if (filename)
+      ralloc_free(filename);
+   if (fd != -1)
+      close(fd);
+
+   return NULL;
 }
 
 void
-cache_put(struct program_cache *cache, cache_key key, const void *data, size_t size)
+cache_put(struct program_cache *cache,
+          cache_key key,
+          const void *data,
+          size_t size)
 {
    uint32_t *s = (uint32_t *) key;
    int i = *s & (INDEX_SIZE - 1);
    unsigned char *entry;
    int fd, ret;
    size_t len;
-   char filename[256];
+   char *filename;
    const char *p = (const char *) data;
 
    /* FIXME: We'll need an fsync here and think about races... maybe even need
@@ -322,8 +334,13 @@ cache_put(struct program_cache *cache, cache_key key, const void *data, size_t s
     * it. */
 
    entry = &cache->index[i * CACHE_KEY_SIZE];
-   get_cache_file(cache, filename, sizeof filename, entry);
+   filename = get_cache_file(cache, entry);
+   if (filename == NULL)
+      return;
+
    unlink(filename);
+   ralloc_free(filename);
+
    memcpy(entry, key, CACHE_KEY_SIZE);
 
    if (data == NULL)
@@ -335,8 +352,12 @@ cache_put(struct program_cache *cache, cache_key key, const void *data, size_t s
     * same file is ok, since they'll both write the same contents, and whoever
     * finishes first will move the complete file in place. */
 
-   get_cache_file(cache, filename, sizeof filename, key);
+   filename = get_cache_file(cache, key);
+   if (filename == NULL)
+      return;
+
    fd = open(filename, O_WRONLY | O_CLOEXEC | O_CREAT, 0644);
+   ralloc_free(filename);
    if (fd == -1)
       return;
 
-- 
2.1.4



More information about the mesa-dev mailing list