[Ocfs2-devel] [PATCH] ocfs2: need rollback when journal_access failed in ocfs2_orphan_add()

Younger Liu younger.liu at huawei.com
Wed Jun 19 23:33:22 PDT 2013


Ok, thanks.
I will resent the patch.
On 2013/6/20 13:52, Jeff Liu wrote:
> On 06/20/2013 09:25 AM, Younger Liu wrote:
> 
>> Hi Jeff
>>
>> On 2013/6/19 18:53, Jeff Liu wrote:
>>> Hey Younger,
>>>
>>> On 06/19/2013 04:57 PM, Younger Liu wrote:
>>>
>>>> While adding a file into orphan dir in ocfs2_orphan_add(),
>>>> it calls __ocfs2_add_entry() before ocfs2_journal_access_di(). 
>>>> If ocfs2_journal_access_di() failed, the file is added into 
>>>> orphan dir, and orphan dir dinode updated, but file dinode 
>>>> has not been updated.
>>>> Accordingly, the data is not consistent between file dinode 
>>>> and orphan dir.
>>>>
>>>> So, need to call ocfs2_journal_access_di() before __ocfs2_add_entry(),
>>>> and if ocfs2_journal_access_di() failed, orphan_fe and 
>>>> orphan_dir_inode->i_nlink need rollback.
>>>
>>> Yes, and this has been introduced by commits 3939fda4.
>>
>> I do not find the patch with 3939fda4. Can you tell me the link?
>> Thanks.
>>
>>> Please see my comments below.
>>>
>>>>
>>>> Signed-off-by: Younger Liu <younger.liu at huawei.com>
>>>> ---
>>>>  fs/ocfs2/namei.c |   38 ++++++++++++++++++++++----------------
>>>>  1 file changed, 22 insertions(+), 16 deletions(-)
>>>>
>>>> diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
>>>> index f53471d..f2da854 100644
>>>> --- a/fs/ocfs2/namei.c
>>>> +++ b/fs/ocfs2/namei.c
>>>> @@ -2012,6 +2012,21 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
>>>>  		goto leave;
>>>>  	}
>>>>  
>>>> +	/*
>>>> +	 * We're going to journal the change of i_flags and i_orphaned_slot.
>>>> +	 * It's safe anyway, though some callers may duplicate the journaling.
>>>> +	 * Journaling within the func just make the logic look more
>>>> +	 * straightforward.
>>>> +	 */
>>>> +	status = ocfs2_journal_access_di(handle,
>>>> +					 INODE_CACHE(inode),
>>>> +					 fe_bh,
>>>> +					 OCFS2_JOURNAL_ACCESS_WRITE);
>>>> +	if (status < 0) {
>>>> +		mlog_errno(status);
>>>> +		goto leave;
>>>> +	}
>>>> +
>>>>  	/* we're a cluster, and nlink can change on disk from
>>>>  	 * underneath us... */
>>>>  	orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
>>>> @@ -2026,22 +2041,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
>>>>  				   orphan_dir_bh, lookup);
>>>>  	if (status < 0) {
>>>>  		mlog_errno(status);
>>>> -		goto leave;
>>>> -	}
>>>> -
>>>> -	/*
>>>> -	 * We're going to journal the change of i_flags and i_orphaned_slot.
>>>> -	 * It's safe anyway, though some callers may duplicate the journaling.
>>>> -	 * Journaling within the func just make the logic look more
>>>> -	 * straightforward.
>>>> -	 */
>>>> -	status = ocfs2_journal_access_di(handle,
>>>> -					 INODE_CACHE(inode),
>>>> -					 fe_bh,
>>>> -					 OCFS2_JOURNAL_ACCESS_WRITE);
>>>> -	if (status < 0) {
>>>> -		mlog_errno(status);
>>>> -		goto leave;
>>>> +		goto rollback;
>>>>  	}
>>>>  
>>>>  	fe->i_flags |= cpu_to_le32(OCFS2_ORPHANED_FL);
>>>> @@ -2057,6 +2057,12 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
>>>>  	trace_ocfs2_orphan_add_end((unsigned long long)OCFS2_I(inode)->ip_blkno,
>>>>  				   osb->slot_num);
>>>>  
>>>> +rollback:
>>>> +	if (status < 0 && S_ISDIR(inode->i_mode)) {
>>>
>>> 	              ^^^^ <-- But that might not be a directory, right? :-P
>>> How about the following?
>>>
>>> 	if (status < 0) {
>>> 		if (S_ISDIR(inode->i_mode))
>>> 			ocfs2_add_links_count(orphan_fe, -1);
>>> 		set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe));
>>> 	}
>>>
>>
>> Of course, that may be not a directory. 
>> But if it is not a directory, there is no change for orphan_dir_inode->i_nlink.
>> So, in my opinion, it is not necessary to change orphan_dir_inode->i_nlink.
> 
> 	
> 	if (S_ISDIR(inode->i_mode))
>                 ocfs2_add_links_count(orphan_fe, 1);
>         set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe)); 
> 	^^^^^^^^^
> 		So we set nlink against orphan_dir_inode no matter IS_DIR(inode->i_mode) or not.
>         ocfs2_journal_dirty(handle, orphan_dir_bh);
> 		Any then orphan_dir buffer got dirty.
> 	
> 	if (status < 0 && S_ISDIR(inode->i_mode)) {
> 		In this way, AFAICS the trans rollback can be triggered only if
> 		the target inode is a dir.
> 	}
> 
> 	As a result, should we rollback in case of:
> 	if (status < 0)
> 		set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe));
> 
> Thanks,
> -Jeff
> 
>>
>>>> +			ocfs2_add_links_count(orphan_fe, -1);
>>>> +		set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe));
>>>> +	}
>>>> +
>>>>  leave:
>>>>  	brelse(orphan_dir_bh);
>>>>  
>>>> -- 1.7.9.7 
>>>
>>>
>>> Thanks,
>>> -Jeff
>>>
>>> .
>>>
>>
> 
> 
> 
> .
> 




More information about the Ocfs2-devel mailing list