On Jun 3, 2020, at 03:44, Chengguang Xu <cgxu519@xxxxxxxxxxxx> wrote: > > Currently ext2 uses mdcache for deduplication of extended (typo) this should be "mbcache" > attribution blocks. However, there is lack of handling for > corrupted blocks, so newly created EAs may still links to > corrupted blocks. This patch tries to drop cached block > when detecting corruption to mitigate the effect. > > Signed-off-by: Chengguang Xu <cgxu519@xxxxxxxxxxxx> > --- > fs/ext2/xattr.c | 25 ++++++++++++++++++++++--- > 1 file changed, 22 insertions(+), 3 deletions(-) > > diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c > index 943cc469f42f..969521e39753 100644 > --- a/fs/ext2/xattr.c > +++ b/fs/ext2/xattr.c > @@ -93,6 +93,8 @@ static int ext2_xattr_set2(struct inode *, struct buffer_head *, > struct ext2_xattr_header *); > > static int ext2_xattr_cache_insert(struct mb_cache *, struct buffer_head *); > +static void ext2_xattr_cache_remove(struct mb_cache *cache, > + struct buffer_head *bh); > static struct buffer_head *ext2_xattr_cache_find(struct inode *, > struct ext2_xattr_header *); > static void ext2_xattr_rehash(struct ext2_xattr_header *, > @@ -237,8 +239,10 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name, > entry = FIRST_ENTRY(bh); > while (!IS_LAST_ENTRY(entry)) { > if (!ext2_xattr_entry_valid(entry, end, > - inode->i_sb->s_blocksize)) > + inode->i_sb->s_blocksize)) { > + ext2_xattr_cache_remove(ea_block_cache, bh); > goto bad_block; > + } > > not_found = ext2_xattr_cmp_entry(name_index, name_len, name, > entry); > @@ -323,8 +327,10 @@ ext2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size) > entry = FIRST_ENTRY(bh); > while (!IS_LAST_ENTRY(entry)) { > if (!ext2_xattr_entry_valid(entry, end, > - inode->i_sb->s_blocksize)) > + inode->i_sb->s_blocksize)) { > + ext2_xattr_cache_remove(ea_block_cache, bh); > goto bad_block; > + } > entry = EXT2_XATTR_NEXT(entry); > } > if (ext2_xattr_cache_insert(ea_block_cache, bh)) > @@ -407,6 +413,7 @@ int > ext2_xattr_set(struct inode *inode, int name_index, const char *name, > const void *value, size_t value_len, int flags) > { > + struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode); > struct super_block *sb = inode->i_sb; > struct buffer_head *bh = NULL; > struct ext2_xattr_header *header = NULL; > @@ -464,8 +471,11 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name, > */ > last = FIRST_ENTRY(bh); > while (!IS_LAST_ENTRY(last)) { > - if (!ext2_xattr_entry_valid(last, end, sb->s_blocksize)) > + if (!ext2_xattr_entry_valid(last, end, > + sb->s_blocksize)) { > + ext2_xattr_cache_remove(ea_block_cache, bh); > goto bad_block; > + } > if (last->e_value_size) { > size_t offs = le16_to_cpu(last->e_value_offs); > if (offs < min_offs) > @@ -881,6 +891,15 @@ ext2_xattr_cache_insert(struct mb_cache *cache, struct buffer_head *bh) > return error; > } > > +static void > +ext2_xattr_cache_remove(struct mb_cache *cache, struct buffer_head *bh) > +{ > + lock_buffer(bh); > + mb_cache_entry_delete(cache, le32_to_cpu(HDR(bh)->h_hash), > + bh->b_blocknr); > + unlock_buffer(bh); > +} > + > /* > * ext2_xattr_cmp() > * > -- > 2.20.1 > >