linux/fs/squashfs/lzo_wrapper.c
<<
>>
Prefs
   1/*
   2 * Squashfs - a compressed read only filesystem for Linux
   3 *
   4 * Copyright (c) 2010 LG Electronics
   5 * Chan Jeong <chan.jeong@lge.com>
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License
   9 * as published by the Free Software Foundation; either version 2,
  10 * or (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 *
  21 * lzo_wrapper.c
  22 */
  23
  24#include <linux/mutex.h>
  25#include <linux/buffer_head.h>
  26#include <linux/slab.h>
  27#include <linux/vmalloc.h>
  28#include <linux/lzo.h>
  29
  30#include "squashfs_fs.h"
  31#include "squashfs_fs_sb.h"
  32#include "squashfs.h"
  33#include "decompressor.h"
  34
  35struct squashfs_lzo {
  36        void    *input;
  37        void    *output;
  38};
  39
  40static void *lzo_init(struct squashfs_sb_info *msblk, void *buff, int len)
  41{
  42        int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE);
  43
  44        struct squashfs_lzo *stream = kzalloc(sizeof(*stream), GFP_KERNEL);
  45        if (stream == NULL)
  46                goto failed;
  47        stream->input = vmalloc(block_size);
  48        if (stream->input == NULL)
  49                goto failed;
  50        stream->output = vmalloc(block_size);
  51        if (stream->output == NULL)
  52                goto failed2;
  53
  54        return stream;
  55
  56failed2:
  57        vfree(stream->input);
  58failed:
  59        ERROR("Failed to allocate lzo workspace\n");
  60        kfree(stream);
  61        return ERR_PTR(-ENOMEM);
  62}
  63
  64
  65static void lzo_free(void *strm)
  66{
  67        struct squashfs_lzo *stream = strm;
  68
  69        if (stream) {
  70                vfree(stream->input);
  71                vfree(stream->output);
  72        }
  73        kfree(stream);
  74}
  75
  76
  77static int lzo_uncompress(struct squashfs_sb_info *msblk, void **buffer,
  78        struct buffer_head **bh, int b, int offset, int length, int srclength,
  79        int pages)
  80{
  81        struct squashfs_lzo *stream = msblk->stream;
  82        void *buff = stream->input;
  83        int avail, i, bytes = length, res;
  84        size_t out_len = srclength;
  85
  86        mutex_lock(&msblk->read_data_mutex);
  87
  88        for (i = 0; i < b; i++) {
  89                wait_on_buffer(bh[i]);
  90                if (!buffer_uptodate(bh[i]))
  91                        goto block_release;
  92
  93                avail = min(bytes, msblk->devblksize - offset);
  94                memcpy(buff, bh[i]->b_data + offset, avail);
  95                buff += avail;
  96                bytes -= avail;
  97                offset = 0;
  98                put_bh(bh[i]);
  99        }
 100
 101        res = lzo1x_decompress_safe(stream->input, (size_t)length,
 102                                        stream->output, &out_len);
 103        if (res != LZO_E_OK)
 104                goto failed;
 105
 106        res = bytes = (int)out_len;
 107        for (i = 0, buff = stream->output; bytes && i < pages; i++) {
 108                avail = min_t(int, bytes, PAGE_CACHE_SIZE);
 109                memcpy(buffer[i], buff, avail);
 110                buff += avail;
 111                bytes -= avail;
 112        }
 113
 114        mutex_unlock(&msblk->read_data_mutex);
 115        return res;
 116
 117block_release:
 118        for (; i < b; i++)
 119                put_bh(bh[i]);
 120
 121failed:
 122        mutex_unlock(&msblk->read_data_mutex);
 123
 124        ERROR("lzo decompression failed, data probably corrupt\n");
 125        return -EIO;
 126}
 127
 128const struct squashfs_decompressor squashfs_lzo_comp_ops = {
 129        .init = lzo_init,
 130        .free = lzo_free,
 131        .decompress = lzo_uncompress,
 132        .id = LZO_COMPRESSION,
 133        .name = "lzo",
 134        .supported = 1
 135};
 136