[RFC PATCH 3/3] erofs: add rust options

Yiyang Wu toolmanp at tlmp.cc
Thu Aug 8 04:47:03 AEST 2024


This commit adds rust option in Kconfig. Note that currently when enabling
rust support, all extended features are disabled only basic operations
are supported.

Signed-off-by: Yiyang Wu <toolmanp at tlmp.cc>
---
 fs/erofs/Kconfig    |  11 +++
 fs/erofs/Makefile   |   1 +
 fs/erofs/data.c     |  83 +++++++++++++----
 fs/erofs/dir.c      |  20 +++-
 fs/erofs/inode.c    |  51 ++++++----
 fs/erofs/internal.h |   3 +
 fs/erofs/namei.c    |  30 ++++--
 fs/erofs/super.c    | 223 ++++++++++++++++++++++++++++++++------------
 8 files changed, 312 insertions(+), 110 deletions(-)

diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig
index 7dcdce660cac..46702df0b3d8 100644
--- a/fs/erofs/Kconfig
+++ b/fs/erofs/Kconfig
@@ -158,3 +158,14 @@ config EROFS_FS_PCPU_KTHREAD_HIPRI
 	  at higher priority.
 
 	  If unsure, say N.
+
+config EROFS_FS_RUST
+	bool "EROFS use RUST Replacement (EXPERIMENTAL)"
+	depends on EROFS_FS && RUST && !EROFS_FS_ZIP && !EROFS_FS_ONDEMAND && !EROFS_FS_XATTR
+	default n
+	help
+	  This permits EROFS to use EXPERIMENTAL rust implementation for
+	  EROFS. This is highly unstable and buggy and should be considered
+	  as an experimental feature only.
+
+	  IF SURE, say Y.
diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile
index 097d672e6b14..a6e4f7f4d570 100644
--- a/fs/erofs/Makefile
+++ b/fs/erofs/Makefile
@@ -8,3 +8,4 @@ erofs-$(CONFIG_EROFS_FS_ZIP_LZMA) += decompressor_lzma.o
 erofs-$(CONFIG_EROFS_FS_ZIP_DEFLATE) += decompressor_deflate.o
 erofs-$(CONFIG_EROFS_FS_ZIP_ZSTD) += decompressor_zstd.o
 erofs-$(CONFIG_EROFS_FS_ONDEMAND) += fscache.o
+erofs-$(CONFIG_EROFS_FS_RUST) += erofs_rust_helper.o erofs_rust.o
diff --git a/fs/erofs/data.c b/fs/erofs/data.c
index 1b7eba38ba1e..b45660112fd9 100644
--- a/fs/erofs/data.c
+++ b/fs/erofs/data.c
@@ -4,6 +4,10 @@
  *             https://www.huawei.com/
  * Copyright (C) 2021, Alibaba Cloud
  */
+
+#ifdef CONFIG_EROFS_FS_RUST
+#include "erofs_rust_bindings.h"
+#endif
 #include "internal.h"
 #include <linux/sched/mm.h>
 #include <trace/events/erofs.h>
@@ -189,6 +193,8 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
 	return err;
 }
 
+#ifndef CONFIG_EROFS_FS_RUST
+
 int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
 {
 	struct erofs_dev_context *devs = EROFS_SB(sb)->devs;
@@ -230,8 +236,10 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
 			if (map->m_pa >= startoff &&
 			    map->m_pa < startoff + length) {
 				map->m_pa -= startoff;
-				map->m_bdev = dif->bdev_file ?
-					      file_bdev(dif->bdev_file) : NULL;
+				map->m_bdev =
+					dif->bdev_file ?
+						file_bdev(dif->bdev_file) :
+						NULL;
 				map->m_daxdev = dif->dax_dev;
 				map->m_dax_part_off = dif->dax_part_off;
 				map->m_fscache = dif->fscache;
@@ -244,7 +252,8 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
 }
 
 static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
-		unsigned int flags, struct iomap *iomap, struct iomap *srcmap)
+			     unsigned int flags, struct iomap *iomap,
+			     struct iomap *srcmap)
 {
 	int ret;
 	struct super_block *sb = inode->i_sb;
@@ -258,7 +267,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
 	if (ret < 0)
 		return ret;
 
-	mdev = (struct erofs_map_dev) {
+	mdev = (struct erofs_map_dev){
 		.m_deviceid = map.m_deviceid,
 		.m_pa = map.m_pa,
 	};
@@ -303,7 +312,8 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
 }
 
 static int erofs_iomap_end(struct inode *inode, loff_t pos, loff_t length,
-		ssize_t written, unsigned int flags, struct iomap *iomap)
+			   ssize_t written, unsigned int flags,
+			   struct iomap *iomap)
 {
 	void *ptr = iomap->private;
 
@@ -322,6 +332,45 @@ static int erofs_iomap_end(struct inode *inode, loff_t pos, loff_t length,
 	return written;
 }
 
+#else
+
+static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
+			     unsigned int flags, struct iomap *iomap,
+			     struct iomap *srcmap)
+{
+	struct erofs_rust_map m;
+	m.m_la = offset;
+	erofs_iomap_begin_rust(inode, &m);
+
+	iomap->bdev = inode->i_sb->s_bdev;
+	iomap->flags = 0;
+	iomap->offset = m.m_la;
+	iomap->length = m.m_llen;
+
+	if (m.inline_data != NULL) {
+		iomap->type = IOMAP_INLINE;
+		iomap->inline_data = m.inline_data;
+		iomap->private = m.private;
+	} else {
+		iomap->type = IOMAP_MAPPED;
+		iomap->addr = m.m_pa;
+		iomap->private = NULL;
+	}
+	return 0;
+}
+
+static int erofs_iomap_end(struct inode *inode, loff_t pos, loff_t length,
+			   ssize_t written, unsigned int flags,
+			   struct iomap *iomap)
+{
+	struct erofs_rust_map m = {
+		.private = iomap->private,
+	};
+	erofs_iomap_end_rust(&m);
+	return written;
+}
+#endif
+
 static const struct iomap_ops erofs_iomap_ops = {
 	.iomap_begin = erofs_iomap_begin,
 	.iomap_end = erofs_iomap_end,
@@ -382,11 +431,12 @@ static ssize_t erofs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
 			blksize_mask = i_blocksize(inode) - 1;
 
 		if ((iocb->ki_pos | iov_iter_count(to) |
-		     iov_iter_alignment(to)) & blksize_mask)
+		     iov_iter_alignment(to)) &
+		    blksize_mask)
 			return -EINVAL;
 
