linux/fs/overlayfs
Amir Goldstein 2ca3c148a0 ovl: check lower ancestry on encode of lower dir file handle
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: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2018-02-16 15:53:20 +01:00
..
copy_up.c ovl: copy up of disconnected dentries 2018-01-24 11:25:58 +01:00
dir.c ovl: whiteout index when union nlink drops to zero 2018-01-24 11:25:56 +01:00
export.c ovl: check lower ancestry on encode of lower dir file handle 2018-02-16 15:53:20 +01:00
inode.c ovl: hash non-dir by lower inode for fsnotify 2018-02-16 15:53:20 +01:00
Kconfig ovl: add support for "nfs_export" configuration 2018-01-24 11:25:37 +01:00
Makefile ovl: encode pure upper file handles 2018-01-24 11:25:59 +01:00
namei.c ovl: fix regression in fsnotify of overlay merge dir 2018-02-05 09:50:29 +01:00
overlayfs.h ovl: check lower ancestry on encode of lower dir file handle 2018-02-16 15:53:20 +01:00
ovl_entry.h ovl: store 'has_upper' and 'opaque' as bit flags 2018-01-24 11:25:58 +01:00
readdir.c ovl: whiteout orphan index entries on mount 2018-01-24 11:25:56 +01:00
super.c ovl: check lower ancestry on encode of lower dir file handle 2018-02-16 15:53:20 +01:00
util.c ovl: store 'has_upper' and 'opaque' as bit flags 2018-01-24 11:25:58 +01:00