Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 5ef3208e3be5 ("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>

authored by

Hongbo Li and committed by
Gao Xiang
03c0d030 6de23f81

+22 -15
+6 -1
fs/erofs/inode.c
··· 222 222 223 223 static int erofs_fill_inode(struct inode *inode) 224 224 { 225 + const struct address_space_operations *aops; 225 226 int err; 226 227 227 228 trace_erofs_fill_inode(inode); ··· 255 254 } 256 255 257 256 mapping_set_large_folios(inode->i_mapping); 258 - return erofs_inode_set_aops(inode, inode, false); 257 + aops = erofs_get_aops(inode, false); 258 + if (IS_ERR(aops)) 259 + return PTR_ERR(aops); 260 + inode->i_mapping->a_ops = aops; 261 + return 0; 259 262 } 260 263 261 264 /*
+7 -9
fs/erofs/internal.h
··· 471 471 return NULL; 472 472 } 473 473 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) 476 476 { 477 477 if (erofs_inode_is_data_compressed(EROFS_I(realinode)->datalayout)) { 478 478 if (!IS_ENABLED(CONFIG_EROFS_FS_ZIP)) 479 - return -EOPNOTSUPP; 479 + return ERR_PTR(-EOPNOTSUPP); 480 480 DO_ONCE_LITE_IF(realinode->i_blkbits != PAGE_SHIFT, 481 481 erofs_info, realinode->i_sb, 482 482 "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; 485 484 } 486 - inode->i_mapping->a_ops = &erofs_aops; 487 485 if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && !no_fscache && 488 486 erofs_is_fscache_mode(realinode->i_sb)) 489 - inode->i_mapping->a_ops = &erofs_fscache_access_aops; 487 + return &erofs_fscache_access_aops; 490 488 if (IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) && 491 489 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; 494 492 } 495 493 496 494 int erofs_register_sysfs(struct super_block *sb);
+9 -5
fs/erofs/ishare.c
··· 40 40 { 41 41 struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); 42 42 struct erofs_inode *vi = EROFS_I(inode); 43 + const struct address_space_operations *aops; 43 44 struct erofs_inode_fingerprint fp; 44 45 struct inode *sharedinode; 45 46 unsigned long hash; 46 47 48 + aops = erofs_get_aops(inode, true); 49 + if (IS_ERR(aops)) 50 + return false; 47 51 if (erofs_xattr_fill_inode_fingerprint(&fp, inode, sbi->domain_id)) 48 52 return false; 49 53 hash = xxh32(fp.opaque, fp.size, 0); ··· 60 56 } 61 57 62 58 if (inode_state_read_once(sharedinode) & I_NEW) { 63 - if (erofs_inode_set_aops(sharedinode, inode, true)) { 64 - iget_failed(sharedinode); 65 - kfree(fp.opaque); 66 - return false; 67 - } 59 + sharedinode->i_mapping->a_ops = aops; 68 60 sharedinode->i_size = vi->vfs_inode.i_size; 69 61 unlock_new_inode(sharedinode); 70 62 } else { 71 63 kfree(fp.opaque); 64 + if (aops != sharedinode->i_mapping->a_ops) { 65 + iput(sharedinode); 66 + return false; 67 + } 72 68 if (sharedinode->i_size != vi->vfs_inode.i_size) { 73 69 _erofs_printk(inode->i_sb, KERN_WARNING 74 70 "size(%lld:%lld) not matches for the same fingerprint\n",