Overlayfs forwards data I/O to the real (upper/lower) file, so the page
cache lives in the real inode's mapping and cachestat() on an overlay
fd returned all zeroes.

Implement the ->cachestat() file operation by forwarding to the real
file via vfs_cachestat(), the same way ovl_fadvise() forwards
for fadvise.

Signed-off-by: Pavel Tikhomirov <[email protected]>
---
 fs/overlayfs/file.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
index 27cc07738f33b..a7e252a91ea43 100644
--- a/fs/overlayfs/file.c
+++ b/fs/overlayfs/file.c
@@ -518,6 +518,21 @@ static int ovl_fadvise(struct file *file, loff_t offset, 
loff_t len, int advice)
                return vfs_fadvise(realfile, offset, len, advice);
 }
 
+#ifdef CONFIG_CACHESTAT_SYSCALL
+static int ovl_cachestat(struct file *file, struct cachestat_range *csr,
+                        struct cachestat *cs)
+{
+       struct file *realfile;
+
+       realfile = ovl_real_file(file);
+       if (IS_ERR(realfile))
+               return PTR_ERR(realfile);
+
+       with_ovl_creds(file_inode(file)->i_sb)
+               return vfs_cachestat(realfile, csr, cs);
+}
+#endif
+
 enum ovl_copyop {
        OVL_COPY,
        OVL_CLONE,
@@ -642,6 +657,9 @@ const struct file_operations ovl_file_operations = {
        .mmap           = ovl_mmap,
        .fallocate      = ovl_fallocate,
        .fadvise        = ovl_fadvise,
+#ifdef CONFIG_CACHESTAT_SYSCALL
+       .cachestat      = ovl_cachestat,
+#endif
        .flush          = ovl_flush,
        .splice_read    = ovl_splice_read,
        .splice_write   = ovl_splice_write,
-- 
2.54.0


Reply via email to