Hi Alex, Sorry for this late reply. A little busy these days :) I have to admit this patch sucks. It makes related procedure vague and probably pollutes current code.
So I decide to compose anchor one to fix via a elegant way. Once the test for the new patch fixing this dio issue is done, I will post it. Thanks, Changwei On 2017/12/22 20:25, alex chen wrote: > Hi Changwei, > > On 2017/12/22 14:41, Changwei Ge wrote: >> A crash issue was reported by John. >> >> The call trace follows: >> ocfs2_split_extent+0x1ad3/0x1b40 [ocfs2] >> ocfs2_change_extent_flag+0x33a/0x470 [ocfs2] >> ocfs2_mark_extent_written+0x172/0x220 [ocfs2] >> ocfs2_dio_end_io+0x62d/0x910 [ocfs2] >> dio_complete+0x19a/0x1a0 >> do_blockdev_direct_IO+0x19dd/0x1eb0 >> __blockdev_direct_IO+0x43/0x50 >> ocfs2_direct_IO+0x8f/0xa0 [ocfs2] >> generic_file_direct_write+0xb2/0x170 >> __generic_file_write_iter+0xc3/0x1b0 >> ocfs2_file_write_iter+0x4bb/0xca0 [ocfs2] >> __vfs_write+0xae/0xf0 >> vfs_write+0xb8/0x1b0 >> SyS_write+0x4f/0xb0 >> system_call_fastpath+0x16/0x75 >> >> The BUG code told that extent tree wants to grow but no metadata >> was reserved ahead of time. >> From my investigation into this issue, the root cause it that although >> enough metadata is reserved, rightmost extent is merged into left one >> due to a certain times of marking extent written. Because during marking >> extent written, we got many physically continuous extents. At last, an >> empty extent showed up and the rightmost path is removed from extent tree. >> >> In order to solve this issue, introduce a member named ::et_lock for extent >> tree. When ocfs2_lock_allocators is invoked and we indeed need to reserve >> metadata, set ::et_lock so that the rightmost path won't be removed during >> marking extents written. >> >> Also, this patch address the issue John reported that ::dw_zero_count is >> not calculated properly. >> >> After applying this patch, the issue John reported was gone. >> Thanks to the reproducer provided by John. >> And this patch has passed ocfs2-test suite running by New H3C Group. >> >> Reported-by: John Lightsey <j...@nixnuts.net> >> Signed-off-by: Changwei Ge <ge.chang...@h3c.com> >> --- >> fs/ocfs2/alloc.c | 4 +++- >> fs/ocfs2/alloc.h | 1 + >> fs/ocfs2/aops.c | 8 +++++--- >> fs/ocfs2/suballoc.c | 3 +++ >> 4 files changed, 12 insertions(+), 4 deletions(-) >> >> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c >> index ab5105f..160e393 100644 >> --- a/fs/ocfs2/alloc.c >> +++ b/fs/ocfs2/alloc.c >> @@ -444,6 +444,7 @@ static void __ocfs2_init_extent_tree(struct >> ocfs2_extent_tree *et, >> et->et_ops = ops; >> et->et_root_bh = bh; >> et->et_ci = ci; >> + et->et_lock = 0; >> et->et_root_journal_access = access; >> if (!obj) >> obj = (void *)bh->b_data; >> @@ -3606,7 +3607,8 @@ static int ocfs2_merge_rec_left(struct ocfs2_path >> *right_path, >> * it and we need to delete the right extent block. >> */ >> if (le16_to_cpu(right_rec->e_leaf_clusters) == 0 && >> - le16_to_cpu(el->l_next_free_rec) == 1) { >> + le16_to_cpu(el->l_next_free_rec) == 1 && >> + !et->et_lock) { >> /* extend credit for ocfs2_remove_rightmost_path */ >> ret = ocfs2_extend_rotate_transaction(handle, 0, >> handle->h_buffer_credits, > If we don't remove the rightmost path when we are splitting extents, when we > should do it? > Does this break the balance of the extent tree? > >> diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h >> index 27b75cf..898671d 100644 >> --- a/fs/ocfs2/alloc.h >> +++ b/fs/ocfs2/alloc.h >> @@ -61,6 +61,7 @@ struct ocfs2_extent_tree { >> ocfs2_journal_access_func et_root_journal_access; >> void *et_object; >> unsigned int et_max_leaf_clusters; >> + int et_lock; >> }; >> >> /* >> diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c >> index d151632..c72ce60 100644 >> --- a/fs/ocfs2/aops.c >> +++ b/fs/ocfs2/aops.c >> @@ -797,6 +797,7 @@ struct ocfs2_write_ctxt { >> struct ocfs2_cached_dealloc_ctxt w_dealloc; >> >> struct list_head w_unwritten_list; >> + unsigned int w_unwritten_count; >> }; >> >> void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages) >> @@ -1386,6 +1387,7 @@ static int ocfs2_unwritten_check(struct inode *inode, >> desc->c_clear_unwritten = 0; >> list_add_tail(&new->ue_ip_node, &oi->ip_unwritten_list); >> list_add_tail(&new->ue_node, &wc->w_unwritten_list); >> + wc->w_unwritten_count++; >> new = NULL; >> unlock: >> spin_unlock(&oi->ip_lock); >> @@ -1762,8 +1764,8 @@ int ocfs2_write_begin_nolock(struct address_space >> *mapping, >> */ >> ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), >> wc->w_di_bh); >> - ret = ocfs2_lock_allocators(inode, &et, >> - clusters_to_alloc, extents_to_split, >> + ret = ocfs2_lock_allocators(inode, &et, clusters_to_alloc, >> + 2*extents_to_split, >> &data_ac, &meta_ac); >> if (ret) { >> mlog_errno(ret); >> @@ -2256,7 +2258,7 @@ static int ocfs2_dio_wr_get_block(struct inode *inode, >> sector_t iblock, >> ue->ue_phys = desc->c_phys; >> >> list_splice_tail_init(&wc->w_unwritten_list, >> &dwc->dw_zero_list); >> - dwc->dw_zero_count++; >> + dwc->dw_zero_count += wc->w_unwritten_count; >> } >> >> ret = ocfs2_write_end_nolock(inode->i_mapping, pos, len, len, wc); >> diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c >> index 9f0b95a..32bc38e 100644 >> --- a/fs/ocfs2/suballoc.c >> +++ b/fs/ocfs2/suballoc.c >> @@ -2727,6 +2727,9 @@ int ocfs2_lock_allocators(struct inode *inode, >> } >> } >> >> + if (extents_to_split) >> + et->et_lock = 1; >> + > If we remove the xattr cluster we need to split the extent in > ocfs2_rm_xattr_cluster() and > why we should not remove the rightmost path? > Can we use the extents_to_split to identify we are marking extent written? > > Thanks, > Alex > >> if (clusters_to_add == 0) >> goto out; >> >> > > _______________________________________________ Ocfs2-devel mailing list Ocfs2-devel@oss.oracle.com https://oss.oracle.com/mailman/listinfo/ocfs2-devel