[Ocfs2-devel] [PATCH v1 4/5] ocfs2: ocfs2_mount_volume does cleanup job before return error
Joseph Qi
joseph.qi at linux.alibaba.com
Tue Apr 12 11:54:35 UTC 2022
On 4/12/22 4:22 PM, Heming Zhao wrote:
> My last reply (on 4.10) had messy format, because thunderbird automatically
> add '\r' after '\n'. For easy review, I use neomutt to resend my replay.
> Please check my comments in below.
>
> On Sat, Apr 09, 2022 at 09:46:19PM +0800, Joseph Qi wrote:
>>
>>
>> On 4/8/22 6:30 PM, Heming Zhao wrote:
>>> After this patch, when error, ocfs2_fill_super doesn't take care to
>>> release resources which are allocated in ocfs2_mount_volume.
>>>
>>> Signed-off-by: Heming Zhao <heming.zhao at suse.com>
>>> ---
>>> fs/ocfs2/super.c | 32 ++++++++++++++++++++------------
>>> 1 file changed, 20 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
>>> index 8443ba031dec..d4b7a29cb364 100644
>>> --- a/fs/ocfs2/super.c
>>> +++ b/fs/ocfs2/super.c
>>> @@ -1803,11 +1803,10 @@ static int ocfs2_get_sector(struct super_block *sb,
>>> static int ocfs2_mount_volume(struct super_block *sb)
>>> {
>>> int status = 0;
>>> - int unlock_super = 0;
>>> struct ocfs2_super *osb = OCFS2_SB(sb);
>>>
>>> if (ocfs2_is_hard_readonly(osb))
>>> - goto leave;
>>> + goto out;
>>>
>>> mutex_init(&osb->obs_trim_fs_mutex);
>>>
>>> @@ -1817,44 +1816,53 @@ static int ocfs2_mount_volume(struct super_block *sb)
>>> if (status == -EBADR && ocfs2_userspace_stack(osb))
>>> mlog(ML_ERROR, "couldn't mount because cluster name on"
>>> " disk does not match the running cluster name.\n");
>>> - goto leave;
>>> + goto out;
>>> }
>>>
>>> status = ocfs2_super_lock(osb, 1);
>>> if (status < 0) {
>>> mlog_errno(status);
>>> - goto leave;
>>> + goto out_dlm;
>>> }
>>> - unlock_super = 1;
>>>
>>> /* This will load up the node map and add ourselves to it. */
>>> status = ocfs2_find_slot(osb);
>>> if (status < 0) {
>>> mlog_errno(status);
>>> - goto leave;
>>> + goto out_super_lock;
>>> }
>>>
>>> /* load all node-local system inodes */
>>> status = ocfs2_init_local_system_inodes(osb);
>>> if (status < 0) {
>>> mlog_errno(status);
>>> - goto leave;
>>> + goto out_super_lock;
>>> }
>>>
>>> status = ocfs2_check_volume(osb);
>>> if (status < 0) {
>>> mlog_errno(status);
>>> - goto leave;
>>> + goto out_system_inodes;
>>> }
>>>
>>> status = ocfs2_truncate_log_init(osb);
>>> - if (status < 0)
>>> + if (status < 0) {
>>> mlog_errno(status);
>>> + goto out_journal_shutdown;
>>
>> ocfs2_check_volume() not only does journal initialization,
>> but also local alloc.
>>
>
> I agree and already handled this case. Please read following explanation.
>
> Call flow:
>
> ocfs2_fill_super
> ocfs2_mount_volume
> + ocfs2_init_local_system_inodes //[1]
> + ocfs2_check_volume
> ocfs2_load_local_alloc //may fail
>
> If ocfs2_load_local_alloc fails, only "//local_alloc:%04d" is bad.
> And other alloced inodes (from [1]) still exist.
>
> Also note, the sys inodes release function is ocfs2_release_system_inodes(),
> which could handle both osb->global_system_inodes[] & osb->local_system_inodes[]
> are NULL pointer case.
>
> The cleanup job will be done in both places:
> - ocfs2_mount_volume (patch 4/5)
> - ocfs2_fill_super (patch 5/5)
>
> Related code after patched 4/5:
> (please check my comment start with "hm:")
> ```
> static int ocfs2_mount_volume(struct super_block *sb)
> {
> ... ...
>
> status = ocfs2_check_volume(osb);
> if (status < 0) {
> mlog_errno(status);
>
> //hm:
> //need to release global/local sys inodes (by //ocfs2_release_system_inodes())
> //which are alloced by above [1].
> goto out_system_inodes;
> }
>
> status = ocfs2_truncate_log_init(osb);
> if (status < 0) {
> mlog_errno(status);
>
> //hm:
> //need to release journal: by ocfs2_journal_shutdown()
> //need to release global/local sys inodes: byocfs2_release_system_inodes()
> goto out_journal_shutdown;
> }
>
> ocfs2_super_unlock(osb, 1);
> return status; //<== hm: will change to 0 under next comment
>
> out_journal_shutdown:
> ocfs2_journal_shutdown(osb); //hm: through to label "out_system_inodes".
> out_system_inodes:
> ocfs2_release_system_inodes(osb);
> out_super_lock:
> ocfs2_super_unlock(osb, 1);
> out_dlm:
> ocfs2_dlm_shutdown(osb, 0);
> out:
> return status;
> }
> ```
I mean we may need call ocfs2_shutdown_local_alloc() to do the cleanup.
In ocfs2_fill_super(), you don't do that.
Thanks,
Joseph
More information about the Ocfs2-devel
mailing list