[PREVIEW] [PATCH 4/4] staging: erofs: add error handling for xattr submodule

Gao Xiang gaoxiang25 at huawei.com
Fri Aug 10 16:52:17 AEST 2018



On 2018/8/10 14:33, Chao Yu wrote:
> Hi Xiang,
> 
> On 2018/8/10 14:15, Gao Xiang wrote:
>> Hi Chao,
>>
>> On 2018/8/10 14:08, Chao Yu wrote:
>>> Hi Xiang,
>>>
>>> On 2018/8/10 11:47, Gao Xiang wrote:
>>>> Hi Chao,
>>>>
>>>> On 2018/8/10 11:40, Chao Yu wrote:
>>>>> On 2018/8/1 14:01, Gao Xiang wrote:
>>>>>> This patch enhances the missing error handling code for
>>>>>> xattr submodule, which improves the stability for the rare cases.
>>>>>>
>>>>>> Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
>>>>>> ---
>>>>>>  drivers/staging/erofs/xattr.c | 114 ++++++++++++++++++++++++++++--------------
>>>>>>  1 file changed, 77 insertions(+), 37 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c
>>>>>> index 702434b..bd911bb 100644
>>>>>> --- a/drivers/staging/erofs/xattr.c
>>>>>> +++ b/drivers/staging/erofs/xattr.c
>>>>>> @@ -24,16 +24,25 @@ struct xattr_iter {
>>>>>>  
>>>>>>  static inline void xattr_iter_end(struct xattr_iter *it, bool atomic)
>>>>>>  {
>>>>>> -	/* only init_inode_xattrs use non-atomic once */
>>>>>> +	/* the only user of kunmap() is 'init_inode_xattrs' */
>>>>>>  	if (unlikely(!atomic))
>>>>>>  		kunmap(it->page);
>>>>>>  	else
>>>>>>  		kunmap_atomic(it->kaddr);
>>>>>> +
>>>>>>  	unlock_page(it->page);
>>>>>>  	put_page(it->page);
>>>>>>  }
>>>>>>  
>>>>>> -static void init_inode_xattrs(struct inode *inode)
>>>>>> +static inline void xattr_iter_end_final(struct xattr_iter *it)
>>>>>> +{
>>>>>> +	if (unlikely(it->page == NULL))
>>>>>> +		return;
>>>>>> +
>>>>>> +	xattr_iter_end(it, true);
>>>>>> +}
>>>>>> +
>>>>>> +static int init_inode_xattrs(struct inode *inode)
>>>>>>  {
>>>>>>  	struct xattr_iter it;
>>>>>>  	unsigned i;
>>>>>> @@ -44,7 +53,7 @@ static void init_inode_xattrs(struct inode *inode)
>>>>>>  	bool atomic_map;
>>>>>>  
>>>>>>  	if (likely(inode_has_inited_xattr(inode)))
>>>>>> -		return;
>>>>>> +		return 0;
>>>>>>  
>>>>>>  	vi = EROFS_V(inode);
>>>>>>  	BUG_ON(!vi->xattr_isize);
>>>>>> @@ -55,7 +64,8 @@ static void init_inode_xattrs(struct inode *inode)
>>>>>>  	it.ofs = erofs_blkoff(iloc(sbi, vi->nid) + vi->inode_isize);
>>>>>>  
>>>>>>  	it.page = erofs_get_inline_page_nofail(inode, it.blkaddr);
>>>>> Need to introduce and use erofs_get_inline_page()?
>>>>>
>>>>>> -	BUG_ON(IS_ERR(it.page));
>>>>>> +	if (unlikely(IS_ERR(it.page)))
>>>>>> +		return PTR_ERR(it.page);
>>>>>>  
>>>>>>  	/* read in shared xattr array (non-atomic, see kmalloc below) */
>>>>>>  	it.kaddr = kmap(it.page);
>>>>>> @@ -64,9 +74,12 @@ static void init_inode_xattrs(struct inode *inode)
>>>>>>  	ih = (struct erofs_xattr_ibody_header *)(it.kaddr + it.ofs);
>>>>>>  
>>>>>>  	vi->xattr_shared_count = ih->h_shared_count;
>>>>>> -	vi->xattr_shared_xattrs = (unsigned *)kmalloc_array(
>>>>>> -		vi->xattr_shared_count, sizeof(unsigned),
>>>>>> -		GFP_KERNEL | __GFP_NOFAIL);
>>>>>> +	vi->xattr_shared_xattrs = kmalloc_array(vi->xattr_shared_count,
>>>>>> +						sizeof(unsigned), GFP_KERNEL);
>>>>>> +	if (unlikely(vi->xattr_shared_xattrs == NULL)) {
>>>>>> +		xattr_iter_end(&it, atomic_map);
>>>>>> +		return -ENOMEM;
>>>>>> +	}
>>>>>>  
>>>>>>  	/* let's skip ibody header */
>>>>>>  	it.ofs += sizeof(struct erofs_xattr_ibody_header);
>>>>>> @@ -79,7 +92,8 @@ static void init_inode_xattrs(struct inode *inode)
>>>>>>  
>>>>>>  			it.page = erofs_get_meta_page_nofail(sb,
>>>>>>  				++it.blkaddr, S_ISDIR(inode->i_mode));
>>>>> Need to use erofs_get_meta_page() instead?
>>>>>
>>>>> Thanks,
>>>> My consideration is for example,
>>>>
>>>> init_inode_xattrs itself can be seen as a part of inode initialization (other fs does it in
>>>> inode initialization, but erofs does it in the first xattr request), if it fail, the only way
>>>> is to retry again...but with more overhead to retry...
>>> I think we can easily return an error to user no matter we encounter -ENOMEM or
>>> -EIO, so erofs_get_meta_page() is enough here, thoughts?
>>>
>> OK, it depends on users (kernel / programs). I think they will simply retry again in the outer loop,
>> which will cause more overhead therefore for inode metadata (not xattrs), I personally tend to retry inside.
> Yes, both are okay, as there is no such restriction in manual or other documents
> saying syscall should success any time, so I think let's take easy to let user
> to handle this condition.
> 
> And one more concern is, for extremely environment, like with very few memory,
> retrying in 'nofail' function, make syscall looks like hanging in kernel side,
> result in apps can not respond to user, that's not a good experience for user.
> 
> Also like f2fs, nofail version function is abused, I think it needs to be
> limited and it's better to be rectified like other filesystem.
> 

Agreed. Thanks for your explainations. :)

Thanks,
Gao Xiang

> Thanks,
> 


More information about the Linux-erofs mailing list