mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 10:41:49 +02:00
Changes since the last update:
- Keep a valid f_path for page cache sharing to fix a recent mincore()
NULL pointer dereference
- Limit LZMA stream pool size when too many processors are available
- Sync up with Hongbo Li's latest email address
-----BEGIN PGP SIGNATURE-----
iQJFBAABCgAvFiEEQ0A6bDUS9Y+83NPFUXZn5Zlu5qoFAmpndxERHHhpYW5nQGtl
cm5lbC5vcmcACgkQUXZn5Zlu5qpMkw/+JjAgjf9G5boFLgBiZGpBXSaZiBoCQcl2
0AAR0S7c2J1Egqf6WMEF+9pe/+vsV/jlGrJ5wU4fLtXozUa/bEVZStrEAj5Qzk3n
0EHBuXA/pqzthHLlfHdAbhNuD6+JAxKfz1tEr7Fgdcn6agIsAyCvLwDse3BRzzAN
50mYVm/txLyoRlw5cTI5WwIPouufRId1PXT3eMacsJ8rZHqUn3pFwUuHeUClgzUi
e1zlaVDppHjeDFVMqTav2/3Tv0ASClzhDKpLD7e1oHBOJ08S9c/9ofKZbvW1xlcU
aEhQXawXT0zAlqYYn/NWEXn7sAJFHqmyl94c/1w5BfAVErPHmGwlXgmegQqipnpJ
B6gFSyaggbZx9iEeFH27wwW/UHefCwx0anfNMpjZheHbrDd+7SnLEINnDQVyD+n7
oC7UQ41k6rYRqfHb1zBHzf8l5OCc4f8d9YYLjn5hSveMWtmFhK075gY1AdYvfNMi
ojb2WRVIMkyIxEJvqNsV149q+dEAXJFtTAGZCm7Jps9cYJ1qnOCsfL8MK81cOn8K
h1SRvLTEGLZyE/KBpEVpn115DqbTcA5eaLlTMGcfqjfBN7S+LeSv3fVMIYN8IR4j
kZcoQZJdSGPdYvUmS0RDYXtV1wQTfgoTBRTsIYhvwYVTInKImP8lVyeqvPUYea+l
ohs2lJ0CQkw=
=XDWu
-----END PGP SIGNATURE-----
Merge tag 'erofs-for-7.2-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs
Pull erofs fixes from Gao Xiang:
"Fix a regression in page cache sharing which can cause a NULL pointer
dereference, and limit LZMA stream memory usage on systems with many
CPUs.
- Keep a valid f_path for page cache sharing to fix a recent
mincore() NULL pointer dereference
- Limit LZMA stream pool size when too many processors are available
- Sync up with Hongbo Li's latest email address"
* tag 'erofs-for-7.2-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs:
erofs: cap LZMA stream pool size
erofs: ensure valid f_path for page cache sharing
MAINTAINERS: update Hongbo Li's email address
This commit is contained in:
commit
e895a6fc20
|
|
@ -9617,7 +9617,7 @@ M: Chao Yu <chao@kernel.org>
|
|||
R: Yue Hu <zbestahu@gmail.com>
|
||||
R: Jeffle Xu <jefflexu@linux.alibaba.com>
|
||||
R: Sandeep Dhavale <dhavale@google.com>
|
||||
R: Hongbo Li <lihongbo22@huawei.com>
|
||||
R: Hongbo Li <hongbohbli@tencent.com>
|
||||
R: Chunhai Guo <guochunhai@vivo.com>
|
||||
L: linux-erofs@lists.ozlabs.org
|
||||
S: Maintained
|
||||
|
|
|
|||
|
|
@ -131,6 +131,20 @@ 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"
|
||||
depends on EROFS_FS_ZIP_LZMA
|
||||
range 1 NR_CPUS
|
||||
default 16
|
||||
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
|
||||
mounted image, so on systems with many CPUs this can reserve a lot
|
||||
of memory. This caps the default; the lzma_streams module parameter
|
||||
still overrides it.
|
||||
|
||||
If unsure, keep the default of 16.
|
||||
|
||||
config EROFS_FS_ZIP_DEFLATE
|
||||
bool "EROFS DEFLATE compressed data support"
|
||||
depends on EROFS_FS_ZIP
|
||||
|
|
@ -189,6 +203,7 @@ config EROFS_FS_PCPU_KTHREAD_HIPRI
|
|||
config EROFS_FS_PAGE_CACHE_SHARE
|
||||
bool "EROFS page cache share support (experimental)"
|
||||
depends on EROFS_FS && EROFS_FS_XATTR
|
||||
select FS_STACK
|
||||
help
|
||||
This enables page cache sharing among inodes with identical
|
||||
content fingerprints on the same machine.
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ static int __init z_erofs_lzma_init(void)
|
|||
|
||||
/* by default, use # of possible CPUs instead */
|
||||
if (!z_erofs_lzma_nstrms)
|
||||
z_erofs_lzma_nstrms = num_possible_cpus();
|
||||
z_erofs_lzma_nstrms = min_t(unsigned int, num_possible_cpus(),
|
||||
CONFIG_EROFS_FS_ZIP_LZMA_DEFAULT_MAX_STREAMS);
|
||||
|
||||
for (i = 0; i < z_erofs_lzma_nstrms; ++i) {
|
||||
struct z_erofs_lzma *strm = kzalloc_obj(*strm);
|
||||
|
|
|
|||
|
|
@ -288,8 +288,8 @@ struct erofs_inode {
|
|||
struct erofs_inode_fingerprint fingerprint;
|
||||
spinlock_t ishare_lock;
|
||||
};
|
||||
/* for each real inode */
|
||||
struct inode *sharedinode;
|
||||
/* for each real filesystem inode */
|
||||
struct dentry *sharedentry;
|
||||
};
|
||||
#endif
|
||||
/* the corresponding vfs inode */
|
||||
|
|
|
|||
|
|
@ -2,14 +2,13 @@
|
|||
/*
|
||||
* Copyright (C) 2024, Alibaba Cloud
|
||||
*/
|
||||
#include <linux/backing-file.h>
|
||||
#include <linux/xxhash.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/security.h>
|
||||
#include "internal.h"
|
||||
#include "xattr.h"
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
static struct vfsmount *erofs_ishare_mnt;
|
||||
|
||||
static int erofs_ishare_iget5_eq(struct inode *inode, void *data)
|
||||
|
|
@ -33,10 +32,12 @@ static int erofs_ishare_iget5_set(struct inode *inode, void *data)
|
|||
|
||||
bool erofs_ishare_fill_inode(struct inode *inode)
|
||||
{
|
||||
static const struct file_operations empty_fops = {};
|
||||
struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
|
||||
const struct address_space_operations *aops;
|
||||
struct erofs_inode *vi = EROFS_I(inode);
|
||||
struct erofs_inode_fingerprint fp;
|
||||
struct dentry *sd;
|
||||
struct inode *si;
|
||||
|
||||
aops = erofs_get_aops(inode);
|
||||
|
|
@ -49,7 +50,9 @@ bool erofs_ishare_fill_inode(struct inode *inode)
|
|||
xxh32(fp.opaque, fp.size, 0),
|
||||
erofs_ishare_iget5_eq, erofs_ishare_iget5_set, &fp);
|
||||
if (si && (inode_state_read_once(si) & I_NEW)) {
|
||||
si->i_fop = &empty_fops;
|
||||
si->i_mapping->a_ops = aops;
|
||||
si->i_mode = 0444 | S_IFREG;
|
||||
si->i_size = inode->i_size;
|
||||
unlock_new_inode(si);
|
||||
} else {
|
||||
|
|
@ -65,7 +68,10 @@ bool erofs_ishare_fill_inode(struct inode *inode)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
vi->sharedinode = si;
|
||||
sd = d_obtain_alias(si); /* disconnected denties for sharedinodes */
|
||||
if (IS_ERR(sd))
|
||||
return false;
|
||||
vi->sharedentry = sd;
|
||||
INIT_LIST_HEAD(&vi->ishare_list);
|
||||
spin_lock(&EROFS_I(si)->ishare_lock);
|
||||
list_add(&vi->ishare_list, &EROFS_I(si)->ishare_list);
|
||||
|
|
@ -75,48 +81,40 @@ bool erofs_ishare_fill_inode(struct inode *inode)
|
|||
|
||||
void erofs_ishare_free_inode(struct inode *inode)
|
||||
{
|
||||
struct erofs_inode *vi = EROFS_I(inode);
|
||||
struct inode *sharedinode = vi->sharedinode;
|
||||
struct erofs_inode *vi = EROFS_I(inode), *svi;
|
||||
|
||||
if (!sharedinode)
|
||||
if (!vi->sharedentry)
|
||||
return;
|
||||
spin_lock(&EROFS_I(sharedinode)->ishare_lock);
|
||||
svi = EROFS_I(d_inode(vi->sharedentry));
|
||||
spin_lock(&svi->ishare_lock);
|
||||
list_del(&vi->ishare_list);
|
||||
spin_unlock(&EROFS_I(sharedinode)->ishare_lock);
|
||||
iput(sharedinode);
|
||||
vi->sharedinode = NULL;
|
||||
spin_unlock(&svi->ishare_lock);
|
||||
dput(vi->sharedentry);
|
||||
vi->sharedentry = NULL;
|
||||
}
|
||||
|
||||
static int erofs_ishare_file_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct inode *sharedinode = EROFS_I(inode)->sharedinode;
|
||||
struct file *realfile;
|
||||
struct path sharedpath = {
|
||||
.mnt = erofs_ishare_mnt,
|
||||
.dentry = EROFS_I(inode)->sharedentry,
|
||||
};
|
||||
struct file *rf;
|
||||
|
||||
if (file->f_flags & O_DIRECT)
|
||||
return -EINVAL;
|
||||
realfile = alloc_empty_backing_file(O_RDONLY|O_NOATIME, current_cred(),
|
||||
file);
|
||||
if (IS_ERR(realfile))
|
||||
return PTR_ERR(realfile);
|
||||
ihold(sharedinode);
|
||||
realfile->f_op = &erofs_file_fops;
|
||||
realfile->f_inode = sharedinode;
|
||||
realfile->f_mapping = sharedinode->i_mapping;
|
||||
path_get(&file->f_path);
|
||||
backing_file_set_user_path(realfile, &file->f_path);
|
||||
|
||||
file_ra_state_init(&realfile->f_ra, file->f_mapping);
|
||||
realfile->private_data = EROFS_I(inode);
|
||||
file->private_data = realfile;
|
||||
rf = backing_file_open(file, file->f_flags | O_NOATIME,
|
||||
&sharedpath, current_cred());
|
||||
if (IS_ERR(rf))
|
||||
return PTR_ERR(rf);
|
||||
file->private_data = rf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int erofs_ishare_file_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct file *realfile = file->private_data;
|
||||
|
||||
iput(realfile->f_inode);
|
||||
fput(realfile);
|
||||
fput(file->private_data);
|
||||
file->private_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user