[RFC 14/19] erofs: introduce fscache support

From: Jeffle Xu
Date: Fri Dec 10 2021 - 02:37:24 EST


This patch only handles the volume cookie and data file cookie for
bootstrap. The corresponding IO path is remained to be implemented in
the following patch.

Signed-off-by: Jeffle Xu <jefflexu@xxxxxxxxxxxxxxxxx>
---
fs/erofs/Makefile | 2 +-
fs/erofs/fscache.c | 37 +++++++++++++++++++++++++++++++++++++
fs/erofs/internal.h | 8 ++++++++
fs/erofs/super.c | 5 +++++
4 files changed, 51 insertions(+), 1 deletion(-)
create mode 100644 fs/erofs/fscache.c

diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile
index 756fe2d65272..f9a3609625aa 100644
--- a/fs/erofs/Makefile
+++ b/fs/erofs/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only

obj-$(CONFIG_EROFS_FS) += erofs.o
-erofs-objs := super.o inode.o data.o namei.o dir.o utils.o pcpubuf.o
+erofs-objs := super.o inode.o data.o namei.o dir.o utils.o pcpubuf.o fscache.o
erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o
erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o
erofs-$(CONFIG_EROFS_FS_ZIP_LZMA) += decompressor_lzma.o
diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c
new file mode 100644
index 000000000000..cf550fdedd1e
--- /dev/null
+++ b/fs/erofs/fscache.c
@@ -0,0 +1,37 @@
+#include "internal.h"
+
+int erofs_fscache_init(struct erofs_sb_info *sbi, char *bootstrap_path)
+{
+ sbi->volume = fscache_acquire_volume("erofs", NULL, 0);
+ if (!sbi->volume) {
+ printk("fscache_acquire_volume() failed\n");
+ return -EINVAL;
+ }
+
+ /*
+ * TODO: @object_size is 0 since erofs can not get size of bootstrap
+ * file.
+ */
+ sbi->bootstrap = fscache_acquire_cookie(sbi->volume, 0,
+ bootstrap_path, strlen(bootstrap_path),
+ NULL, 0,
+ 1 /*TODO: we don't want FSCACHE_COOKIE_NO_DATA_TO_READ set */
+ );
+
+ if (!sbi->bootstrap) {
+ printk("fscache_acquire_cookie() for bootstrap failed\n");
+ /* cleanup for sbi->volume is delayed to erofs_fscache_cleanup() */
+ return -EINVAL;
+ }
+
+ fscache_use_cookie(sbi->bootstrap, false);
+
+ return 0;
+}
+
+void erofs_fscache_cleanup(struct erofs_sb_info *sbi)
+{
+ fscache_unuse_cookie(sbi->bootstrap, NULL, NULL);
+ fscache_relinquish_cookie(sbi->bootstrap, false);
+ fscache_relinquish_volume(sbi->volume, 0, false);
+}
diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index cf69d9c9cbed..8136ec63a9de 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/iomap.h>
+#include <linux/fscache.h>
#include "erofs_fs.h"

/* redefine pr_fmt "erofs: " */
@@ -106,6 +107,9 @@ struct erofs_sb_info {
/* pseudo inode to manage cached pages */
struct inode *managed_cache;

+ struct fscache_volume *volume;
+ struct fscache_cookie *bootstrap;
+
struct erofs_sb_lz4_info lz4;
#endif /* CONFIG_EROFS_FS_ZIP */
struct erofs_dev_context *devs;
@@ -569,6 +573,10 @@ static inline int z_erofs_load_lzma_config(struct super_block *sb,
}
#endif /* !CONFIG_EROFS_FS_ZIP */

+/* fscache.c */
+int erofs_fscache_init(struct erofs_sb_info *sbi, char *bootstrap_path);
+void erofs_fscache_cleanup(struct erofs_sb_info *sbi);
+
#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */

#endif /* __EROFS_INTERNAL_H */
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index 51695f6d4449..f2a5f4cd53fd 100644
--- a/fs/erofs/super.c
+++ b/fs/erofs/super.c
@@ -665,6 +665,10 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
else
sbi->dax_dev = NULL;

+ err = erofs_fscache_init(sbi, ctx->opt.bootstrap_path);
+ if (err)
+ return err;
+
err = erofs_read_superblock(sb);
if (err)
return err;
@@ -823,6 +827,7 @@ static void erofs_kill_sb(struct super_block *sb)

erofs_free_dev_context(sbi->devs);
fs_put_dax(sbi->dax_dev);
+ erofs_fscache_cleanup(sbi);
kfree(sbi);
sb->s_fs_info = NULL;
}
--
2.27.0