-		return iomap_dio_rw(iocb, to, &erofs_iomap_ops,
-				    NULL, 0, NULL, 0);
+		return iomap_dio_rw(iocb, to, &erofs_iomap_ops, NULL, 0, NULL,
+				    0);
 	}
 	return filemap_read(iocb, to, 0);
 }
@@ -402,8 +452,7 @@ const struct address_space_operations erofs_raw_access_aops = {
 };
 
 #ifdef CONFIG_FS_DAX
-static vm_fault_t erofs_dax_huge_fault(struct vm_fault *vmf,
-		unsigned int order)
+static vm_fault_t erofs_dax_huge_fault(struct vm_fault *vmf, unsigned int order)
 {
 	return dax_iomap_fault(vmf, order, NULL, NULL, &erofs_iomap_ops);
 }
@@ -414,8 +463,8 @@ static vm_fault_t erofs_dax_fault(struct vm_fault *vmf)
 }
 
 static const struct vm_operations_struct erofs_dax_vm_ops = {
-	.fault		= erofs_dax_fault,
-	.huge_fault	= erofs_dax_huge_fault,
+	.fault = erofs_dax_fault,
+	.huge_fault = erofs_dax_huge_fault,
 };
 
 static int erofs_file_mmap(struct file *file, struct vm_area_struct *vma)
@@ -431,13 +480,13 @@ static int erofs_file_mmap(struct file *file, struct vm_area_struct *vma)
 	return 0;
 }
 #else
-#define erofs_file_mmap	generic_file_readonly_mmap
+#define erofs_file_mmap generic_file_readonly_mmap
 #endif
 
 const struct file_operations erofs_file_fops = {
-	.llseek		= generic_file_llseek,
-	.read_iter	= erofs_file_read_iter,
-	.mmap		= erofs_file_mmap,
+	.llseek = generic_file_llseek,
+	.read_iter = erofs_file_read_iter,
+	.mmap = erofs_file_mmap,
 	.get_unmapped_area = thp_get_unmapped_area,
-	.splice_read	= filemap_splice_read,
+	.splice_read = filemap_splice_read,
 };
diff --git a/fs/erofs/dir.c b/fs/erofs/dir.c
index c3b90abdee37..b91e26181f5b 100644
--- a/fs/erofs/dir.c
+++ b/fs/erofs/dir.c
@@ -4,8 +4,15 @@
  *             https://www.huawei.com/
  * Copyright (C) 2022, Alibaba Cloud
  */
+
+#ifdef CONFIG_EROFS_FS_RUST
+#include "erofs_rust_bindings.h"
+#endif
+
 #include "internal.h"
 
+#ifndef CONFIG_EROFS_FS_RUST
+
 static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx,
 			       void *dentry_blk, struct erofs_dirent *de,
 			       unsigned int nameoff0, unsigned int maxsize)
@@ -93,8 +100,15 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
 	return err < 0 ? err : 0;
 }
 
+#endif
+
 const struct file_operations erofs_dir_fops = {
-	.llseek		= generic_file_llseek,
-	.read		= generic_read_dir,
-	.iterate_shared	= erofs_readdir,
+	.llseek = generic_file_llseek,
+	.read = generic_read_dir,
+#ifdef CONFIG_EROFS_FS_RUST
+	.iterate_shared = erofs_readdir_rust,
+#else
+
+	.iterate_shared = erofs_readdir,
+#endif
 };
diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c
index 43c09aae2afc..22a9b5b24c31 100644
--- a/fs/erofs/inode.c
+++ b/fs/erofs/inode.c
@@ -8,8 +8,8 @@
 
 #include <trace/events/erofs.h>
 
