mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
Changes since last update:
- Hold real inodes to fix mmap usage with page cache sharing
- Fix metadata reads at the end of file-backed images with sub-page
block sizes
- Ensure disallowing superblock_share when device= is specified
- Drop unnecessary .read_folio() checks for file-backed mounts to
allow tmpfs as a backing fs
-----BEGIN PGP SIGNATURE-----
iQJFBAABCgAvFiEEQ0A6bDUS9Y+83NPFUXZn5Zlu5qoFAmrg3FERHHhpYW5nQGtl
cm5lbC5vcmcACgkQUXZn5Zlu5qrsKg//RUS1rgussihehHtUbGyWY+nXc4HZjPTF
WfKXGtgyqwzfEY7ycqqgJheFxD/z+NFMIR1lrm4P9VcA/mDmHJ3EZavmQGz6bDY7
SWU6gNS7KQ8mflvRronPRutbXJsB8lI/vlYEqJcIvwe2DBkDTyPTeFET27SgKHk2
MtcywEQn6ij9b3WHJ45Ou313oBycv1Rn8lXEekwslBZxgZbqQ+7OS/1PXtasypT8
WQCo70Kux7P5+kqCAk2kQ6v7Vf/IBHpJR6gU8QzEJYULWBTmij+qJyGcXhaz3ngy
FJkIdX0hkCMFsPPJF+8dmuaf1G/ikCSqMwjOr2NxuZpkHdyyQKDAn4njQ5PUHFP7
nYg86dIUteguts2p4CG6MUCHiv8gY9gETrr3u2QW04UOHTkwyFfR2nw83HcbEh1R
XN3lrIIAD25UHZuUqs0pFw8+jaPv2ZKj/HHFFDw5PLtkkSxY42kUVkx5oGofaOI8
h4h3LFADf5Rkwjwo+pOGdM7m8OgYPZ7U0fLWSHOEOMxbkJCIwI8uCTw3qZBaukBv
Vu8Zsomt+IFNYmtjVUypOuM/5dhmgcZzEVqEZ77PFgjTKfriVnmLjcCJAupaSBLU
OS+Ul7HBd+uU7hdgoODdi1uNKZ0xiz34KeAC69M2suRQZEX0R9zTEnN9gPei0qLH
jBSdCQ7AJBY=
=VNdm
-----END PGP SIGNATURE-----
Merge tag 'erofs-for-7.4-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs
Pull erofs fixes from Gao Xiang:
"These patches address several new reported issues related to page
cache sharing, the new superblock_share feature, and recent metadata
path changes for file-backed mounts:
- Hold real inodes to fix mmap usage with page cache sharing
- Fix metadata reads at the end of file-backed images with sub-page
block sizes
- Ensure disallowing superblock_share when device= is specified
- Drop unnecessary .read_folio() checks for file-backed mounts to
allow tmpfs as a backing fs"
* tag 'erofs-for-7.4-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs:
erofs: drop unnecessary .read_folio() checks for file-backed mounts
erofs: fix disallowing superblock_share if device= is set
erofs: fix metadata reads at the end of file-backed images
erofs: hold real inodes for shared files
This commit is contained in:
commit
83f32c7732
|
|
@ -142,17 +142,29 @@ int erofs_read_meta_folio(struct file *file, struct folio *folio)
|
|||
.dev = { .m_pa = folio_pos(folio), },
|
||||
};
|
||||
struct inode *inode = folio_inode(folio);
|
||||
size_t len = folio_size(folio);
|
||||
loff_t pos, isize;
|
||||
int err;
|
||||
|
||||
err = erofs_map_dev(inode->i_sb, &io.dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pos = io.dev.m_dif->fsoff + io.dev.m_pa;
|
||||
isize = i_size_read(file_inode(io.dev.m_dif->file));
|
||||
if (pos + folio_size(folio) > isize) {
|
||||
len = isize > pos ? isize - pos : 0;
|
||||
folio_zero_segment(folio, len, folio_size(folio));
|
||||
if (!len) {
|
||||
folio_end_read(folio, true);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
io.rq = erofs_fileio_rq_alloc(inode->i_sb, io.dev.m_dif->file);
|
||||
io.rq->bio.bi_end_io = erofs_fileio_meta_endio;
|
||||
io.rq->bio.bi_iter.bi_sector =
|
||||
(io.dev.m_dif->fsoff + io.dev.m_pa) >> 9;
|
||||
bio_add_folio_nofail(&io.rq->bio, folio, folio_size(folio), 0);
|
||||
io.rq->bio.bi_iter.bi_sector = pos >> 9;
|
||||
bio_add_folio_nofail(&io.rq->bio, folio, len, 0);
|
||||
erofs_fileio_rq_submit(io.rq);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,9 +30,18 @@ static int erofs_ishare_iget5_set(struct inode *inode, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int erofs_ishare_backing_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
iput(file->private_data);
|
||||
file->private_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool erofs_ishare_fill_inode(struct inode *inode)
|
||||
{
|
||||
static const struct file_operations empty_fops = {};
|
||||
static const struct file_operations backing_fops = {
|
||||
.release = erofs_ishare_backing_release,
|
||||
};
|
||||
struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
|
||||
const struct address_space_operations *aops;
|
||||
struct erofs_inode *vi = EROFS_I(inode);
|
||||
|
|
@ -50,7 +59,7 @@ 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_fop = &backing_fops;
|
||||
si->i_mapping->a_ops = aops;
|
||||
si->i_mode = 0444 | S_IFREG;
|
||||
si->i_size = inode->i_size;
|
||||
|
|
@ -102,16 +111,24 @@ static int erofs_ishare_file_open(struct inode *inode, struct file *file)
|
|||
.mnt = erofs_ishare_mnt,
|
||||
.dentry = EROFS_I(inode)->sharedentry,
|
||||
};
|
||||
struct file *rf;
|
||||
struct file *sf;
|
||||
|
||||
if (file->f_flags & O_DIRECT)
|
||||
return -EINVAL;
|
||||
|
||||
rf = backing_file_open(file, file->f_flags | O_NOATIME,
|
||||
sf = backing_file_open(file, file->f_flags | O_NOATIME,
|
||||
&sharedpath, current_cred());
|
||||
if (IS_ERR(rf))
|
||||
return PTR_ERR(rf);
|
||||
file->private_data = rf;
|
||||
if (IS_ERR(sf))
|
||||
return PTR_ERR(sf);
|
||||
/*
|
||||
* A VMA only holds a reference to the shared file so that the original
|
||||
* file may be released: the shared file must therefore hold a reference
|
||||
* to one of the real inodes ("inode" passed here), and that reference
|
||||
* will be released by erofs_ishare_backing_release().
|
||||
*/
|
||||
ihold(inode);
|
||||
sf->private_data = inode;
|
||||
file->private_data = sf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -125,13 +142,13 @@ static int erofs_ishare_file_release(struct inode *inode, struct file *file)
|
|||
static ssize_t erofs_ishare_file_read_iter(struct kiocb *iocb,
|
||||
struct iov_iter *to)
|
||||
{
|
||||
struct file *realfile = iocb->ki_filp->private_data;
|
||||
struct file *sf = iocb->ki_filp->private_data;
|
||||
struct kiocb dedup_iocb;
|
||||
ssize_t nread;
|
||||
|
||||
if (!iov_iter_count(to))
|
||||
return 0;
|
||||
kiocb_clone(&dedup_iocb, iocb, realfile);
|
||||
kiocb_clone(&dedup_iocb, iocb, sf);
|
||||
nread = filemap_read(&dedup_iocb, to, 0);
|
||||
iocb->ki_pos = dedup_iocb.ki_pos;
|
||||
return nread;
|
||||
|
|
@ -139,12 +156,12 @@ static ssize_t erofs_ishare_file_read_iter(struct kiocb *iocb,
|
|||
|
||||
static int erofs_ishare_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
struct file *realfile = file->private_data;
|
||||
struct file *sf = file->private_data;
|
||||
int err;
|
||||
|
||||
vma_set_file(vma, realfile);
|
||||
vma_set_file(vma, sf);
|
||||
|
||||
err = security_mmap_backing_file(vma, realfile, file);
|
||||
err = security_mmap_backing_file(vma, sf, file);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
@ -178,7 +195,7 @@ const struct file_operations erofs_ishare_fops = {
|
|||
struct inode *erofs_real_inode(struct inode *inode, bool *need_iput)
|
||||
{
|
||||
struct erofs_inode *vi, *vi_share;
|
||||
struct inode *realinode;
|
||||
struct inode *realinode = NULL;
|
||||
|
||||
*need_iput = false;
|
||||
if (inode->i_sb != erofs_ishare_mnt->mnt_sb)
|
||||
|
|
|
|||
|
|
@ -827,7 +827,8 @@ static int erofs_sb_share_test_super(struct super_block *sb,
|
|||
return 0;
|
||||
return file_inode(sbi->dif0.file) == file_inode(new_sbi->dif0.file) &&
|
||||
sbi->dif0.fsoff == new_sbi->dif0.fsoff &&
|
||||
!memcmp(&sbi->opt, &new_sbi->opt, sizeof(sbi->opt));
|
||||
!memcmp(&sbi->opt, &new_sbi->opt, sizeof(sbi->opt)) &&
|
||||
!new_sbi->devs->extra_devices;
|
||||
}
|
||||
|
||||
static int erofs_file_get_tree(struct fs_context *fc)
|
||||
|
|
@ -850,8 +851,7 @@ static int erofs_fc_get_tree(struct fs_context *fc)
|
|||
errorfc(fc, "source fd option not supported");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!S_ISREG(file_inode(sbi->dif0.file)->i_mode) ||
|
||||
!sbi->dif0.file->f_mapping->a_ops->read_folio) {
|
||||
if (!S_ISREG(file_inode(sbi->dif0.file)->i_mode)) {
|
||||
errorfc(fc, "source is unsupported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -871,8 +871,7 @@ static int erofs_fc_get_tree(struct fs_context *fc)
|
|||
return PTR_ERR(file);
|
||||
sbi->dif0.file = file;
|
||||
|
||||
if (S_ISREG(file_inode(sbi->dif0.file)->i_mode) &&
|
||||
sbi->dif0.file->f_mapping->a_ops->read_folio)
|
||||
if (S_ISREG(file_inode(sbi->dif0.file)->i_mode))
|
||||
return erofs_file_get_tree(fc);
|
||||
}
|
||||
return ret;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user