• Filipe Manana's avatar
    Btrfs: send, fix invalid path after renaming and linking file · 72c3668f
    Filipe Manana authored
    Currently an incremental snapshot can generate link operations which
    contain an invalid target path. Such case happens when in the send
    snapshot a file was renamed, a new hard link added for it and some
    other inode (with a lower number) got renamed to the former name of
    that file. Example:
    
    Parent snapshot
    
     .                  (ino 256)
     |
     |--- f1            (ino 257)
     |--- f2            (ino 258)
     |--- f3            (ino 259)
    
    Send snapshot
    
     .                  (ino 256)
     |
     |--- f2            (ino 257)
     |--- f3            (ino 258)
     |--- f4            (ino 259)
     |--- f5            (ino 258)
    
    The following steps happen when computing the incremental send stream:
    
    1) When processing inode 257, inode 258 is orphanized (renamed to
       "o258-7-0"), because its current reference has the same name as the
       new reference for inode 257;
    
    2) When processing inode 258, we iterate over all its new references,
       which have the names "f3" and "f5". The first iteration sees name
       "f5" and renames the inode from its orphan name ("o258-7-0") to
       "f5", while the second iteration sees the name "f3" and, incorrectly,
       issues a link operation with a target name matching the orphan name,
       which no longer exists. The first iteration had reset the current
       valid path of the inode to "f5", but in the second iteration we lost
       it because we found another inode, with a higher number of 259, which
       has a reference named "f3" as well, so we orphanized inode 259 and
       recomputed the current valid path of inode 258 to its old orphan
       name because inode 259 could be an ancestor of inode 258 and therefore
       the current valid path could contain the pre-orphanization name of
       inode 259. However in this case inode 259 is not an ancestor of inode
       258 so the current valid path should not be recomputed.
       This makes the receiver fail with the following error:
    
       ERROR: link f3 -> o258-7-0 failed: No such file or directory
    
    So fix this by not recomputing the current valid path for an inode
    whenever we find a colliding reference from some not yet processed inode
    (inode number higher then the one currently being processed), unless
    that other inode is an ancestor of the one we are currently processing.
    
    A test case for fstests will follow soon.
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    72c3668f
send.c 156 KB