Hi Jeff, On Wed, Sep 07, 2016 at 10:25:54AM -0400, Jeff Mahoney wrote: > On 9/6/16 5:51 PM, Liu Bo wrote: > > Hi Filipe, > > > > On Mon, Sep 05, 2016 at 04:28:09PM +0100, Filipe Manana wrote: > >> On Fri, Sep 2, 2016 at 8:35 PM, Liu Bo <bo.li....@oracle.com> wrote: > >>> This can only happen with CONFIG_BTRFS_FS_CHECK_INTEGRITY=y. > >>> > >>> Commit 1ba98d0 ("Btrfs: detect corruption when non-root leaf has zero > >>> item") > >>> assumes that a leaf is its root when leaf->bytenr == > >>> btrfs_root_bytenr(root), > >>> however, we should not use btrfs_root_bytenr(root) since it's mainly got > >>> updated during committing transaction. So the check can fail when doing > >>> COW on this leaf while it is a root. > >>> > >>> This changes to use "if (leaf == btrfs_root_node(root))" instead, just > >>> like > >>> how we check whether leaf is a root in __btrfs_cow_block(). > >>> > >>> Reported-by: Jeff Mahoney <je...@suse.com> > >>> Signed-off-by: Liu Bo <bo.li....@oracle.com> > >> > >> Hi Bo, > >> > >> Even with this patch applied against latest branch for-linus-4.8, at > >> least on a build with CONFIG_BTRFS_FS_CHECK_INTEGRITY=y, > >> the issue still happens for me when running fsstress with balance in > >> parallel: > > > > Thanks for the report. > > > > This panic shows that we can have non-root btree leaf with 0 nritems during > > split_leaf(), but a btrfs_search_slot which calls split_leaf() like this is > > inserting an item, and while we set @right's nritems to 0, we also assign > > @disk_key > > associated with @right in the parent node, so I think we're actually having > > nritem 0 temporarily and we can remove this btrfs_mark_buffer_dirty() like > > the > > following quick patch. > > > > Thanks, > > > > -liubo > > > > diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c > > index d1c56c9..5e5ceb5 100644 > > --- a/fs/btrfs/ctree.c > > +++ b/fs/btrfs/ctree.c > > @@ -4341,7 +4341,11 @@ again: > > if (path->slots[1] == 0) > > fixup_low_keys(fs_info, path, &disk_key, 1); > > } > > - btrfs_mark_buffer_dirty(right); > > + /* > > + * We create a new leaf 'right' for the required ins_len and > > + * we'll do btrfs_mark_buffer_dirty() on this leaf after copying > > + * the content of ins_len to 'right'. > > + */ > > return ret; > > } > > > > > > > > I think you're on the right track here. I need to see if I still have > the code lying around, but when I was debugging the btrfs_rename issue > that ended up being a compiler bug, I hooked into check_leaf and ran > into similar issues. We mark the buffer dirty before it's in a > consistent state.
That's right. One thing that I'm not 100% sure is that if there is a chance that this metadata leaf gets flushed by writeback throttle code and we panic after it so that we get a 'nritem 0 non-root' leaf, no? But anyway, even if we have it, we'd know it by the newly added check in check_leaf. Thanks, -liubo -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html