* [WIP] [PATCH v2 0/5] erofs-utils: introduce fuse implementation
[not found] <20201024130959.23720-1-hsiangkao.ref@aol.com>
@ 2020-10-24 13:09 ` Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 1/5] " Gao Xiang via Linux-erofs
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Gao Xiang via Linux-erofs @ 2020-10-24 13:09 UTC (permalink / raw)
To: linux-erofs; +Cc: Zhang Shiming, Guo Weichao
background & v1:
https://lore.kernel.org/r/20201017051621.7810-1-hsiangkao@aol.com
changes since v1:
- fold in incremental patches in v1;
- get rid of "-Wextra" to adapt common erofs-utils code;
- get rid of duplicated logging code since fprintf is MT-safe for POSIX;
TODO:
- move fuse common code to liberofs;
- make fuse code MT-safe;
- minor cleanup.
Thanks,
Gao Xiang
Gao Xiang (2):
erofs-utils: fuse: drop "-Wextra" and "-Wno-implicit-fallthrough"
erofs-utils: fuse: get rid of duplicated logging code
Huang Jianan (2):
erofs-utils: fuse: add special file support
erofs-utils: fuse: add compressed file support
Li Guifu (1):
erofs-utils: introduce fuse implementation
Makefile.am | 2 +-
README | 28 ++-
configure.ac | 3 +-
fuse/Makefile.am | 17 ++
fuse/decompress.c | 83 ++++++++
fuse/decompress.h | 42 ++++
fuse/dentry.c | 130 ++++++++++++
fuse/dentry.h | 43 ++++
fuse/disk_io.c | 72 +++++++
fuse/disk_io.h | 21 ++
fuse/getattr.c | 65 ++++++
fuse/getattr.h | 15 ++
fuse/init.c | 117 +++++++++++
fuse/init.h | 24 +++
fuse/main.c | 167 ++++++++++++++++
fuse/namei.c | 242 +++++++++++++++++++++++
fuse/namei.h | 22 +++
fuse/open.c | 22 +++
fuse/open.h | 15 ++
fuse/read.c | 213 ++++++++++++++++++++
fuse/read.h | 17 ++
fuse/readir.c | 122 ++++++++++++
fuse/readir.h | 17 ++
fuse/zmap.c | 418 +++++++++++++++++++++++++++++++++++++++
include/erofs/defs.h | 16 ++
include/erofs/internal.h | 79 ++++++++
include/erofs_fs.h | 4 +
27 files changed, 2013 insertions(+), 3 deletions(-)
create mode 100644 fuse/Makefile.am
create mode 100644 fuse/decompress.c
create mode 100644 fuse/decompress.h
create mode 100644 fuse/dentry.c
create mode 100644 fuse/dentry.h
create mode 100644 fuse/disk_io.c
create mode 100644 fuse/disk_io.h
create mode 100644 fuse/getattr.c
create mode 100644 fuse/getattr.h
create mode 100644 fuse/init.c
create mode 100644 fuse/init.h
create mode 100644 fuse/main.c
create mode 100644 fuse/namei.c
create mode 100644 fuse/namei.h
create mode 100644 fuse/open.c
create mode 100644 fuse/open.h
create mode 100644 fuse/read.c
create mode 100644 fuse/read.h
create mode 100644 fuse/readir.c
create mode 100644 fuse/readir.h
create mode 100644 fuse/zmap.c
--
2.24.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [WIP] [PATCH v2 1/5] erofs-utils: introduce fuse implementation
2020-10-24 13:09 ` [WIP] [PATCH v2 0/5] erofs-utils: introduce fuse implementation Gao Xiang via Linux-erofs
@ 2020-10-24 13:09 ` Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 2/5] erofs-utils: fuse: add special file support Gao Xiang via Linux-erofs
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Gao Xiang via Linux-erofs @ 2020-10-24 13:09 UTC (permalink / raw)
To: linux-erofs; +Cc: Zhang Shiming, Guo Weichao
From: Li Guifu <blucerlee@gmail.com>
Let's add erofsfuse approach, and benefits are:
- images can be supported on various platforms;
- new unpack tool can be developed based on this;
- new on-disk features can be iterated, verified effectively.
This commit only aims at reading a regular file.
Other file (e.g. compressed file) support is out of scope for now.
Signed-off-by: Li Guifu <blucerlee@gmail.com>
Signed-off-by: Huang Jianan <huangjianan@oppo.com>
Signed-off-by: Guo Weichao <guoweichao@oppo.com>
Signed-off-by: Gao Xiang <hsiangkao@aol.com>
---
Makefile.am | 2 +-
README | 28 ++++-
configure.ac | 3 +-
fuse/Makefile.am | 14 +++
fuse/dentry.c | 129 ++++++++++++++++++++++
fuse/dentry.h | 42 ++++++++
fuse/disk_io.c | 72 +++++++++++++
fuse/disk_io.h | 21 ++++
fuse/getattr.c | 64 +++++++++++
fuse/getattr.h | 15 +++
fuse/init.c | 98 +++++++++++++++++
fuse/init.h | 22 ++++
fuse/logging.c | 81 ++++++++++++++
fuse/logging.h | 55 ++++++++++
fuse/main.c | 170 +++++++++++++++++++++++++++++
fuse/namei.c | 227 +++++++++++++++++++++++++++++++++++++++
fuse/namei.h | 22 ++++
fuse/open.c | 22 ++++
fuse/open.h | 15 +++
fuse/read.c | 113 +++++++++++++++++++
fuse/read.h | 16 +++
fuse/readir.c | 122 +++++++++++++++++++++
fuse/readir.h | 17 +++
include/erofs/defs.h | 3 +
include/erofs/internal.h | 37 +++++++
25 files changed, 1407 insertions(+), 3 deletions(-)
create mode 100644 fuse/Makefile.am
create mode 100644 fuse/dentry.c
create mode 100644 fuse/dentry.h
create mode 100644 fuse/disk_io.c
create mode 100644 fuse/disk_io.h
create mode 100644 fuse/getattr.c
create mode 100644 fuse/getattr.h
create mode 100644 fuse/init.c
create mode 100644 fuse/init.h
create mode 100644 fuse/logging.c
create mode 100644 fuse/logging.h
create mode 100644 fuse/main.c
create mode 100644 fuse/namei.c
create mode 100644 fuse/namei.h
create mode 100644 fuse/open.c
create mode 100644 fuse/open.h
create mode 100644 fuse/read.c
create mode 100644 fuse/read.h
create mode 100644 fuse/readir.c
create mode 100644 fuse/readir.h
diff --git a/Makefile.am b/Makefile.am
index 1d20577068c5..24f4a7b3d5ad 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,4 +3,4 @@
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = man lib mkfs
+SUBDIRS = man lib mkfs fuse
diff --git a/README b/README
index 5addd6b80e04..870858c48b7d 100644
--- a/README
+++ b/README
@@ -2,7 +2,8 @@ erofs-utils
===========
erofs-utils includes user-space tools for erofs filesystem images.
-Currently only mkfs.erofs is available.
+One is mkfs.erofs to create a image, the other is erofsfuse which
+is used to mount a image on a directory
mkfs.erofs
----------
@@ -95,6 +96,31 @@ It may still be useful since new erofs-utils has not been widely used in
commercial products. However, if that happens, please report bug to us
as well.
+erofs-utils: erofsfuse
+----------------------
+erofsfuse mount a erofs filesystem image created by mkfs.erofs to a directory, and then
+It can be listed, read files and so on.
+
+Dependencies
+~~~~~~~~~~~~
+FUSE library version: 2.9.7
+fusermount version: 2.9.7
+using FUSE kernel interface version 7.19
+
+How to installed fuse
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+sudo apt-get update
+sudo apt-get install -y fuse libfuse-dev
+
+How to build erofsfuse
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ $ ./autogen.sh
+ $ ./configure
+ $ make
+
+erofsfuse binary will be generated under fuse folder.
+
Contribution
------------
diff --git a/configure.ac b/configure.ac
index 0f40a840cf4f..4194a77f1e36 100644
--- a/configure.ac
+++ b/configure.ac
@@ -245,6 +245,7 @@ fi
AC_CONFIG_FILES([Makefile
man/Makefile
lib/Makefile
- mkfs/Makefile])
+ mkfs/Makefile
+ fuse/Makefile])
AC_OUTPUT
diff --git a/fuse/Makefile.am b/fuse/Makefile.am
new file mode 100644
index 000000000000..fffd67a53fe1
--- /dev/null
+++ b/fuse/Makefile.am
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Makefile.am
+
+AUTOMAKE_OPTIONS = foreign
+bin_PROGRAMS = erofsfuse
+erofsfuse_SOURCES = main.c dentry.c getattr.c logging.c namei.c read.c disk_io.c init.c open.c readir.c
+erofsfuse_CFLAGS = -Wall -Werror -Wextra \
+ -I$(top_srcdir)/include \
+ $(shell pkg-config fuse --cflags) \
+ -DFUSE_USE_VERSION=26 \
+ -std=gnu99
+LDFLAGS += $(shell pkg-config fuse --libs)
+erofsfuse_LDADD = $(top_builddir)/lib/liberofs.la -ldl
+
diff --git a/fuse/dentry.c b/fuse/dentry.c
new file mode 100644
index 000000000000..1ae37e3abc86
--- /dev/null
+++ b/fuse/dentry.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/dentry.c
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#include "dentry.h"
+#include "erofs/internal.h"
+#include "logging.h"
+
+#define DCACHE_ENTRY_CALLOC() calloc(1, sizeof(struct dcache_entry))
+#define DCACHE_ENTRY_LIFE 8
+
+struct dcache_entry root_entry;
+
+int dcache_init_root(uint32_t nid)
+{
+ if (root_entry.nid)
+ return -1;
+
+ /* Root entry doesn't need most of the fields. Namely, it only uses the
+ * nid field and the subdirs pointer.
+ */
+ logi("Initializing root_entry dcache entry");
+ root_entry.nid = nid;
+ root_entry.subdirs = NULL;
+ root_entry.siblings = NULL;
+
+ return 0;
+}
+
+/* Inserts a node as a subdirs of a given parent. The parent is updated to
+ * point the newly inserted subdirs as the first subdirs. We return the new
+ * entry so that further entries can be inserted.
+ *
+ * [0] [0]
+ * / ==> \
+ * / ==> \
+ * .->[1]->[2]-. .->[1]->[3]->[2]-.
+ * `-----------麓 `----------------麓
+ */
+struct dcache_entry *dcache_insert(struct dcache_entry *parent,
+ const char *name, int namelen, uint32_t nid)
+{
+ struct dcache_entry *new_entry;
+
+ logd("Inserting %s,%d to dcache", name, namelen);
+
+ /* TODO: Deal with names that exceed the allocated size */
+ if (namelen + 1 > DCACHE_ENTRY_NAME_LEN)
+ return NULL;
+
+ if (parent == NULL)
+ parent = &root_entry;
+
+ new_entry = DCACHE_ENTRY_CALLOC();
+ if (!new_entry)
+ return NULL;
+
+ strncpy(new_entry->name, name, namelen);
+ new_entry->name[namelen] = 0;
+ new_entry->nid = nid;
+
+ if (!parent->subdirs) {
+ new_entry->siblings = new_entry;
+ parent->subdirs = new_entry;
+ } else {
+ new_entry->siblings = parent->subdirs->siblings;
+ parent->subdirs->siblings = new_entry;
+ parent->subdirs = new_entry;
+ }
+
+ return new_entry;
+}
+
+/* Lookup a cache entry for a given file name. Return value is a struct pointer
+ * that can be used to both obtain the nid number and insert further child
+ * entries.
+ * TODO: Prune entries by using the LRU counter
+ */
+struct dcache_entry *dcache_lookup(struct dcache_entry *parent,
+ const char *name, int namelen)
+{
+ struct dcache_entry *iter;
+
+ if (parent == NULL)
+ parent = &root_entry;
+
+ if (!parent->subdirs)
+ return NULL;
+
+ /* Iterate the list of siblings to see if there is any match */
+ iter = parent->subdirs;
+
+ do {
+ if (strncmp(iter->name, name, namelen) == 0 &&
+ iter->name[namelen] == 0) {
+ parent->subdirs = iter;
+
+ return iter;
+ }
+
+ iter = iter->siblings;
+ } while (iter != parent->subdirs);
+
+ return NULL;
+}
+
+struct dcache_entry *dcache_try_insert(struct dcache_entry *parent,
+ const char *name, int namelen, uint32_t nid)
+{
+ struct dcache_entry *d = dcache_lookup(parent, name, namelen);
+
+ if (d)
+ return d;
+
+ return dcache_insert(parent, name, namelen, nid);
+
+}
+erofs_nid_t dcache_get_nid(struct dcache_entry *entry)
+{
+ return entry ? entry->nid : root_entry.nid;
+}
+
+struct dcache_entry *dcache_root(void)
+{
+ return &root_entry;
+}
+
diff --git a/fuse/dentry.h b/fuse/dentry.h
new file mode 100644
index 000000000000..cb4d87972b2d
--- /dev/null
+++ b/fuse/dentry.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * erofs-utils/fuse/dentry.h
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#ifndef _EROFS_DENTRY_H
+#define _EROFS_DENTRY_H
+
+#include <stdint.h>
+#include "erofs/internal.h"
+
+#ifdef __64BITS
+#define DCACHE_ENTRY_NAME_LEN 40
+#else
+#define DCACHE_ENTRY_NAME_LEN 48
+#endif
+
+/* This struct declares a node of a k-tree. Every node has a pointer to one of
+ * the subdirs and a pointer (in a circular list fashion) to its siblings.
+ */
+
+struct dcache_entry {
+ struct dcache_entry *subdirs;
+ struct dcache_entry *siblings;
+ uint32_t nid;
+ uint16_t lru_count;
+ uint8_t user_count;
+ char name[DCACHE_ENTRY_NAME_LEN];
+};
+
+struct dcache_entry *dcache_insert(struct dcache_entry *parent,
+ const char *name, int namelen, uint32_t n);
+struct dcache_entry *dcache_lookup(struct dcache_entry *parent,
+ const char *name, int namelen);
+struct dcache_entry *dcache_try_insert(struct dcache_entry *parent,
+ const char *name, int namelen,
+ uint32_t nid);
+
+erofs_nid_t dcache_get_nid(struct dcache_entry *entry);
+int dcache_init_root(uint32_t n);
+#endif
diff --git a/fuse/disk_io.c b/fuse/disk_io.c
new file mode 100644
index 000000000000..3fc087699dc9
--- /dev/null
+++ b/fuse/disk_io.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/disk_io.c
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#define _XOPEN_SOURCE 500
+#include "disk_io.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include "logging.h"
+
+#ifdef __FreeBSD__
+#include <string.h>
+#endif
+
+static const char *erofs_devname;
+static int erofs_devfd = -1;
+static pthread_mutex_t read_lock = PTHREAD_MUTEX_INITIALIZER;
+
+int dev_open(const char *path)
+{
+ int fd = open(path, O_RDONLY);
+
+ if (fd < 0)
+ return -errno;
+
+ erofs_devfd = fd;
+ erofs_devname = path;
+
+ return 0;
+}
+
+static inline int pread_wrapper(int fd, void *buf, size_t count, off_t offset)
+{
+ return pread(fd, buf, count, offset);
+}
+
+int dev_read(void *buf, size_t count, off_t offset)
+{
+ ssize_t pread_ret;
+ int lerrno;
+
+ ASSERT(erofs_devfd >= 0);
+
+ pthread_mutex_lock(&read_lock);
+ pread_ret = pread_wrapper(erofs_devfd, buf, count, offset);
+ lerrno = errno;
+ logd("Disk Read: offset[0x%jx] count[%zd] pread_ret=%zd %s",
+ offset, count, pread_ret, strerror(lerrno));
+ pthread_mutex_unlock(&read_lock);
+ if (count == 0)
+ logw("Read operation with 0 size");
+
+ ASSERT((size_t)pread_ret == count);
+
+ return pread_ret;
+}
+
+void dev_close(void)
+{
+ if (erofs_devfd >= 0) {
+ close(erofs_devfd);
+ erofs_devfd = -1;
+ }
+}
diff --git a/fuse/disk_io.h b/fuse/disk_io.h
new file mode 100644
index 000000000000..d2c3dd598bc0
--- /dev/null
+++ b/fuse/disk_io.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * erofs-utils/fuse/disk_io.h
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#ifndef __DISK_IO_H
+#define __DISK_IO_H
+
+#include "erofs/defs.h"
+#include "erofs/internal.h"
+
+int dev_open(const char *path);
+void dev_close(void);
+int dev_read(void *buf, size_t count, off_t offset);
+
+static inline int dev_read_blk(void *buf, uint32_t nr)
+{
+ return dev_read(buf, EROFS_BLKSIZ, blknr_to_addr(nr));
+}
+#endif
diff --git a/fuse/getattr.c b/fuse/getattr.c
new file mode 100644
index 000000000000..2518adb8947f
--- /dev/null
+++ b/fuse/getattr.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/getattr.c
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#include "getattr.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "erofs/defs.h"
+#include "erofs/internal.h"
+#include "erofs_fs.h"
+
+#include "logging.h"
+#include "namei.h"
+
+extern struct erofs_super_block super;
+
+/* GNU's definitions of the attributes
+ * (http://www.gnu.org/software/libc/manual/html_node/Attribute-Meanings.html):
+ * st_uid: The user ID of the file鈥檚 owner.
+ * st_gid: The group ID of the file.
+ * st_atime: This is the last access time for the file.
+ * st_mtime: This is the time of the last modification to the contents of the
+ * file.
+ * st_mode: Specifies the mode of the file. This includes file type information
+ * (see Testing File Type) and the file permission bits (see Permission
+ * Bits).
+ * st_nlink: The number of hard links to the file.This count keeps track of how
+ * many directories have entries for this file. If the count is ever
+ * decremented to zero, then the file itself is discarded as soon as
+ * no process still holds it open. Symbolic links are not counted in
+ * the total.
+ * st_size: This specifies the size of a regular file in bytes. For files that
+ * are really devices this field isn鈥檛 usually meaningful.For symbolic
+ * links this specifies the length of the file name the link refers to.
+ */
+int erofs_getattr(const char *path, struct stat *stbuf)
+{
+ struct erofs_vnode v;
+ int ret;
+
+ logd("getattr(%s)", path);
+ memset(&v, 0, sizeof(v));
+ ret = erofs_iget_by_path(path, &v);
+ if (ret)
+ return -ENOENT;
+
+ stbuf->st_mode = le16_to_cpu(v.i_mode);
+ stbuf->st_nlink = le16_to_cpu(v.i_nlink);
+ stbuf->st_size = le32_to_cpu(v.i_size);
+ stbuf->st_blocks = stbuf->st_size / EROFS_BLKSIZ;
+ stbuf->st_uid = le16_to_cpu(v.i_uid);
+ stbuf->st_gid = le16_to_cpu(v.i_gid);
+ stbuf->st_atime = super.build_time;
+ stbuf->st_mtime = super.build_time;
+ stbuf->st_ctime = super.build_time;
+
+ return 0;
+}
diff --git a/fuse/getattr.h b/fuse/getattr.h
new file mode 100644
index 000000000000..735529a91d5b
--- /dev/null
+++ b/fuse/getattr.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * erofs-utils/fuse/getattr.h
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#ifndef __EROFS_GETATTR_H
+#define __EROFS_GETATTR_H
+
+#include <fuse.h>
+#include <fuse_opt.h>
+
+int erofs_getattr(const char *path, struct stat *st);
+
+#endif
diff --git a/fuse/init.c b/fuse/init.c
new file mode 100644
index 000000000000..043629ff1088
--- /dev/null
+++ b/fuse/init.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/init.c
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#include "init.h"
+#include <string.h>
+#include <asm-generic/errno-base.h>
+
+#include "namei.h"
+#include "disk_io.h"
+#include "logging.h"
+
+#define STR(_X) (#_X)
+#define SUPER_MEM(_X) (super._X)
+
+
+struct erofs_super_block super;
+static struct erofs_super_block *sbk = &super;
+
+int erofs_init_super(void)
+{
+ int ret;
+ char buf[EROFS_BLKSIZ];
+ struct erofs_super_block *sb;
+
+ memset(buf, 0, sizeof(buf));
+ ret = dev_read_blk(buf, 0);
+ if (ret != EROFS_BLKSIZ) {
+ logi("Failed to read super block ret=%d", ret);
+ return -EINVAL;
+ }
+
+ sb = (struct erofs_super_block *) (buf + BOOT_SECTOR_SIZE);
+ sbk->magic = le32_to_cpu(sb->magic);
+ if (sbk->magic != EROFS_SUPER_MAGIC_V1) {
+ logi("EROFS magic[0x%X] NOT matched to [0x%X] ",
+ super.magic, EROFS_SUPER_MAGIC_V1);
+ return -EINVAL;
+ }
+
+ sbk->checksum = le32_to_cpu(sb->checksum);
+ sbk->feature_compat = le32_to_cpu(sb->feature_compat);
+ sbk->blkszbits = sb->blkszbits;
+ ASSERT(sbk->blkszbits != 32);
+
+ sbk->inos = le64_to_cpu(sb->inos);
+ sbk->build_time = le64_to_cpu(sb->build_time);
+ sbk->build_time_nsec = le32_to_cpu(sb->build_time_nsec);
+ sbk->blocks = le32_to_cpu(sb->blocks);
+ sbk->meta_blkaddr = le32_to_cpu(sb->meta_blkaddr);
+ sbk->xattr_blkaddr = le32_to_cpu(sb->xattr_blkaddr);
+ memcpy(sbk->uuid, sb->uuid, 16);
+ memcpy(sbk->volume_name, sb->volume_name, 16);
+ sbk->root_nid = le16_to_cpu(sb->root_nid);
+
+ logp("%-15s:0x%X", STR(magic), SUPER_MEM(magic));
+ logp("%-15s:0x%X", STR(feature_compat), SUPER_MEM(feature_compat));
+ logp("%-15s:%u", STR(blkszbits), SUPER_MEM(blkszbits));
+ logp("%-15s:%u", STR(root_nid), SUPER_MEM(root_nid));
+ logp("%-15s:%ul", STR(inos), SUPER_MEM(inos));
+ logp("%-15s:%d", STR(meta_blkaddr), SUPER_MEM(meta_blkaddr));
+ logp("%-15s:%d", STR(xattr_blkaddr), SUPER_MEM(xattr_blkaddr));
+
+ return 0;
+}
+
+erofs_nid_t erofs_get_root_nid(void)
+{
+ return sbk->root_nid;
+}
+
+erofs_nid_t addr2nid(erofs_off_t addr)
+{
+ erofs_nid_t offset = (erofs_nid_t)sbk->meta_blkaddr * EROFS_BLKSIZ;
+
+ ASSERT(IS_SLOT_ALIGN(addr));
+ return (addr - offset) >> EROFS_ISLOTBITS;
+}
+
+erofs_off_t nid2addr(erofs_nid_t nid)
+{
+ erofs_off_t offset = (erofs_off_t)sbk->meta_blkaddr * EROFS_BLKSIZ;
+
+ return (nid << EROFS_ISLOTBITS) + offset;
+}
+
+void *erofs_init(struct fuse_conn_info *info)
+{
+ logi("Using FUSE protocol %d.%d", info->proto_major, info->proto_minor);
+
+ if (inode_init(erofs_get_root_nid()) != 0) {
+ loge("inode initialization failed")
+ ABORT();
+ }
+ return NULL;
+}
diff --git a/fuse/init.h b/fuse/init.h
new file mode 100644
index 000000000000..34085f2b548d
--- /dev/null
+++ b/fuse/init.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * erofs-utils/fuse/init.h
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#ifndef __EROFS_INIT_H
+#define __EROFS_INIT_H
+
+#include <fuse.h>
+#include <fuse_opt.h>
+#include "erofs/internal.h"
+
+#define BOOT_SECTOR_SIZE 0x400
+
+int erofs_init_super(void);
+erofs_nid_t erofs_get_root_nid(void);
+erofs_off_t nid2addr(erofs_nid_t nid);
+erofs_nid_t addr2nid(erofs_off_t addr);
+void *erofs_init(struct fuse_conn_info *info);
+
+#endif
diff --git a/fuse/logging.c b/fuse/logging.c
new file mode 100644
index 000000000000..192f546b94ec
--- /dev/null
+++ b/fuse/logging.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/logging.c
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#include "logging.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <pthread.h>
+
+static int loglevel = DEFAULT_LOG_LEVEL;
+static FILE *logfile;
+static const char * const loglevel_str[] = {
+ [LOG_EMERG] = "[emerg]",
+ [LOG_ALERT] = "[alert]",
+ [LOG_DUMP] = "[dump] ",
+ [LOG_ERR] = "[err] ",
+ [LOG_WARNING] = "[warn] ",
+ [LOG_NOTICE] = "[notic]",
+ [LOG_INFO] = "[info] ",
+ [LOG_DEBUG] = "[debug]",
+};
+
+void __LOG(int level, const char *func, int line, const char *format, ...)
+{
+ static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+ va_list ap;
+ FILE *fp = logfile ? logfile : stdout;
+
+ if (!fp)
+ return;
+ if (level < 0 || level > loglevel)
+ return;
+
+ /* We have a lock here so different threads don interleave the log
+ * output
+ */
+ pthread_mutex_lock(&lock);
+ va_start(ap, format);
+ fprintf(fp, "%s", loglevel_str[level]);
+ if (func)
+ fprintf(fp, "%s", func);
+ if (line >= 0)
+ fprintf(fp, "(%d):", line);
+ vfprintf(fp, format, ap);
+ fprintf(fp, "\n");
+ va_end(ap);
+ fflush(fp);
+ pthread_mutex_unlock(&lock);
+}
+
+inline void logging_setlevel(int new_level)
+{
+ loglevel = new_level;
+}
+
+int logging_open(const char *path)
+{
+ if (path == NULL)
+ return 0;
+
+ logfile = fopen(path, "w");
+ if (logfile == NULL) {
+ perror("open");
+ return -1;
+ }
+
+ return 0;
+}
+
+void logging_close(void)
+{
+ if (logfile) {
+ fflush(logfile);
+ fclose(logfile);
+ logfile = NULL;
+ }
+}
+
diff --git a/fuse/logging.h b/fuse/logging.h
new file mode 100644
index 000000000000..3aa77ab08107
--- /dev/null
+++ b/fuse/logging.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * erofs-utils/fuse/logging.h
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#ifndef __LOGGING_H
+#define __LOGGING_H
+
+#include <assert.h>
+#include <stdlib.h>
+
+#define LOG_EMERG 0
+#define LOG_ALERT 1
+#define LOG_DUMP 2
+#define LOG_ERR 3
+#define LOG_WARNING 4
+#define LOG_NOTICE 5
+#define LOG_INFO 6
+#define LOG_DEBUG 7
+
+#define logem(...) __LOG(LOG_EMERG, __func__, __LINE__, ##__VA_ARGS__)
+#define loga(...) __LOG(LOG_ALERT, __func__, __LINE__, ##__VA_ARGS__)
+#define loge(...) __LOG(LOG_ERR, __func__, __LINE__, ##__VA_ARGS__)
+#define logw(...) __LOG(LOG_WARNING, __func__, __LINE__, ##__VA_ARGS__)
+#define logn(...) __LOG(LOG_NOTICE, __func__, __LINE__, ##__VA_ARGS__)
+#define logi(...) __LOG(LOG_INFO, __func__, __LINE__, ##__VA_ARGS__)
+#define logp(...) __LOG(LOG_DUMP, "", -1, ##__VA_ARGS__)
+#define logd(...) __LOG(LOG_DEBUG, __func__, __LINE__, ##__VA_ARGS__)
+
+#define DEFAULT_LOG_FILE "fuse.log"
+
+#ifdef _DEBUG
+#define DEFAULT_LOG_LEVEL LOG_DEBUG
+
+#define ASSERT(assertion) ({ \
+ if (!(assertion)) { \
+ logw("ASSERT FAIL: " #assertion); \
+ assert(assertion); \
+ } \
+})
+#define ABORT(_X) abort(_X)
+#else
+#define DEFAULT_LOG_LEVEL LOG_ERR
+#define ASSERT(assertion)
+#define ABORT(_X)
+#endif
+
+void __LOG(int level, const char *func, int line, const char *format, ...);
+void logging_setlevel(int new_level);
+int logging_open(const char *path);
+void logging_close(void);
+
+#endif
+
diff --git a/fuse/main.c b/fuse/main.c
new file mode 100644
index 000000000000..edecbed9a65a
--- /dev/null
+++ b/fuse/main.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/main.c
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <execinfo.h>
+#include <signal.h>
+#include <stddef.h>
+
+#include "logging.h"
+#include "init.h"
+#include "read.h"
+#include "getattr.h"
+#include "open.h"
+#include "readir.h"
+#include "disk_io.h"
+
+enum {
+ EROFS_OPT_HELP,
+ EROFS_OPT_VER,
+};
+
+struct options {
+ const char *disk;
+ const char *mount;
+ const char *logfile;
+ unsigned int debug_lvl;
+};
+static struct options cfg;
+
+#define OPTION(t, p) { t, offsetof(struct options, p), 1 }
+
+static const struct fuse_opt option_spec[] = {
+ OPTION("--log=%s", logfile),
+ OPTION("--dbg=%u", debug_lvl),
+ FUSE_OPT_KEY("-h", EROFS_OPT_HELP),
+ FUSE_OPT_KEY("-v", EROFS_OPT_VER),
+ FUSE_OPT_END
+};
+
+static void usage(void)
+{
+ fprintf(stderr, "\terofsfuse [options] <image> <mountpoint>\n");
+ fprintf(stderr, "\t --log=<file> output log file\n");
+ fprintf(stderr, "\t --dbg=<level> log debug level 0 ~ 7\n");
+ fprintf(stderr, "\t -h show help\n");
+ fprintf(stderr, "\t -v show version\n");
+ exit(1);
+}
+
+static void dump_cfg(void)
+{
+ fprintf(stderr, "\tdisk :%s\n", cfg.disk);
+ fprintf(stderr, "\tmount:%s\n", cfg.mount);
+ fprintf(stderr, "\tdebug_lvl:%u\n", cfg.debug_lvl);
+ fprintf(stderr, "\tlogfile :%s\n", cfg.logfile);
+}
+
+static int optional_opt_func(void *data, const char *arg, int key,
+ struct fuse_args *outargs)
+{
+ UNUSED(data);
+ UNUSED(outargs);
+
+ switch (key) {
+ case FUSE_OPT_KEY_OPT:
+ return 1;
+
+ case FUSE_OPT_KEY_NONOPT:
+ if (!cfg.disk) {
+ cfg.disk = strdup(arg);
+ return 0;
+ } else if (!cfg.mount)
+ cfg.mount = strdup(arg);
+
+ return 1;
+ case EROFS_OPT_HELP:
+ usage();
+ break;
+
+ case EROFS_OPT_VER:
+ fprintf(stderr, "EROFS FUSE VERSION v 1.0.0\n");
+ exit(0);
+ }
+
+ return 1;
+}
+
+static void signal_handle_sigsegv(int signal)
+{
+ void *array[10];
+ size_t nptrs;
+ char **strings;
+ size_t i;
+
+ UNUSED(signal);
+ logd("========================================");
+ logd("Segmentation Fault. Starting backtrace:");
+ nptrs = backtrace(array, 10);
+ strings = backtrace_symbols(array, nptrs);
+ if (strings) {
+ for (i = 0; i < nptrs; i++)
+ logd("%s", strings[i]);
+ free(strings);
+ }
+ logd("========================================");
+
+ abort();
+}
+
+static struct fuse_operations erofs_ops = {
+ .getattr = erofs_getattr,
+ .readdir = erofs_readdir,
+ .open = erofs_open,
+ .read = erofs_read,
+ .init = erofs_init,
+};
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_FAILURE;
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+
+ if (signal(SIGSEGV, signal_handle_sigsegv) == SIG_ERR) {
+ fprintf(stderr, "Failed to initialize signals\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Parse options */
+ if (fuse_opt_parse(&args, &cfg, option_spec, optional_opt_func) < 0)
+ return 1;
+
+ dump_cfg();
+
+ if (logging_open(cfg.logfile) < 0) {
+ fprintf(stderr, "Failed to initialize logging\n");
+ goto exit;
+ }
+
+ logging_setlevel(cfg.debug_lvl);
+
+ if (dev_open(cfg.disk) < 0) {
+ fprintf(stderr, "Failed to open disk:%s\n", cfg.disk);
+ goto exit_log;
+ }
+
+ if (erofs_init_super()) {
+ fprintf(stderr, "Failed to read erofs super block\n");
+ goto exit_dev;
+ }
+
+ logi("fuse start");
+
+ ret = fuse_main(args.argc, args.argv, &erofs_ops, NULL);
+
+ logi("fuse done ret=%d", ret);
+
+exit_dev:
+ dev_close();
+exit_log:
+ logging_close();
+exit:
+ fuse_opt_free_args(&args);
+ return ret;
+}
+
diff --git a/fuse/namei.c b/fuse/namei.c
new file mode 100644
index 000000000000..4d162047db15
--- /dev/null
+++ b/fuse/namei.c
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/namei.c
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#include "namei.h"
+#include <linux/kdev_t.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "erofs/defs.h"
+#include "logging.h"
+#include "disk_io.h"
+#include "dentry.h"
+#include "init.h"
+
+#define IS_PATH_SEPARATOR(__c) ((__c) == '/')
+#define MINORBITS 20
+#define MINORMASK ((1U << MINORBITS) - 1)
+#define DT_UNKNOWN 0
+
+static const char *skip_trailing_backslash(const char *path)
+{
+ while (IS_PATH_SEPARATOR(*path))
+ path++;
+ return path;
+}
+
+static uint8_t get_path_token_len(const char *path)
+{
+ uint8_t len = 0;
+
+ while (path[len] != '/' && path[len])
+ len++;
+ return len;
+}
+
+int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi)
+{
+ int ret;
+ char buf[EROFS_BLKSIZ];
+ struct erofs_inode_compact *v1;
+ const erofs_off_t addr = nid2addr(nid);
+ const size_t size = EROFS_BLKSIZ - erofs_blkoff(addr);
+
+ ret = dev_read(buf, size, addr);
+ if (ret != (int)size)
+ return -EIO;
+
+ v1 = (struct erofs_inode_compact *)buf;
+ vi->datalayout = __inode_data_mapping(le16_to_cpu(v1->i_format));
+ vi->inode_isize = sizeof(struct erofs_inode_compact);
+ vi->xattr_isize = erofs_xattr_ibody_size(v1->i_xattr_icount);
+ vi->i_size = le32_to_cpu(v1->i_size);
+ vi->i_mode = le16_to_cpu(v1->i_mode);
+ vi->i_uid = le16_to_cpu(v1->i_uid);
+ vi->i_gid = le16_to_cpu(v1->i_gid);
+ vi->i_nlink = le16_to_cpu(v1->i_nlink);
+ vi->nid = nid;
+
+ switch (vi->i_mode & S_IFMT) {
+ case S_IFBLK:
+ case S_IFCHR:
+ /* fixme: add special devices support
+ * vi->i_rdev = new_decode_dev(le32_to_cpu(v1->i_u.rdev));
+ */
+ break;
+ case S_IFIFO:
+ case S_IFSOCK:
+ /*fixme: vi->i_rdev = 0; */
+ break;
+ case S_IFREG:
+ case S_IFLNK:
+ case S_IFDIR:
+ vi->raw_blkaddr = le32_to_cpu(v1->i_u.raw_blkaddr);
+ break;
+ default:
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/* dirent + name string */
+struct dcache_entry *list_name(const char *buf, struct dcache_entry *parent,
+ const char *name, unsigned int len,
+ uint32_t dirend)
+{
+ struct dcache_entry *entry = NULL;
+ struct erofs_dirent *ds, *de;
+
+ ds = (struct erofs_dirent *)buf;
+ de = (struct erofs_dirent *)(buf + le16_to_cpu(ds->nameoff));
+
+ while (ds < de) {
+ erofs_nid_t nid = le64_to_cpu(ds->nid);
+ uint16_t nameoff = le16_to_cpu(ds->nameoff);
+ char *d_name = (char *)(buf + nameoff);
+ uint16_t name_len = (ds + 1 >= de) ?
+ (uint16_t)strnlen(d_name, dirend - nameoff) :
+ le16_to_cpu(ds[1].nameoff) - nameoff;
+
+ #if defined(EROFS_DEBUG_ENTRY)
+ {
+ char debug[EROFS_BLKSIZ];
+
+ memcpy(debug, d_name, name_len);
+ debug[name_len] = '\0';
+ logi("list entry: %s nid=%u", debug, nid);
+ }
+ #endif
+
+ entry = dcache_try_insert(parent, d_name, name_len, nid);
+ if (len == name_len && !memcmp(name, d_name, name_len))
+ return entry;
+
+ entry = NULL;
+ ++ds;
+ }
+
+ return entry;
+}
+
+struct dcache_entry *disk_lookup(struct dcache_entry *parent, const char *name,
+ unsigned int name_len)
+{
+ int ret;
+ char buf[EROFS_BLKSIZ];
+ struct dcache_entry *entry = NULL;
+ struct erofs_vnode v;
+ uint32_t nr_cnt, dir_nr, dirsize, blkno;
+
+ ret = erofs_iget_by_nid(parent->nid, &v);
+ if (ret)
+ return NULL;
+
+ /* to check whether dirent is in the inline dirs */
+ blkno = v.raw_blkaddr;
+ dirsize = v.i_size;
+ dir_nr = erofs_blknr(dirsize);
+
+ nr_cnt = 0;
+ while (nr_cnt < dir_nr) {
+ if (dev_read_blk(buf, blkno + nr_cnt) != EROFS_BLKSIZ)
+ return NULL;
+
+ entry = list_name(buf, parent, name, name_len, EROFS_BLKSIZ);
+ if (entry)
+ goto next;
+
+ ++nr_cnt;
+ }
+
+ if (v.datalayout == EROFS_INODE_FLAT_INLINE) {
+ uint32_t dir_off = erofs_blkoff(dirsize);
+ off_t dir_addr = nid2addr(dcache_get_nid(parent)) +
+ v.inode_isize + v.xattr_isize;
+
+ memset(buf, 0, sizeof(buf));
+ ret = dev_read(buf, dir_off, dir_addr);
+ if (ret < 0 && (uint32_t)ret != dir_off)
+ return NULL;
+
+ entry = list_name(buf, parent, name, name_len, dir_off);
+ }
+next:
+ return entry;
+}
+
+extern struct dcache_entry root_entry;
+int walk_path(const char *_path, erofs_nid_t *out_nid)
+{
+ struct dcache_entry *next, *ret;
+ const char *path = _path;
+
+ ret = next = &root_entry;
+ for (;;) {
+ uint8_t path_len;
+
+ path = skip_trailing_backslash(path);
+ path_len = get_path_token_len(path);
+ ret = next;
+ if (path_len == 0)
+ break;
+
+ next = dcache_lookup(ret, path, path_len);
+ if (!next) {
+ next = disk_lookup(ret, path, path_len);
+ if (!next)
+ return -ENOENT;
+ }
+
+ path += path_len;
+ }
+
+ if (!ret)
+ return -ENOENT;
+ logd("find path = %s nid=%u", _path, ret->nid);
+
+ *out_nid = ret->nid;
+ return 0;
+
+}
+
+int erofs_iget_by_path(const char *path, struct erofs_vnode *v)
+{
+ int ret;
+ erofs_nid_t nid;
+
+ ret = walk_path(path, &nid);
+ if (ret)
+ return ret;
+
+ return erofs_iget_by_nid(nid, v);
+}
+
+int inode_init(erofs_nid_t root)
+{
+ dcache_init_root(root);
+
+ return 0;
+}
+
diff --git a/fuse/namei.h b/fuse/namei.h
new file mode 100644
index 000000000000..1803a673daaf
--- /dev/null
+++ b/fuse/namei.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * erofs-utils/fuse/inode.h
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#ifndef __INODE_H
+#define __INODE_H
+
+#include "erofs/internal.h"
+#include "erofs_fs.h"
+
+int inode_init(erofs_nid_t root);
+struct dcache_entry *get_cached_dentry(struct dcache_entry **parent,
+ const char **path);
+int erofs_iget_by_path(const char *path, struct erofs_vnode *v);
+int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *v);
+struct dcache_entry *disk_lookup(struct dcache_entry *parent, const char *name,
+ unsigned int name_len);
+int walk_path(const char *path, erofs_nid_t *out_nid);
+
+#endif
diff --git a/fuse/open.c b/fuse/open.c
new file mode 100644
index 000000000000..c219d3870000
--- /dev/null
+++ b/fuse/open.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/open.c
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#include "open.h"
+#include <asm-generic/errno-base.h>
+#include <fuse.h>
+#include <fuse_opt.h>
+#include "logging.h"
+
+int erofs_open(const char *path, struct fuse_file_info *fi)
+{
+ logi("open path=%s", path);
+
+ if ((fi->flags & O_ACCMODE) != O_RDONLY)
+ return -EACCES;
+
+ return 0;
+}
+
diff --git a/fuse/open.h b/fuse/open.h
new file mode 100644
index 000000000000..dfc8b3cdd515
--- /dev/null
+++ b/fuse/open.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * erofs-utils/fuse/open.h
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#ifndef __EROFS_OPEN_H
+#define __EROFS_OPEN_H
+
+#include <fuse.h>
+#include <fuse_opt.h>
+
+int erofs_open(const char *path, struct fuse_file_info *fi);
+
+#endif
diff --git a/fuse/read.c b/fuse/read.c
new file mode 100644
index 000000000000..7e8f9516f853
--- /dev/null
+++ b/fuse/read.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/read.c
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#include "read.h"
+#include <errno.h>
+#include <linux/fs.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#include "erofs/defs.h"
+#include "erofs/internal.h"
+#include "logging.h"
+#include "namei.h"
+#include "disk_io.h"
+#include "init.h"
+
+size_t erofs_read_data(struct erofs_vnode *vnode, char *buffer,
+ size_t size, off_t offset)
+{
+ int ret;
+ size_t sum, rdsz = 0;
+ uint32_t addr = blknr_to_addr(vnode->raw_blkaddr) + offset;
+
+ sum = (offset + size) > vnode->i_size ?
+ (size_t)(vnode->i_size - offset) : size;
+ while (rdsz < sum) {
+ size_t count = min(EROFS_BLKSIZ, (uint32_t)(sum - rdsz));
+
+ ret = dev_read(buffer + rdsz, count, addr + rdsz);
+ if (ret < 0 || (size_t)ret != count)
+ return -EIO;
+ rdsz += count;
+ }
+
+ logi("nid:%u size=%zd offset=%llu realsize=%zd done",
+ vnode->nid, size, (long long)offset, rdsz);
+ return rdsz;
+
+}
+
+size_t erofs_read_data_inline(struct erofs_vnode *vnode, char *buffer,
+ size_t size, off_t offset)
+{
+ int ret;
+ size_t sum, suminline, rdsz = 0;
+ uint32_t addr = blknr_to_addr(vnode->raw_blkaddr) + offset;
+ uint32_t szblk = vnode->i_size - erofs_blkoff(vnode->i_size);
+
+ sum = (offset + size) > szblk ? (size_t)(szblk - offset) : size;
+ suminline = size - sum;
+
+ while (rdsz < sum) {
+ size_t count = min(EROFS_BLKSIZ, (uint32_t)(sum - rdsz));
+
+ ret = dev_read(buffer + rdsz, count, addr + rdsz);
+ if (ret < 0 || (uint32_t)ret != count)
+ return -EIO;
+ rdsz += count;
+ }
+
+ if (!suminline)
+ goto finished;
+
+ addr = nid2addr(vnode->nid) + vnode->inode_isize + vnode->xattr_isize;
+ ret = dev_read(buffer + rdsz, suminline, addr);
+ if (ret < 0 || (size_t)ret != suminline)
+ return -EIO;
+ rdsz += suminline;
+
+finished:
+ logi("nid:%u size=%zd suminline=%u offset=%llu realsize=%zd done",
+ vnode->nid, size, suminline, (long long)offset, rdsz);
+ return rdsz;
+
+}
+
+
+int erofs_read(const char *path, char *buffer, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ int ret;
+ erofs_nid_t nid;
+ struct erofs_vnode v;
+
+ UNUSED(fi);
+ logi("path:%s size=%zd offset=%llu", path, size, (long long)offset);
+
+ ret = walk_path(path, &nid);
+ if (ret)
+ return ret;
+
+ ret = erofs_iget_by_nid(nid, &v);
+ if (ret)
+ return ret;
+
+ logi("path:%s nid=%llu mode=%u", path, nid, v.datalayout);
+ switch (v.datalayout) {
+ case EROFS_INODE_FLAT_PLAIN:
+ return erofs_read_data(&v, buffer, size, offset);
+
+ case EROFS_INODE_FLAT_INLINE:
+ return erofs_read_data_inline(&v, buffer, size, offset);
+
+ case EROFS_INODE_FLAT_COMPRESSION_LEGACY:
+ case EROFS_INODE_FLAT_COMPRESSION:
+ /* Fixme: */
+ default:
+ return -EINVAL;
+ }
+}
diff --git a/fuse/read.h b/fuse/read.h
new file mode 100644
index 000000000000..3f4af1495510
--- /dev/null
+++ b/fuse/read.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * erofs-utils/fuse/read.h
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#ifndef __EROFS_READ_H
+#define __EROFS_READ_H
+
+#include <fuse.h>
+#include <fuse_opt.h>
+
+int erofs_read(const char *path, char *buffer, size_t size, off_t offset,
+ struct fuse_file_info *fi);
+
+#endif
diff --git a/fuse/readir.c b/fuse/readir.c
new file mode 100644
index 000000000000..b00274dad9f4
--- /dev/null
+++ b/fuse/readir.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/readir.c
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#include "readir.h"
+#include <errno.h>
+#include <linux/fs.h>
+#include <sys/stat.h>
+
+#include "erofs/defs.h"
+#include "erofs/internal.h"
+#include "erofs_fs.h"
+#include "namei.h"
+#include "disk_io.h"
+#include "logging.h"
+#include "init.h"
+
+erofs_nid_t split_entry(char *entry, off_t ofs, char *end, char *name,
+ uint32_t dirend)
+{
+ struct erofs_dirent *de = (struct erofs_dirent *)(entry + ofs);
+ uint16_t nameoff = le16_to_cpu(de->nameoff);
+ const char *de_name = entry + nameoff;
+ uint32_t de_namelen;
+
+ if ((void *)(de + 1) >= (void *)end)
+ de_namelen = strnlen(de_name, dirend - nameoff);
+ else
+ de_namelen = le16_to_cpu(de[1].nameoff) - nameoff;
+
+ memcpy(name, de_name, de_namelen);
+ name[de_namelen] = '\0';
+ return le64_to_cpu(de->nid);
+}
+
+int fill_dir(char *entrybuf, fuse_fill_dir_t filler, void *buf,
+ uint32_t dirend)
+{
+ uint32_t ofs;
+ uint16_t nameoff;
+ char *end;
+ char name[EROFS_BLKSIZ];
+
+ nameoff = le16_to_cpu(((struct erofs_dirent *)entrybuf)->nameoff);
+ end = entrybuf + nameoff;
+ ofs = 0;
+ while (ofs < nameoff) {
+ (void)split_entry(entrybuf, ofs, end, name, dirend);
+ filler(buf, name, NULL, 0);
+ ofs += sizeof(struct erofs_dirent);
+ }
+
+ return 0;
+}
+
+/** Function to add an entry in a readdir() operation
+ *
+ * @param buf the buffer passed to the readdir() operation
+ * @param name the file name of the directory entry
+ * @param stat file attributes, can be NULL
+ * @param off offset of the next entry or zero
+ * @return 1 if buffer is full, zero otherwise
+ */
+int erofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi)
+{
+ int ret;
+ erofs_nid_t nid;
+ struct erofs_vnode v;
+ char dirsbuf[EROFS_BLKSIZ];
+ uint32_t dir_nr, dir_off, nr_cnt;
+
+ logd("readdir:%s offset=%llu", path, (long long)offset);
+ UNUSED(fi);
+
+ ret = walk_path(path, &nid);
+ if (ret)
+ return ret;
+
+ logd("path=%s nid = %u", path, nid);
+ ret = erofs_iget_by_nid(nid, &v);
+ if (ret)
+ return ret;
+
+ if (!S_ISDIR(v.i_mode))
+ return -ENOTDIR;
+
+ if (!v.i_size)
+ return 0;
+
+ dir_nr = erofs_blknr(v.i_size);
+ dir_off = erofs_blkoff(v.i_size);
+ nr_cnt = 0;
+
+ logd("dir_size=%u dir_nr = %u dir_off=%u", v.i_size, dir_nr, dir_off);
+
+ while (nr_cnt < dir_nr) {
+ memset(dirsbuf, 0, sizeof(dirsbuf));
+ ret = dev_read_blk(dirsbuf, v.raw_blkaddr + nr_cnt);
+ if (ret != EROFS_BLKSIZ)
+ return -EIO;
+ fill_dir(dirsbuf, filler, buf, EROFS_BLKSIZ);
+ ++nr_cnt;
+ }
+
+ if (v.datalayout == EROFS_INODE_FLAT_INLINE) {
+ off_t addr;
+
+ addr = nid2addr(nid) + v.inode_isize + v.xattr_isize;
+
+ memset(dirsbuf, 0, sizeof(dirsbuf));
+ ret = dev_read(dirsbuf, dir_off, addr);
+ if (ret < 0 || (uint32_t)ret != dir_off)
+ return -EIO;
+ fill_dir(dirsbuf, filler, buf, dir_off);
+ }
+
+ return 0;
+}
+
diff --git a/fuse/readir.h b/fuse/readir.h
new file mode 100644
index 000000000000..ee2ab8bdd0f0
--- /dev/null
+++ b/fuse/readir.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * erofs-utils/fuse/readir.h
+ *
+ * Created by Li Guifu <blucerlee@gmail.com>
+ */
+#ifndef __EROFS_READDIR_H
+#define __EROFS_READDIR_H
+
+#include <fuse.h>
+#include <fuse_opt.h>
+
+int erofs_readdir(const char *path, void *buffer, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi);
+
+
+#endif
diff --git a/include/erofs/defs.h b/include/erofs/defs.h
index 8dee661ab9f0..e97de36aa04b 100644
--- a/include/erofs/defs.h
+++ b/include/erofs/defs.h
@@ -24,6 +24,9 @@
#ifdef HAVE_LINUX_TYPES_H
#include <linux/types.h>
#endif
+#ifndef UNUSED
+#define UNUSED(_X) ((void) _X)
+#endif
/*
* container_of - cast a member of a structure out to the containing structure
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index cabb2faa0072..1e3c23ae88b6 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -55,6 +55,8 @@ typedef u32 erofs_blk_t;
#define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ)
#define BLK_ROUND_UP(addr) DIV_ROUND_UP(addr, EROFS_BLKSIZ)
+#define IS_SLOT_ALIGN(__ADDR) (((__ADDR) % (EROFS_SLOTSIZE)) ? 0 : 1)
+#define IS_BLK_ALIGN(__ADDR) (((__ADDR) % (EROFS_BLKSIZ)) ? 0 : 1)
struct erofs_buffer_head;
@@ -132,11 +134,46 @@ struct erofs_inode {
#endif
};
+struct erofs_vnode {
+ uint8_t datalayout;
+
+ uint32_t i_size;
+ /* inline size in bytes */
+ uint16_t inode_isize;
+ uint16_t xattr_isize;
+
+ uint16_t xattr_shared_count;
+ char *xattr_shared_xattrs;
+
+ erofs_blk_t raw_blkaddr;
+ erofs_nid_t nid;
+ uint32_t i_ino;
+
+ uint16_t i_mode;
+ uint16_t i_uid;
+ uint16_t i_gid;
+ uint16_t i_nlink;
+
+ /* if file is inline read inline data witch inode */
+ char *idata;
+};
+
static inline bool is_inode_layout_compression(struct erofs_inode *inode)
{
return erofs_inode_is_data_compressed(inode->datalayout);
}
+#define __inode_advise(x, bit, bits) \
+ (((x) >> (bit)) & ((1 << (bits)) - 1))
+
+#define __inode_version(advise) \
+ __inode_advise(advise, EROFS_I_VERSION_BIT, \
+ EROFS_I_VERSION_BITS)
+
+#define __inode_data_mapping(advise) \
+ __inode_advise(advise, EROFS_I_DATALAYOUT_BIT,\
+ EROFS_I_DATALAYOUT_BITS)
+
#define IS_ROOT(x) ((x) == (x)->i_parent)
struct erofs_dentry {
--
2.24.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [WIP] [PATCH v2 2/5] erofs-utils: fuse: add special file support
2020-10-24 13:09 ` [WIP] [PATCH v2 0/5] erofs-utils: introduce fuse implementation Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 1/5] " Gao Xiang via Linux-erofs
@ 2020-10-24 13:09 ` Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 3/5] erofs-utils: fuse: add compressed " Gao Xiang via Linux-erofs
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Gao Xiang via Linux-erofs @ 2020-10-24 13:09 UTC (permalink / raw)
To: linux-erofs; +Cc: Zhang Shiming, Guo Weichao
From: Huang Jianan <huangjianan@oppo.com>
Signed-off-by: Huang Jianan <huangjianan@oppo.com>
Signed-off-by: Guo Weichao <guoweichao@oppo.com>
Signed-off-by: Gao Xiang <hsiangkao@aol.com>
---
fuse/getattr.c | 1 +
fuse/main.c | 1 +
fuse/namei.c | 14 ++++++++++----
fuse/read.c | 26 ++++++++++++++++++++++++++
fuse/read.h | 1 +
include/erofs/internal.h | 1 +
6 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/fuse/getattr.c b/fuse/getattr.c
index 2518adb8947f..e5200ebeef1a 100644
--- a/fuse/getattr.c
+++ b/fuse/getattr.c
@@ -56,6 +56,7 @@ int erofs_getattr(const char *path, struct stat *stbuf)
stbuf->st_blocks = stbuf->st_size / EROFS_BLKSIZ;
stbuf->st_uid = le16_to_cpu(v.i_uid);
stbuf->st_gid = le16_to_cpu(v.i_gid);
+ stbuf->st_rdev = le32_to_cpu(v.i_rdev);
stbuf->st_atime = super.build_time;
stbuf->st_mtime = super.build_time;
stbuf->st_ctime = super.build_time;
diff --git a/fuse/main.c b/fuse/main.c
index edecbed9a65a..9c8169725fa7 100644
--- a/fuse/main.c
+++ b/fuse/main.c
@@ -113,6 +113,7 @@ static void signal_handle_sigsegv(int signal)
}
static struct fuse_operations erofs_ops = {
+ .readlink = erofs_readlink,
.getattr = erofs_getattr,
.readdir = erofs_readdir,
.open = erofs_open,
diff --git a/fuse/namei.c b/fuse/namei.c
index 4d162047db15..6917d78d4f22 100644
--- a/fuse/namei.c
+++ b/fuse/namei.c
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
+#include <sys/sysmacros.h>
#include "erofs/defs.h"
#include "logging.h"
@@ -39,6 +40,13 @@ static uint8_t get_path_token_len(const char *path)
return len;
}
+static inline dev_t new_decode_dev(u32 dev)
+{
+ unsigned major = (dev & 0xfff00) >> 8;
+ unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
+ return makedev(major, minor);
+}
+
int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi)
{
int ret;
@@ -65,13 +73,11 @@ int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi)
switch (vi->i_mode & S_IFMT) {
case S_IFBLK:
case S_IFCHR:
- /* fixme: add special devices support
- * vi->i_rdev = new_decode_dev(le32_to_cpu(v1->i_u.rdev));
- */
+ vi->i_rdev = new_decode_dev(le32_to_cpu(v1->i_u.rdev));
break;
case S_IFIFO:
case S_IFSOCK:
- /*fixme: vi->i_rdev = 0; */
+ vi->i_rdev = 0;
break;
case S_IFREG:
case S_IFLNK:
diff --git a/fuse/read.c b/fuse/read.c
index 7e8f9516f853..760c9aa37f91 100644
--- a/fuse/read.c
+++ b/fuse/read.c
@@ -111,3 +111,29 @@ int erofs_read(const char *path, char *buffer, size_t size, off_t offset,
return -EINVAL;
}
}
+
+int erofs_readlink(const char *path, char *buffer, size_t size)
+{
+ int ret;
+ erofs_nid_t nid;
+ size_t lnksz;
+ struct erofs_vnode v;
+
+ ret = walk_path(path, &nid);
+ if (ret)
+ return ret;
+
+ ret = erofs_iget_by_nid(nid, &v);
+ if (ret)
+ return ret;
+
+ lnksz = min((size_t)v.i_size, size - 1);
+
+ ret = erofs_read(path, buffer, lnksz, 0, NULL);
+ buffer[lnksz] = '\0';
+ if (ret != (int)lnksz)
+ return ret;
+
+ logi("path:%s link=%s size=%llu", path, buffer, lnksz);
+ return 0;
+}
\ No newline at end of file
diff --git a/fuse/read.h b/fuse/read.h
index 3f4af1495510..e901c607dc91 100644
--- a/fuse/read.h
+++ b/fuse/read.h
@@ -12,5 +12,6 @@
int erofs_read(const char *path, char *buffer, size_t size, off_t offset,
struct fuse_file_info *fi);
+int erofs_readlink(const char *path, char *buffer, size_t size);
#endif
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 1e3c23ae88b6..e2769a6be4c9 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -153,6 +153,7 @@ struct erofs_vnode {
uint16_t i_uid;
uint16_t i_gid;
uint16_t i_nlink;
+ uint32_t i_rdev;
/* if file is inline read inline data witch inode */
char *idata;
--
2.24.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [WIP] [PATCH v2 3/5] erofs-utils: fuse: add compressed file support
2020-10-24 13:09 ` [WIP] [PATCH v2 0/5] erofs-utils: introduce fuse implementation Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 1/5] " Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 2/5] erofs-utils: fuse: add special file support Gao Xiang via Linux-erofs
@ 2020-10-24 13:09 ` Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 4/5] erofs-utils: fuse: drop "-Wextra" and "-Wno-implicit-fallthrough" Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 5/5] erofs-utils: fuse: get rid of duplicated logging code Gao Xiang via Linux-erofs
4 siblings, 0 replies; 9+ messages in thread
From: Gao Xiang via Linux-erofs @ 2020-10-24 13:09 UTC (permalink / raw)
To: linux-erofs; +Cc: Zhang Shiming, Guo Weichao
From: Huang Jianan <huangjianan@oppo.com>
Signed-off-by: Huang Jianan <huangjianan@oppo.com>
Signed-off-by: Guo Weichao <guoweichao@oppo.com>
Signed-off-by: Gao Xiang <hsiangkao@aol.com>
---
fuse/Makefile.am | 8 +-
fuse/decompress.c | 84 ++++++++
fuse/decompress.h | 42 ++++
fuse/dentry.h | 5 +-
fuse/init.c | 22 ++-
fuse/init.h | 2 +
fuse/namei.c | 11 +-
fuse/read.c | 78 +++++++-
fuse/zmap.c | 417 +++++++++++++++++++++++++++++++++++++++
include/erofs/defs.h | 13 ++
include/erofs/internal.h | 43 +++-
include/erofs_fs.h | 4 +
12 files changed, 720 insertions(+), 9 deletions(-)
create mode 100644 fuse/decompress.c
create mode 100644 fuse/decompress.h
create mode 100644 fuse/zmap.c
diff --git a/fuse/Makefile.am b/fuse/Makefile.am
index fffd67a53fe1..052c7163dff7 100644
--- a/fuse/Makefile.am
+++ b/fuse/Makefile.am
@@ -3,12 +3,16 @@
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = erofsfuse
-erofsfuse_SOURCES = main.c dentry.c getattr.c logging.c namei.c read.c disk_io.c init.c open.c readir.c
+erofsfuse_SOURCES = main.c dentry.c getattr.c logging.c namei.c read.c disk_io.c init.c open.c readir.c zmap.c
+if ENABLE_LZ4
+erofsfuse_SOURCES += decompress.c
+endif
erofsfuse_CFLAGS = -Wall -Werror -Wextra \
+ -Wno-implicit-fallthrough \
-I$(top_srcdir)/include \
$(shell pkg-config fuse --cflags) \
-DFUSE_USE_VERSION=26 \
-std=gnu99
LDFLAGS += $(shell pkg-config fuse --libs)
-erofsfuse_LDADD = $(top_builddir)/lib/liberofs.la -ldl
+erofsfuse_LDADD = $(top_builddir)/lib/liberofs.la -ldl ${LZ4_LIBS}
diff --git a/fuse/decompress.c b/fuse/decompress.c
new file mode 100644
index 000000000000..f2aa84146946
--- /dev/null
+++ b/fuse/decompress.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/decompress.c
+ *
+ * Copyright (C), 2008-2020, OPPO Mobile Comm Corp., Ltd.
+ * Created by Huang Jianan <huangjianan@oppo.com>
+ */
+#include <stdlib.h>
+#include <lz4.h>
+
+#include "erofs/internal.h"
+#include "erofs/err.h"
+#include "decompress.h"
+#include "logging.h"
+#include "init.h"
+
+static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq)
+{
+ int ret = 0;
+ char *dest = rq->out;
+ char *src = rq->in;
+ char *buff = NULL;
+ bool support_0padding = false;
+ unsigned int inputmargin = 0;
+
+ if (sbk->feature_incompat & EROFS_FEATURE_INCOMPAT_LZ4_0PADDING) {
+ support_0padding = true;
+
+ while (!src[inputmargin & ~PAGE_MASK])
+ if (!(++inputmargin & ~PAGE_MASK))
+ break;
+
+ if (inputmargin >= rq->inputsize)
+ return -EIO;
+ }
+
+ if (rq->decodedskip) {
+ buff = malloc(rq->decodedlength);
+ if (!buff)
+ return -ENOMEM;
+ dest = buff;
+ }
+
+ if (rq->partial_decoding || !support_0padding)
+ ret = LZ4_decompress_safe_partial(src + inputmargin, dest,
+ rq->inputsize - inputmargin,
+ rq->decodedlength, rq->decodedlength);
+ else
+ ret = LZ4_decompress_safe(src + inputmargin, dest,
+ rq->inputsize - inputmargin,
+ rq->decodedlength);
+
+ if (ret != (int)rq->decodedlength) {
+ ret = -EIO;
+ goto out;
+ }
+
+ if (rq->decodedskip)
+ memcpy(rq->out, dest + rq->decodedskip,
+ rq->decodedlength - rq->decodedskip);
+
+out:
+ if (buff)
+ free(buff);
+
+ return ret;
+}
+
+int z_erofs_decompress(struct z_erofs_decompress_req *rq)
+{
+ if (rq->alg == Z_EROFS_COMPRESSION_SHIFTED) {
+ if (rq->inputsize != EROFS_BLKSIZ)
+ return -EFSCORRUPTED;
+
+ DBG_BUGON(rq->decodedlength > EROFS_BLKSIZ);
+ DBG_BUGON(rq->decodedlength < rq->decodedskip);
+
+ memcpy(rq->out, rq->in + rq->decodedskip,
+ rq->decodedlength - rq->decodedskip);
+ return 0;
+ }
+
+ return z_erofs_decompress_generic(rq);
+}
diff --git a/fuse/decompress.h b/fuse/decompress.h
new file mode 100644
index 000000000000..508aabab1664
--- /dev/null
+++ b/fuse/decompress.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * erofs-utils/fuse/decompress.h
+ *
+ * Copyright (C), 2008-2020, OPPO Mobile Comm Corp., Ltd.
+ * Created by Huang Jianan <huangjianan@oppo.com>
+ */
+#ifndef __EROFS_DECOMPRESS_H
+#define __EROFS_DECOMPRESS_H
+
+#include "erofs/internal.h"
+
+enum {
+ Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
+ Z_EROFS_COMPRESSION_RUNTIME_MAX
+};
+
+struct z_erofs_decompress_req {
+ char *in, *out;
+
+ /*
+ * initial decompressed bytes that need to be skipped
+ * when finally copying to output buffer
+ */
+ unsigned int decodedskip;
+ unsigned int inputsize, decodedlength;
+
+ /* indicate the algorithm will be used for decompression */
+ unsigned int alg;
+ bool partial_decoding;
+};
+
+#ifdef LZ4_ENABLED
+int z_erofs_decompress(struct z_erofs_decompress_req *rq);
+#else
+int z_erofs_decompress(struct z_erofs_decompress_req *rq)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
+#endif
diff --git a/fuse/dentry.h b/fuse/dentry.h
index cb4d87972b2d..12f4cf6bafd9 100644
--- a/fuse/dentry.h
+++ b/fuse/dentry.h
@@ -10,10 +10,11 @@
#include <stdint.h>
#include "erofs/internal.h"
+/* fixme: Deal with names that exceed the allocated size */
#ifdef __64BITS
-#define DCACHE_ENTRY_NAME_LEN 40
+#define DCACHE_ENTRY_NAME_LEN EROFS_NAME_LEN
#else
-#define DCACHE_ENTRY_NAME_LEN 48
+#define DCACHE_ENTRY_NAME_LEN EROFS_NAME_LEN
#endif
/* This struct declares a node of a k-tree. Every node has a pointer to one of
diff --git a/fuse/init.c b/fuse/init.c
index 043629ff1088..48125c5791fa 100644
--- a/fuse/init.c
+++ b/fuse/init.c
@@ -17,7 +17,23 @@
struct erofs_super_block super;
-static struct erofs_super_block *sbk = &super;
+struct erofs_super_block *sbk = &super;
+
+static bool check_layout_compatibility(struct erofs_super_block *sb,
+ struct erofs_super_block *dsb)
+{
+ const unsigned int feature = le32_to_cpu(dsb->feature_incompat);
+
+ sb->feature_incompat = feature;
+
+ /* check if current kernel meets all mandatory requirements */
+ if (feature & (~EROFS_ALL_FEATURE_INCOMPAT)) {
+ loge("unidentified incompatible feature %x, please upgrade kernel version",
+ feature & ~EROFS_ALL_FEATURE_INCOMPAT);
+ return false;
+ }
+ return true;
+}
int erofs_init_super(void)
{
@@ -40,6 +56,9 @@ int erofs_init_super(void)
return -EINVAL;
}
+ if (!check_layout_compatibility(sbk, sb))
+ return -EINVAL;
+
sbk->checksum = le32_to_cpu(sb->checksum);
sbk->feature_compat = le32_to_cpu(sb->feature_compat);
sbk->blkszbits = sb->blkszbits;
@@ -56,6 +75,7 @@ int erofs_init_super(void)
sbk->root_nid = le16_to_cpu(sb->root_nid);
logp("%-15s:0x%X", STR(magic), SUPER_MEM(magic));
+ logp("%-15s:0x%X", STR(feature_incompat), SUPER_MEM(feature_incompat));
logp("%-15s:0x%X", STR(feature_compat), SUPER_MEM(feature_compat));
logp("%-15s:%u", STR(blkszbits), SUPER_MEM(blkszbits));
logp("%-15s:%u", STR(root_nid), SUPER_MEM(root_nid));
diff --git a/fuse/init.h b/fuse/init.h
index 34085f2b548d..405a92913b4a 100644
--- a/fuse/init.h
+++ b/fuse/init.h
@@ -13,6 +13,8 @@
#define BOOT_SECTOR_SIZE 0x400
+extern struct erofs_super_block *sbk;
+
int erofs_init_super(void);
erofs_nid_t erofs_get_root_nid(void);
erofs_off_t nid2addr(erofs_nid_t nid);
diff --git a/fuse/namei.c b/fuse/namei.c
index 6917d78d4f22..c33af4b04b45 100644
--- a/fuse/namei.c
+++ b/fuse/namei.c
@@ -49,7 +49,7 @@ static inline dev_t new_decode_dev(u32 dev)
int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi)
{
- int ret;
+ int ret, ifmt;
char buf[EROFS_BLKSIZ];
struct erofs_inode_compact *v1;
const erofs_off_t addr = nid2addr(nid);
@@ -60,6 +60,11 @@ int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi)
return -EIO;
v1 = (struct erofs_inode_compact *)buf;
+ /* fixme: support extended inode */
+ ifmt = le16_to_cpu(v1->i_format);
+ if (__inode_version(ifmt) != EROFS_INODE_LAYOUT_COMPACT)
+ return -EOPNOTSUPP;
+
vi->datalayout = __inode_data_mapping(le16_to_cpu(v1->i_format));
vi->inode_isize = sizeof(struct erofs_inode_compact);
vi->xattr_isize = erofs_xattr_ibody_size(v1->i_xattr_icount);
@@ -88,6 +93,10 @@ int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi)
return -EIO;
}
+ vi->z_inited = false;
+ if (erofs_inode_is_data_compressed(vi->datalayout))
+ z_erofs_fill_inode(vi);
+
return 0;
}
diff --git a/fuse/read.c b/fuse/read.c
index 760c9aa37f91..e2f967aefb8a 100644
--- a/fuse/read.c
+++ b/fuse/read.c
@@ -3,6 +3,7 @@
* erofs-utils/fuse/read.c
*
* Created by Li Guifu <blucerlee@gmail.com>
+ * Compression support by Huang Jianan <huangjianan@oppo.com>
*/
#include "read.h"
#include <errno.h>
@@ -16,6 +17,7 @@
#include "namei.h"
#include "disk_io.h"
#include "init.h"
+#include "decompress.h"
size_t erofs_read_data(struct erofs_vnode *vnode, char *buffer,
size_t size, off_t offset)
@@ -77,6 +79,77 @@ finished:
}
+size_t erofs_read_data_compression(struct erofs_vnode *vnode, char *buffer,
+ erofs_off_t size, erofs_off_t offset)
+{
+ int ret;
+ erofs_off_t end, length, skip;
+ struct erofs_map_blocks map = {
+ .index = UINT_MAX,
+ };
+ bool partial;
+ unsigned int algorithmformat;
+ char raw[EROFS_BLKSIZ];
+
+ end = offset + size;
+ while (end > offset) {
+ map.m_la = end - 1;
+
+ ret = z_erofs_map_blocks_iter(vnode, &map);
+ if (ret)
+ return ret;
+
+ if (!(map.m_flags & EROFS_MAP_MAPPED)) {
+ end = map.m_la;
+ continue;
+ }
+
+ ret = dev_read(raw, EROFS_BLKSIZ, map.m_pa);
+ if (ret < 0 || (size_t)ret != EROFS_BLKSIZ)
+ return -EIO;
+
+ algorithmformat = map.m_flags & EROFS_MAP_ZIPPED ?
+ Z_EROFS_COMPRESSION_LZ4 :
+ Z_EROFS_COMPRESSION_SHIFTED;
+
+ /*
+ * trim to the needed size if the returned extent is quite
+ * larger than requested, and set up partial flag as well.
+ */
+ if (end < map.m_la + map.m_llen) {
+ length = end - map.m_la;
+ partial = true;
+ } else {
+ ASSERT(end == map.m_la + map.m_llen);
+ length = map.m_llen;
+ partial = !(map.m_flags & EROFS_MAP_FULL_MAPPED);
+ }
+
+ if (map.m_la < offset) {
+ skip = offset - map.m_la;
+ end = offset;
+ } else {
+ skip = 0;
+ end = map.m_la;
+ }
+
+ ret = z_erofs_decompress(&(struct z_erofs_decompress_req) {
+ .in = raw,
+ .out = buffer + end - offset,
+ .decodedskip = skip,
+ .inputsize = map.m_plen,
+ .decodedlength = length,
+ .alg = algorithmformat,
+ .partial_decoding = partial
+ });
+ if (ret < 0)
+ return ret;
+ }
+
+ logi("nid:%u size=%zd offset=%llu done",
+ vnode->nid, size, (long long)offset);
+ return size;
+}
int erofs_read(const char *path, char *buffer, size_t size, off_t offset,
struct fuse_file_info *fi)
@@ -106,7 +179,8 @@ int erofs_read(const char *path, char *buffer, size_t size, off_t offset,
case EROFS_INODE_FLAT_COMPRESSION_LEGACY:
case EROFS_INODE_FLAT_COMPRESSION:
- /* Fixme: */
+ return erofs_read_data_compression(&v, buffer, size, offset);
+
default:
return -EINVAL;
}
@@ -136,4 +210,4 @@ int erofs_readlink(const char *path, char *buffer, size_t size)
logi("path:%s link=%s size=%llu", path, buffer, lnksz);
return 0;
-}
\ No newline at end of file
+}
diff --git a/fuse/zmap.c b/fuse/zmap.c
new file mode 100644
index 000000000000..8ec0a7707fd6
--- /dev/null
+++ b/fuse/zmap.c
@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * erofs-utils/fuse/zmap.c
+ *
+ * (a large amount of code was adapted from Linux kernel. )
+ *
+ * Copyright (C) 2018-2019 HUAWEI, Inc.
+ * https://www.huawei.com/
+ * Created by Gao Xiang <gaoxiang25@huawei.com>
+ * Modified by Huang Jianan <huangjianan@oppo.com>
+ */
+#include "init.h"
+#include "disk_io.h"
+#include "logging.h"
+
+int z_erofs_fill_inode(struct erofs_vnode *vi)
+{
+ if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) {
+ vi->z_advise = 0;
+ vi->z_algorithmtype[0] = 0;
+ vi->z_algorithmtype[1] = 0;
+ vi->z_logical_clusterbits = LOG_BLOCK_SIZE;
+ vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits;
+ vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits;
+ vi->z_inited = true;
+ }
+
+ return 0;
+}
+
+static int z_erofs_fill_inode_lazy(struct erofs_vnode *vi)
+{
+ int ret;
+ erofs_off_t pos;
+ struct z_erofs_map_header *h;
+ char buf[8];
+
+ if (vi->z_inited)
+ return 0;
+
+ DBG_BUGON(vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY);
+
+ pos = round_up(nid2addr(vi->nid) + vi->inode_isize + vi->xattr_isize, 8);
+
+ ret = dev_read(buf, 8, pos);
+ if (ret < 0 && (uint32_t)ret != 8)
+ return -EIO;
+
+ h = (struct z_erofs_map_header *)buf;
+ vi->z_advise = le16_to_cpu(h->h_advise);
+ vi->z_algorithmtype[0] = h->h_algorithmtype & 15;
+ vi->z_algorithmtype[1] = h->h_algorithmtype >> 4;
+
+ if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX) {
+ loge("unknown compression format %u for nid %llu",
+ vi->z_algorithmtype[0], vi->nid);
+ return -EOPNOTSUPP;
+ }
+
+ vi->z_logical_clusterbits = LOG_BLOCK_SIZE + (h->h_clusterbits & 7);
+ vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits +
+ ((h->h_clusterbits >> 3) & 3);
+
+ if (vi->z_physical_clusterbits[0] != LOG_BLOCK_SIZE) {
+ loge("unsupported physical clusterbits %u for nid %llu",
+ vi->z_physical_clusterbits[0], vi->nid);
+ return -EOPNOTSUPP;
+ }
+
+ vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits +
+ ((h->h_clusterbits >> 5) & 7);
+ vi->z_inited = true;
+
+ return 0;
+}
+
+struct z_erofs_maprecorder {
+ struct erofs_vnode *vnode;
+ struct erofs_map_blocks *map;
+ void *kaddr;
+
+ unsigned long lcn;
+ /* compression extent information gathered */
+ u8 type;
+ u16 clusterofs;
+ u16 delta[2];
+ erofs_blk_t pblk;
+};
+
+static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m,
+ erofs_blk_t eblk)
+{
+ int ret;
+ struct erofs_map_blocks *const map = m->map;
+ char *mpage = map->mpage;
+
+ if (map->index == eblk)
+ return 0;
+
+ ret = dev_read(mpage, EROFS_BLKSIZ, blknr_to_addr(eblk));
+ if (ret < 0 && (uint32_t)ret != EROFS_BLKSIZ)
+ return -EIO;
+
+ map->index = eblk;
+
+ return 0;
+}
+
+static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m,
+ unsigned long lcn)
+{
+ struct erofs_vnode *const vi = m->vnode;
+ const erofs_off_t ibase = nid2addr(vi->nid);
+ const erofs_off_t pos =
+ Z_EROFS_VLE_LEGACY_INDEX_ALIGN(ibase + vi->inode_isize +
+ vi->xattr_isize) +
+ lcn * sizeof(struct z_erofs_vle_decompressed_index);
+ struct z_erofs_vle_decompressed_index *di;
+ unsigned int advise, type;
+ int err;
+
+ err = z_erofs_reload_indexes(m, erofs_blknr(pos));
+ if (err)
+ return err;
+
+ m->lcn = lcn;
+ di = m->kaddr + erofs_blkoff(pos);
+
+ advise = le16_to_cpu(di->di_advise);
+ type = (advise >> Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT) &
+ ((1 << Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) - 1);
+ switch (type) {
+ case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
+ m->clusterofs = 1 << vi->z_logical_clusterbits;
+ m->delta[0] = le16_to_cpu(di->di_u.delta[0]);
+ m->delta[1] = le16_to_cpu(di->di_u.delta[1]);
+ break;
+ case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
+ case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
+ m->clusterofs = le16_to_cpu(di->di_clusterofs);
+ m->pblk = le32_to_cpu(di->di_u.blkaddr);
+ break;
+ default:
+ DBG_BUGON(1);
+ return -EOPNOTSUPP;
+ }
+ m->type = type;
+ return 0;
+}
+
+static unsigned int decode_compactedbits(unsigned int lobits,
+ unsigned int lomask,
+ u8 *in, unsigned int pos, u8 *type)
+{
+ const unsigned int v = get_unaligned_le32(in + pos / 8) >> (pos & 7);
+ const unsigned int lo = v & lomask;
+
+ *type = (v >> lobits) & 3;
+ return lo;
+}
+
+static int unpack_compacted_index(struct z_erofs_maprecorder *m,
+ unsigned int amortizedshift,
+ unsigned int eofs)
+{
+ struct erofs_vnode *const vi = m->vnode;
+ const unsigned int lclusterbits = vi->z_logical_clusterbits;
+ const unsigned int lomask = (1 << lclusterbits) - 1;
+ unsigned int vcnt, base, lo, encodebits, nblk;
+ int i;
+ u8 *in, type;
+
+ if (1 << amortizedshift == 4)
+ vcnt = 2;
+ else if (1 << amortizedshift == 2 && lclusterbits == 12)
+ vcnt = 16;
+ else
+ return -EOPNOTSUPP;
+
+ encodebits = ((vcnt << amortizedshift) - sizeof(__le32)) * 8 / vcnt;
+ base = round_down(eofs, vcnt << amortizedshift);
+ in = m->kaddr + base;
+
+ i = (eofs - base) >> amortizedshift;
+
+ lo = decode_compactedbits(lclusterbits, lomask,
+ in, encodebits * i, &type);
+ m->type = type;
+ if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
+ m->clusterofs = 1 << lclusterbits;
+ if (i + 1 != (int)vcnt) {
+ m->delta[0] = lo;
+ return 0;
+ }
+ /*
+ * since the last lcluster in the pack is special,
+ * of which lo saves delta[1] rather than delta[0].
+ * Hence, get delta[0] by the previous lcluster indirectly.
+ */
+ lo = decode_compactedbits(lclusterbits, lomask,
+ in, encodebits * (i - 1), &type);
+ if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
+ lo = 0;
+ m->delta[0] = lo + 1;
+ return 0;
+ }
+ m->clusterofs = lo;
+ m->delta[0] = 0;
+ /* figout out blkaddr (pblk) for HEAD lclusters */
+ nblk = 1;
+ while (i > 0) {
+ --i;
+ lo = decode_compactedbits(lclusterbits, lomask,
+ in, encodebits * i, &type);
+ if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
+ i -= lo;
+
+ if (i >= 0)
+ ++nblk;
+ }
+ in += (vcnt << amortizedshift) - sizeof(__le32);
+ m->pblk = le32_to_cpu(*(__le32 *)in) + nblk;
+ return 0;
+}
+
+static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m,
+ unsigned long lcn)
+{
+ struct erofs_vnode *const vi = m->vnode;
+ const unsigned int lclusterbits = vi->z_logical_clusterbits;
+ const erofs_off_t ebase = round_up(nid2addr(vi->nid) + vi->inode_isize +
+ vi->xattr_isize, 8) +
+ sizeof(struct z_erofs_map_header);
+ const unsigned int totalidx = DIV_ROUND_UP(vi->i_size, EROFS_BLKSIZ);
+ unsigned int compacted_4b_initial, compacted_2b;
+ unsigned int amortizedshift;
+ erofs_off_t pos;
+ int err;
+
+ if (lclusterbits != 12)
+ return -EOPNOTSUPP;
+
+ if (lcn >= totalidx)
+ return -EINVAL;
+
+ m->lcn = lcn;
+ /* used to align to 32-byte (compacted_2b) alignment */
+ compacted_4b_initial = (32 - ebase % 32) / 4;
+ if (compacted_4b_initial == 32 / 4)
+ compacted_4b_initial = 0;
+
+ if (vi->z_advise & Z_EROFS_ADVISE_COMPACTED_2B)
+ compacted_2b = rounddown(totalidx - compacted_4b_initial, 16);
+ else
+ compacted_2b = 0;
+
+ pos = ebase;
+ if (lcn < compacted_4b_initial) {
+ amortizedshift = 2;
+ goto out;
+ }
+ pos += compacted_4b_initial * 4;
+ lcn -= compacted_4b_initial;
+
+ if (lcn < compacted_2b) {
+ amortizedshift = 1;
+ goto out;
+ }
+ pos += compacted_2b * 2;
+ lcn -= compacted_2b;
+ amortizedshift = 2;
+out:
+ pos += lcn * (1 << amortizedshift);
+ err = z_erofs_reload_indexes(m, erofs_blknr(pos));
+ if (err)
+ return err;
+ return unpack_compacted_index(m, amortizedshift, erofs_blkoff(pos));
+}
+
+static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m,
+ unsigned int lcn)
+{
+ const unsigned int datamode = m->vnode->datalayout;
+
+ if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY)
+ return legacy_load_cluster_from_disk(m, lcn);
+
+ if (datamode == EROFS_INODE_FLAT_COMPRESSION)
+ return compacted_load_cluster_from_disk(m, lcn);
+
+ return -EINVAL;
+}
+
+static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
+ unsigned int lookback_distance)
+{
+ struct erofs_vnode *const vi = m->vnode;
+ struct erofs_map_blocks *const map = m->map;
+ const unsigned int lclusterbits = vi->z_logical_clusterbits;
+ unsigned long lcn = m->lcn;
+ int err;
+
+ if (lcn < lookback_distance) {
+ loge("bogus lookback distance @ nid %llu", vi->nid);
+ DBG_BUGON(1);
+ return -EFSCORRUPTED;
+ }
+
+ /* load extent head logical cluster if needed */
+ lcn -= lookback_distance;
+ err = z_erofs_load_cluster_from_disk(m, lcn);
+ if (err)
+ return err;
+
+ switch (m->type) {
+ case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
+ if (!m->delta[0]) {
+ loge("invalid lookback distance 0 @ nid %llu",
+ vi->nid);
+ DBG_BUGON(1);
+ return -EFSCORRUPTED;
+ }
+ return z_erofs_extent_lookback(m, m->delta[0]);
+ case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
+ map->m_flags &= ~EROFS_MAP_ZIPPED;
+ case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
+ map->m_la = (lcn << lclusterbits) | m->clusterofs;
+ break;
+ default:
+ loge("unknown type %u @ lcn %lu of nid %llu",
+ m->type, lcn, vi->nid);
+ DBG_BUGON(1);
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+int z_erofs_map_blocks_iter(struct erofs_vnode *vi,
+ struct erofs_map_blocks *map)
+{
+ struct z_erofs_maprecorder m = {
+ .vnode = vi,
+ .map = map,
+ .kaddr = map->mpage,
+ };
+ int err = 0;
+ unsigned int lclusterbits, endoff;
+ unsigned long long ofs, end;
+
+ /* when trying to read beyond EOF, leave it unmapped */
+ if (map->m_la >= vi->i_size) {
+ map->m_llen = map->m_la + 1 - vi->i_size;
+ map->m_la = vi->i_size;
+ map->m_flags = 0;
+ goto out;
+ }
+
+ err = z_erofs_fill_inode_lazy(vi);
+ if (err)
+ goto out;
+
+ lclusterbits = vi->z_logical_clusterbits;
+ ofs = map->m_la;
+ m.lcn = ofs >> lclusterbits;
+ endoff = ofs & ((1 << lclusterbits) - 1);
+
+ err = z_erofs_load_cluster_from_disk(&m, m.lcn);
+ if (err)
+ goto out;
+
+ map->m_flags = EROFS_MAP_ZIPPED; /* by default, compressed */
+ end = (m.lcn + 1ULL) << lclusterbits;
+ switch (m.type) {
+ case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
+ if (endoff >= m.clusterofs)
+ map->m_flags &= ~EROFS_MAP_ZIPPED;
+ case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
+ if (endoff >= m.clusterofs) {
+ map->m_la = (m.lcn << lclusterbits) | m.clusterofs;
+ break;
+ }
+ /* m.lcn should be >= 1 if endoff < m.clusterofs */
+ if (!m.lcn) {
+ loge("invalid logical cluster 0 at nid %llu",
+ vi->nid);
+ err = -EFSCORRUPTED;
+ goto out;
+ }
+ end = (m.lcn << lclusterbits) | m.clusterofs;
+ map->m_flags |= EROFS_MAP_FULL_MAPPED;
+ m.delta[0] = 1;
+ case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
+ /* get the correspoinding first chunk */
+ err = z_erofs_extent_lookback(&m, m.delta[0]);
+ if (err)
+ goto out;
+ break;
+ default:
+ loge("unknown type %u @ offset %llu of nid %llu",
+ m.type, ofs, vi->nid);
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ map->m_llen = end - map->m_la;
+ map->m_plen = 1 << lclusterbits;
+ map->m_pa = blknr_to_addr(m.pblk);
+ map->m_flags |= EROFS_MAP_MAPPED;
+
+out:
+ logd("m_la %llu m_pa %llu m_llen %llu m_plen %llu m_flags 0%o",
+ map->m_la, map->m_pa,
+ map->m_llen, map->m_plen, map->m_flags);
+
+ DBG_BUGON(err < 0 && err != -ENOMEM);
+ return err;
+}
diff --git a/include/erofs/defs.h b/include/erofs/defs.h
index e97de36aa04b..c42ca401a8ee 100644
--- a/include/erofs/defs.h
+++ b/include/erofs/defs.h
@@ -173,5 +173,18 @@ typedef int64_t s64;
#define __maybe_unused __attribute__((__unused__))
#endif
+struct __una_u32 { u32 x; } __packed;
+
+static inline u32 __get_unaligned_cpu32(const void *p)
+{
+ const struct __una_u32 *ptr = (const struct __una_u32 *)p;
+ return ptr->x;
+}
+
+static inline u32 get_unaligned_le32(const void *p)
+{
+ return __get_unaligned_cpu32((const u8 *)p);
+}
+
#endif
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index e2769a6be4c9..6c5fbd3c5d3c 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -36,6 +36,8 @@ typedef unsigned short umode_t;
#error incompatible PAGE_SIZE is already defined
#endif
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
#define LOG_BLOCK_SIZE (12)
#define EROFS_BLKSIZ (1U << LOG_BLOCK_SIZE)
@@ -145,7 +147,15 @@ struct erofs_vnode {
uint16_t xattr_shared_count;
char *xattr_shared_xattrs;
- erofs_blk_t raw_blkaddr;
+ union {
+ erofs_blk_t raw_blkaddr;
+ struct {
+ uint16_t z_advise;
+ uint8_t z_algorithmtype[2];
+ uint8_t z_logical_clusterbits;
+ uint8_t z_physical_clusterbits[2];
+ };
+ };
erofs_nid_t nid;
uint32_t i_ino;
@@ -155,6 +165,7 @@ struct erofs_vnode {
uint16_t i_nlink;
uint32_t i_rdev;
+ bool z_inited;
/* if file is inline read inline data witch inode */
char *idata;
};
@@ -207,5 +218,35 @@ static inline const char *erofs_strerror(int err)
return msg;
}
+enum {
+ BH_Mapped ,
+ BH_Zipped ,
+ BH_FullMapped,
+};
+
+/* Has a disk mapping */
+#define EROFS_MAP_MAPPED (1 << BH_Mapped)
+/* The extent has been compressed */
+#define EROFS_MAP_ZIPPED (1 << BH_Zipped)
+/* The length of extent is full */
+#define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped)
+
+struct erofs_map_blocks {
+ char mpage[EROFS_BLKSIZ];
+
+ erofs_off_t m_pa, m_la;
+ u64 m_plen, m_llen;
+
+ unsigned int m_flags;
+ erofs_blk_t index;
+};
+
+/* zmap.c */
+int z_erofs_fill_inode(struct erofs_vnode *vi);
+int z_erofs_map_blocks_iter(struct erofs_vnode *vi,
+ struct erofs_map_blocks *map);
+
+#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
+
#endif
diff --git a/include/erofs_fs.h b/include/erofs_fs.h
index 4cd79f01d820..a69f179a51a5 100644
--- a/include/erofs_fs.h
+++ b/include/erofs_fs.h
@@ -279,6 +279,10 @@ struct z_erofs_vle_decompressed_index {
} di_u;
};
+#define Z_EROFS_VLE_LEGACY_INDEX_ALIGN(size) \
+ (round_up(size, sizeof(struct z_erofs_vle_decompressed_index)) + \
+ sizeof(struct z_erofs_map_header) + Z_EROFS_VLE_LEGACY_HEADER_PADDING)
+
#define Z_EROFS_VLE_EXTENT_ALIGN(size) round_up(size, \
sizeof(struct z_erofs_vle_decompressed_index))
--
2.24.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [WIP] [PATCH v2 4/5] erofs-utils: fuse: drop "-Wextra" and "-Wno-implicit-fallthrough"
2020-10-24 13:09 ` [WIP] [PATCH v2 0/5] erofs-utils: introduce fuse implementation Gao Xiang via Linux-erofs
` (2 preceding siblings ...)
2020-10-24 13:09 ` [WIP] [PATCH v2 3/5] erofs-utils: fuse: add compressed " Gao Xiang via Linux-erofs
@ 2020-10-24 13:09 ` Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 5/5] erofs-utils: fuse: get rid of duplicated logging code Gao Xiang via Linux-erofs
4 siblings, 0 replies; 9+ messages in thread
From: Gao Xiang via Linux-erofs @ 2020-10-24 13:09 UTC (permalink / raw)
To: linux-erofs; +Cc: Zhang Shiming, Guo Weichao
[ will be folded to the original patch. ]
Signed-off-by: Gao Xiang <hsiangkao@aol.com>
---
fuse/Makefile.am | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/fuse/Makefile.am b/fuse/Makefile.am
index 052c7163dff7..a50d2c4d0ab3 100644
--- a/fuse/Makefile.am
+++ b/fuse/Makefile.am
@@ -7,8 +7,7 @@ erofsfuse_SOURCES = main.c dentry.c getattr.c logging.c namei.c read.c disk_io.c
if ENABLE_LZ4
erofsfuse_SOURCES += decompress.c
endif
-erofsfuse_CFLAGS = -Wall -Werror -Wextra \
- -Wno-implicit-fallthrough \
+erofsfuse_CFLAGS = -Wall -Werror \
-I$(top_srcdir)/include \
$(shell pkg-config fuse --cflags) \
-DFUSE_USE_VERSION=26 \
--
2.24.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [WIP] [PATCH v2 5/5] erofs-utils: fuse: get rid of duplicated logging code
2020-10-24 13:09 ` [WIP] [PATCH v2 0/5] erofs-utils: introduce fuse implementation Gao Xiang via Linux-erofs
` (3 preceding siblings ...)
2020-10-24 13:09 ` [WIP] [PATCH v2 4/5] erofs-utils: fuse: drop "-Wextra" and "-Wno-implicit-fallthrough" Gao Xiang via Linux-erofs
@ 2020-10-24 13:09 ` Gao Xiang via Linux-erofs
2020-10-24 15:27 ` [WIP] [PATCH 6/5] erofs-utils: fuse: get rid of duplicated I/O ops Gao Xiang via Linux-erofs
4 siblings, 1 reply; 9+ messages in thread
From: Gao Xiang via Linux-erofs @ 2020-10-24 13:09 UTC (permalink / raw)
To: linux-erofs; +Cc: Zhang Shiming, Guo Weichao
[ will be folded to the original patch. ]
Signed-off-by: Gao Xiang <hsiangkao@aol.com>
---
fuse/Makefile.am | 2 +-
fuse/decompress.c | 1 -
fuse/dentry.c | 7 ++--
fuse/disk_io.c | 10 +++---
fuse/getattr.c | 4 +--
fuse/init.c | 39 +++++++++++------------
fuse/logging.c | 81 -----------------------------------------------
fuse/logging.h | 55 --------------------------------
fuse/main.c | 52 ++++++++++++++----------------
fuse/namei.c | 6 ++--
fuse/open.c | 4 +--
fuse/read.c | 22 ++++++-------
fuse/readir.c | 8 ++---
fuse/zmap.c | 35 ++++++++++----------
14 files changed, 93 insertions(+), 233 deletions(-)
delete mode 100644 fuse/logging.c
delete mode 100644 fuse/logging.h
diff --git a/fuse/Makefile.am b/fuse/Makefile.am
index a50d2c4d0ab3..8b8c4e10d90d 100644
--- a/fuse/Makefile.am
+++ b/fuse/Makefile.am
@@ -3,7 +3,7 @@
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = erofsfuse
-erofsfuse_SOURCES = main.c dentry.c getattr.c logging.c namei.c read.c disk_io.c init.c open.c readir.c zmap.c
+erofsfuse_SOURCES = main.c dentry.c getattr.c namei.c read.c disk_io.c init.c open.c readir.c zmap.c
if ENABLE_LZ4
erofsfuse_SOURCES += decompress.c
endif
diff --git a/fuse/decompress.c b/fuse/decompress.c
index f2aa84146946..e32a27017a45 100644
--- a/fuse/decompress.c
+++ b/fuse/decompress.c
@@ -11,7 +11,6 @@
#include "erofs/internal.h"
#include "erofs/err.h"
#include "decompress.h"
-#include "logging.h"
#include "init.h"
static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq)
diff --git a/fuse/dentry.c b/fuse/dentry.c
index 1ae37e3abc86..0f722294d530 100644
--- a/fuse/dentry.c
+++ b/fuse/dentry.c
@@ -4,9 +4,10 @@
*
* Created by Li Guifu <blucerlee@gmail.com>
*/
+#include <stdlib.h>
#include "dentry.h"
#include "erofs/internal.h"
-#include "logging.h"
+#include "erofs/print.h"
#define DCACHE_ENTRY_CALLOC() calloc(1, sizeof(struct dcache_entry))
#define DCACHE_ENTRY_LIFE 8
@@ -21,7 +22,7 @@ int dcache_init_root(uint32_t nid)
/* Root entry doesn't need most of the fields. Namely, it only uses the
* nid field and the subdirs pointer.
*/
- logi("Initializing root_entry dcache entry");
+ erofs_info("Initializing root_entry dcache entry");
root_entry.nid = nid;
root_entry.subdirs = NULL;
root_entry.siblings = NULL;
@@ -44,7 +45,7 @@ struct dcache_entry *dcache_insert(struct dcache_entry *parent,
{
struct dcache_entry *new_entry;
- logd("Inserting %s,%d to dcache", name, namelen);
+ erofs_dbg("Inserting %s,%d to dcache", name, namelen);
/* TODO: Deal with names that exceed the allocated size */
if (namelen + 1 > DCACHE_ENTRY_NAME_LEN)
diff --git a/fuse/disk_io.c b/fuse/disk_io.c
index 3fc087699dc9..bb1ee9a202db 100644
--- a/fuse/disk_io.c
+++ b/fuse/disk_io.c
@@ -14,7 +14,7 @@
#include <pthread.h>
#include <errno.h>
-#include "logging.h"
+#include "erofs/print.h"
#ifdef __FreeBSD__
#include <string.h>
@@ -47,18 +47,18 @@ int dev_read(void *buf, size_t count, off_t offset)
ssize_t pread_ret;
int lerrno;
- ASSERT(erofs_devfd >= 0);
+ DBG_BUGON(erofs_devfd < 0);
pthread_mutex_lock(&read_lock);
pread_ret = pread_wrapper(erofs_devfd, buf, count, offset);
lerrno = errno;
- logd("Disk Read: offset[0x%jx] count[%zd] pread_ret=%zd %s",
+ erofs_dbg("Disk Read: offset[0x%jx] count[%zd] pread_ret=%zd %s",
offset, count, pread_ret, strerror(lerrno));
pthread_mutex_unlock(&read_lock);
if (count == 0)
- logw("Read operation with 0 size");
+ erofs_warn("Read operation with 0 size");
- ASSERT((size_t)pread_ret == count);
+ DBG_BUGON((size_t)pread_ret != count);
return pread_ret;
}
diff --git a/fuse/getattr.c b/fuse/getattr.c
index e5200ebeef1a..4c5991e7e487 100644
--- a/fuse/getattr.c
+++ b/fuse/getattr.c
@@ -14,8 +14,8 @@
#include "erofs/defs.h"
#include "erofs/internal.h"
#include "erofs_fs.h"
+#include "erofs/print.h"
-#include "logging.h"
#include "namei.h"
extern struct erofs_super_block super;
@@ -44,7 +44,7 @@ int erofs_getattr(const char *path, struct stat *stbuf)
struct erofs_vnode v;
int ret;
- logd("getattr(%s)", path);
+ erofs_dbg("getattr(%s)", path);
memset(&v, 0, sizeof(v));
ret = erofs_iget_by_path(path, &v);
if (ret)
diff --git a/fuse/init.c b/fuse/init.c
index 48125c5791fa..6917e995370b 100644
--- a/fuse/init.c
+++ b/fuse/init.c
@@ -6,11 +6,12 @@
*/
#include "init.h"
#include <string.h>
+#include <stdlib.h>
#include <asm-generic/errno-base.h>
#include "namei.h"
#include "disk_io.h"
-#include "logging.h"
+#include "erofs/print.h"
#define STR(_X) (#_X)
#define SUPER_MEM(_X) (super._X)
@@ -28,8 +29,8 @@ static bool check_layout_compatibility(struct erofs_super_block *sb,
/* check if current kernel meets all mandatory requirements */
if (feature & (~EROFS_ALL_FEATURE_INCOMPAT)) {
- loge("unidentified incompatible feature %x, please upgrade kernel version",
- feature & ~EROFS_ALL_FEATURE_INCOMPAT);
+ erofs_err("unidentified incompatible feature %x, please upgrade kernel version",
+ feature & ~EROFS_ALL_FEATURE_INCOMPAT);
return false;
}
return true;
@@ -44,15 +45,15 @@ int erofs_init_super(void)
memset(buf, 0, sizeof(buf));
ret = dev_read_blk(buf, 0);
if (ret != EROFS_BLKSIZ) {
- logi("Failed to read super block ret=%d", ret);
+ erofs_err("Failed to read super block ret=%d", ret);
return -EINVAL;
}
sb = (struct erofs_super_block *) (buf + BOOT_SECTOR_SIZE);
sbk->magic = le32_to_cpu(sb->magic);
if (sbk->magic != EROFS_SUPER_MAGIC_V1) {
- logi("EROFS magic[0x%X] NOT matched to [0x%X] ",
- super.magic, EROFS_SUPER_MAGIC_V1);
+ erofs_err("EROFS magic[0x%X] NOT matched to [0x%X] ",
+ super.magic, EROFS_SUPER_MAGIC_V1);
return -EINVAL;
}
@@ -62,7 +63,6 @@ int erofs_init_super(void)
sbk->checksum = le32_to_cpu(sb->checksum);
sbk->feature_compat = le32_to_cpu(sb->feature_compat);
sbk->blkszbits = sb->blkszbits;
- ASSERT(sbk->blkszbits != 32);
sbk->inos = le64_to_cpu(sb->inos);
sbk->build_time = le64_to_cpu(sb->build_time);
@@ -74,15 +74,14 @@ int erofs_init_super(void)
memcpy(sbk->volume_name, sb->volume_name, 16);
sbk->root_nid = le16_to_cpu(sb->root_nid);
- logp("%-15s:0x%X", STR(magic), SUPER_MEM(magic));
- logp("%-15s:0x%X", STR(feature_incompat), SUPER_MEM(feature_incompat));
- logp("%-15s:0x%X", STR(feature_compat), SUPER_MEM(feature_compat));
- logp("%-15s:%u", STR(blkszbits), SUPER_MEM(blkszbits));
- logp("%-15s:%u", STR(root_nid), SUPER_MEM(root_nid));
- logp("%-15s:%ul", STR(inos), SUPER_MEM(inos));
- logp("%-15s:%d", STR(meta_blkaddr), SUPER_MEM(meta_blkaddr));
- logp("%-15s:%d", STR(xattr_blkaddr), SUPER_MEM(xattr_blkaddr));
-
+ erofs_dump("%-15s:0x%X\n", STR(magic), SUPER_MEM(magic));
+ erofs_dump("%-15s:0x%X\n", STR(feature_incompat), SUPER_MEM(feature_incompat));
+ erofs_dump("%-15s:0x%X\n", STR(feature_compat), SUPER_MEM(feature_compat));
+ erofs_dump("%-15s:%u\n", STR(blkszbits), SUPER_MEM(blkszbits));
+ erofs_dump("%-15s:%u\n", STR(root_nid), SUPER_MEM(root_nid));
+ erofs_dump("%-15s:%llu\n", STR(inos), (unsigned long long)SUPER_MEM(inos));
+ erofs_dump("%-15s:%d\n", STR(meta_blkaddr), SUPER_MEM(meta_blkaddr));
+ erofs_dump("%-15s:%d\n", STR(xattr_blkaddr), SUPER_MEM(xattr_blkaddr));
return 0;
}
@@ -95,7 +94,7 @@ erofs_nid_t addr2nid(erofs_off_t addr)
{
erofs_nid_t offset = (erofs_nid_t)sbk->meta_blkaddr * EROFS_BLKSIZ;
- ASSERT(IS_SLOT_ALIGN(addr));
+ DBG_BUGON(!IS_SLOT_ALIGN(addr));
return (addr - offset) >> EROFS_ISLOTBITS;
}
@@ -108,11 +107,11 @@ erofs_off_t nid2addr(erofs_nid_t nid)
void *erofs_init(struct fuse_conn_info *info)
{
- logi("Using FUSE protocol %d.%d", info->proto_major, info->proto_minor);
+ erofs_info("Using FUSE protocol %d.%d", info->proto_major, info->proto_minor);
if (inode_init(erofs_get_root_nid()) != 0) {
- loge("inode initialization failed")
- ABORT();
+ erofs_err("inode initialization failed");
+ abort();
}
return NULL;
}
diff --git a/fuse/logging.c b/fuse/logging.c
deleted file mode 100644
index 192f546b94ec..000000000000
--- a/fuse/logging.c
+++ /dev/null
@@ -1,81 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * erofs-utils/fuse/logging.c
- *
- * Created by Li Guifu <blucerlee@gmail.com>
- */
-#include "logging.h"
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <pthread.h>
-
-static int loglevel = DEFAULT_LOG_LEVEL;
-static FILE *logfile;
-static const char * const loglevel_str[] = {
- [LOG_EMERG] = "[emerg]",
- [LOG_ALERT] = "[alert]",
- [LOG_DUMP] = "[dump] ",
- [LOG_ERR] = "[err] ",
- [LOG_WARNING] = "[warn] ",
- [LOG_NOTICE] = "[notic]",
- [LOG_INFO] = "[info] ",
- [LOG_DEBUG] = "[debug]",
-};
-
-void __LOG(int level, const char *func, int line, const char *format, ...)
-{
- static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
- va_list ap;
- FILE *fp = logfile ? logfile : stdout;
-
- if (!fp)
- return;
- if (level < 0 || level > loglevel)
- return;
-
- /* We have a lock here so different threads don interleave the log
- * output
- */
- pthread_mutex_lock(&lock);
- va_start(ap, format);
- fprintf(fp, "%s", loglevel_str[level]);
- if (func)
- fprintf(fp, "%s", func);
- if (line >= 0)
- fprintf(fp, "(%d):", line);
- vfprintf(fp, format, ap);
- fprintf(fp, "\n");
- va_end(ap);
- fflush(fp);
- pthread_mutex_unlock(&lock);
-}
-
-inline void logging_setlevel(int new_level)
-{
- loglevel = new_level;
-}
-
-int logging_open(const char *path)
-{
- if (path == NULL)
- return 0;
-
- logfile = fopen(path, "w");
- if (logfile == NULL) {
- perror("open");
- return -1;
- }
-
- return 0;
-}
-
-void logging_close(void)
-{
- if (logfile) {
- fflush(logfile);
- fclose(logfile);
- logfile = NULL;
- }
-}
-
diff --git a/fuse/logging.h b/fuse/logging.h
deleted file mode 100644
index 3aa77ab08107..000000000000
--- a/fuse/logging.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * erofs-utils/fuse/logging.h
- *
- * Created by Li Guifu <blucerlee@gmail.com>
- */
-#ifndef __LOGGING_H
-#define __LOGGING_H
-
-#include <assert.h>
-#include <stdlib.h>
-
-#define LOG_EMERG 0
-#define LOG_ALERT 1
-#define LOG_DUMP 2
-#define LOG_ERR 3
-#define LOG_WARNING 4
-#define LOG_NOTICE 5
-#define LOG_INFO 6
-#define LOG_DEBUG 7
-
-#define logem(...) __LOG(LOG_EMERG, __func__, __LINE__, ##__VA_ARGS__)
-#define loga(...) __LOG(LOG_ALERT, __func__, __LINE__, ##__VA_ARGS__)
-#define loge(...) __LOG(LOG_ERR, __func__, __LINE__, ##__VA_ARGS__)
-#define logw(...) __LOG(LOG_WARNING, __func__, __LINE__, ##__VA_ARGS__)
-#define logn(...) __LOG(LOG_NOTICE, __func__, __LINE__, ##__VA_ARGS__)
-#define logi(...) __LOG(LOG_INFO, __func__, __LINE__, ##__VA_ARGS__)
-#define logp(...) __LOG(LOG_DUMP, "", -1, ##__VA_ARGS__)
-#define logd(...) __LOG(LOG_DEBUG, __func__, __LINE__, ##__VA_ARGS__)
-
-#define DEFAULT_LOG_FILE "fuse.log"
-
-#ifdef _DEBUG
-#define DEFAULT_LOG_LEVEL LOG_DEBUG
-
-#define ASSERT(assertion) ({ \
- if (!(assertion)) { \
- logw("ASSERT FAIL: " #assertion); \
- assert(assertion); \
- } \
-})
-#define ABORT(_X) abort(_X)
-#else
-#define DEFAULT_LOG_LEVEL LOG_ERR
-#define ASSERT(assertion)
-#define ABORT(_X)
-#endif
-
-void __LOG(int level, const char *func, int line, const char *format, ...);
-void logging_setlevel(int new_level);
-int logging_open(const char *path);
-void logging_close(void);
-
-#endif
-
diff --git a/fuse/main.c b/fuse/main.c
index 9c8169725fa7..9008fea32639 100644
--- a/fuse/main.c
+++ b/fuse/main.c
@@ -11,7 +11,7 @@
#include <signal.h>
#include <stddef.h>
-#include "logging.h"
+#include "erofs/print.h"
#include "init.h"
#include "read.h"
#include "getattr.h"
@@ -19,6 +19,9 @@
#include "readir.h"
#include "disk_io.h"
+/* XXX: after liberofs is linked in, it should be removed */
+struct erofs_configure cfg;
+
enum {
EROFS_OPT_HELP,
EROFS_OPT_VER,
@@ -30,7 +33,7 @@ struct options {
const char *logfile;
unsigned int debug_lvl;
};
-static struct options cfg;
+static struct options fusecfg;
#define OPTION(t, p) { t, offsetof(struct options, p), 1 }
@@ -54,10 +57,10 @@ static void usage(void)
static void dump_cfg(void)
{
- fprintf(stderr, "\tdisk :%s\n", cfg.disk);
- fprintf(stderr, "\tmount:%s\n", cfg.mount);
- fprintf(stderr, "\tdebug_lvl:%u\n", cfg.debug_lvl);
- fprintf(stderr, "\tlogfile :%s\n", cfg.logfile);
+ fprintf(stderr, "\tdisk :%s\n", fusecfg.disk);
+ fprintf(stderr, "\tmount:%s\n", fusecfg.mount);
+ fprintf(stderr, "\tdebug_lvl:%u\n", fusecfg.debug_lvl);
+ fprintf(stderr, "\tlogfile :%s\n", fusecfg.logfile);
}
static int optional_opt_func(void *data, const char *arg, int key,
@@ -71,11 +74,11 @@ static int optional_opt_func(void *data, const char *arg, int key,
return 1;
case FUSE_OPT_KEY_NONOPT:
- if (!cfg.disk) {
- cfg.disk = strdup(arg);
+ if (!fusecfg.disk) {
+ fusecfg.disk = strdup(arg);
return 0;
- } else if (!cfg.mount)
- cfg.mount = strdup(arg);
+ } else if (!fusecfg.mount)
+ fusecfg.mount = strdup(arg);
return 1;
case EROFS_OPT_HELP:
@@ -98,16 +101,16 @@ static void signal_handle_sigsegv(int signal)
size_t i;
UNUSED(signal);
- logd("========================================");
- logd("Segmentation Fault. Starting backtrace:");
+ erofs_dbg("========================================");
+ erofs_dbg("Segmentation Fault. Starting backtrace:");
nptrs = backtrace(array, 10);
strings = backtrace_symbols(array, nptrs);
if (strings) {
for (i = 0; i < nptrs; i++)
- logd("%s", strings[i]);
+ erofs_dbg("%s", strings[i]);
free(strings);
}
- logd("========================================");
+ erofs_dbg("========================================");
abort();
}
@@ -132,21 +135,16 @@ int main(int argc, char *argv[])
}
/* Parse options */
- if (fuse_opt_parse(&args, &cfg, option_spec, optional_opt_func) < 0)
+ if (fuse_opt_parse(&args, &fusecfg, option_spec, optional_opt_func) < 0)
return 1;
dump_cfg();
- if (logging_open(cfg.logfile) < 0) {
- fprintf(stderr, "Failed to initialize logging\n");
- goto exit;
- }
+ cfg.c_dbg_lvl = fusecfg.debug_lvl;
- logging_setlevel(cfg.debug_lvl);
-
- if (dev_open(cfg.disk) < 0) {
- fprintf(stderr, "Failed to open disk:%s\n", cfg.disk);
- goto exit_log;
+ if (dev_open(fusecfg.disk) < 0) {
+ fprintf(stderr, "Failed to open disk:%s\n", fusecfg.disk);
+ goto exit;
}
if (erofs_init_super()) {
@@ -154,16 +152,14 @@ int main(int argc, char *argv[])
goto exit_dev;
}
- logi("fuse start");
+ erofs_info("fuse start");
ret = fuse_main(args.argc, args.argv, &erofs_ops, NULL);
- logi("fuse done ret=%d", ret);
+ erofs_info("fuse done ret=%d", ret);
exit_dev:
dev_close();
-exit_log:
- logging_close();
exit:
fuse_opt_free_args(&args);
return ret;
diff --git a/fuse/namei.c b/fuse/namei.c
index c33af4b04b45..172e1bcdb457 100644
--- a/fuse/namei.c
+++ b/fuse/namei.c
@@ -14,7 +14,7 @@
#include <sys/sysmacros.h>
#include "erofs/defs.h"
-#include "logging.h"
+#include "erofs/print.h"
#include "disk_io.h"
#include "dentry.h"
#include "init.h"
@@ -125,7 +125,7 @@ struct dcache_entry *list_name(const char *buf, struct dcache_entry *parent,
memcpy(debug, d_name, name_len);
debug[name_len] = '\0';
- logi("list entry: %s nid=%u", debug, nid);
+ erofs_info("list entry: %s nid=%u", debug, nid);
}
#endif
@@ -214,7 +214,7 @@ int walk_path(const char *_path, erofs_nid_t *out_nid)
if (!ret)
return -ENOENT;
- logd("find path = %s nid=%u", _path, ret->nid);
+ erofs_dbg("find path = %s nid=%u", _path, ret->nid);
*out_nid = ret->nid;
return 0;
diff --git a/fuse/open.c b/fuse/open.c
index c219d3870000..beb9a8615512 100644
--- a/fuse/open.c
+++ b/fuse/open.c
@@ -8,11 +8,11 @@
#include <asm-generic/errno-base.h>
#include <fuse.h>
#include <fuse_opt.h>
-#include "logging.h"
+#include "erofs/print.h"
int erofs_open(const char *path, struct fuse_file_info *fi)
{
- logi("open path=%s", path);
+ erofs_info("open path=%s", path);
if ((fi->flags & O_ACCMODE) != O_RDONLY)
return -EACCES;
diff --git a/fuse/read.c b/fuse/read.c
index e2f967aefb8a..0969e9ca1caf 100644
--- a/fuse/read.c
+++ b/fuse/read.c
@@ -13,7 +13,7 @@
#include "erofs/defs.h"
#include "erofs/internal.h"
-#include "logging.h"
+#include "erofs/print.h"
#include "namei.h"
#include "disk_io.h"
#include "init.h"
@@ -37,8 +37,8 @@ size_t erofs_read_data(struct erofs_vnode *vnode, char *buffer,
rdsz += count;
}
- logi("nid:%u size=%zd offset=%llu realsize=%zd done",
- vnode->nid, size, (long long)offset, rdsz);
+ erofs_info("nid:%llu size=%zd offset=%llu realsize=%zd done",
+ (unsigned long long)vnode->nid, size, (long long)offset, rdsz);
return rdsz;
}
@@ -73,8 +73,8 @@ size_t erofs_read_data_inline(struct erofs_vnode *vnode, char *buffer,
rdsz += suminline;
finished:
- logi("nid:%u size=%zd suminline=%u offset=%llu realsize=%zd done",
- vnode->nid, size, suminline, (long long)offset, rdsz);
+ erofs_info("nid:%llu size=%zd suminline=%u offset=%llu realsize=%zd done",
+ (unsigned long long)vnode->nid, size, (unsigned)suminline, (long long)offset, rdsz);
return rdsz;
}
@@ -120,7 +120,7 @@ size_t erofs_read_data_compression(struct erofs_vnode *vnode, char *buffer,
length = end - map.m_la;
partial = true;
} else {
- ASSERT(end == map.m_la + map.m_llen);
+ DBG_BUGON(end != map.m_la + map.m_llen);
length = map.m_llen;
partial = !(map.m_flags & EROFS_MAP_FULL_MAPPED);
}
@@ -146,8 +146,8 @@ size_t erofs_read_data_compression(struct erofs_vnode *vnode, char *buffer,
return ret;
}
- logi("nid:%u size=%zd offset=%llu done",
- vnode->nid, size, (long long)offset);
+ erofs_info("nid:%llu size=%zd offset=%llu done",
+ (unsigned long long)vnode->nid, size, (long long)offset);
return size;
}
@@ -159,7 +159,7 @@ int erofs_read(const char *path, char *buffer, size_t size, off_t offset,
struct erofs_vnode v;
UNUSED(fi);
- logi("path:%s size=%zd offset=%llu", path, size, (long long)offset);
+ erofs_info("path:%s size=%zd offset=%llu", path, size, (long long)offset);
ret = walk_path(path, &nid);
if (ret)
@@ -169,7 +169,7 @@ int erofs_read(const char *path, char *buffer, size_t size, off_t offset,
if (ret)
return ret;
- logi("path:%s nid=%llu mode=%u", path, nid, v.datalayout);
+ erofs_info("path:%s nid=%llu mode=%u", path, (unsigned long long)nid, v.datalayout);
switch (v.datalayout) {
case EROFS_INODE_FLAT_PLAIN:
return erofs_read_data(&v, buffer, size, offset);
@@ -208,6 +208,6 @@ int erofs_readlink(const char *path, char *buffer, size_t size)
if (ret != (int)lnksz)
return ret;
- logi("path:%s link=%s size=%llu", path, buffer, lnksz);
+ erofs_info("path:%s link=%s size=%llu", path, buffer, (unsigned long long)lnksz);
return 0;
}
diff --git a/fuse/readir.c b/fuse/readir.c
index b00274dad9f4..0fefcd8fd0cb 100644
--- a/fuse/readir.c
+++ b/fuse/readir.c
@@ -14,7 +14,7 @@
#include "erofs_fs.h"
#include "namei.h"
#include "disk_io.h"
-#include "logging.h"
+#include "erofs/print.h"
#include "init.h"
erofs_nid_t split_entry(char *entry, off_t ofs, char *end, char *name,
@@ -72,14 +72,14 @@ int erofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
char dirsbuf[EROFS_BLKSIZ];
uint32_t dir_nr, dir_off, nr_cnt;
- logd("readdir:%s offset=%llu", path, (long long)offset);
+ erofs_dbg("readdir:%s offset=%llu", path, (long long)offset);
UNUSED(fi);
ret = walk_path(path, &nid);
if (ret)
return ret;
- logd("path=%s nid = %u", path, nid);
+ erofs_dbg("path=%s nid = %llu", path, (unsigned long long)nid);
ret = erofs_iget_by_nid(nid, &v);
if (ret)
return ret;
@@ -94,7 +94,7 @@ int erofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
dir_off = erofs_blkoff(v.i_size);
nr_cnt = 0;
- logd("dir_size=%u dir_nr = %u dir_off=%u", v.i_size, dir_nr, dir_off);
+ erofs_dbg("dir_size=%u dir_nr = %u dir_off=%u", v.i_size, dir_nr, dir_off);
while (nr_cnt < dir_nr) {
memset(dirsbuf, 0, sizeof(dirsbuf));
diff --git a/fuse/zmap.c b/fuse/zmap.c
index 8ec0a7707fd6..85034d385c58 100644
--- a/fuse/zmap.c
+++ b/fuse/zmap.c
@@ -11,7 +11,7 @@
*/
#include "init.h"
#include "disk_io.h"
-#include "logging.h"
+#include "erofs/print.h"
int z_erofs_fill_inode(struct erofs_vnode *vi)
{
@@ -52,8 +52,8 @@ static int z_erofs_fill_inode_lazy(struct erofs_vnode *vi)
vi->z_algorithmtype[1] = h->h_algorithmtype >> 4;
if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX) {
- loge("unknown compression format %u for nid %llu",
- vi->z_algorithmtype[0], vi->nid);
+ erofs_err("unknown compression format %u for nid %llu",
+ vi->z_algorithmtype[0], (unsigned long long)vi->nid);
return -EOPNOTSUPP;
}
@@ -62,8 +62,8 @@ static int z_erofs_fill_inode_lazy(struct erofs_vnode *vi)
((h->h_clusterbits >> 3) & 3);
if (vi->z_physical_clusterbits[0] != LOG_BLOCK_SIZE) {
- loge("unsupported physical clusterbits %u for nid %llu",
- vi->z_physical_clusterbits[0], vi->nid);
+ erofs_err("unsupported physical clusterbits %u for nid %llu",
+ vi->z_physical_clusterbits[0], (unsigned long long)vi->nid);
return -EOPNOTSUPP;
}
@@ -301,7 +301,8 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
int err;
if (lcn < lookback_distance) {
- loge("bogus lookback distance @ nid %llu", vi->nid);
+ erofs_err("bogus lookback distance @ nid %llu",
+ (unsigned long long)vi->nid);
DBG_BUGON(1);
return -EFSCORRUPTED;
}
@@ -315,8 +316,8 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
switch (m->type) {
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
if (!m->delta[0]) {
- loge("invalid lookback distance 0 @ nid %llu",
- vi->nid);
+ erofs_err("invalid lookback distance 0 @ nid %llu",
+ (unsigned long long)vi->nid);
DBG_BUGON(1);
return -EFSCORRUPTED;
}
@@ -327,8 +328,8 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
map->m_la = (lcn << lclusterbits) | m->clusterofs;
break;
default:
- loge("unknown type %u @ lcn %lu of nid %llu",
- m->type, lcn, vi->nid);
+ erofs_err("unknown type %u @ lcn %lu of nid %llu",
+ m->type, lcn, (unsigned long long)vi->nid);
DBG_BUGON(1);
return -EOPNOTSUPP;
}
@@ -381,8 +382,8 @@ int z_erofs_map_blocks_iter(struct erofs_vnode *vi,
}
/* m.lcn should be >= 1 if endoff < m.clusterofs */
if (!m.lcn) {
- loge("invalid logical cluster 0 at nid %llu",
- vi->nid);
+ erofs_err("invalid logical cluster 0 at nid %llu",
+ (unsigned long long)vi->nid);
err = -EFSCORRUPTED;
goto out;
}
@@ -396,8 +397,8 @@ int z_erofs_map_blocks_iter(struct erofs_vnode *vi,
goto out;
break;
default:
- loge("unknown type %u @ offset %llu of nid %llu",
- m.type, ofs, vi->nid);
+ erofs_err("unknown type %u @ offset %llu of nid %llu",
+ m.type, ofs, (unsigned long long)vi->nid);
err = -EOPNOTSUPP;
goto out;
}
@@ -408,9 +409,9 @@ int z_erofs_map_blocks_iter(struct erofs_vnode *vi,
map->m_flags |= EROFS_MAP_MAPPED;
out:
- logd("m_la %llu m_pa %llu m_llen %llu m_plen %llu m_flags 0%o",
- map->m_la, map->m_pa,
- map->m_llen, map->m_plen, map->m_flags);
+ erofs_dbg("m_la %" PRIu64 " m_pa %" PRIu64 " m_llen %" PRIu64 " m_plen %" PRIu64 " m_flags 0%o",
+ map->m_la, map->m_pa,
+ map->m_llen, map->m_plen, map->m_flags);
DBG_BUGON(err < 0 && err != -ENOMEM);
return err;
--
2.24.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [WIP] [PATCH 6/5] erofs-utils: fuse: get rid of duplicated I/O ops
2020-10-24 13:09 ` [WIP] [PATCH v2 5/5] erofs-utils: fuse: get rid of duplicated logging code Gao Xiang via Linux-erofs
@ 2020-10-24 15:27 ` Gao Xiang via Linux-erofs
2020-10-24 15:27 ` [WIP] [PATCH 7/5] erofs-utils: fuse: move feature_incompat to sbi Gao Xiang via Linux-erofs
2020-10-24 15:27 ` [WIP] [PATCH 8/5] erofs-utils: fuse: move decompress backend to lib Gao Xiang via Linux-erofs
0 siblings, 2 replies; 9+ messages in thread
From: Gao Xiang via Linux-erofs @ 2020-10-24 15:27 UTC (permalink / raw)
To: linux-erofs; +Cc: Zhang Shiming, Guo Weichao
[ will be folded to the original patch. ]
Signed-off-by: Gao Xiang <hsiangkao@aol.com>
---
fuse/Makefile.am | 2 +-
fuse/disk_io.c | 72 ----------------------------------------------
fuse/disk_io.h | 21 --------------
fuse/init.c | 6 ++--
fuse/main.c | 4 +--
fuse/namei.c | 13 +++++----
fuse/read.c | 18 ++++++------
fuse/readir.c | 10 +++----
fuse/zmap.c | 10 +++----
include/erofs/io.h | 1 +
lib/io.c | 16 +++++++++++
11 files changed, 49 insertions(+), 124 deletions(-)
delete mode 100644 fuse/disk_io.c
delete mode 100644 fuse/disk_io.h
diff --git a/fuse/Makefile.am b/fuse/Makefile.am
index 8b8c4e10d90d..dc8839c84d73 100644
--- a/fuse/Makefile.am
+++ b/fuse/Makefile.am
@@ -3,7 +3,7 @@
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = erofsfuse
-erofsfuse_SOURCES = main.c dentry.c getattr.c namei.c read.c disk_io.c init.c open.c readir.c zmap.c
+erofsfuse_SOURCES = main.c dentry.c getattr.c namei.c read.c init.c open.c readir.c zmap.c
if ENABLE_LZ4
erofsfuse_SOURCES += decompress.c
endif
diff --git a/fuse/disk_io.c b/fuse/disk_io.c
deleted file mode 100644
index bb1ee9a202db..000000000000
--- a/fuse/disk_io.c
+++ /dev/null
@@ -1,72 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * erofs-utils/fuse/disk_io.c
- *
- * Created by Li Guifu <blucerlee@gmail.com>
- */
-#define _XOPEN_SOURCE 500
-#include "disk_io.h"
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <pthread.h>
-#include <errno.h>
-
-#include "erofs/print.h"
-
-#ifdef __FreeBSD__
-#include <string.h>
-#endif
-
-static const char *erofs_devname;
-static int erofs_devfd = -1;
-static pthread_mutex_t read_lock = PTHREAD_MUTEX_INITIALIZER;
-
-int dev_open(const char *path)
-{
- int fd = open(path, O_RDONLY);
-
- if (fd < 0)
- return -errno;
-
- erofs_devfd = fd;
- erofs_devname = path;
-
- return 0;
-}
-
-static inline int pread_wrapper(int fd, void *buf, size_t count, off_t offset)
-{
- return pread(fd, buf, count, offset);
-}
-
-int dev_read(void *buf, size_t count, off_t offset)
-{
- ssize_t pread_ret;
- int lerrno;
-
- DBG_BUGON(erofs_devfd < 0);
-
- pthread_mutex_lock(&read_lock);
- pread_ret = pread_wrapper(erofs_devfd, buf, count, offset);
- lerrno = errno;
- erofs_dbg("Disk Read: offset[0x%jx] count[%zd] pread_ret=%zd %s",
- offset, count, pread_ret, strerror(lerrno));
- pthread_mutex_unlock(&read_lock);
- if (count == 0)
- erofs_warn("Read operation with 0 size");
-
- DBG_BUGON((size_t)pread_ret != count);
-
- return pread_ret;
-}
-
-void dev_close(void)
-{
- if (erofs_devfd >= 0) {
- close(erofs_devfd);
- erofs_devfd = -1;
- }
-}
diff --git a/fuse/disk_io.h b/fuse/disk_io.h
deleted file mode 100644
index d2c3dd598bc0..000000000000
--- a/fuse/disk_io.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * erofs-utils/fuse/disk_io.h
- *
- * Created by Li Guifu <blucerlee@gmail.com>
- */
-#ifndef __DISK_IO_H
-#define __DISK_IO_H
-
-#include "erofs/defs.h"
-#include "erofs/internal.h"
-
-int dev_open(const char *path);
-void dev_close(void);
-int dev_read(void *buf, size_t count, off_t offset);
-
-static inline int dev_read_blk(void *buf, uint32_t nr)
-{
- return dev_read(buf, EROFS_BLKSIZ, blknr_to_addr(nr));
-}
-#endif
diff --git a/fuse/init.c b/fuse/init.c
index 6917e995370b..867f4bf90e9a 100644
--- a/fuse/init.c
+++ b/fuse/init.c
@@ -10,7 +10,7 @@
#include <asm-generic/errno-base.h>
#include "namei.h"
-#include "disk_io.h"
+#include "erofs/io.h"
#include "erofs/print.h"
#define STR(_X) (#_X)
@@ -43,8 +43,8 @@ int erofs_init_super(void)
struct erofs_super_block *sb;
memset(buf, 0, sizeof(buf));
- ret = dev_read_blk(buf, 0);
- if (ret != EROFS_BLKSIZ) {
+ ret = blk_read(buf, 0, 1);
+ if (ret < 0) {
erofs_err("Failed to read super block ret=%d", ret);
return -EINVAL;
}
diff --git a/fuse/main.c b/fuse/main.c
index 9008fea32639..26f49f6fc299 100644
--- a/fuse/main.c
+++ b/fuse/main.c
@@ -17,7 +17,7 @@
#include "getattr.h"
#include "open.h"
#include "readir.h"
-#include "disk_io.h"
+#include "erofs/io.h"
/* XXX: after liberofs is linked in, it should be removed */
struct erofs_configure cfg;
@@ -142,7 +142,7 @@ int main(int argc, char *argv[])
cfg.c_dbg_lvl = fusecfg.debug_lvl;
- if (dev_open(fusecfg.disk) < 0) {
+ if (dev_open_ro(fusecfg.disk) < 0) {
fprintf(stderr, "Failed to open disk:%s\n", fusecfg.disk);
goto exit;
}
diff --git a/fuse/namei.c b/fuse/namei.c
index 172e1bcdb457..79273f89be1b 100644
--- a/fuse/namei.c
+++ b/fuse/namei.c
@@ -15,7 +15,7 @@
#include "erofs/defs.h"
#include "erofs/print.h"
-#include "disk_io.h"
+#include "erofs/io.h"
#include "dentry.h"
#include "init.h"
@@ -55,8 +55,8 @@ int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi)
const erofs_off_t addr = nid2addr(nid);
const size_t size = EROFS_BLKSIZ - erofs_blkoff(addr);
- ret = dev_read(buf, size, addr);
- if (ret != (int)size)
+ ret = dev_read(buf, addr, size);
+ if (ret < 0)
return -EIO;
v1 = (struct erofs_inode_compact *)buf;
@@ -160,7 +160,8 @@ struct dcache_entry *disk_lookup(struct dcache_entry *parent, const char *name,
nr_cnt = 0;
while (nr_cnt < dir_nr) {
- if (dev_read_blk(buf, blkno + nr_cnt) != EROFS_BLKSIZ)
+ ret = blk_read(buf, blkno + nr_cnt, 1);
+ if (ret < 0)
return NULL;
entry = list_name(buf, parent, name, name_len, EROFS_BLKSIZ);
@@ -176,8 +177,8 @@ struct dcache_entry *disk_lookup(struct dcache_entry *parent, const char *name,
v.inode_isize + v.xattr_isize;
memset(buf, 0, sizeof(buf));
- ret = dev_read(buf, dir_off, dir_addr);
- if (ret < 0 && (uint32_t)ret != dir_off)
+ ret = dev_read(buf, dir_addr, dir_off);
+ if (ret < 0)
return NULL;
entry = list_name(buf, parent, name, name_len, dir_off);
diff --git a/fuse/read.c b/fuse/read.c
index 86a2bfa1b165..8e332e89478f 100644
--- a/fuse/read.c
+++ b/fuse/read.c
@@ -15,7 +15,7 @@
#include "erofs/internal.h"
#include "erofs/print.h"
#include "namei.h"
-#include "disk_io.h"
+#include "erofs/io.h"
#include "init.h"
#include "decompress.h"
@@ -31,8 +31,8 @@ size_t erofs_read_data(struct erofs_vnode *vnode, char *buffer,
while (rdsz < sum) {
size_t count = min(EROFS_BLKSIZ, (uint32_t)(sum - rdsz));
- ret = dev_read(buffer + rdsz, count, addr + rdsz);
- if (ret < 0 || (size_t)ret != count)
+ ret = dev_read(buffer + rdsz, addr + rdsz, count);
+ if (ret < 0)
return -EIO;
rdsz += count;
}
@@ -57,8 +57,8 @@ size_t erofs_read_data_inline(struct erofs_vnode *vnode, char *buffer,
while (rdsz < sum) {
size_t count = min(EROFS_BLKSIZ, (uint32_t)(sum - rdsz));
- ret = dev_read(buffer + rdsz, count, addr + rdsz);
- if (ret < 0 || (uint32_t)ret != count)
+ ret = dev_read(buffer + rdsz, addr + rdsz, count);
+ if (ret < 0)
return -EIO;
rdsz += count;
}
@@ -67,8 +67,8 @@ size_t erofs_read_data_inline(struct erofs_vnode *vnode, char *buffer,
goto finished;
addr = nid2addr(vnode->nid) + vnode->inode_isize + vnode->xattr_isize;
- ret = dev_read(buffer + rdsz, suminline, addr);
- if (ret < 0 || (size_t)ret != suminline)
+ ret = dev_read(buffer + rdsz, addr, suminline);
+ if (ret < 0)
return -EIO;
rdsz += suminline;
@@ -104,8 +104,8 @@ size_t erofs_read_data_compression(struct erofs_vnode *vnode, char *buffer,
continue;
}
- ret = dev_read(raw, EROFS_BLKSIZ, map.m_pa);
- if (ret < 0 || (size_t)ret != EROFS_BLKSIZ)
+ ret = dev_read(raw, map.m_pa, EROFS_BLKSIZ);
+ if (ret < 0)
return -EIO;
algorithmformat = map.m_flags & EROFS_MAP_ZIPPED ?
diff --git a/fuse/readir.c b/fuse/readir.c
index 0fefcd8fd0cb..8111047803df 100644
--- a/fuse/readir.c
+++ b/fuse/readir.c
@@ -13,7 +13,7 @@
#include "erofs/internal.h"
#include "erofs_fs.h"
#include "namei.h"
-#include "disk_io.h"
+#include "erofs/io.h"
#include "erofs/print.h"
#include "init.h"
@@ -98,8 +98,8 @@ int erofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
while (nr_cnt < dir_nr) {
memset(dirsbuf, 0, sizeof(dirsbuf));
- ret = dev_read_blk(dirsbuf, v.raw_blkaddr + nr_cnt);
- if (ret != EROFS_BLKSIZ)
+ ret = blk_read(dirsbuf, v.raw_blkaddr + nr_cnt, 1);
+ if (ret < 0)
return -EIO;
fill_dir(dirsbuf, filler, buf, EROFS_BLKSIZ);
++nr_cnt;
@@ -111,8 +111,8 @@ int erofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
addr = nid2addr(nid) + v.inode_isize + v.xattr_isize;
memset(dirsbuf, 0, sizeof(dirsbuf));
- ret = dev_read(dirsbuf, dir_off, addr);
- if (ret < 0 || (uint32_t)ret != dir_off)
+ ret = dev_read(dirsbuf, addr, dir_off);
+ if (ret < 0)
return -EIO;
fill_dir(dirsbuf, filler, buf, dir_off);
}
diff --git a/fuse/zmap.c b/fuse/zmap.c
index 85034d385c58..9860b770362c 100644
--- a/fuse/zmap.c
+++ b/fuse/zmap.c
@@ -10,7 +10,7 @@
* Modified by Huang Jianan <huangjianan@oppo.com>
*/
#include "init.h"
-#include "disk_io.h"
+#include "erofs/io.h"
#include "erofs/print.h"
int z_erofs_fill_inode(struct erofs_vnode *vi)
@@ -42,8 +42,8 @@ static int z_erofs_fill_inode_lazy(struct erofs_vnode *vi)
pos = round_up(nid2addr(vi->nid) + vi->inode_isize + vi->xattr_isize, 8);
- ret = dev_read(buf, 8, pos);
- if (ret < 0 && (uint32_t)ret != 8)
+ ret = dev_read(buf, pos, 8);
+ if (ret < 0)
return -EIO;
h = (struct z_erofs_map_header *)buf;
@@ -97,8 +97,8 @@ static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m,
if (map->index == eblk)
return 0;
- ret = dev_read(mpage, EROFS_BLKSIZ, blknr_to_addr(eblk));
- if (ret < 0 && (uint32_t)ret != EROFS_BLKSIZ)
+ ret = blk_read(mpage, eblk, 1);
+ if (ret < 0)
return -EIO;
map->index = eblk;
diff --git a/include/erofs/io.h b/include/erofs/io.h
index a23de64541c6..557424578ece 100644
--- a/include/erofs/io.h
+++ b/include/erofs/io.h
@@ -17,6 +17,7 @@
#endif
int dev_open(const char *devname);
+int dev_open_ro(const char *dev);
void dev_close(void);
int dev_write(const void *buf, u64 offset, size_t len);
int dev_read(void *buf, u64 offset, size_t len);
diff --git a/lib/io.c b/lib/io.c
index 4f5d9a6edaa4..d835f34da50f 100644
--- a/lib/io.c
+++ b/lib/io.c
@@ -108,6 +108,22 @@ int dev_open(const char *dev)
return 0;
}
+/* XXX: temporary soluation. Disk I/O implementation needs to be refactored. */
+int dev_open_ro(const char *dev)
+{
+ int fd = open(dev, O_RDONLY | O_BINARY);
+
+ if (fd < 0) {
+ erofs_err("failed to open(%s).", dev);
+ return -errno;
+ }
+
+ erofs_devfd = fd;
+ erofs_devname = dev;
+ erofs_devsz = INT64_MAX;
+ return 0;
+}
+
u64 dev_length(void)
{
return erofs_devsz;
--
2.24.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [WIP] [PATCH 7/5] erofs-utils: fuse: move feature_incompat to sbi
2020-10-24 15:27 ` [WIP] [PATCH 6/5] erofs-utils: fuse: get rid of duplicated I/O ops Gao Xiang via Linux-erofs
@ 2020-10-24 15:27 ` Gao Xiang via Linux-erofs
2020-10-24 15:27 ` [WIP] [PATCH 8/5] erofs-utils: fuse: move decompress backend to lib Gao Xiang via Linux-erofs
1 sibling, 0 replies; 9+ messages in thread
From: Gao Xiang via Linux-erofs @ 2020-10-24 15:27 UTC (permalink / raw)
To: linux-erofs; +Cc: Zhang Shiming, Guo Weichao
In preparation to move decompress.c to lib/,
move feature_incompat to sbi only.
Laterly, sbk needs to be completely dropped.
[ will be folded to the original patch. ]
Signed-off-by: Gao Xiang <hsiangkao@aol.com>
---
fuse/decompress.c | 2 +-
fuse/init.c | 12 +++++++-----
fuse/init.h | 2 --
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/fuse/decompress.c b/fuse/decompress.c
index e32a27017a45..766e6639aa68 100644
--- a/fuse/decompress.c
+++ b/fuse/decompress.c
@@ -22,7 +22,7 @@ static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq)
bool support_0padding = false;
unsigned int inputmargin = 0;
- if (sbk->feature_incompat & EROFS_FEATURE_INCOMPAT_LZ4_0PADDING) {
+ if (erofs_sb_has_lz4_0padding()) {
support_0padding = true;
while (!src[inputmargin & ~PAGE_MASK])
diff --git a/fuse/init.c b/fuse/init.c
index 867f4bf90e9a..c6a3af697532 100644
--- a/fuse/init.c
+++ b/fuse/init.c
@@ -18,14 +18,16 @@
struct erofs_super_block super;
-struct erofs_super_block *sbk = &super;
+/* XXX: sbk needs to be replaced with sbi */
+static struct erofs_super_block *sbk = &super;
+struct erofs_sb_info sbi;
-static bool check_layout_compatibility(struct erofs_super_block *sb,
+static bool check_layout_compatibility(struct erofs_sb_info *sbi,
struct erofs_super_block *dsb)
{
const unsigned int feature = le32_to_cpu(dsb->feature_incompat);
- sb->feature_incompat = feature;
+ sbi->feature_incompat = feature;
/* check if current kernel meets all mandatory requirements */
if (feature & (~EROFS_ALL_FEATURE_INCOMPAT)) {
@@ -57,7 +59,7 @@ int erofs_init_super(void)
return -EINVAL;
}
- if (!check_layout_compatibility(sbk, sb))
+ if (!check_layout_compatibility(&sbi, sb))
return -EINVAL;
sbk->checksum = le32_to_cpu(sb->checksum);
@@ -75,7 +77,7 @@ int erofs_init_super(void)
sbk->root_nid = le16_to_cpu(sb->root_nid);
erofs_dump("%-15s:0x%X\n", STR(magic), SUPER_MEM(magic));
- erofs_dump("%-15s:0x%X\n", STR(feature_incompat), SUPER_MEM(feature_incompat));
+ erofs_dump("%-15s:0x%X\n", STR(feature_incompat), sbi.feature_incompat);
erofs_dump("%-15s:0x%X\n", STR(feature_compat), SUPER_MEM(feature_compat));
erofs_dump("%-15s:%u\n", STR(blkszbits), SUPER_MEM(blkszbits));
erofs_dump("%-15s:%u\n", STR(root_nid), SUPER_MEM(root_nid));
diff --git a/fuse/init.h b/fuse/init.h
index 405a92913b4a..34085f2b548d 100644
--- a/fuse/init.h
+++ b/fuse/init.h
@@ -13,8 +13,6 @@
#define BOOT_SECTOR_SIZE 0x400
-extern struct erofs_super_block *sbk;
-
int erofs_init_super(void);
erofs_nid_t erofs_get_root_nid(void);
erofs_off_t nid2addr(erofs_nid_t nid);
--
2.24.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [WIP] [PATCH 8/5] erofs-utils: fuse: move decompress backend to lib
2020-10-24 15:27 ` [WIP] [PATCH 6/5] erofs-utils: fuse: get rid of duplicated I/O ops Gao Xiang via Linux-erofs
2020-10-24 15:27 ` [WIP] [PATCH 7/5] erofs-utils: fuse: move feature_incompat to sbi Gao Xiang via Linux-erofs
@ 2020-10-24 15:27 ` Gao Xiang via Linux-erofs
1 sibling, 0 replies; 9+ messages in thread
From: Gao Xiang via Linux-erofs @ 2020-10-24 15:27 UTC (permalink / raw)
To: linux-erofs; +Cc: Zhang Shiming, Guo Weichao
[ will be folded to the original patch. ]
Signed-off-by: Gao Xiang <hsiangkao@aol.com>
---
fuse/Makefile.am | 3 ---
fuse/read.c | 2 +-
{fuse => include/erofs}/decompress.h | 11 ++---------
lib/Makefile.am | 4 ++--
{fuse => lib}/decompress.c | 16 ++++++++++------
5 files changed, 15 insertions(+), 21 deletions(-)
rename {fuse => include/erofs}/decompress.h (80%)
rename {fuse => lib}/decompress.c (84%)
diff --git a/fuse/Makefile.am b/fuse/Makefile.am
index dc8839c84d73..2b2608f57b03 100644
--- a/fuse/Makefile.am
+++ b/fuse/Makefile.am
@@ -4,9 +4,6 @@
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = erofsfuse
erofsfuse_SOURCES = main.c dentry.c getattr.c namei.c read.c init.c open.c readir.c zmap.c
-if ENABLE_LZ4
-erofsfuse_SOURCES += decompress.c
-endif
erofsfuse_CFLAGS = -Wall -Werror \
-I$(top_srcdir)/include \
$(shell pkg-config fuse --cflags) \
diff --git a/fuse/read.c b/fuse/read.c
index 8e332e89478f..11f7e6161f8f 100644
--- a/fuse/read.c
+++ b/fuse/read.c
@@ -17,7 +17,7 @@
#include "namei.h"
#include "erofs/io.h"
#include "init.h"
-#include "decompress.h"
+#include "erofs/decompress.h"
size_t erofs_read_data(struct erofs_vnode *vnode, char *buffer,
size_t size, off_t offset)
diff --git a/fuse/decompress.h b/include/erofs/decompress.h
similarity index 80%
rename from fuse/decompress.h
rename to include/erofs/decompress.h
index 508aabab1664..beaac359b21f 100644
--- a/fuse/decompress.h
+++ b/include/erofs/decompress.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * erofs-utils/fuse/decompress.h
+ * erofs-utils/include/erofs/decompress.h
*
* Copyright (C), 2008-2020, OPPO Mobile Comm Corp., Ltd.
* Created by Huang Jianan <huangjianan@oppo.com>
@@ -8,7 +8,7 @@
#ifndef __EROFS_DECOMPRESS_H
#define __EROFS_DECOMPRESS_H
-#include "erofs/internal.h"
+#include "internal.h"
enum {
Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
@@ -30,13 +30,6 @@ struct z_erofs_decompress_req {
bool partial_decoding;
};
-#ifdef LZ4_ENABLED
int z_erofs_decompress(struct z_erofs_decompress_req *rq);
-#else
-int z_erofs_decompress(struct z_erofs_decompress_req *rq)
-{
- return -EOPNOTSUPP;
-}
-#endif
#endif
diff --git a/lib/Makefile.am b/lib/Makefile.am
index e4b51e65f053..c921a62a8b23 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -2,8 +2,8 @@
# Makefile.am
noinst_LTLIBRARIES = liberofs.la
-liberofs_la_SOURCES = config.c io.c cache.c inode.c xattr.c \
- compress.c compressor.c exclude.c
+liberofs_la_SOURCES = config.c io.c cache.c inode.c xattr.c exclude.c \
+ compress.c compressor.c decompress.c
liberofs_la_CFLAGS = -Wall -Werror -I$(top_srcdir)/include
if ENABLE_LZ4
liberofs_la_CFLAGS += ${LZ4_CFLAGS}
diff --git a/fuse/decompress.c b/lib/decompress.c
similarity index 84%
rename from fuse/decompress.c
rename to lib/decompress.c
index 766e6639aa68..870b85430dd1 100644
--- a/fuse/decompress.c
+++ b/lib/decompress.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * erofs-utils/fuse/decompress.c
+ * erofs-utils/lib/decompress.c
*
* Copyright (C), 2008-2020, OPPO Mobile Comm Corp., Ltd.
* Created by Huang Jianan <huangjianan@oppo.com>
@@ -8,12 +8,11 @@
#include <stdlib.h>
#include <lz4.h>
-#include "erofs/internal.h"
+#include "erofs/decompress.h"
#include "erofs/err.h"
-#include "decompress.h"
-#include "init.h"
-static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq)
+#ifdef LZ4_ENABLED
+static int z_erofs_decompress_lz4(struct z_erofs_decompress_req *rq)
{
int ret = 0;
char *dest = rq->out;
@@ -64,6 +63,7 @@ out:
return ret;
}
+#endif
int z_erofs_decompress(struct z_erofs_decompress_req *rq)
{
@@ -79,5 +79,9 @@ int z_erofs_decompress(struct z_erofs_decompress_req *rq)
return 0;
}
- return z_erofs_decompress_generic(rq);
+#ifdef LZ4_ENABLED
+ if (rq->alg == Z_EROFS_COMPRESSION_LZ4)
+ return z_erofs_decompress_lz4(rq);
+#endif
+ return -EOPNOTSUPP;
}
--
2.24.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2020-10-24 15:28 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20201024130959.23720-1-hsiangkao.ref@aol.com>
2020-10-24 13:09 ` [WIP] [PATCH v2 0/5] erofs-utils: introduce fuse implementation Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 1/5] " Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 2/5] erofs-utils: fuse: add special file support Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 3/5] erofs-utils: fuse: add compressed " Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 4/5] erofs-utils: fuse: drop "-Wextra" and "-Wno-implicit-fallthrough" Gao Xiang via Linux-erofs
2020-10-24 13:09 ` [WIP] [PATCH v2 5/5] erofs-utils: fuse: get rid of duplicated logging code Gao Xiang via Linux-erofs
2020-10-24 15:27 ` [WIP] [PATCH 6/5] erofs-utils: fuse: get rid of duplicated I/O ops Gao Xiang via Linux-erofs
2020-10-24 15:27 ` [WIP] [PATCH 7/5] erofs-utils: fuse: move feature_incompat to sbi Gao Xiang via Linux-erofs
2020-10-24 15:27 ` [WIP] [PATCH 8/5] erofs-utils: fuse: move decompress backend to lib Gao Xiang via Linux-erofs
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).