| From foo@baz Mon Apr 9 17:09:24 CEST 2018 |
| From: Amir Goldstein <amir73il@gmail.com> |
| Date: Mon, 24 Apr 2017 19:54:13 +0300 |
| Subject: ovl: persistent inode numbers for upper hardlinks |
| |
| From: Amir Goldstein <amir73il@gmail.com> |
| |
| |
| [ Upstream commit 5b6c9053fb38a66fd5c6177fcf5022b24767811a ] |
| |
| An upper type non directory dentry that is a copy up target |
| should have a reference to its lower copy up origin. |
| |
| There are three ways for an upper type dentry to be instantiated: |
| 1. A lower type dentry that is being copied up |
| 2. An entry that is found in upper dir by ovl_lookup() |
| 3. A negative dentry is hardlinked to an upper type dentry |
| |
| In the first case, the lower reference is set before copy up. |
| In the second case, the lower reference is found by ovl_lookup(). |
| In the last case of hardlinked upper dentry, it is not easy to |
| update the lower reference of the negative dentry. Instead, |
| drop the newly hardlinked negative dentry from dcache and let |
| the next access call ovl_lookup() to find its lower reference. |
| |
| This makes sure that the inode number reported by stat(2) after |
| the hardlink is created is the same inode number that will be |
| reported by stat(2) after mount cycle, which is the inode number |
| of the lower copy up origin of the hardlink source. |
| |
| NOTE that this does not fix breaking of lower hardlinks on copy |
| up, but only fixes the case of lower nlink == 1, whose upper copy |
| up inode is hardlinked in upper dir. |
| |
| Signed-off-by: Amir Goldstein <amir73il@gmail.com> |
| Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/overlayfs/dir.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| --- a/fs/overlayfs/dir.c |
| +++ b/fs/overlayfs/dir.c |
| @@ -180,6 +180,9 @@ static void ovl_instantiate(struct dentr |
| inc_nlink(inode); |
| } |
| d_instantiate(dentry, inode); |
| + /* Force lookup of new upper hardlink to find its lower */ |
| + if (hardlink) |
| + d_drop(dentry); |
| } |
| |
| static int ovl_create_upper(struct dentry *dentry, struct inode *inode, |