• Dave Chinner's avatar
    libxfs: directory node splitting does not have an extra block · 160ae76f
    Dave Chinner authored
    xfsprogs source commit 4280e59dcbc4cd8e01585efe788a68eb378048e8
    
    xfs_da3_split() has to handle all three versions of the
    directory/attribute btree structure. The attr tree is v1, the dir
    tre is v2 or v3. The main difference between the v1 and v2/3 trees
    is the way tree nodes are split - in the v1 tree we can require a
    double split to occur because the object to be inserted may be
    larger than the space made by splitting a leaf. In this case we need
    to do a double split - one to split the full leaf, then another to
    allocate an empty leaf block in the correct location for the new
    entry.  This does not happen with dir (v2/v3) formats as the objects
    being inserted are always guaranteed to fit into the new space in
    the split blocks.
    
    Indeed, for directories they *may* be an extra block on this buffer
    pointer. However, it's guaranteed not to be a leaf block (i.e. a
    directory data block) - the directory code only ever places hash
    index or free space blocks in this pointer (as a cursor of
    sorts), and so to use it as a directory data block will immediately
    corrupt the directory.
    
    The problem is that the code assumes that there may be extra blocks
    that we need to link into the tree once we've split the root, but
    this is not true for either dir or attr trees, because the extra
    attr block is always consumed by the last node split before we split
    the root. Hence the linking in an extra block is always wrong at the
    root split level, and this manifests itself in repair as a directory
    corruption in a repaired directory, leaving the directory rebuild
    incomplete.
    
    This is a dir v2 zero-day bug - it was in the initial dir v2 commit
    that was made back in February 1998.
    
    Fix this by ensuring the linking of the blocks after the root split
    never tries to make use of the extra blocks that may be held in the
    cursor. They are held there for other purposes and should never be
    touched by the root splitting code.
    Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
    Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
    Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
    Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
    
    160ae76f
xfs_da_btree.c 70.1 KB