linux/fs/squashfs/decompressor_multi_percpu.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2013
   4 * Phillip Lougher <phillip@squashfs.org.uk>
   5 */
   6
   7#include <linux/types.h>
   8#include <linux/slab.h>
   9#include <linux/percpu.h>
  10#include <linux/buffer_head.h>
  11#include <linux/local_lock.h>
  12
  13#include "squashfs_fs.h"
  14#include "squashfs_fs_sb.h"
  15#include "decompressor.h"
  16#include "squashfs.h"
  17
  18/*
  19 * This file implements multi-threaded decompression using percpu
  20 * variables, one thread per cpu core.
  21 */
  22
  23struct squashfs_stream {
  24        void                    *stream;
  25        local_lock_t    lock;
  26};
  27
  28void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
  29                                                void *comp_opts)
  30{
  31        struct squashfs_stream *stream;
  32        struct squashfs_stream __percpu *percpu;
  33        int err, cpu;
  34
  35        percpu = alloc_percpu(struct squashfs_stream);
  36        if (percpu == NULL)
  37                return ERR_PTR(-ENOMEM);
  38
  39        for_each_possible_cpu(cpu) {
  40                stream = per_cpu_ptr(percpu, cpu);
  41                stream->stream = msblk->decompressor->init(msblk, comp_opts);
  42                if (IS_ERR(stream->stream)) {
  43                        err = PTR_ERR(stream->stream);
  44                        goto out;
  45                }
  46                local_lock_init(&stream->lock);
  47        }
  48
  49        kfree(comp_opts);
  50        return (__force void *) percpu;
  51
  52out:
  53        for_each_possible_cpu(cpu) {
  54                stream = per_cpu_ptr(percpu, cpu);
  55                if (!IS_ERR_OR_NULL(stream->stream))
  56                        msblk->decompressor->free(stream->stream);
  57        }
  58        free_percpu(percpu);
  59        return ERR_PTR(err);
  60}
  61
  62void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
  63{
  64        struct squashfs_stream __percpu *percpu =
  65                        (struct squashfs_stream __percpu *) msblk->stream;
  66        struct squashfs_stream *stream;
  67        int cpu;
  68
  69        if (msblk->stream) {
  70                for_each_possible_cpu(cpu) {
  71                        stream = per_cpu_ptr(percpu, cpu);
  72                        msblk->decompressor->free(stream->stream);
  73                }
  74                free_percpu(percpu);
  75        }
  76}
  77
  78int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
  79        int offset, int length, struct squashfs_page_actor *output)
  80{
  81        struct squashfs_stream *stream;
  82        int res;
  83
  84        local_lock(&msblk->stream->lock);
  85        stream = this_cpu_ptr(msblk->stream);
  86
  87        res = msblk->decompressor->decompress(msblk, stream->stream, bio,
  88                                              offset, length, output);
  89
  90        local_unlock(&msblk->stream->lock);
  91
  92        if (res < 0)
  93                ERROR("%s decompression failed, data probably corrupt\n",
  94                        msblk->decompressor->name);
  95
  96        return res;
  97}
  98
  99int squashfs_max_decompressors(void)
 100{
 101        return num_possible_cpus();
 102}
 103