brintos

brintos / linux-shallow public Read only

0
0
Text · 2.6 KiB · e4d7e50 Raw
111 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 20134 * 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/local_lock.h>11 12#include "squashfs_fs.h"13#include "squashfs_fs_sb.h"14#include "decompressor.h"15#include "squashfs.h"16 17/*18 * This file implements multi-threaded decompression using percpu19 * variables, one thread per cpu core.20 */21 22struct squashfs_stream {23	void			*stream;24	local_lock_t	lock;25};26 27static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,28						void *comp_opts)29{30	struct squashfs_stream *stream;31	struct squashfs_stream __percpu *percpu;32	int err, cpu;33 34	percpu = alloc_percpu(struct squashfs_stream);35	if (percpu == NULL)36		return ERR_PTR(-ENOMEM);37 38	for_each_possible_cpu(cpu) {39		stream = per_cpu_ptr(percpu, cpu);40		stream->stream = msblk->decompressor->init(msblk, comp_opts);41		if (IS_ERR(stream->stream)) {42			err = PTR_ERR(stream->stream);43			goto out;44		}45		local_lock_init(&stream->lock);46	}47 48	kfree(comp_opts);49	return (void *)(__force unsigned long) percpu;50 51out:52	for_each_possible_cpu(cpu) {53		stream = per_cpu_ptr(percpu, cpu);54		if (!IS_ERR_OR_NULL(stream->stream))55			msblk->decompressor->free(stream->stream);56	}57	free_percpu(percpu);58	return ERR_PTR(err);59}60 61static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)62{63	struct squashfs_stream __percpu *percpu =64			(void __percpu *)(unsigned long) msblk->stream;65	struct squashfs_stream *stream;66	int cpu;67 68	if (msblk->stream) {69		for_each_possible_cpu(cpu) {70			stream = per_cpu_ptr(percpu, cpu);71			msblk->decompressor->free(stream->stream);72		}73		free_percpu(percpu);74	}75}76 77static int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,78	int offset, int length, struct squashfs_page_actor *output)79{80	struct squashfs_stream *stream;81	struct squashfs_stream __percpu *percpu =82			(void __percpu *)(unsigned long) msblk->stream;83	int res;84 85	local_lock(&percpu->lock);86	stream = this_cpu_ptr(percpu);87 88	res = msblk->decompressor->decompress(msblk, stream->stream, bio,89					      offset, length, output);90 91	local_unlock(&percpu->lock);92 93	if (res < 0)94		ERROR("%s decompression failed, data probably corrupt\n",95			msblk->decompressor->name);96 97	return res;98}99 100static int squashfs_max_decompressors(void)101{102	return num_possible_cpus();103}104 105const struct squashfs_decompressor_thread_ops squashfs_decompressor_percpu = {106	.create = squashfs_decompressor_create,107	.destroy = squashfs_decompressor_destroy,108	.decompress = squashfs_decompress,109	.max_decompressors = squashfs_max_decompressors,110};111