ocfs2: return -EROFS to upper if inode block is invalid
diff mbox

Message ID 5A41AFE2.5010506@huawei.com
State New
Headers show

Commit Message

piaojun Dec. 26, 2017, 2:11 a.m. UTC
If metadata is corrupted such as 'invalid inode block', we will get
failed by calling 'mount()' as below:

ocfs2_mount
  ocfs2_initialize_super
    ocfs2_init_global_system_inodes : return -EINVAL if inode is NULL
      ocfs2_get_system_file_inode
        _ocfs2_get_system_file_inode : return NULL if inode is errno
          ocfs2_iget
            ocfs2_read_locked_inode
              ocfs2_validate_inode_block

In this situation we need return -EROFS to upper application, so that
user can fix it by fsck. And then mount again.

Signed-off-by: Jun Piao <piaojun@huawei.com>
Reviewed-by: Alex Chen <alex.chen@huawei.com>
---
 fs/ocfs2/super.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

Comments

Gang He Dec. 26, 2017, 2:22 a.m. UTC | #1
Hi Piaojun,

Just one quick question, if the file system is read-only, this can make ocfs2_get_system_file_inode() function invoke failure?
If ture, I think this code change make sense.

Thanks
Gang



>>> 
> If metadata is corrupted such as 'invalid inode block', we will get
> failed by calling 'mount()' as below:
> 
> ocfs2_mount
>   ocfs2_initialize_super
>     ocfs2_init_global_system_inodes : return -EINVAL if inode is NULL
>       ocfs2_get_system_file_inode
>         _ocfs2_get_system_file_inode : return NULL if inode is errno
>           ocfs2_iget
>             ocfs2_read_locked_inode
>               ocfs2_validate_inode_block
> 
> In this situation we need return -EROFS to upper application, so that
> user can fix it by fsck. And then mount again.
> 
> Signed-off-by: Jun Piao <piaojun@huawei.com>
> Reviewed-by: Alex Chen <alex.chen@huawei.com>
> ---
>  fs/ocfs2/super.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
> index 040bbb6..dea21a7 100644
> --- a/fs/ocfs2/super.c
> +++ b/fs/ocfs2/super.c
> @@ -474,7 +474,10 @@ static int ocfs2_init_global_system_inodes(struct 
> ocfs2_super *osb)
>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>  		if (!new) {
>  			ocfs2_release_system_inodes(osb);
> -			status = -EINVAL;
> +			if (ocfs2_is_soft_readonly(osb))
> +				status = -EROFS;
> +			else
> +				status = -EINVAL;
>  			mlog_errno(status);
>  			/* FIXME: Should ERROR_RO_FS */
>  			mlog(ML_ERROR, "Unable to load system inode %d, "
> @@ -505,7 +508,10 @@ static int ocfs2_init_local_system_inodes(struct 
> ocfs2_super *osb)
>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>  		if (!new) {
>  			ocfs2_release_system_inodes(osb);
> -			status = -EINVAL;
> +			if (ocfs2_is_soft_readonly(osb))
> +				status = -EROFS;
> +			else
> +				status = -EINVAL;
>  			mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
>  			     status, i, osb->slot_num);
>  			goto bail;
> -- 
> 
> _______________________________________________
> Ocfs2-devel mailing list
> Ocfs2-devel@oss.oracle.com 
> https://oss.oracle.com/mailman/listinfo/ocfs2-devel
piaojun Dec. 26, 2017, 2:31 a.m. UTC | #2
Hi Gang,

Just like the dumped stack below, ocfs2_validate_inode_block() will
find out 'invalid inode' and then return error to upper callers. At
last invoke failure of ocfs2_get_system_file_inode().

thanks,
Jun

On 2017/12/26 10:22, Gang He wrote:
> Hi Piaojun,
> 
> Just one quick question, if the file system is read-only, this can make ocfs2_get_system_file_inode() function invoke failure?
> If ture, I think this code change make sense.
> 
> Thanks
> Gang
> 
> 
> 
>>>>
>> If metadata is corrupted such as 'invalid inode block', we will get
>> failed by calling 'mount()' as below:
>>
>> ocfs2_mount
>>   ocfs2_initialize_super
>>     ocfs2_init_global_system_inodes : return -EINVAL if inode is NULL
>>       ocfs2_get_system_file_inode
>>         _ocfs2_get_system_file_inode : return NULL if inode is errno
>>           ocfs2_iget
>>             ocfs2_read_locked_inode
>>               ocfs2_validate_inode_block
>>
>> In this situation we need return -EROFS to upper application, so that
>> user can fix it by fsck. And then mount again.
>>
>> Signed-off-by: Jun Piao <piaojun@huawei.com>
>> Reviewed-by: Alex Chen <alex.chen@huawei.com>
>> ---
>>  fs/ocfs2/super.c | 10 ++++++++--
>>  1 file changed, 8 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
>> index 040bbb6..dea21a7 100644
>> --- a/fs/ocfs2/super.c
>> +++ b/fs/ocfs2/super.c
>> @@ -474,7 +474,10 @@ static int ocfs2_init_global_system_inodes(struct 
>> ocfs2_super *osb)
>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>  		if (!new) {
>>  			ocfs2_release_system_inodes(osb);
>> -			status = -EINVAL;
>> +			if (ocfs2_is_soft_readonly(osb))
>> +				status = -EROFS;
>> +			else
>> +				status = -EINVAL;
>>  			mlog_errno(status);
>>  			/* FIXME: Should ERROR_RO_FS */
>>  			mlog(ML_ERROR, "Unable to load system inode %d, "
>> @@ -505,7 +508,10 @@ static int ocfs2_init_local_system_inodes(struct 
>> ocfs2_super *osb)
>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>  		if (!new) {
>>  			ocfs2_release_system_inodes(osb);
>> -			status = -EINVAL;
>> +			if (ocfs2_is_soft_readonly(osb))
>> +				status = -EROFS;
>> +			else
>> +				status = -EINVAL;
>>  			mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
>>  			     status, i, osb->slot_num);
>>  			goto bail;
>> -- 
>>
>> _______________________________________________
>> Ocfs2-devel mailing list
>> Ocfs2-devel@oss.oracle.com 
>> https://oss.oracle.com/mailman/listinfo/ocfs2-devel
> 
> .
>
Joseph Qi Dec. 26, 2017, 3:05 a.m. UTC | #3
On 17/12/26 10:11, piaojun wrote:
> If metadata is corrupted such as 'invalid inode block', we will get
> failed by calling 'mount()' as below:
> 
> ocfs2_mount
>   ocfs2_initialize_super
>     ocfs2_init_global_system_inodes : return -EINVAL if inode is NULL
>       ocfs2_get_system_file_inode
>         _ocfs2_get_system_file_inode : return NULL if inode is errno
Do you mean inode is bad?

>           ocfs2_iget
>             ocfs2_read_locked_inode
>               ocfs2_validate_inode_block
> 
> In this situation we need return -EROFS to upper application, so that
> user can fix it by fsck. And then mount again.
> 
> Signed-off-by: Jun Piao <piaojun@huawei.com>
> Reviewed-by: Alex Chen <alex.chen@huawei.com>
> ---
>  fs/ocfs2/super.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
> index 040bbb6..dea21a7 100644
> --- a/fs/ocfs2/super.c
> +++ b/fs/ocfs2/super.c
> @@ -474,7 +474,10 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>  		if (!new) {
>  			ocfs2_release_system_inodes(osb);
> -			status = -EINVAL;
> +			if (ocfs2_is_soft_readonly(osb))
I'm afraid that having bad inode doesn't means ocfs2 is readonly.
And the calling application is mount.ocfs2. So do you mean mount.ocfs2
have to handle EROFS like printing corresponding error log?

> +				status = -EROFS;
> +			else
> +				status = -EINVAL;
>  			mlog_errno(status);
>  			/* FIXME: Should ERROR_RO_FS */
>  			mlog(ML_ERROR, "Unable to load system inode %d, "
> @@ -505,7 +508,10 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>  		if (!new) {
>  			ocfs2_release_system_inodes(osb);
> -			status = -EINVAL;
> +			if (ocfs2_is_soft_readonly(osb))
> +				status = -EROFS;
> +			else
> +				status = -EINVAL;
>  			mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
>  			     status, i, osb->slot_num);
>  			goto bail;
>
Changwei Ge Dec. 26, 2017, 3:34 a.m. UTC | #4
Hi Jun,

What I concern is if we don't return -EROFS to mount.ocfs2, what bad result will come?
This patch is a bug fix or something else?
Can you elaborate your intention of this patch?

Thanks,
Changwei

On 2017/12/26 10:14, piaojun wrote:
> If metadata is corrupted such as 'invalid inode block', we will get
> failed by calling 'mount()' as below:
> 
> ocfs2_mount
>    ocfs2_initialize_super
>      ocfs2_init_global_system_inodes : return -EINVAL if inode is NULL
>        ocfs2_get_system_file_inode
>          _ocfs2_get_system_file_inode : return NULL if inode is errno
>            ocfs2_iget
>              ocfs2_read_locked_inode
>                ocfs2_validate_inode_block
> 
> In this situation we need return -EROFS to upper application, so that
> user can fix it by fsck. And then mount again.
> 
> Signed-off-by: Jun Piao <piaojun@huawei.com>
> Reviewed-by: Alex Chen <alex.chen@huawei.com>
> ---
>   fs/ocfs2/super.c | 10 ++++++++--
>   1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
> index 040bbb6..dea21a7 100644
> --- a/fs/ocfs2/super.c
> +++ b/fs/ocfs2/super.c
> @@ -474,7 +474,10 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
>   		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>   		if (!new) {
>   			ocfs2_release_system_inodes(osb);
> -			status = -EINVAL;
> +			if (ocfs2_is_soft_readonly(osb))
> +				status = -EROFS;
> +			else
> +				status = -EINVAL;
>   			mlog_errno(status);
>   			/* FIXME: Should ERROR_RO_FS */
>   			mlog(ML_ERROR, "Unable to load system inode %d, "
> @@ -505,7 +508,10 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
>   		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>   		if (!new) {
>   			ocfs2_release_system_inodes(osb);
> -			status = -EINVAL;
> +			if (ocfs2_is_soft_readonly(osb))
> +				status = -EROFS;
> +			else
> +				status = -EINVAL;
>   			mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
>   			     status, i, osb->slot_num);
>   			goto bail;
>
piaojun Dec. 26, 2017, 5:35 a.m. UTC | #5
Hi Joseph,

On 2017/12/26 11:05, Joseph Qi wrote:
> 
> 
> On 17/12/26 10:11, piaojun wrote:
>> If metadata is corrupted such as 'invalid inode block', we will get
>> failed by calling 'mount()' as below:
>>
>> ocfs2_mount
>>   ocfs2_initialize_super
>>     ocfs2_init_global_system_inodes : return -EINVAL if inode is NULL
>>       ocfs2_get_system_file_inode
>>         _ocfs2_get_system_file_inode : return NULL if inode is errno
> Do you mean inode is bad?
> 
Here we have to face two abnormal cases:
1. inode is bad;
2. read inode from disk failed due to bad storage link.
>>           ocfs2_iget
>>             ocfs2_read_locked_inode
>>               ocfs2_validate_inode_block
>>
>> In this situation we need return -EROFS to upper application, so that
>> user can fix it by fsck. And then mount again.
>>
>> Signed-off-by: Jun Piao <piaojun@huawei.com>
>> Reviewed-by: Alex Chen <alex.chen@huawei.com>
>> ---
>>  fs/ocfs2/super.c | 10 ++++++++--
>>  1 file changed, 8 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
>> index 040bbb6..dea21a7 100644
>> --- a/fs/ocfs2/super.c
>> +++ b/fs/ocfs2/super.c
>> @@ -474,7 +474,10 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>  		if (!new) {
>>  			ocfs2_release_system_inodes(osb);
>> -			status = -EINVAL;
>> +			if (ocfs2_is_soft_readonly(osb))
> I'm afraid that having bad inode doesn't means ocfs2 is readonly.
> And the calling application is mount.ocfs2. So do you mean mount.ocfs2
> have to handle EROFS like printing corresponding error log?
> 
I agree that 'bad inode' also means other abnormal cases like
'bad storage link' or 'no memory', but we can distinguish that by
ocfs2_is_soft_readonly(). I found that 'mount.ocfs2' did not
distinguish any error type and just return 1 for all error cases. I
wonder if we should return the exact errno for users?

thanks,
Jun

>> +				status = -EROFS;
>> +			else
>> +				status = -EINVAL;
>>  			mlog_errno(status);
>>  			/* FIXME: Should ERROR_RO_FS */
>>  			mlog(ML_ERROR, "Unable to load system inode %d, "
>> @@ -505,7 +508,10 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>  		if (!new) {
>>  			ocfs2_release_system_inodes(osb);
>> -			status = -EINVAL;
>> +			if (ocfs2_is_soft_readonly(osb))
>> +				status = -EROFS;
>> +			else
>> +				status = -EINVAL;
>>  			mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
>>  			     status, i, osb->slot_num);
>>  			goto bail;
>>
> .
>
piaojun Dec. 26, 2017, 5:41 a.m. UTC | #6
Hi Changwei,

I just want to return exact errno to users so that they can fix
read-only problem rather than doing meaningless retry.

thanks,
Jun

On 2017/12/26 11:34, Changwei Ge wrote:
> Hi Jun,
> 
> What I concern is if we don't return -EROFS to mount.ocfs2, what bad result will come?
> This patch is a bug fix or something else?
> Can you elaborate your intention of this patch?
> 
> Thanks,
> Changwei
> 
> On 2017/12/26 10:14, piaojun wrote:
>> If metadata is corrupted such as 'invalid inode block', we will get
>> failed by calling 'mount()' as below:
>>
>> ocfs2_mount
>>    ocfs2_initialize_super
>>      ocfs2_init_global_system_inodes : return -EINVAL if inode is NULL
>>        ocfs2_get_system_file_inode
>>          _ocfs2_get_system_file_inode : return NULL if inode is errno
>>            ocfs2_iget
>>              ocfs2_read_locked_inode
>>                ocfs2_validate_inode_block
>>
>> In this situation we need return -EROFS to upper application, so that
>> user can fix it by fsck. And then mount again.
>>
>> Signed-off-by: Jun Piao <piaojun@huawei.com>
>> Reviewed-by: Alex Chen <alex.chen@huawei.com>
>> ---
>>   fs/ocfs2/super.c | 10 ++++++++--
>>   1 file changed, 8 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
>> index 040bbb6..dea21a7 100644
>> --- a/fs/ocfs2/super.c
>> +++ b/fs/ocfs2/super.c
>> @@ -474,7 +474,10 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
>>   		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>   		if (!new) {
>>   			ocfs2_release_system_inodes(osb);
>> -			status = -EINVAL;
>> +			if (ocfs2_is_soft_readonly(osb))
>> +				status = -EROFS;
>> +			else
>> +				status = -EINVAL;
>>   			mlog_errno(status);
>>   			/* FIXME: Should ERROR_RO_FS */
>>   			mlog(ML_ERROR, "Unable to load system inode %d, "
>> @@ -505,7 +508,10 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
>>   		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>   		if (!new) {
>>   			ocfs2_release_system_inodes(osb);
>> -			status = -EINVAL;
>> +			if (ocfs2_is_soft_readonly(osb))
>> +				status = -EROFS;
>> +			else
>> +				status = -EINVAL;
>>   			mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
>>   			     status, i, osb->slot_num);
>>   			goto bail;
>>
> 
> .
>
Joseph Qi Dec. 26, 2017, 6:10 a.m. UTC | #7
On 17/12/26 13:35, piaojun wrote:
> Hi Joseph,
> 
> On 2017/12/26 11:05, Joseph Qi wrote:
>>
>>
>> On 17/12/26 10:11, piaojun wrote:
>>> If metadata is corrupted such as 'invalid inode block', we will get
>>> failed by calling 'mount()' as below:
>>>
>>> ocfs2_mount
>>>   ocfs2_initialize_super
>>>     ocfs2_init_global_system_inodes : return -EINVAL if inode is NULL
>>>       ocfs2_get_system_file_inode
>>>         _ocfs2_get_system_file_inode : return NULL if inode is errno
>> Do you mean inode is bad?
>>
> Here we have to face two abnormal cases:
> 1. inode is bad;
> 2. read inode from disk failed due to bad storage link.
>>>           ocfs2_iget
>>>             ocfs2_read_locked_inode
>>>               ocfs2_validate_inode_block
>>>
>>> In this situation we need return -EROFS to upper application, so that
>>> user can fix it by fsck. And then mount again.
>>>
>>> Signed-off-by: Jun Piao <piaojun@huawei.com>
>>> Reviewed-by: Alex Chen <alex.chen@huawei.com>
>>> ---
>>>  fs/ocfs2/super.c | 10 ++++++++--
>>>  1 file changed, 8 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
>>> index 040bbb6..dea21a7 100644
>>> --- a/fs/ocfs2/super.c
>>> +++ b/fs/ocfs2/super.c
>>> @@ -474,7 +474,10 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
>>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>>  		if (!new) {
>>>  			ocfs2_release_system_inodes(osb);
>>> -			status = -EINVAL;
>>> +			if (ocfs2_is_soft_readonly(osb))
>> I'm afraid that having bad inode doesn't means ocfs2 is readonly.
>> And the calling application is mount.ocfs2. So do you mean mount.ocfs2
>> have to handle EROFS like printing corresponding error log?
>>
> I agree that 'bad inode' also means other abnormal cases like
> 'bad storage link' or 'no memory', but we can distinguish that by
> ocfs2_is_soft_readonly(). I found that 'mount.ocfs2' did not
> distinguish any error type and just return 1 for all error cases. I
> wonder if we should return the exact errno for users?
> Soft readonly is an in-memory status. The case you described is just
trying to read inode and then check if it is bad. So where to set the
status before?

> thanks,
> Jun
> 
>>> +				status = -EROFS;
>>> +			else
>>> +				status = -EINVAL;
>>>  			mlog_errno(status);
>>>  			/* FIXME: Should ERROR_RO_FS */
>>>  			mlog(ML_ERROR, "Unable to load system inode %d, "
>>> @@ -505,7 +508,10 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
>>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>>  		if (!new) {
>>>  			ocfs2_release_system_inodes(osb);
>>> -			status = -EINVAL;
>>> +			if (ocfs2_is_soft_readonly(osb))
>>> +				status = -EROFS;
>>> +			else
>>> +				status = -EINVAL;
>>>  			mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
>>>  			     status, i, osb->slot_num);
>>>  			goto bail;
>>>
>> .
>>
piaojun Dec. 26, 2017, 6:45 a.m. UTC | #8
Hi Joseph,

On 2017/12/26 14:10, Joseph Qi wrote:
> 
> 
> On 17/12/26 13:35, piaojun wrote:
>> Hi Joseph,
>>
>> On 2017/12/26 11:05, Joseph Qi wrote:
>>>
>>>
>>> On 17/12/26 10:11, piaojun wrote:
>>>> If metadata is corrupted such as 'invalid inode block', we will get
>>>> failed by calling 'mount()' as below:
>>>>
>>>> ocfs2_mount
>>>>   ocfs2_initialize_super
>>>>     ocfs2_init_global_system_inodes : return -EINVAL if inode is NULL
>>>>       ocfs2_get_system_file_inode
>>>>         _ocfs2_get_system_file_inode : return NULL if inode is errno
>>> Do you mean inode is bad?
>>>
>> Here we have to face two abnormal cases:
>> 1. inode is bad;
>> 2. read inode from disk failed due to bad storage link.
>>>>           ocfs2_iget
>>>>             ocfs2_read_locked_inode
>>>>               ocfs2_validate_inode_block
>>>>
>>>> In this situation we need return -EROFS to upper application, so that
>>>> user can fix it by fsck. And then mount again.
>>>>
>>>> Signed-off-by: Jun Piao <piaojun@huawei.com>
>>>> Reviewed-by: Alex Chen <alex.chen@huawei.com>
>>>> ---
>>>>  fs/ocfs2/super.c | 10 ++++++++--
>>>>  1 file changed, 8 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
>>>> index 040bbb6..dea21a7 100644
>>>> --- a/fs/ocfs2/super.c
>>>> +++ b/fs/ocfs2/super.c
>>>> @@ -474,7 +474,10 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
>>>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>>>  		if (!new) {
>>>>  			ocfs2_release_system_inodes(osb);
>>>> -			status = -EINVAL;
>>>> +			if (ocfs2_is_soft_readonly(osb))
>>> I'm afraid that having bad inode doesn't means ocfs2 is readonly.
>>> And the calling application is mount.ocfs2. So do you mean mount.ocfs2
>>> have to handle EROFS like printing corresponding error log?
>>>
>> I agree that 'bad inode' also means other abnormal cases like
>> 'bad storage link' or 'no memory', but we can distinguish that by
>> ocfs2_is_soft_readonly(). I found that 'mount.ocfs2' did not
>> distinguish any error type and just return 1 for all error cases. I
>> wonder if we should return the exact errno for users?
>> Soft readonly is an in-memory status. The case you described is just
> trying to read inode and then check if it is bad. So where to set the
> status before?
> 
we set readonly status in the following process:
ocfs2_validate_inode_block()
  ocfs2_error
    ocfs2_handle_error
      ocfs2_set_ro_flag(osb, 0);

I have a suggestion that we could distinguish readonly status in
'mount.ocfs2', and return -EROFS to users so that they can fix it.
>> thanks,
>> Jun
>>
>>>> +				status = -EROFS;
>>>> +			else
>>>> +				status = -EINVAL;
>>>>  			mlog_errno(status);
>>>>  			/* FIXME: Should ERROR_RO_FS */
>>>>  			mlog(ML_ERROR, "Unable to load system inode %d, "
>>>> @@ -505,7 +508,10 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
>>>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>>>  		if (!new) {
>>>>  			ocfs2_release_system_inodes(osb);
>>>> -			status = -EINVAL;
>>>> +			if (ocfs2_is_soft_readonly(osb))
>>>> +				status = -EROFS;
>>>> +			else
>>>> +				status = -EINVAL;
>>>>  			mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
>>>>  			     status, i, osb->slot_num);
>>>>  			goto bail;
>>>>
>>> .
>>>
> .
>
Joseph Qi Dec. 26, 2017, 6:59 a.m. UTC | #9
On 17/12/26 14:45, piaojun wrote:
> Hi Joseph,
> 
> On 2017/12/26 14:10, Joseph Qi wrote:
>>
>>
>> On 17/12/26 13:35, piaojun wrote:
>>> Hi Joseph,
>>>
>>> On 2017/12/26 11:05, Joseph Qi wrote:
>>>>
>>>>
>>>> On 17/12/26 10:11, piaojun wrote:
>>>>> If metadata is corrupted such as 'invalid inode block', we will get
>>>>> failed by calling 'mount()' as below:
>>>>>
>>>>> ocfs2_mount
>>>>>   ocfs2_initialize_super
>>>>>     ocfs2_init_global_system_inodes : return -EINVAL if inode is NULL
>>>>>       ocfs2_get_system_file_inode
>>>>>         _ocfs2_get_system_file_inode : return NULL if inode is errno
>>>> Do you mean inode is bad?
>>>>
>>> Here we have to face two abnormal cases:
>>> 1. inode is bad;
>>> 2. read inode from disk failed due to bad storage link.
>>>>>           ocfs2_iget
>>>>>             ocfs2_read_locked_inode
>>>>>               ocfs2_validate_inode_block
>>>>>
>>>>> In this situation we need return -EROFS to upper application, so that
>>>>> user can fix it by fsck. And then mount again.
>>>>>
>>>>> Signed-off-by: Jun Piao <piaojun@huawei.com>
>>>>> Reviewed-by: Alex Chen <alex.chen@huawei.com>
>>>>> ---
>>>>>  fs/ocfs2/super.c | 10 ++++++++--
>>>>>  1 file changed, 8 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
>>>>> index 040bbb6..dea21a7 100644
>>>>> --- a/fs/ocfs2/super.c
>>>>> +++ b/fs/ocfs2/super.c
>>>>> @@ -474,7 +474,10 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
>>>>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>>>>  		if (!new) {
>>>>>  			ocfs2_release_system_inodes(osb);
>>>>> -			status = -EINVAL;
>>>>> +			if (ocfs2_is_soft_readonly(osb))
>>>> I'm afraid that having bad inode doesn't means ocfs2 is readonly.
>>>> And the calling application is mount.ocfs2. So do you mean mount.ocfs2
>>>> have to handle EROFS like printing corresponding error log?
>>>>
>>> I agree that 'bad inode' also means other abnormal cases like
>>> 'bad storage link' or 'no memory', but we can distinguish that by
>>> ocfs2_is_soft_readonly(). I found that 'mount.ocfs2' did not
>>> distinguish any error type and just return 1 for all error cases. I
>>> wonder if we should return the exact errno for users?
>>> Soft readonly is an in-memory status. The case you described is just
>> trying to read inode and then check if it is bad. So where to set the
>> status before?
>>
> we set readonly status in the following process:
> ocfs2_validate_inode_block()
>   ocfs2_error
>     ocfs2_handle_error
>       ocfs2_set_ro_flag(osb, 0);
> 
> I have a suggestion that we could distinguish readonly status in
> 'mount.ocfs2', and return -EROFS to users so that they can fix it.
IC. Please update this information to patch description as well.
And suggest just use ternary operator instead of if/else.
BTW, so mount.ocfs2 should be updated correspondingly, right?

Thanks,
Joseph
>>> thanks,
>>> Jun
>>>
>>>>> +				status = -EROFS;
>>>>> +			else
>>>>> +				status = -EINVAL;
>>>>>  			mlog_errno(status);
>>>>>  			/* FIXME: Should ERROR_RO_FS */
>>>>>  			mlog(ML_ERROR, "Unable to load system inode %d, "
>>>>> @@ -505,7 +508,10 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
>>>>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>>>>  		if (!new) {
>>>>>  			ocfs2_release_system_inodes(osb);
>>>>> -			status = -EINVAL;
>>>>> +			if (ocfs2_is_soft_readonly(osb))
>>>>> +				status = -EROFS;
>>>>> +			else
>>>>> +				status = -EINVAL;
>>>>>  			mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
>>>>>  			     status, i, osb->slot_num);
>>>>>  			goto bail;
>>>>>
>>>> .
>>>>
>> .
>>
piaojun Dec. 26, 2017, 7:05 a.m. UTC | #10
Hi Joseph,

On 2017/12/26 14:59, Joseph Qi wrote:
> 
> 
> On 17/12/26 14:45, piaojun wrote:
>> Hi Joseph,
>>
>> On 2017/12/26 14:10, Joseph Qi wrote:
>>>
>>>
>>> On 17/12/26 13:35, piaojun wrote:
>>>> Hi Joseph,
>>>>
>>>> On 2017/12/26 11:05, Joseph Qi wrote:
>>>>>
>>>>>
>>>>> On 17/12/26 10:11, piaojun wrote:
>>>>>> If metadata is corrupted such as 'invalid inode block', we will get
>>>>>> failed by calling 'mount()' as below:
>>>>>>
>>>>>> ocfs2_mount
>>>>>>   ocfs2_initialize_super
>>>>>>     ocfs2_init_global_system_inodes : return -EINVAL if inode is NULL
>>>>>>       ocfs2_get_system_file_inode
>>>>>>         _ocfs2_get_system_file_inode : return NULL if inode is errno
>>>>> Do you mean inode is bad?
>>>>>
>>>> Here we have to face two abnormal cases:
>>>> 1. inode is bad;
>>>> 2. read inode from disk failed due to bad storage link.
>>>>>>           ocfs2_iget
>>>>>>             ocfs2_read_locked_inode
>>>>>>               ocfs2_validate_inode_block
>>>>>>
>>>>>> In this situation we need return -EROFS to upper application, so that
>>>>>> user can fix it by fsck. And then mount again.
>>>>>>
>>>>>> Signed-off-by: Jun Piao <piaojun@huawei.com>
>>>>>> Reviewed-by: Alex Chen <alex.chen@huawei.com>
>>>>>> ---
>>>>>>  fs/ocfs2/super.c | 10 ++++++++--
>>>>>>  1 file changed, 8 insertions(+), 2 deletions(-)
>>>>>>
>>>>>> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
>>>>>> index 040bbb6..dea21a7 100644
>>>>>> --- a/fs/ocfs2/super.c
>>>>>> +++ b/fs/ocfs2/super.c
>>>>>> @@ -474,7 +474,10 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
>>>>>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>>>>>  		if (!new) {
>>>>>>  			ocfs2_release_system_inodes(osb);
>>>>>> -			status = -EINVAL;
>>>>>> +			if (ocfs2_is_soft_readonly(osb))
>>>>> I'm afraid that having bad inode doesn't means ocfs2 is readonly.
>>>>> And the calling application is mount.ocfs2. So do you mean mount.ocfs2
>>>>> have to handle EROFS like printing corresponding error log?
>>>>>
>>>> I agree that 'bad inode' also means other abnormal cases like
>>>> 'bad storage link' or 'no memory', but we can distinguish that by
>>>> ocfs2_is_soft_readonly(). I found that 'mount.ocfs2' did not
>>>> distinguish any error type and just return 1 for all error cases. I
>>>> wonder if we should return the exact errno for users?
>>>> Soft readonly is an in-memory status. The case you described is just
>>> trying to read inode and then check if it is bad. So where to set the
>>> status before?
>>>
>> we set readonly status in the following process:
>> ocfs2_validate_inode_block()
>>   ocfs2_error
>>     ocfs2_handle_error
>>       ocfs2_set_ro_flag(osb, 0);
>>
>> I have a suggestion that we could distinguish readonly status in
>> 'mount.ocfs2', and return -EROFS to users so that they can fix it.
> IC. Please update this information to patch description as well.
> And suggest just use ternary operator instead of if/else.
> BTW, so mount.ocfs2 should be updated correspondingly, right?
> 
> Thanks,
> Joseph

Thanks for your advices, and I will post a patch for mount.ocfs2
correspondingly.

>>>> thanks,
>>>> Jun
>>>>
>>>>>> +				status = -EROFS;
>>>>>> +			else
>>>>>> +				status = -EINVAL;
>>>>>>  			mlog_errno(status);
>>>>>>  			/* FIXME: Should ERROR_RO_FS */
>>>>>>  			mlog(ML_ERROR, "Unable to load system inode %d, "
>>>>>> @@ -505,7 +508,10 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
>>>>>>  		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
>>>>>>  		if (!new) {
>>>>>>  			ocfs2_release_system_inodes(osb);
>>>>>> -			status = -EINVAL;
>>>>>> +			if (ocfs2_is_soft_readonly(osb))
>>>>>> +				status = -EROFS;
>>>>>> +			else
>>>>>> +				status = -EINVAL;
>>>>>>  			mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
>>>>>>  			     status, i, osb->slot_num);
>>>>>>  			goto bail;
>>>>>>
>>>>> .
>>>>>
>>> .
>>>
> .
>

Patch
diff mbox

diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 040bbb6..dea21a7 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -474,7 +474,10 @@  static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
 		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
 		if (!new) {
 			ocfs2_release_system_inodes(osb);
-			status = -EINVAL;
+			if (ocfs2_is_soft_readonly(osb))
+				status = -EROFS;
+			else
+				status = -EINVAL;
 			mlog_errno(status);
 			/* FIXME: Should ERROR_RO_FS */
 			mlog(ML_ERROR, "Unable to load system inode %d, "
@@ -505,7 +508,10 @@  static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
 		new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
 		if (!new) {
 			ocfs2_release_system_inodes(osb);
-			status = -EINVAL;
+			if (ocfs2_is_soft_readonly(osb))
+				status = -EROFS;
+			else
+				status = -EINVAL;
 			mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
 			     status, i, osb->slot_num);
 			goto bail;