summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-25 12:27:41 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-25 12:27:41 -0700
commit73ae59e975966d24e32926247ddb45a537ebe184 (patch)
tree09f44d048daa0afe5d13be93cbd08e29386df183
parent7bb6284aa7b3c369b41e7f33fcbe193161f008e7 (diff)
parenta7d28aa0e9b2c983b915d091f9596f0e3b253355 (diff)
Merge tag 'erofs-for-7.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs
Pull more erofs updates from Gao Xiang: - Fix up the EROFS_FS_ZIP_LZMA_DEFAULT_MAX_STREAMS default logic so that "make savedefconfig" won't write the needless default value to the defconfig file - Add support for SEEK_{HOLE,DATA}, splice() as well as enable large folios in inode_share mode - Fix z_erofs_gbuf_growsize() after the previous buffer resizing fails * tag 'erofs-for-7.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs: erofs: simplify z_erofs_gbuf_growsize() erofs: skip sufficiently large global buffers when resizing erofs: support large folios in inode_share mode erofs: support splice() in inode_share mode erofs: support SEEK_HOLE/SEEK_DATA in inode_share mode erofs: Fix EROFS_FS_ZIP_LZMA_DEFAULT_MAX_STREAMS default logic
-rw-r--r--fs/erofs/Kconfig8
-rw-r--r--fs/erofs/data.c2
-rw-r--r--fs/erofs/internal.h1
-rw-r--r--fs/erofs/ishare.c12
-rw-r--r--fs/erofs/zutil.c20
5 files changed, 26 insertions, 17 deletions
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;
}