mirror of
https://github.com/torvalds/linux.git
synced 2026-09-14 08:01:12 +02:00
Changes since last update:
- Fix the missing sysfs feature entry for xattr prefixes
- Fix invalid LZMA decoders on resize failure
- Disable LZ4 rolling decompression for now due to the uncontrolled
LZ4 implementation
- Rearrange the inode_share cache key to avoid potential collisions
- Fix erofs_bread() when fsoffset is used on sub-page-block EROFS
filesystems
-----BEGIN PGP SIGNATURE-----
iQJFBAABCgAvFiEEQ0A6bDUS9Y+83NPFUXZn5Zlu5qoFAmqlRUkRHHhpYW5nQGtl
cm5lbC5vcmcACgkQUXZn5Zlu5qpHEg/8C9Ih/XK8spRppF+rWGUnhf+9iARJE4aP
31NJgvs8h5R8tfxu3vOhOlhOT3pybxAuPI2qkx+c5kZRlo1wtCN2HQPH5NeZ7nUn
JhA99YHs7UTz8FYa2gKO4F9gTqorEOJO4R3jrSPNFT2V5Ae3ApgLhvfjZfSv4+4X
zQox+fdmzKT3G4sOuCPhTz4Fo5NleiJSrA+sVBn8lPcT3xCJZiUsJb7hK31rco0J
tnAVJsbhy9Yq7FZiUDIdbAQl9ukPoYbF8rYXVkcbXGFE8Qq1Gmm1Ep1OndmB3k0U
JFOub70cp4x/T8EKjc+W7Ft1mhq9yZkGlVMUb3otb3cFIOYBfl/8ClO3i0xltBXG
4uafbtc5Lfs7tSOaYoJ0JHDzgIx91hFbCXEM0QW+WYXh9bLTpSZv3FG93tQ4QSHN
1m8jqjF5i4eGnp/xEFFSltrgqtwmiyIgeSg8tHyTG7pIao5zengZiysdcmZi2Akl
/0txH8hSx3qldt69PadotW2rGROPb8SOgDpFvlcfitSwOoN2RF0R+Mq/afog+WkY
99EmJ32okgGN9LK8scX1cynW30X065pWzWpLm3WvbBDNmKl+jX+i4RkuEOKFV3zQ
IqOZjmHCDHv2NJq7EzC8XE18Z6LewXXX1nw6iO/5UneZgrODltlDfuq9f4pdwYI2
UugUZKgygoU=
=fmjB
-----END PGP SIGNATURE-----
Merge tag 'erofs-for-7.3-rc3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs
Pull erofs updates from Gao Xiang:
"The most impactful fix here is to disable LZ4 rolling decompression
for now.
AWS folks recently found their systems could get corrupted data with
some rare, specific LZ4 datasets, and after a deeper analysis, I found
the root cause is that there could be uncontrolled backward memory
copies in the current LZ4 implementation and it breaks the assumption
of the rolling decompression optimization, since the kernel LZ4
codebase is out of our control and it needs more time to plan how to
do next, so disable LZ4 rolling decompression for now to ensure data
correctness for real production on these rare cases first. The
technical details also see the corresponding commit.
Other changes are random minor fixes.
Summary:
- Disable LZ4 rolling decompression for now due to the uncontrolled
LZ4 implementation
- Fix missing sysfs feature entry for xattr prefixes
- Fix invalid LZMA decoders on resize failure
- Rearrange the inode_share cache key to avoid potential collisions
- Fix erofs_bread() when fsoffset is used on sub-page-block EROFS
filesystems"
* tag 'erofs-for-7.3-rc3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs:
erofs: add missing buf->off in erofs_bread()
erofs: delimit inode_share cache key components
erofs: disable LZ4 rolling decompression for now
erofs: preserve LZMA decoders on resize failure
erofs: add sysfs feature entry for xattr prefixes
This commit is contained in:
commit
4d85a45df0
|
|
@ -5,7 +5,7 @@ Description: Shows all enabled kernel features.
|
|||
Supported features:
|
||||
compr_cfgs, big_pcluster, chunked_file, device_table,
|
||||
compr_head2, sb_chksum, ztailpacking, dedupe, fragments,
|
||||
48bit, metabox.
|
||||
xattr_prefixes, 48bit, metabox.
|
||||
|
||||
What: /sys/fs/erofs/<disk>/sync_decompress
|
||||
Date: November 2021
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, bool need_kmap)
|
|||
return NULL;
|
||||
if (!buf->base)
|
||||
buf->base = kmap_local_page(buf->page);
|
||||
return buf->base + (offset & ~PAGE_MASK);
|
||||
return buf->base + ((buf->off + offset) & ~PAGE_MASK);
|
||||
}
|
||||
|
||||
int erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb,
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
#include "compress.h"
|
||||
#include <linux/lz4.h>
|
||||
|
||||
#define LZ4_MAX_DISTANCE_PAGES (DIV_ROUND_UP(LZ4_DISTANCE_MAX, PAGE_SIZE) + 1)
|
||||
|
||||
static int z_erofs_load_lz4_config(struct super_block *sb,
|
||||
struct erofs_super_block *dsb, void *data, int size)
|
||||
{
|
||||
|
|
@ -21,8 +19,6 @@ static int z_erofs_load_lz4_config(struct super_block *sb,
|
|||
erofs_err(sb, "invalid lz4 cfgs, size=%u", size);
|
||||
return -EINVAL;
|
||||
}
|
||||
distance = le16_to_cpu(lz4->max_distance);
|
||||
|
||||
sbi->lz4.max_pclusterblks = le16_to_cpu(lz4->max_pclusterblks);
|
||||
if (!sbi->lz4.max_pclusterblks) {
|
||||
sbi->lz4.max_pclusterblks = 1; /* reserved case */
|
||||
|
|
@ -39,45 +35,25 @@ static int z_erofs_load_lz4_config(struct super_block *sb,
|
|||
sbi->lz4.max_pclusterblks = 1;
|
||||
sbi->available_compr_algs = 1 << Z_EROFS_COMPRESSION_LZ4;
|
||||
}
|
||||
|
||||
sbi->lz4.max_distance_pages = distance ?
|
||||
DIV_ROUND_UP(distance, PAGE_SIZE) + 1 :
|
||||
LZ4_MAX_DISTANCE_PAGES;
|
||||
return z_erofs_gbuf_growsize(sbi->lz4.max_pclusterblks);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill all gaps with bounce pages if it's a sparse page list. Also check if
|
||||
* all physical pages are consecutive, which can be seen for moderate CR.
|
||||
* Fill all gaps with bounce pages if it's a sparse page list (for example some
|
||||
* folios are already uptodate and thus can be mapped into userspace). Also
|
||||
* check if pages are physically consecutive, which can be seen for moderate CR.
|
||||
*/
|
||||
static int z_erofs_lz4_prepare_dstpages(struct z_erofs_decompress_req *rq,
|
||||
struct page **pagepool)
|
||||
static int z_erofs_oneshot_prepare_dstpages(struct z_erofs_decompress_req *rq,
|
||||
struct page **pagepool)
|
||||
{
|
||||
struct page *availables[LZ4_MAX_DISTANCE_PAGES] = { NULL };
|
||||
unsigned long bounced[DIV_ROUND_UP(LZ4_MAX_DISTANCE_PAGES,
|
||||
BITS_PER_LONG)] = { 0 };
|
||||
unsigned int lz4_max_distance_pages =
|
||||
EROFS_SB(rq->sb)->lz4.max_distance_pages;
|
||||
void *kaddr = NULL;
|
||||
unsigned int i, j, top;
|
||||
unsigned int i;
|
||||
|
||||
top = 0;
|
||||
for (i = j = 0; i < rq->outpages; ++i, ++j) {
|
||||
struct page *const page = rq->out[i];
|
||||
struct page *victim;
|
||||
|
||||
if (j >= lz4_max_distance_pages)
|
||||
j = 0;
|
||||
|
||||
/* 'valid' bounced can only be tested after a complete round */
|
||||
if (!rq->fillgaps && test_bit(j, bounced)) {
|
||||
DBG_BUGON(i < lz4_max_distance_pages);
|
||||
DBG_BUGON(top >= lz4_max_distance_pages);
|
||||
availables[top++] = rq->out[i - lz4_max_distance_pages];
|
||||
}
|
||||
for (i = 0; i < rq->outpages; ++i) {
|
||||
struct page *page, *victim;
|
||||
|
||||
page = rq->out[i];
|
||||
if (page) {
|
||||
__clear_bit(j, bounced);
|
||||
if (!PageHighMem(page)) {
|
||||
if (!i) {
|
||||
kaddr = page_address(page);
|
||||
|
|
@ -89,21 +65,14 @@ static int z_erofs_lz4_prepare_dstpages(struct z_erofs_decompress_req *rq,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
kaddr = NULL;
|
||||
continue;
|
||||
}
|
||||
kaddr = NULL;
|
||||
__set_bit(j, bounced);
|
||||
|
||||
if (top) {
|
||||
victim = availables[--top];
|
||||
} else {
|
||||
victim = __erofs_allocpage(pagepool, rq->gfp, true);
|
||||
if (!victim)
|
||||
return -ENOMEM;
|
||||
set_page_private(victim, Z_EROFS_SHORTLIVED_PAGE);
|
||||
rq->out[i] = victim;
|
||||
}
|
||||
rq->out[i] = victim;
|
||||
kaddr = NULL;
|
||||
}
|
||||
return kaddr ? 1 : 0;
|
||||
}
|
||||
|
|
@ -266,7 +235,7 @@ static const char *z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq,
|
|||
dst_maptype = 0;
|
||||
} else {
|
||||
/* general decoding path which can be used for all cases */
|
||||
ret = z_erofs_lz4_prepare_dstpages(rq, pagepool);
|
||||
ret = z_erofs_oneshot_prepare_dstpages(rq, pagepool);
|
||||
if (ret < 0)
|
||||
return ERR_PTR(ret);
|
||||
if (ret > 0) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
struct z_erofs_lzma {
|
||||
struct z_erofs_lzma *next;
|
||||
struct xz_dec_microlzma *state;
|
||||
unsigned int dict_size;
|
||||
u8 bounce[PAGE_SIZE];
|
||||
};
|
||||
|
||||
|
|
@ -128,11 +129,19 @@ static int z_erofs_load_lzma_config(struct super_block *sb,
|
|||
err = 0;
|
||||
/* 2. walk each isolated stream and grow max dict_size if needed */
|
||||
for (strm = head; strm; strm = strm->next) {
|
||||
struct xz_dec_microlzma *state;
|
||||
|
||||
if (strm->dict_size >= dict_size)
|
||||
continue;
|
||||
state = xz_dec_microlzma_alloc(XZ_PREALLOC, dict_size);
|
||||
if (!state) {
|
||||
err = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
if (strm->state)
|
||||
xz_dec_microlzma_end(strm->state);
|
||||
strm->state = xz_dec_microlzma_alloc(XZ_PREALLOC, dict_size);
|
||||
if (!strm->state)
|
||||
err = -ENOMEM;
|
||||
strm->state = state;
|
||||
strm->dict_size = dict_size;
|
||||
}
|
||||
|
||||
/* 3. push back all to the global list and update max dict_size */
|
||||
|
|
@ -142,7 +151,8 @@ static int z_erofs_load_lzma_config(struct super_block *sb,
|
|||
spin_unlock(&z_erofs_lzma_lock);
|
||||
wake_up_all(&z_erofs_lzma_wq);
|
||||
|
||||
z_erofs_lzma_max_dictsize = dict_size;
|
||||
if (!err)
|
||||
z_erofs_lzma_max_dictsize = dict_size;
|
||||
mutex_unlock(&lzma_resize_mutex);
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,12 +71,8 @@ struct erofs_dev_context {
|
|||
bool flatdev;
|
||||
};
|
||||
|
||||
/* all filesystem-wide lz4 configurations */
|
||||
struct erofs_sb_lz4_info {
|
||||
/* # of pages needed for EROFS lz4 rolling decompression */
|
||||
u16 max_distance_pages;
|
||||
/* maximum possible blocks for pclusters in the filesystem */
|
||||
u16 max_pclusterblks;
|
||||
u16 max_pclusterblks; /* maximum physical blocks for LZ4 pclusters */
|
||||
};
|
||||
|
||||
struct erofs_xattr_prefix_item {
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ EROFS_ATTR_FEATURE(sb_chksum);
|
|||
EROFS_ATTR_FEATURE(ztailpacking);
|
||||
EROFS_ATTR_FEATURE(fragments);
|
||||
EROFS_ATTR_FEATURE(dedupe);
|
||||
EROFS_ATTR_FEATURE(xattr_prefixes);
|
||||
EROFS_ATTR_FEATURE(48bit);
|
||||
EROFS_ATTR_FEATURE(metabox);
|
||||
|
||||
|
|
@ -108,6 +109,7 @@ static struct attribute *erofs_feat_attrs[] = {
|
|||
ATTR_LIST(ztailpacking),
|
||||
ATTR_LIST(fragments),
|
||||
ATTR_LIST(dedupe),
|
||||
ATTR_LIST(xattr_prefixes),
|
||||
ATTR_LIST(48bit),
|
||||
ATTR_LIST(metabox),
|
||||
NULL,
|
||||
|
|
|
|||
|
|
@ -620,8 +620,8 @@ int erofs_xattr_fill_inode_fingerprint(struct erofs_inode_fingerprint *fp,
|
|||
{
|
||||
struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
|
||||
struct erofs_xattr_prefix_item *prefix;
|
||||
int domainlen, valuelen, base_index;
|
||||
const char *infix;
|
||||
int valuelen, base_index;
|
||||
|
||||
if (!test_opt(&sbi->opt, INODE_SHARE))
|
||||
return -EOPNOTSUPP;
|
||||
|
|
@ -633,17 +633,18 @@ int erofs_xattr_fill_inode_fingerprint(struct erofs_inode_fingerprint *fp,
|
|||
valuelen = erofs_getxattr(inode, base_index, infix, NULL, 0);
|
||||
if (valuelen <= 0 || valuelen > (1 << sbi->blkszbits))
|
||||
return -EFSCORRUPTED;
|
||||
fp->size = valuelen + (domain_id ? strlen(domain_id) : 0);
|
||||
domainlen = strlen(domain_id);
|
||||
fp->size = domainlen + 1 + valuelen;
|
||||
fp->opaque = kmalloc(fp->size, GFP_KERNEL);
|
||||
if (!fp->opaque)
|
||||
return -ENOMEM;
|
||||
memcpy(fp->opaque, domain_id, domainlen + 1);
|
||||
if (valuelen != erofs_getxattr(inode, base_index, infix,
|
||||
fp->opaque, valuelen)) {
|
||||
fp->opaque + domainlen + 1, valuelen)) {
|
||||
kfree(fp->opaque);
|
||||
fp->opaque = NULL;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
memcpy(fp->opaque + valuelen, domain_id, fp->size - valuelen);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1259,7 +1259,7 @@ static int z_erofs_decompress_pcluster(struct z_erofs_backend *be, bool eio)
|
|||
const struct z_erofs_decompressor *alg =
|
||||
z_erofs_decomp[pcl->algorithmformat];
|
||||
bool try_free = true;
|
||||
int i, j, jtop, err2, err = eio ? -EIO : 0;
|
||||
int i, err2, err = eio ? -EIO : 0;
|
||||
struct page *page;
|
||||
bool overlapped;
|
||||
const char *reason;
|
||||
|
|
@ -1348,7 +1348,6 @@ static int z_erofs_decompress_pcluster(struct z_erofs_backend *be, bool eio)
|
|||
be->compressed_pages >= be->onstack_pages + Z_EROFS_ONSTACK_PAGES)
|
||||
kvfree(be->compressed_pages);
|
||||
|
||||
jtop = 0;
|
||||
z_erofs_fill_other_copies(be, err);
|
||||
for (i = 0; i < be->nr_pages; ++i) {
|
||||
page = be->decompressed_pages[i];
|
||||
|
|
@ -1356,22 +1355,11 @@ static int z_erofs_decompress_pcluster(struct z_erofs_backend *be, bool eio)
|
|||
continue;
|
||||
|
||||
DBG_BUGON(z_erofs_page_is_invalidated(page));
|
||||
if (!z_erofs_is_shortlived_page(page)) {
|
||||
if (!z_erofs_is_shortlived_page(page))
|
||||
erofs_onlinefolio_end(page_folio(page), err, true);
|
||||
continue;
|
||||
}
|
||||
if (pcl->algorithmformat != Z_EROFS_COMPRESSION_LZ4) {
|
||||
else
|
||||
erofs_pagepool_add(be->pagepool, page);
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < jtop && be->decompressed_pages[j] != page; ++j)
|
||||
;
|
||||
if (j >= jtop) /* this bounce page is newly detected */
|
||||
be->decompressed_pages[jtop++] = page;
|
||||
}
|
||||
while (jtop)
|
||||
erofs_pagepool_add(be->pagepool,
|
||||
be->decompressed_pages[--jtop]);
|
||||
if (be->decompressed_pages != be->onstack_pages)
|
||||
kvfree(be->decompressed_pages);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user