Skip to content

Commit 03c0d03

Browse files
Hongbo Lihsiangkao
authored andcommitted
erofs: allow sharing page cache with the same aops only
Inode with identical data but different @aops cannot be mixed because the page cache is managed by different subsystems (e.g., @aops for compressed on-disk inodes cannot handle plain on-disk inodes). In this patch, we never allow inodes to share the page cache among plain, compressed, and fileio cases. When a shared inode is created, we initialize @aops that is the same as the initial real inode, and subsequent inodes cannot share the page cache if the inferred @aops differ from the corresponding shared inode. This is reasonable as a first step because, in typical use cases, if an inode is compressible, it will fall into compressed inodes across different filesystem images unless users use plain filesystems. However, in that cases, users will use plain filesystems all the time. Fixes: 5ef3208 ("erofs: introduce the page cache share feature") Signed-off-by: Hongbo Li <lihongbo22@huawei.com> Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com> Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
1 parent 6de23f8 commit 03c0d03

3 files changed

Lines changed: 22 additions & 15 deletions

File tree

fs/erofs/inode.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ static int erofs_read_inode(struct inode *inode)
222222

223223
static int erofs_fill_inode(struct inode *inode)
224224
{
225+
const struct address_space_operations *aops;
225226
int err;
226227

227228
trace_erofs_fill_inode(inode);
@@ -254,7 +255,11 @@ static int erofs_fill_inode(struct inode *inode)
254255
}
255256

256257
mapping_set_large_folios(inode->i_mapping);
257-
return erofs_inode_set_aops(inode, inode, false);
258+
aops = erofs_get_aops(inode, false);
259+
if (IS_ERR(aops))
260+
return PTR_ERR(aops);
261+
inode->i_mapping->a_ops = aops;
262+
return 0;
258263
}
259264

260265
/*

fs/erofs/internal.h

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -471,26 +471,24 @@ static inline void *erofs_vm_map_ram(struct page **pages, unsigned int count)
471471
return NULL;
472472
}
473473

474-
static inline int erofs_inode_set_aops(struct inode *inode,
475-
struct inode *realinode, bool no_fscache)
474+
static inline const struct address_space_operations *
475+
erofs_get_aops(struct inode *realinode, bool no_fscache)
476476
{
477477
if (erofs_inode_is_data_compressed(EROFS_I(realinode)->datalayout)) {
478478
if (!IS_ENABLED(CONFIG_EROFS_FS_ZIP))
479-
return -EOPNOTSUPP;
479+
return ERR_PTR(-EOPNOTSUPP);
480480
DO_ONCE_LITE_IF(realinode->i_blkbits != PAGE_SHIFT,
481481
erofs_info, realinode->i_sb,
482482
"EXPERIMENTAL EROFS subpage compressed block support in use. Use at your own risk!");
483-
inode->i_mapping->a_ops = &z_erofs_aops;
484-
return 0;
483+
return &z_erofs_aops;
485484
}
486-
inode->i_mapping->a_ops = &erofs_aops;
487485
if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && !no_fscache &&
488486
erofs_is_fscache_mode(realinode->i_sb))
489-
inode->i_mapping->a_ops = &erofs_fscache_access_aops;
487+
return &erofs_fscache_access_aops;
490488
if (IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) &&
491489
erofs_is_fileio_mode(EROFS_SB(realinode->i_sb)))
492-
inode->i_mapping->a_ops = &erofs_fileio_aops;
493-
return 0;
490+
return &erofs_fileio_aops;
491+
return &erofs_aops;
494492
}
495493

496494
int erofs_register_sysfs(struct super_block *sb);

fs/erofs/ishare.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,14 @@ bool erofs_ishare_fill_inode(struct inode *inode)
4040
{
4141
struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
4242
struct erofs_inode *vi = EROFS_I(inode);
43+
const struct address_space_operations *aops;
4344
struct erofs_inode_fingerprint fp;
4445
struct inode *sharedinode;
4546
unsigned long hash;
4647

48+
aops = erofs_get_aops(inode, true);
49+
if (IS_ERR(aops))
50+
return false;
4751
if (erofs_xattr_fill_inode_fingerprint(&fp, inode, sbi->domain_id))
4852
return false;
4953
hash = xxh32(fp.opaque, fp.size, 0);
@@ -56,15 +60,15 @@ bool erofs_ishare_fill_inode(struct inode *inode)
5660
}
5761

5862
if (inode_state_read_once(sharedinode) & I_NEW) {
59-
if (erofs_inode_set_aops(sharedinode, inode, true)) {
60-
iget_failed(sharedinode);
61-
kfree(fp.opaque);
62-
return false;
63-
}
63+
sharedinode->i_mapping->a_ops = aops;
6464
sharedinode->i_size = vi->vfs_inode.i_size;
6565
unlock_new_inode(sharedinode);
6666
} else {
6767
kfree(fp.opaque);
68+
if (aops != sharedinode->i_mapping->a_ops) {
69+
iput(sharedinode);
70+
return false;
71+
}
6872
if (sharedinode->i_size != vi->vfs_inode.i_size) {
6973
_erofs_printk(inode->i_sb, KERN_WARNING
7074
"size(%lld:%lld) not matches for the same fingerprint\n",

0 commit comments

Comments
 (0)