blob: 747cd6007444cd582e00457ae4401543c7e6cc0d [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/storage/blobfs/compression/blob-compressor.h"
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>
#include <zircon/types.h>
#include <memory>
#include <fbl/algorithm.h>
#include <fbl/auto_call.h>
#include <fbl/macros.h>
#include "src/storage/blobfs/compression/chunked.h"
#include "src/storage/blobfs/compression/lz4.h"
#include "src/storage/blobfs/compression/zstd-plain.h"
#include "src/storage/blobfs/compression/zstd-seekable.h"
namespace blobfs {
std::optional<BlobCompressor> BlobCompressor::Create(CompressionSettings settings,
size_t blob_size) {
switch (settings.compression_algorithm) {
case CompressionAlgorithm::LZ4: {
fzl::OwnedVmoMapper compressed_blob;
const size_t max = fbl::round_up(LZ4Compressor::BufferMax(blob_size), kBlobfsBlockSize);
zx_status_t status = compressed_blob.CreateAndMap(max, "lz4-blob");
if (status != ZX_OK) {
return std::nullopt;
}
std::unique_ptr<LZ4Compressor> compressor;
status = LZ4Compressor::Create(blob_size, compressed_blob.start(), compressed_blob.size(),
&compressor);
if (status != ZX_OK) {
return std::nullopt;
}
auto result = BlobCompressor(std::move(compressor), std::move(compressed_blob),
settings.compression_algorithm);
return std::make_optional(std::move(result));
}
case CompressionAlgorithm::ZSTD: {
fzl::OwnedVmoMapper compressed_blob;
const size_t max = fbl::round_up(ZSTDCompressor::BufferMax(blob_size), kBlobfsBlockSize);
zx_status_t status = compressed_blob.CreateAndMap(max, "zstd-blob");
if (status != ZX_OK) {
return std::nullopt;
}
std::unique_ptr<ZSTDCompressor> compressor;
status = ZSTDCompressor::Create(settings, blob_size, compressed_blob.start(),
compressed_blob.size(), &compressor);
if (status != ZX_OK) {
return std::nullopt;
}
auto result = BlobCompressor(std::move(compressor), std::move(compressed_blob),
settings.compression_algorithm);
return std::make_optional(std::move(result));
}
case CompressionAlgorithm::ZSTD_SEEKABLE: {
fzl::OwnedVmoMapper compressed_blob;
const size_t max =
fbl::round_up(ZSTDSeekableCompressor::BufferMax(blob_size), kBlobfsBlockSize);
zx_status_t status = compressed_blob.CreateAndMap(max, "zstd-seekable-blob");
if (status != ZX_OK) {
return std::nullopt;
}
std::unique_ptr<ZSTDSeekableCompressor> compressor;
status = ZSTDSeekableCompressor::Create(settings, blob_size, compressed_blob.start(),
compressed_blob.size(), &compressor);
if (status != ZX_OK) {
return std::nullopt;
}
auto result = BlobCompressor(std::move(compressor), std::move(compressed_blob),
settings.compression_algorithm);
return std::make_optional(std::move(result));
}
case CompressionAlgorithm::CHUNKED: {
std::unique_ptr<ChunkedCompressor> compressor;
size_t max;
zx_status_t status = ChunkedCompressor::Create(settings, blob_size, &max, &compressor);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "Failed to create compressor: " << zx_status_get_string(status);
return std::nullopt;
}
fzl::OwnedVmoMapper compressed_blob;
max = fbl::round_up(max, kBlobfsBlockSize);
status = compressed_blob.CreateAndMap(max, "chunk-compressed-blob");
if (status != ZX_OK) {
FX_LOGS(ERROR) << "Failed to create mapping for compressed data: "
<< zx_status_get_string(status);
return std::nullopt;
}
status = compressor->SetOutput(compressed_blob.start(), compressed_blob.size());
if (status != ZX_OK) {
FX_LOGS(ERROR) << "Failed to initialize compressor: "
<< zx_status_get_string(status);
return std::nullopt;
}
return BlobCompressor(std::move(compressor), std::move(compressed_blob),
settings.compression_algorithm);
}
case CompressionAlgorithm::UNCOMPRESSED:
ZX_DEBUG_ASSERT(false);
return std::nullopt;
}
}
BlobCompressor::BlobCompressor(std::unique_ptr<Compressor> compressor,
fzl::OwnedVmoMapper compressed_blob, CompressionAlgorithm algorithm)
: compressor_(std::move(compressor)),
compressed_blob_(std::move(compressed_blob)),
algorithm_(algorithm) {
ZX_ASSERT(algorithm_ != CompressionAlgorithm::UNCOMPRESSED);
}
} // namespace blobfs