Merge git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-linus
[pandora-kernel.git] / fs / squashfs / cache.c
index c37b520..f744be9 100644 (file)
@@ -2,7 +2,7 @@
  * Squashfs - a compressed read only filesystem for Linux
  *
  * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
- * Phillip Lougher <phillip@lougher.demon.co.uk>
+ * Phillip Lougher <phillip@squashfs.org.uk>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -29,7 +29,7 @@
  * plus functions layered ontop of the generic cache implementation to
  * access the metadata and fragment caches.
  *
- * To avoid out of memory and fragmentation isssues with vmalloc the cache
+ * To avoid out of memory and fragmentation issues with vmalloc the cache
  * uses sequences of kmalloced PAGE_CACHE_SIZE buffers.
  *
  * It should be noted that the cache is not used for file datablocks, these
@@ -393,19 +393,36 @@ struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *sb,
 /*
  * Read a filesystem table (uncompressed sequence of bytes) from disk
  */
-int squashfs_read_table(struct super_block *sb, void *buffer, u64 block,
-       int length)
+void *squashfs_read_table(struct super_block *sb, u64 block, int length)
 {
        int pages = (length + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
        int i, res;
-       void **data = kcalloc(pages, sizeof(void *), GFP_KERNEL);
-       if (data == NULL)
-               return -ENOMEM;
+       void *table, *buffer, **data;
+
+       table = buffer = kmalloc(length, GFP_KERNEL);
+       if (table == NULL)
+               return ERR_PTR(-ENOMEM);
+
+       data = kcalloc(pages, sizeof(void *), GFP_KERNEL);
+       if (data == NULL) {
+               res = -ENOMEM;
+               goto failed;
+       }
 
        for (i = 0; i < pages; i++, buffer += PAGE_CACHE_SIZE)
                data[i] = buffer;
+
        res = squashfs_read_data(sb, data, block, length |
                SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length, pages);
+
        kfree(data);
-       return res;
+
+       if (res < 0)
+               goto failed;
+
+       return table;
+
+failed:
+       kfree(table);
+       return ERR_PTR(res);
 }