• Kent Overstreet's avatar
    bcachefs: bcachefs_metadata_version_inode_has_child_snapshots · 9b23fdbd
    Kent Overstreet authored
    There's an inherent race in taking a snapshot while an unlinked file is
    open, and then reattaching it in the child snapshot.
    
    In the interior snapshot node the file will appear unlinked, as though
    it should be deleted - it's not referenced by anything in that snapshot
    - but we can't delete it, because the file data is referenced by the
    child snapshot.
    
    This was being handled incorrectly with
    propagate_key_to_snapshot_leaves() - but that doesn't resolve the
    fundamental inconsistency of "this file looks like it should be deleted
    according to normal rules, but - ".
    
    To fix this, we need to fix the rule for when an inode is deleted. The
    previous rule, ignoring snapshots (there was no well-defined rule
    for with snapshots) was:
      Unlinked, non open files are deleted, either at recovery time or
      during online fsck
    
    The new rule is:
      Unlinked, non open files, that do not exist in child snapshots, are
      deleted.
    
    To make this work transactionally, we add a new inode flag,
    BCH_INODE_has_child_snapshot; it overrides BCH_INODE_unlinked when
    considering whether to delete an inode, or put it on the deleted list.
    
    For transactional consistency, clearing it handled by the inode trigger:
    when deleting an inode we check if there are parent inodes which can now
    have the BCH_INODE_has_child_snapshot flag cleared.
    Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
    9b23fdbd
fs.c 58 KB