-static void *erofs_read_inode(struct erofs_buf *buf,
-			      struct inode *inode, unsigned int *ofs)
+static void *erofs_read_inode(struct erofs_buf *buf, struct inode *inode,
+			      unsigned int *ofs)
 {
 	struct super_block *sb = inode->i_sb;
 	struct erofs_sb_info *sbi = EROFS_SB(sb);
@@ -36,8 +36,8 @@ static void *erofs_read_inode(struct erofs_buf *buf,
 	dic = kaddr + *ofs;
 	ifmt = le16_to_cpu(dic->i_format);
 	if (ifmt & ~EROFS_I_ALL) {
-		erofs_err(sb, "unsupported i_format %u of nid %llu",
-			  ifmt, vi->nid);
+		erofs_err(sb, "unsupported i_format %u of nid %llu", ifmt,
+			  vi->nid);
 		err = -EOPNOTSUPP;
 		goto err_out;
 	}
@@ -66,11 +66,14 @@ static void *erofs_read_inode(struct erofs_buf *buf,
 				goto err_out;
 			}
 			memcpy(copied, dic, gotten);
-			kaddr = erofs_read_metabuf(buf, sb, erofs_pos(sb, blkaddr + 1),
+			kaddr = erofs_read_metabuf(buf, sb,
+						   erofs_pos(sb, blkaddr + 1),
 						   EROFS_KMAP);
 			if (IS_ERR(kaddr)) {
-				erofs_err(sb, "failed to get inode payload block (nid: %llu), err %ld",
-					  vi->nid, PTR_ERR(kaddr));
+				erofs_err(
+					sb,
+					"failed to get inode payload block (nid: %llu), err %ld",
+					vi->nid, PTR_ERR(kaddr));
 				kfree(copied);
 				return kaddr;
 			}
@@ -105,11 +108,11 @@ static void *erofs_read_inode(struct erofs_buf *buf,
 		set_nlink(inode, le16_to_cpu(dic->i_nlink));
 		/* use build time for compact inodes */
 		inode_set_ctime(inode, sbi->build_time, sbi->build_time_nsec);
-
 		inode->i_size = le32_to_cpu(dic->i_size);
 		break;
 	default:
-		erofs_err(sb, "unsupported on-disk inode version %u of nid %llu",
+		erofs_err(sb,
+			  "unsupported on-disk inode version %u of nid %llu",
 			  erofs_inode_version(ifmt), vi->nid);
 		err = -EOPNOTSUPP;
 		goto err_out;
@@ -148,11 +151,12 @@ static void *erofs_read_inode(struct erofs_buf *buf,
 			err = -EOPNOTSUPP;
 			goto err_out;
 		}
-		vi->chunkbits = sb->s_blocksize_bits +
+		vi->chunkbits =
+			sb->s_blocksize_bits +
 			(vi->chunkformat & EROFS_CHUNK_FORMAT_BLKBITS_MASK);
 	}
-	inode_set_mtime_to_ts(inode,
-			      inode_set_atime_to_ts(inode, inode_get_ctime(inode)));
+	inode_set_mtime_to_ts(
+		inode, inode_set_atime_to_ts(inode, inode_get_ctime(inode)));
 
 	inode->i_flags &= ~S_DAX;
 	if (test_opt(&sbi->opt, DAX_ALWAYS) && S_ISREG(inode->i_mode) &&
@@ -182,8 +186,8 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr,
 	char *lnk;
 
 	/* if it cannot be handled with fast symlink scheme */
-	if (vi->datalayout != EROFS_INODE_FLAT_INLINE ||
-	    inode->i_size >= bsz || inode->i_size < 0) {
+	if (vi->datalayout != EROFS_INODE_FLAT_INLINE || inode->i_size >= bsz ||
+	    inode->i_size < 0) {
 		inode->i_op = &erofs_symlink_iops;
 		return 0;
 	}
@@ -226,6 +230,7 @@ static int erofs_fill_inode(struct inode *inode)
 		return PTR_ERR(kaddr);
 
 	/* setup the new inode */
+
 	switch (inode->i_mode & S_IFMT) {
 	case S_IFREG:
 		inode->i_op = &erofs_generic_iops;
@@ -259,9 +264,9 @@ static int erofs_fill_inode(struct inode *inode)
 
 	if (erofs_inode_is_data_compressed(vi->datalayout)) {
 #ifdef CONFIG_EROFS_FS_ZIP
-		DO_ONCE_LITE_IF(inode->i_blkbits != PAGE_SHIFT,
-			  erofs_info, inode->i_sb,
-			  "EXPERIMENTAL EROFS subpage compressed block support in use. Use at your own risk!");
+		DO_ONCE_LITE_IF(
+			inode->i_blkbits != PAGE_SHIFT, erofs_info, inode->i_sb,
+			"EXPERIMENTAL EROFS subpage compressed block support in use. Use at your own risk!");
 		inode->i_mapping->a_ops = &z_erofs_aops;
 		err = 0;
 		goto out_unlock;
@@ -334,14 +339,14 @@ int erofs_getattr(struct mnt_idmap *idmap, const struct path *path,
 		  unsigned int query_flags)
 {
 	struct inode *const inode = d_inode(path->dentry);
+#ifndef CONFIG_EROFS_FS_RUST
 	bool compressed =
 		erofs_inode_is_data_compressed(EROFS_I(inode)->datalayout);
 
 	if (compressed)
 		stat->attributes |= STATX_ATTR_COMPRESSED;
 	stat->attributes |= STATX_ATTR_IMMUTABLE;
-	stat->attributes_mask |= (STATX_ATTR_COMPRESSED |
-				  STATX_ATTR_IMMUTABLE);
+	stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_IMMUTABLE);
 
 	/*
 	 * Return the DIO alignment restrictions if requested.
@@ -357,27 +362,35 @@ int erofs_getattr(struct mnt_idmap *idmap, const struct path *path,
 			stat->dio_offset_align = stat->dio_mem_align;
 		}
 	}
+
+#endif
 	generic_fillattr(idmap, request_mask, inode, stat);
 	return 0;
 }
 
 const struct inode_operations erofs_generic_iops = {
 	.getattr = erofs_getattr,
+#ifndef CONFIG_EROFS_FS_RUST
 	.listxattr = erofs_listxattr,
 	.get_inode_acl = erofs_get_acl,
+#endif
 	.fiemap = erofs_fiemap,
 };
 
 const struct inode_operations erofs_symlink_iops = {
 	.get_link = page_get_link,
 	.getattr = erofs_getattr,
+#ifndef CONFIG_EROFS_FS_RUST
 	.listxattr = erofs_listxattr,
 	.get_inode_acl = erofs_get_acl,
+#endif
 };
 
 const struct inode_operations erofs_fast_symlink_iops = {
 	.get_link = simple_get_link,
 	.getattr = erofs_getattr,
+#ifndef CONFIG_EROFS_FS_RUST
 	.listxattr = erofs_listxattr,
 	.get_inode_acl = erofs_get_acl,
+#endif
 };
diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 45dc15ebd870..aa48f8abc724 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -19,6 +19,9 @@
 #include <linux/vmalloc.h>
 #include <linux/iomap.h>
 #include "erofs_fs.h"
+#ifdef CONFIG_EROFS_FS_RUST
+#include "erofs_rust_bindings.h"
+#endif
 
 /* redefine pr_fmt "erofs: " */
 #undef pr_fmt
diff --git a/fs/erofs/namei.c b/fs/erofs/namei.c
index c94d0c1608a8..12fd429adad4 100644
--- a/fs/erofs/namei.c
+++ b/fs/erofs/namei.c
@@ -4,6 +4,7 @@
  *             https://www.huawei.com/
  * Copyright (C) 2022, Alibaba Cloud
  */
+
 #include "xattr.h"
 #include <trace/events/erofs.h>
 
@@ -40,7 +41,7 @@ static inline int erofs_dirnamecmp(const struct erofs_qstr *qn,
 	return qn->name[i] == '\0' ? 0 : 1;
 }
 
-#define nameoff_from_disk(off, sz)	(le16_to_cpu(off) & ((sz) - 1))
+#define nameoff_from_disk(off, sz) (le16_to_cpu(off) & ((sz) - 1))
 
 static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name,
 					       u8 *data,
@@ -58,15 +59,16 @@ static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name,
 
 	while (head <= back) {
 		const int mid = head + (back - head) / 2;
-		const int nameoff = nameoff_from_disk(de[mid].nameoff,
-						      dirblksize);
+		const int nameoff =
+			nameoff_from_disk(de[mid].nameoff, dirblksize);
 		unsigned int matched = min(startprfx, endprfx);
 		struct erofs_qstr dname = {
 			.name = data + nameoff,
 			.end = mid >= ndirents - 1 ?
-				data + dirblksize :
-				data + nameoff_from_disk(de[mid + 1].nameoff,
-							 dirblksize)
+				       data + dirblksize :
+				       data + nameoff_from_disk(
+						      de[mid + 1].nameoff,
+						      dirblksize)
 		};
 
 		/* string comparison without already matched prefix */
@@ -87,7 +89,8 @@ static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name,
 }
 
 static void *erofs_find_target_block(struct erofs_buf *target,
-		struct inode *dir, struct erofs_qstr *name, int *_ndirents)
+				     struct inode *dir, struct erofs_qstr *name,
+				     int *_ndirents)
 {
 	unsigned int bsz = i_blocksize(dir);
 	int head = 0, back = erofs_iblks(dir) - 1;
@@ -124,7 +127,8 @@ static void *erofs_find_target_block(struct erofs_buf *target,
 			if (ndirents == 1)
 				dname.end = (u8 *)de + bsz;
 			else
-				dname.end = (u8 *)de +
+				dname.end =
+					(u8 *)de +
 					nameoff_from_disk(de[1].nameoff, bsz);
 
 			/* string comparison without already matched prefix */
@@ -150,7 +154,7 @@ static void *erofs_find_target_block(struct erofs_buf *target,
 			*_ndirents = ndirents;
 			continue;
 		}
-out:		/* free if the candidate is valid */
+out: /* free if the candidate is valid */
 		if (!IS_ERR(candidate))
 			erofs_put_metabuf(target);
 		return de;
@@ -190,6 +194,7 @@ int erofs_namei(struct inode *dir, const struct qstr *name, erofs_nid_t *nid,
 	return PTR_ERR_OR_ZERO(de);
 }
 
+#ifndef CONFIG_EROFS_FS_RUST
 static struct dentry *erofs_lookup(struct inode *dir, struct dentry *dentry,
 				   unsigned int flags)
 {
@@ -214,11 +219,16 @@ static struct dentry *erofs_lookup(struct inode *dir, struct dentry *dentry,
 		inode = erofs_iget(dir->i_sb, nid);
 	return d_splice_alias(inode, dentry);
 }
+#endif
 
 const struct inode_operations erofs_dir_iops = {
-	.lookup = erofs_lookup,
 	.getattr = erofs_getattr,
+#ifdef CONFIG_EROFS_FS_RUST
+	.lookup = erofs_lookup_rust,
+#else
 	.listxattr = erofs_listxattr,
 	.get_inode_acl = erofs_get_acl,
+	.lookup = erofs_lookup,
+#endif
 	.fiemap = erofs_fiemap,
 };
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index 6cb5c8916174..f6963e31d516 100644
--- a/fs/erofs/super.c
+++ b/fs/erofs/super.c
@@ -4,6 +4,7 @@
  *             https://www.huawei.com/
  * Copyright (C) 2021, Alibaba Cloud
  */
+#include "erofs_rust_bindings.h"
 #include <linux/statfs.h>
 #include <linux/seq_file.h>
 #include <linux/crc32c.h>
@@ -51,6 +52,7 @@ void _erofs_info(struct super_block *sb, const char *func, const char *fmt, ...)
 	va_end(args);
 }
 
+#ifndef CONFIG_EROFS_FS_RUST
 static int erofs_superblock_csum_verify(struct super_block *sb, void *sbdata)
 {
 	size_t len = 1 << EROFS_SB(sb)->blkszbits;
@@ -71,8 +73,8 @@ static int erofs_superblock_csum_verify(struct super_block *sb, void *sbdata)
 	kfree(dsb);
 
 	if (crc != expected_crc) {
-		erofs_err(sb, "invalid checksum 0x%08x, 0x%08x expected",
-			  crc, expected_crc);
+		erofs_err(sb, "invalid checksum 0x%08x, 0x%08x expected", crc,
+			  expected_crc);
 		return -EBADMSG;
 	}
 	return 0;
@@ -85,27 +87,35 @@ static void erofs_inode_init_once(void *ptr)
 	inode_init_once(&vi->vfs_inode);
 }
 
+#endif
+
 static struct inode *erofs_alloc_inode(struct super_block *sb)
 {
-	struct erofs_inode *vi =
-		alloc_inode_sb(sb, erofs_inode_cachep, GFP_KERNEL);
+	void *vi = alloc_inode_sb(sb, erofs_inode_cachep, GFP_KERNEL);
 
 	if (!vi)
 		return NULL;
 
-	/* zero out everything except vfs_inode */
+		/* zero out everything except vfs_inode */
+#ifdef CONFIG_EROFS_FS_RUST
+	return (struct inode *)(vi + EROFS_INODE_OFFSET);
+#else
 	memset(vi, 0, offsetof(struct erofs_inode, vfs_inode));
-	return &vi->vfs_inode;
+	return &((struct erofs_inode *)vi)->vfs_inode;
+#endif
 }
 
 static void erofs_free_inode(struct inode *inode)
 {
-	struct erofs_inode *vi = EROFS_I(inode);
-
 	if (inode->i_op == &erofs_fast_symlink_iops)
 		kfree(inode->i_link);
+#ifndef CONFIG_EROFS_FS_RUST
+	struct erofs_inode *vi = EROFS_I(inode);
 	kfree(vi->xattr_shared_xattrs);
 	kmem_cache_free(erofs_inode_cachep, vi);
+#else
+	kmem_cache_free(erofs_inode_cachep, (void *)inode - EROFS_INODE_OFFSET);
+#endif
 }
 
 /* read variable-sized metadata, offset will be aligned by 4-byte */
@@ -143,6 +153,8 @@ void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
 	return buffer;
 }
 
+#ifndef CONFIG_EROFS_FS_RUST
+
 #ifndef CONFIG_EROFS_FS_ZIP
 static int z_erofs_parse_cfgs(struct super_block *sb,
 			      struct erofs_super_block *dsb)
@@ -184,12 +196,12 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
 		dif->fscache = fscache;
 	} else if (!sbi->devs->flatdev) {
 		bdev_file = bdev_file_open_by_path(dif->path, BLK_OPEN_READ,
-						sb->s_type, NULL);
+						   sb->s_type, NULL);
 		if (IS_ERR(bdev_file))
 			return PTR_ERR(bdev_file);
 		dif->bdev_file = bdev_file;
-		dif->dax_dev = fs_dax_get_by_bdev(file_bdev(bdev_file),
-				&dif->dax_part_off, NULL, NULL);
+		dif->dax_dev = fs_dax_get_by_bdev(
+			file_bdev(bdev_file), &dif->dax_part_off, NULL, NULL);
 	}
 
 	dif->blocks = le32_to_cpu(dis->blocks);
@@ -244,7 +256,8 @@ static int erofs_scan_devices(struct super_block *sb,
 				break;
 			}
 
-			err = idr_alloc(&sbi->devs->tree, dif, 0, 0, GFP_KERNEL);
+			err = idr_alloc(&sbi->devs->tree, dif, 0, 0,
+					GFP_KERNEL);
 			if (err < 0) {
 				kfree(dif);
 				break;
@@ -282,7 +295,7 @@ static int erofs_read_superblock(struct super_block *sb)
 		goto out;
 	}
 
-	sbi->blkszbits  = dsb->blkszbits;
+	sbi->blkszbits = dsb->blkszbits;
 	if (sbi->blkszbits < 9 || sbi->blkszbits > PAGE_SHIFT) {
 		erofs_err(sb, "blkszbits %u isn't supported", sbi->blkszbits);
 		goto out;
@@ -333,7 +346,7 @@ static int erofs_read_superblock(struct super_block *sb)
 
 	ret = strscpy(sbi->volume_name, dsb->volume_name,
 		      sizeof(dsb->volume_name));
-	if (ret < 0) {	/* -E2BIG */
+	if (ret < 0) { /* -E2BIG */
 		erofs_err(sb, "bad volume name without NIL terminator");
 		ret = -EFSCORRUPTED;
 		goto out;
@@ -348,7 +361,9 @@ static int erofs_read_superblock(struct super_block *sb)
 	ret = erofs_scan_devices(sb, dsb);
 
 	if (erofs_is_fscache_mode(sb))
-		erofs_info(sb, "EXPERIMENTAL fscache-based on-demand read feature in use. Use at your own risk!");
+		erofs_info(
+			sb,
+			"EXPERIMENTAL fscache-based on-demand read feature in use. Use at your own risk!");
 out:
 	erofs_put_metabuf(&buf);
 	return ret;
@@ -369,6 +384,8 @@ static void erofs_default_options(struct erofs_sb_info *sbi)
 #endif
 }
 
+#endif
+
 enum {
 	Opt_user_xattr,
 	Opt_acl,
@@ -382,31 +399,32 @@ enum {
 };
 
 static const struct constant_table erofs_param_cache_strategy[] = {
-	{"disabled",	EROFS_ZIP_CACHE_DISABLED},
-	{"readahead",	EROFS_ZIP_CACHE_READAHEAD},
-	{"readaround",	EROFS_ZIP_CACHE_READAROUND},
+	{ "disabled", EROFS_ZIP_CACHE_DISABLED },
+	{ "readahead", EROFS_ZIP_CACHE_READAHEAD },
+	{ "readaround", EROFS_ZIP_CACHE_READAROUND },
 	{}
 };
 
 static const struct constant_table erofs_dax_param_enums[] = {
-	{"always",	EROFS_MOUNT_DAX_ALWAYS},
-	{"never",	EROFS_MOUNT_DAX_NEVER},
+	{ "always", EROFS_MOUNT_DAX_ALWAYS },
+	{ "never", EROFS_MOUNT_DAX_NEVER },
 	{}
 };
 
 static const struct fs_parameter_spec erofs_fs_parameters[] = {
-	fsparam_flag_no("user_xattr",	Opt_user_xattr),
-	fsparam_flag_no("acl",		Opt_acl),
-	fsparam_enum("cache_strategy",	Opt_cache_strategy,
+	fsparam_flag_no("user_xattr", Opt_user_xattr),
+	fsparam_flag_no("acl", Opt_acl),
+	fsparam_enum("cache_strategy", Opt_cache_strategy,
 		     erofs_param_cache_strategy),
-	fsparam_flag("dax",             Opt_dax),
-	fsparam_enum("dax",		Opt_dax_enum, erofs_dax_param_enums),
-	fsparam_string("device",	Opt_device),
-	fsparam_string("fsid",		Opt_fsid),
-	fsparam_string("domain_id",	Opt_domain_id),
+	fsparam_flag("dax", Opt_dax),
+	fsparam_enum("dax", Opt_dax_enum, erofs_dax_param_enums),
+	fsparam_string("device", Opt_device),
+	fsparam_string("fsid", Opt_fsid),
+	fsparam_string("domain_id", Opt_domain_id),
 	{}
 };
 
+#ifndef CONFIG_EROFS_FS_RUST
 static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
 {
 #ifdef CONFIG_FS_DAX
@@ -431,19 +449,25 @@ static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
 #endif
 }
 
+#endif
+
 static int erofs_fc_parse_param(struct fs_context *fc,
 				struct fs_parameter *param)
 {
+#ifndef CONFIG_EROFS_FS_RUST
+
 	struct erofs_sb_info *sbi = fc->s_fs_info;
-	struct fs_parse_result result;
 	struct erofs_device_info *dif;
-	int opt, ret;
+#endif
 
+	struct fs_parse_result result;
+	int opt, ret;
 	opt = fs_parse(fc, erofs_fs_parameters, param, &result);
 	if (opt < 0)
 		return opt;
-
 	switch (opt) {
+#ifndef CONFIG_EROFS_FS_RUST
+
 	case Opt_user_xattr:
 #ifdef CONFIG_EROFS_FS_XATTR
 		if (result.boolean)
@@ -468,7 +492,8 @@ static int erofs_fc_parse_param(struct fs_context *fc,
 #ifdef CONFIG_EROFS_FS_ZIP
 		sbi->opt.cache_strategy = result.uint_32;
 #else
-		errorfc(fc, "compression not supported, cache_strategy ignored");
+		errorfc(fc,
+			"compression not supported, cache_strategy ignored");
 #endif
 		break;
 	case Opt_dax:
@@ -514,35 +539,51 @@ static int erofs_fc_parse_param(struct fs_context *fc,
 #else
 	case Opt_fsid:
 	case Opt_domain_id:
-		errorfc(fc, "%s option not supported", erofs_fs_parameters[opt].name);
+		errorfc(fc, "%s option not supported",
+			erofs_fs_parameters[opt].name);
 		break;
+
+	default:
+
 #endif
+#else
 	default:
+		(void)ret;
+#endif
 		return -ENOPARAM;
 	}
 	return 0;
 }
 
-static struct inode *erofs_nfs_get_inode(struct super_block *sb,
-					 u64 ino, u32 generation)
+static struct inode *erofs_nfs_get_inode(struct super_block *sb, u64 ino,
+					 u32 generation)
 {
+#ifdef CONFIG_EROFS_FS_RUST
+	return erofs_iget_rust(sb, ino);
+#else
 	return erofs_iget(sb, ino);
+#endif
 }
 
 static struct dentry *erofs_fh_to_dentry(struct super_block *sb,
-		struct fid *fid, int fh_len, int fh_type)
+					 struct fid *fid, int fh_len,
+					 int fh_type)
 {
 	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
 				    erofs_nfs_get_inode);
 }
 
 static struct dentry *erofs_fh_to_parent(struct super_block *sb,
-		struct fid *fid, int fh_len, int fh_type)
+					 struct fid *fid, int fh_len,
+					 int fh_type)
 {
 	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
 				    erofs_nfs_get_inode);
 }
 
+#ifdef CONFIG_EROFS_FS_RUST
+
+#else
 static struct dentry *erofs_get_parent(struct dentry *child)
 {
 	erofs_nid_t nid;
@@ -555,21 +596,29 @@ static struct dentry *erofs_get_parent(struct dentry *child)
 	return d_obtain_alias(erofs_iget(child->d_sb, nid));
 }
 
+#endif
+
 static const struct export_operations erofs_export_ops = {
 	.encode_fh = generic_encode_ino32_fh,
 	.fh_to_dentry = erofs_fh_to_dentry,
 	.fh_to_parent = erofs_fh_to_parent,
+#ifdef CONFIG_EROFS_FS_RUST
+	.get_parent = erofs_get_parent_rust,
+#else
 	.get_parent = erofs_get_parent,
+#endif
 };
 
+#ifndef CONFIG_EROFS_FS_RUST
+
 static void erofs_set_sysfs_name(struct super_block *sb)
 {
 	struct erofs_sb_info *sbi = EROFS_SB(sb);
 
 	if (erofs_is_fscache_mode(sb)) {
 		if (sbi->domain_id)
-			super_set_sysfs_name_generic(sb, "%s,%s",sbi->domain_id,
-						     sbi->fsid);
+			super_set_sysfs_name_generic(sb, "%s,%s",
+						     sbi->domain_id, sbi->fsid);
 		else
 			super_set_sysfs_name_generic(sb, "%s", sbi->fsid);
 		return;
@@ -606,9 +655,8 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
 			return -EINVAL;
 		}
 
-		sbi->dax_dev = fs_dax_get_by_bdev(sb->s_bdev,
-						  &sbi->dax_part_off,
-						  NULL, NULL);
+		sbi->dax_dev = fs_dax_get_by_bdev(
+			sb->s_bdev, &sbi->dax_part_off, NULL, NULL);
 	}
 
 	err = erofs_read_superblock(sb);
@@ -628,7 +676,8 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	if (test_opt(&sbi->opt, DAX_ALWAYS)) {
 		if (!sbi->dax_dev) {
-			errorfc(fc, "DAX unsupported by block device. Turning off DAX.");
+			errorfc(fc,
+				"DAX unsupported by block device. Turning off DAX.");
 			clear_opt(&sbi->opt, DAX_ALWAYS);
 		} else if (sbi->blkszbits != PAGE_SHIFT) {
 			errorfc(fc, "unsupported blocksize for DAX");
@@ -679,6 +728,7 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
 		return err;
 
 	err = erofs_xattr_prefixes_init(sb);
+
 	if (err)
 		return err;
 
@@ -690,18 +740,38 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
 	return 0;
 }
 
+#else
+static int erofs_fc_fill_super_rust(struct super_block *sb,
+				    struct fs_context *fc)
+{
+	sb->s_magic = EROFS_SUPER_MAGIC;
+	sb->s_flags |= SB_RDONLY | SB_NOATIME;
+	sb->s_maxbytes = MAX_LFS_FILESIZE;
+	sb->s_op = &erofs_sops;
+	sb->s_time_gran = 1;
+	sb->s_xattr = NULL;
+	sb->s_export_op = &erofs_export_ops;
+	sb->s_fs_info = erofs_alloc_sbi_rust(sb, sb->s_bdev->bd_mapping);
+	sb->s_root = erofs_make_root_rust(sb);
+	return 0;
+}
+#define erofs_fc_fill_super erofs_fc_fill_super_rust
+#endif
+
 static int erofs_fc_get_tree(struct fs_context *fc)
 {
+#ifndef CONFIG_EROFS_FS_RUST
 	struct erofs_sb_info *sbi = fc->s_fs_info;
-
 	if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid)
 		return get_tree_nodev(fc, erofs_fc_fill_super);
+#endif
 
 	return get_tree_bdev(fc, erofs_fc_fill_super);
 }
 
 static int erofs_fc_reconfigure(struct fs_context *fc)
 {
+#ifndef CONFIG_EROFS_FS_RUST
 	struct super_block *sb = fc->root->d_sb;
 	struct erofs_sb_info *sbi = EROFS_SB(sb);
 	struct erofs_sb_info *new_sbi = fc->s_fs_info;
@@ -718,10 +788,12 @@ static int erofs_fc_reconfigure(struct fs_context *fc)
 
 	sbi->opt = new_sbi->opt;
 
+#endif
 	fc->sb_flags |= SB_RDONLY;
 	return 0;
 }
 
+#ifndef CONFIG_EROFS_FS_RUST
 static int erofs_release_device_info(int id, void *ptr, void *data)
 {
 	struct erofs_device_info *dif = ptr;
@@ -758,15 +830,23 @@ static void erofs_fc_free(struct fs_context *fc)
 	kfree(sbi);
 }
 
+#else
+
+static void erofs_fc_free(struct fs_context *fc)
+{
+}
+
+#endif
 static const struct fs_context_operations erofs_context_ops = {
-	.parse_param	= erofs_fc_parse_param,
-	.get_tree       = erofs_fc_get_tree,
-	.reconfigure    = erofs_fc_reconfigure,
-	.free		= erofs_fc_free,
+	.parse_param = erofs_fc_parse_param,
+	.get_tree = erofs_fc_get_tree,
+	.reconfigure = erofs_fc_reconfigure,
+	.free = erofs_fc_free,
 };
 
 static int erofs_init_fs_context(struct fs_context *fc)
 {
+#ifndef CONFIG_EROFS_FS_RUST
 	struct erofs_sb_info *sbi;
 
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
@@ -783,12 +863,14 @@ static int erofs_init_fs_context(struct fs_context *fc)
 	idr_init(&sbi->devs->tree);
 	init_rwsem(&sbi->devs->rwsem);
 	erofs_default_options(sbi);
+#endif
 	fc->ops = &erofs_context_ops;
 	return 0;
 }
 
 static void erofs_kill_sb(struct super_block *sb)
 {
+#ifndef CONFIG_EROFS_FS_RUST
 	struct erofs_sb_info *sbi = EROFS_SB(sb);
 
 	if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid)
@@ -802,11 +884,15 @@ static void erofs_kill_sb(struct super_block *sb)
 	kfree(sbi->fsid);
 	kfree(sbi->domain_id);
 	kfree(sbi);
+#else
+	erofs_free_sbi_rust(sb);
 	sb->s_fs_info = NULL;
+#endif
 }
 
 static void erofs_put_super(struct super_block *sb)
 {
+#ifndef CONFIG_EROFS_FS_RUST
 	struct erofs_sb_info *const sbi = EROFS_SB(sb);
 
 	DBG_BUGON(!sbi);
@@ -823,14 +909,15 @@ static void erofs_put_super(struct super_block *sb)
 	erofs_free_dev_context(sbi->devs);
 	sbi->devs = NULL;
 	erofs_fscache_unregister_fs(sb);
+#endif
 }
 
 static struct file_system_type erofs_fs_type = {
-	.owner          = THIS_MODULE,
-	.name           = "erofs",
+	.owner = THIS_MODULE,
+	.name = "erofs",
 	.init_fs_context = erofs_init_fs_context,
-	.kill_sb        = erofs_kill_sb,
-	.fs_flags       = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
+	.kill_sb = erofs_kill_sb,
+	.fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
 };
 MODULE_ALIAS_FS("erofs");
 
@@ -840,10 +927,17 @@ static int __init erofs_module_init(void)
 
 	erofs_check_ondisk_layout_definitions();
 
-	erofs_inode_cachep = kmem_cache_create("erofs_inode",
-			sizeof(struct erofs_inode), 0,
-			SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT,
-			erofs_inode_init_once);
+#ifdef CONFIG_EROFS_FS_RUST
+	erofs_inode_cachep =
+		kmem_cache_create("erofs_inode", EROFS_INODE_SIZE, 0,
+				  SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT,
+				  erofs_inode_init_once_rust);
+#else
+	erofs_inode_cachep = kmem_cache_create(
+		"erofs_inode", sizeof(struct erofs_inode), 0,
+		SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT, erofs_inode_init_once);
+#endif
+
 	if (!erofs_inode_cachep)
 		return -ENOMEM;
 
@@ -891,6 +985,7 @@ static void __exit erofs_module_exit(void)
 
 static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+#ifndef CONFIG_EROFS_FS_RUST
 	struct super_block *sb = dentry->d_sb;
 	struct erofs_sb_info *sbi = EROFS_SB(sb);
 
@@ -903,26 +998,31 @@ static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	buf->f_namelen = EROFS_NAME_LEN;
 
 	if (uuid_is_null(&sb->s_uuid))
-		buf->f_fsid = u64_to_fsid(erofs_is_fscache_mode(sb) ? 0 :
+		buf->f_fsid = u64_to_fsid(
+			erofs_is_fscache_mode(sb) ?
+				0 :
 				huge_encode_dev(sb->s_bdev->bd_dev));
 	else
 		buf->f_fsid = uuid_to_fsid(sb->s_uuid.b);
+#endif
 	return 0;
 }
 
 static int erofs_show_options(struct seq_file *seq, struct dentry *root)
 {
+#ifndef CONFIG_EROFS_FS_RUST
 	struct erofs_sb_info *sbi = EROFS_SB(root->d_sb);
 	struct erofs_mount_opts *opt = &sbi->opt;
 
 	if (IS_ENABLED(CONFIG_EROFS_FS_XATTR))
-		seq_puts(seq, test_opt(opt, XATTR_USER) ?
-				",user_xattr" : ",nouser_xattr");
+		seq_puts(seq, test_opt(opt, XATTR_USER) ? ",user_xattr" :
+							  ",nouser_xattr");
 	if (IS_ENABLED(CONFIG_EROFS_FS_POSIX_ACL))
 		seq_puts(seq, test_opt(opt, POSIX_ACL) ? ",acl" : ",noacl");
 	if (IS_ENABLED(CONFIG_EROFS_FS_ZIP))
-		seq_printf(seq, ",cache_strategy=%s",
-			  erofs_param_cache_strategy[opt->cache_strategy].name);
+		seq_printf(
+			seq, ",cache_strategy=%s",
+			erofs_param_cache_strategy[opt->cache_strategy].name);
 	if (test_opt(opt, DAX_ALWAYS))
 		seq_puts(seq, ",dax=always");
 	if (test_opt(opt, DAX_NEVER))
@@ -932,6 +1032,7 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root)
 		seq_printf(seq, ",fsid=%s", sbi->fsid);
 	if (sbi->domain_id)
 		seq_printf(seq, ",domain_id=%s", sbi->domain_id);
+#endif
 #endif
 	return 0;
 }
-- 
2.45.2



More information about the Linux-erofs mailing list