/* * Helper for S390x with hardware zlib compression support. * * That hardware acceleration requires a buffer size larger than a single page * to get ideal performance, thus we need to do the memory copy rather than * use the page cache directly as input buffer.
*/ staticint copy_data_into_buffer(struct address_space *mapping, struct workspace *workspace, u64 filepos, unsignedlong length)
{
u64 cur = filepos;
/* It's only for hardware accelerated zlib code. */
ASSERT(zlib_deflate_dfltcc_enabled());
while (cur < filepos + length) { struct folio *folio; void *data_in; unsignedint offset; unsignedlong copy_length; int ret;
ret = btrfs_compress_filemap_get_folio(mapping, cur, &folio); if (ret < 0) return ret;
while (workspace->strm.total_in < len) { /* * Get next input pages and copy the contents to * the workspace buffer if required.
*/ if (workspace->strm.avail_in == 0) { unsignedlong bytes_left = len - workspace->strm.total_in; unsignedint copy_length = min(bytes_left, workspace->buf_size);
/* * This can only happen when hardware zlib compression is * enabled.
*/ if (copy_length > PAGE_SIZE) {
ret = copy_data_into_buffer(mapping, workspace,
start, copy_length); if (ret < 0) goto out;
start += copy_length;
workspace->strm.next_in = workspace->buf;
workspace->strm.avail_in = copy_length;
} else { unsignedint cur_len;
/* we're making it bigger, give up */ if (workspace->strm.total_in > 8192 &&
workspace->strm.total_in <
workspace->strm.total_out) {
ret = -E2BIG; goto out;
} /* we need another page for writing out. Test this * before the total_in so we will pull in a new page for * the stream end if required
*/ if (workspace->strm.avail_out == 0) { if (nr_folios == nr_dest_folios) {
ret = -E2BIG; goto out;
}
out_folio = btrfs_alloc_compr_folio(); if (out_folio == NULL) {
ret = -ENOMEM; goto out;
}
cfolio_out = folio_address(out_folio);
folios[nr_folios] = out_folio;
nr_folios++;
workspace->strm.avail_out = PAGE_SIZE;
workspace->strm.next_out = cfolio_out;
} /* we're all done */ if (workspace->strm.total_in >= len) break; if (workspace->strm.total_out > max_out) break;
}
workspace->strm.avail_in = 0; /* * Call deflate with Z_FINISH flush parameter providing more output * space but no more input data, until it returns with Z_STREAM_END.
*/ while (ret != Z_STREAM_END) {
ret = zlib_deflate(&workspace->strm, Z_FINISH); if (ret == Z_STREAM_END) break; if (ret != Z_OK && ret != Z_BUF_ERROR) {
zlib_deflateEnd(&workspace->strm);
ret = -EIO; goto out;
} elseif (workspace->strm.avail_out == 0) { /* Get another folio for the stream end. */ if (nr_folios == nr_dest_folios) {
ret = -E2BIG; goto out;
}
out_folio = btrfs_alloc_compr_folio(); if (out_folio == NULL) {
ret = -ENOMEM; goto out;
}
cfolio_out = folio_address(out_folio);
folios[nr_folios] = out_folio;
nr_folios++;
workspace->strm.avail_out = PAGE_SIZE;
workspace->strm.next_out = cfolio_out;
}
}
zlib_deflateEnd(&workspace->strm);
if (workspace->strm.total_out >= workspace->strm.total_in) {
ret = -E2BIG; goto out;
}
ret = 0;
*total_out = workspace->strm.total_out;
*total_in = workspace->strm.total_in;
out:
*out_folios = nr_folios; if (data_in) {
kunmap_local(data_in);
folio_put(in_folio);
}
/* If it's deflate, and it's got no preset dictionary, then
we can tell zlib to skip the adler32 check. */ if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
((data_in[0] & 0x0f) == Z_DEFLATED) &&
!(((data_in[0]<<8) + data_in[1]) % 31)) {
/* * Everything (in/out buf) should be at most one sector, there should * be no need to switch any input/output buffer.
*/
ret = zlib_inflate(&workspace->strm, Z_FINISH);
to_copy = min(workspace->strm.total_out, destlen); if (ret != Z_STREAM_END) goto out;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.