Introduce one anonymous inode for managing page cache of corresponding
blob file. Then erofs could read directly from the address space of the
anonymous inode when cache hit.

Signed-off-by: Jeffle Xu <jeffl...@linux.alibaba.com>
---
 fs/erofs/fscache.c  | 45 ++++++++++++++++++++++++++++++++++++++++++---
 fs/erofs/internal.h |  3 ++-
 2 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c
index c043d7709d65..3addd9aa549c 100644
--- a/fs/erofs/fscache.c
+++ b/fs/erofs/fscache.c
@@ -6,6 +6,9 @@
 
 static struct fscache_volume *volume;
 
+static const struct address_space_operations erofs_fscache_blob_aops = {
+};
+
 static int erofs_fscache_init_cookie(struct erofs_fscache_context *ctx,
                                     char *path)
 {
@@ -36,8 +39,34 @@ void erofs_fscache_cleanup_cookie(struct 
erofs_fscache_context *ctx)
        ctx->cookie = NULL;
 }
 
+static int erofs_fscache_get_inode(struct erofs_fscache_context *ctx,
+                                  struct super_block *sb)
+{
+       struct inode *const inode = new_inode(sb);
+
+       if (!inode)
+               return -ENOMEM;
+
+       set_nlink(inode, 1);
+       inode->i_size = OFFSET_MAX;
+
+       inode->i_mapping->a_ops = &erofs_fscache_blob_aops;
+       mapping_set_gfp_mask(inode->i_mapping,
+                       GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE);
+       ctx->inode = inode;
+       return 0;
+}
+
+static inline
+void erofs_fscache_put_inode(struct erofs_fscache_context *ctx)
+{
+       iput(ctx->inode);
+       ctx->inode = NULL;
+}
+
 static int erofs_fscache_init_ctx(struct erofs_fscache_context *ctx,
-                                 struct super_block *sb, char *path)
+                                 struct super_block *sb, char *path,
+                                 bool need_inode)
 {
        int ret;
 
@@ -47,6 +76,15 @@ static int erofs_fscache_init_ctx(struct 
erofs_fscache_context *ctx,
                return ret;
        }
 
+       if (need_inode) {
+               ret = erofs_fscache_get_inode(ctx, sb);
+               if (ret) {
+                       erofs_err(sb, "failed to get anonymous inode");
+                       erofs_fscache_cleanup_cookie(ctx);
+                       return ret;
+               }
+       }
+
        return 0;
 }
 
@@ -54,10 +92,11 @@ static inline
 void erofs_fscache_cleanup_ctx(struct erofs_fscache_context *ctx)
 {
        erofs_fscache_cleanup_cookie(ctx);
+       erofs_fscache_put_inode(ctx);
 }
 
 struct erofs_fscache_context *erofs_fscache_get_ctx(struct super_block *sb,
-                                               char *path)
+                                               char *path, bool need_inode)
 {
        struct erofs_fscache_context *ctx;
        int ret;
@@ -66,7 +105,7 @@ struct erofs_fscache_context *erofs_fscache_get_ctx(struct 
super_block *sb,
        if (!ctx)
                return ERR_PTR(-ENOMEM);
 
-       ret = erofs_fscache_init_ctx(ctx, sb, path);
+       ret = erofs_fscache_init_ctx(ctx, sb, path, need_inode);
        if (ret) {
                kfree(ctx);
                return ERR_PTR(ret);
diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 1f5bc69e8e9f..bb5e992fe0df 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -99,6 +99,7 @@ struct erofs_sb_lz4_info {
 
 struct erofs_fscache_context {
        struct fscache_cookie *cookie;
+       struct inode *inode;
 };
 
 struct erofs_sb_info {
@@ -626,7 +627,7 @@ int erofs_init_fscache(void);
 void erofs_exit_fscache(void);
 
 struct erofs_fscache_context *erofs_fscache_get_ctx(struct super_block *sb,
-                                               char *path);
+                                               char *path, bool need_inode);
 void erofs_fscache_put_ctx(struct erofs_fscache_context *ctx);
 
 #define EFSCORRUPTED    EUCLEAN         /* Filesystem is corrupted */
-- 
2.27.0

--
Linux-cachefs mailing list
Linux-cachefs@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-cachefs

Reply via email to