On asynchronous base filesystems like NFS, eCryptFS leaves inodes for
deleted files in the cache until unmounting. Change call in
ecryptfs_do_unlink() from set_nlink() to drop_nlink() in order to reliably
evict inodes from the cache even on top of NFS.
Signed-off-by: Dan Robertson <[email protected]>
Signed-off-by: Jeffrey Mitchell <[email protected]>
---
fs/ecryptfs/inode.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index e23752d..f7594b6 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -147,7 +147,7 @@ static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry,
goto out_unlock;
}
fsstack_copy_attr_times(dir, lower_dir_inode);
- set_nlink(inode, ecryptfs_inode_to_lower(inode)->i_nlink);
+ drop_nlink(inode);
inode->i_ctime = dir->i_ctime;
out_unlock:
dput(lower_dentry);
--
2.7.4
Steps to reproduce issue:
Mount nfs
Inside the nfs mount, create back and front directories for ecryptfs
Use ecryptfs to mount one directory onto the other
Create a few files inside the ecryptfs mount
Set ftrace to monitor ecryptfs_do_unlink() and ecryptfs_evict_inode()
Delete files
Unmount ecryptfs
ftrace output before patch:
# tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
1) | /* Tracing enabled */
1) | /* Writing to files */
1) | /* Unlinking first file */
0) * 27804.34 us | ecryptfs_do_unlink();
1) | /* rm'ing second file */
------------------------------------------
0) unlink-1384 => rm-1385
------------------------------------------
0) * 32828.63 us | ecryptfs_do_unlink();
1) | /* Unmounting eCryptFS */
------------------------------------------
1) trace-a-1365 => umount-1387
------------------------------------------
1) 2.408 us | ecryptfs_evict_inode();
1) 8.914 us | ecryptfs_evict_inode();
1) 3.344 us | ecryptfs_evict_inode();
ftrace output after patch:
# tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
0) | /* Tracing enabled */
0) | /* Writing to files */
0) | /* Unlinking first file */
1) * 24728.81 us | ecryptfs_do_unlink();
1) + 20.923 us | ecryptfs_evict_inode();
0) | /* rm'ing second file */
------------------------------------------
1) unlink-1333 => rm-1334
------------------------------------------
1) * 41093.71 us | ecryptfs_do_unlink();
1) + 11.384 us | ecryptfs_evict_inode();
0) | /* Unmounting eCryptFS */
------------------------------------------
0) trace-a-1314 => umount-1336
------------------------------------------
0) 2.986 us | ecryptfs_evict_inode();
On Fri, May 08, 2020 at 09:31:33AM -0500, Jeffrey Mitchell wrote:
> On asynchronous base filesystems like NFS, eCryptFS leaves inodes for
> deleted files in the cache until unmounting. Change call in
> ecryptfs_do_unlink() from set_nlink() to drop_nlink() in order to reliably
> evict inodes from the cache even on top of NFS.
>
> Signed-off-by: Dan Robertson <[email protected]>
> Signed-off-by: Jeffrey Mitchell <[email protected]>
> ---
> fs/ecryptfs/inode.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
> index e23752d..f7594b6 100644
> --- a/fs/ecryptfs/inode.c
> +++ b/fs/ecryptfs/inode.c
> @@ -147,7 +147,7 @@ static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry,
> goto out_unlock;
> }
> fsstack_copy_attr_times(dir, lower_dir_inode);
> - set_nlink(inode, ecryptfs_inode_to_lower(inode)->i_nlink);
> + drop_nlink(inode);
> inode->i_ctime = dir->i_ctime;
> out_unlock:
> dput(lower_dentry);
> --
> 2.7.4
>