[Ocfs2-devel] [PATCH] ocfs2: need rollback when journal_access failed in ocfs2_orphan_add()
Jeff Liu
jeff.liu at oracle.com
Wed Jun 19 22:52:31 PDT 2013
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