diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 2dfc313588d2..37495e95a78d 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -132,11 +132,13 @@ config EROFS_FS_ZIP_LZMA Say N if you want to disable LZMA compression support. config EROFS_FS_ZIP_LZMA_DEFAULT_MAX_STREAMS - int "EROFS LZMA default maximum decompression streams" + int "EROFS LZMA default maximum decompression streams" if SMP depends on EROFS_FS_ZIP_LZMA range 1 NR_CPUS if SMP range 1 1 if !SMP - default 16 + default 16 if SMP && NR_CPUS >= 16 + default NR_CPUS if SMP + default 1 help By default EROFS allocates one LZMA decompression stream per CPU. Each stream can hold a dictionary of up to 8 MiB taken from the @@ -144,7 +146,7 @@ config EROFS_FS_ZIP_LZMA_DEFAULT_MAX_STREAMS of memory. This caps the default; the lzma_streams module parameter still overrides it. - If unsure, keep the default of 16. + If unsure, keep the suggested default (16 or lower). config EROFS_FS_ZIP_DEFLATE bool "EROFS DEFLATE compressed data support" diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 20962f8b60a8..0885b1f2fc92 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -497,7 +497,7 @@ static int erofs_file_mmap_prepare(struct vm_area_desc *desc) #define erofs_file_mmap_prepare generic_file_readonly_mmap_prepare #endif -static loff_t erofs_file_llseek(struct file *file, loff_t offset, int whence) +loff_t erofs_file_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; const struct iomap_ops *ops = &erofs_iomap_ops; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 9b7370f0f3df..65974e57aebf 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -415,6 +415,7 @@ void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb, int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *dev); int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len); +loff_t erofs_file_llseek(struct file *file, loff_t offset, int whence); int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map); void erofs_onlinefolio_init(struct folio *folio); void erofs_onlinefolio_split(struct folio *folio); diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c index fa7d4112dec5..a1cf2aff8d32 100644 --- a/fs/erofs/ishare.c +++ b/fs/erofs/ishare.c @@ -54,6 +54,7 @@ bool erofs_ishare_fill_inode(struct inode *inode) si->i_mapping->a_ops = aops; si->i_mode = 0444 | S_IFREG; si->i_size = inode->i_size; + mapping_set_large_folios(si->i_mapping); unlock_new_inode(si); } else { kfree(fp.opaque); @@ -148,6 +149,13 @@ static int erofs_ishare_mmap(struct file *file, struct vm_area_struct *vma) return generic_file_readonly_mmap(file, vma); } +static ssize_t erofs_ishare_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, + size_t len, unsigned int flags) +{ + return filemap_splice_read(in->private_data, ppos, pipe, len, flags); +} + static int erofs_ishare_fadvise(struct file *file, loff_t offset, loff_t len, int advice) { @@ -156,12 +164,12 @@ static int erofs_ishare_fadvise(struct file *file, loff_t offset, const struct file_operations erofs_ishare_fops = { .open = erofs_ishare_file_open, - .llseek = generic_file_llseek, + .llseek = erofs_file_llseek, .read_iter = erofs_ishare_file_read_iter, .mmap = erofs_ishare_mmap, .release = erofs_ishare_file_release, .get_unmapped_area = thp_get_unmapped_area, - .splice_read = filemap_splice_read, + .splice_read = erofs_ishare_splice_read, .fadvise = erofs_ishare_fadvise, }; diff --git a/fs/erofs/zutil.c b/fs/erofs/zutil.c index a0ce9226bc02..960cfe86eeb6 100644 --- a/fs/erofs/zutil.c +++ b/fs/erofs/zutil.c @@ -70,15 +70,15 @@ int z_erofs_gbuf_growsize(unsigned int nrpages) void *ptr, *old_ptr; int last, i, j; - mutex_lock(&gbuf_resize_mutex); + guard(mutex)(&gbuf_resize_mutex); /* avoid shrinking gbufs, since no idea how many fses rely on */ - if (nrpages <= z_erofs_gbuf_nrpages) { - mutex_unlock(&gbuf_resize_mutex); + if (nrpages <= z_erofs_gbuf_nrpages) return 0; - } for (i = 0; i < z_erofs_gbuf_count; ++i) { gbuf = &z_erofs_gbufpool[i]; + if (gbuf->nrpages >= nrpages) + continue; tmp_pages = kzalloc_objs(*tmp_pages, nrpages); if (!tmp_pages) goto out; @@ -87,8 +87,7 @@ int z_erofs_gbuf_growsize(unsigned int nrpages) tmp_pages[j] = gbuf->pages[j]; do { last = j; - j = alloc_pages_bulk(GFP_KERNEL, nrpages, - tmp_pages); + j = alloc_pages_bulk(GFP_KERNEL, nrpages, tmp_pages); if (last == j) goto out; } while (j != nrpages); @@ -99,24 +98,23 @@ int z_erofs_gbuf_growsize(unsigned int nrpages) spin_lock(&gbuf->lock); kfree(gbuf->pages); - gbuf->pages = tmp_pages; old_ptr = gbuf->ptr; + gbuf->pages = tmp_pages; gbuf->ptr = ptr; gbuf->nrpages = nrpages; spin_unlock(&gbuf->lock); - if (old_ptr) - vunmap(old_ptr); + vunmap(old_ptr); + tmp_pages = NULL; } z_erofs_gbuf_nrpages = nrpages; out: - if (i < z_erofs_gbuf_count && tmp_pages) { + if (unlikely(tmp_pages)) { for (j = 0; j < nrpages; ++j) if (tmp_pages[j] && (j >= gbuf->nrpages || tmp_pages[j] != gbuf->pages[j])) __free_page(tmp_pages[j]); kfree(tmp_pages); } - mutex_unlock(&gbuf_resize_mutex); return i < z_erofs_gbuf_count ? -ENOMEM : 0; }