• Amir Goldstein's avatar
    ovl: check lower ancestry on encode of lower dir file handle · 2ca3c148
    Amir Goldstein authored
    This change relaxes copy up on encode of merge dir with lower layer > 1
    and handles the case of encoding a merge dir with lower layer 1, where an
    ancestor is a non-indexed merge dir. In that case, decode of the lower
    file handle will not have been possible if the non-indexed ancestor is
    redirected before or after encode.
    
    Before encoding a non-upper directory file handle from real layer N, we
    need to check if it will be possible to reconnect an overlay dentry from
    the real lower decoded dentry. This is done by following the overlay
    ancestry up to a "layer N connected" ancestor and verifying that all
    parents along the way are "layer N connectable". If an ancestor that is
    NOT "layer N connectable" is found, we need to copy up an ancestor, which
    is "layer N connectable", thus making that ancestor "layer N connected".
    For example:
    
     layer 1: /a
     layer 2: /a/b/c
    
    The overlay dentry /a is NOT "layer 2 connectable", because if dir /a is
    copied up and renamed, upper dir /a will be indexed by lower dir /a from
    layer 1. The dir /a from layer 2 will never be indexed, so the algorithm
    in ovl_lookup_real_ancestor() (*) will not be able to lookup a connected
    overlay dentry from the connected lower dentry /a/b/c.
    
    To avoid this problem on decode time, we need to copy up an ancestor of
    /a/b/c, which is "layer 2 connectable", on encode time. That ancestor is
    /a/b. After copy up (and index) of /a/b, it will become "layer 2 connected"
    and when the time comes to decode the file handle from lower dentry /a/b/c,
    ovl_lookup_real_ancestor() will find the indexed ancestor /a/b and decoding
    a connected overlay dentry will be accomplished.
    
    (*) the algorithm in ovl_lookup_real_ancestor() can be improved to lookup
    an entry /a in the lower layers above layer N and find the indexed dir /a
    from layer 1. If that improvement is made, then the check for "layer N
    connected" will need to verify there are no redirects in lower layers above
    layer N. In the example above, /a will be "layer 2 connectable". However,
    if layer 2 dir /a is a target of a layer 1 redirect, then /a will NOT be
    "layer 2 connectable":
    
     layer 1: /A (redirect = /a)
     layer 2: /a/b/c
    Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
    Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
    2ca3c148
export.c 21.7 KB