On 2023/9/2 00:09, Li Yiyan wrote:
Add support for the fuse low-level API in erofsfuse, proven correct in> 22 test
cases. Lowlevel API offers improved performance compared to the
high-level API, while maintaining compatibility with fuse version
2(>=2.6) and 3 (>=3.0).
Support FUSE low-level APIs for erofsfuse. Lowlevel APIs offer
improved performance compared to the previous high-level APIs,
while maintaining compatibility with libfuse version 2(>=2.6)
and 3 (>=3.0).
Dataset: linux 5.15
Compression algorithm: -z4hc,12
Compression algorithm: lz4hc, 12
Additional options: -T0 -C16384
Test options: --warmup 3 -p "echo 3 > /proc/sys/vm/drop_caches; sleep 1"
Evaluation result (highlevel->lowlevel avg time):
- Sequence metadata: 777.3 ms->180.9 ms
- Sequence data: 3.282 s->818.1 ms
- Random metadata: 1.571 s->928.3 ms
- Random data: 2.461 s->597.8 ms
Signed-off-by: Li Yiyan <[email protected]>
---
...
+
+static int erofsfuse_add_dentry(struct erofs_dir_context *ctx)
{
- struct erofsfuse_dir_context *fusectx = (void *)ctx;
- struct stat st = {0};
+ size_t size = 0;
char dname[EROFS_NAME_LEN + 1];
+ struct erofsfuse_readdir_context *readdir_ctx = (void *)ctx;
+
+ if (readdir_ctx->offset < readdir_ctx->start_off) {
+ readdir_ctx->offset +=
+ ctx->de_namelen + sizeof(struct erofs_dirent);
+ return 0;
+ }
strncpy(dname, ctx->dname, ctx->de_namelen);
dname[ctx->de_namelen] = '\0';
- st.st_mode = erofs_ftype_to_dtype(ctx->de_ftype) << 12;
here << 12 means S_SHIFT.
- fusectx->filler(fusectx->buf, dname, &st, 0);
+ readdir_ctx->offset += ctx->de_namelen + sizeof(struct erofs_dirent);
+
+ if (!readdir_ctx->is_plus) { /* fuse 3 still use non-plus readdir */
+ struct stat st = { 0 };
+
+ st.st_mode = erofs_ftype_to_dtype(ctx->de_ftype);
I'm afriad that is incorrect. Maybe we need a erofs_ftype_to_umode()
helper then.
+ st.st_ino = ctx->de_nid;
+ size = fuse_add_direntry(readdir_ctx->req, readdir_ctx->buf,
+ readdir_ctx->buf_size, dname, &st,
+ readdir_ctx->offset);
+ } else {
+#if FUSE_MAJOR_VERSION >= 3
+ struct fuse_entry_param param;
I think here you could define as
struct fuse_entry_param param = {
.ino = erofsfuse_to_ino(ctx->de_nid),
.attr.st_ino = ctx->de_nid,
.attr.st_mode = erofs_ftype_to_umode(ctx->de_ftype),
};
to avoid uninitialized fields.
+
+ param.ino = erofsfuse_to_ino(ctx->de_nid);
+ param.generation = 0;
+ param.attr.st_ino = ctx->de_nid;
+ param.attr.st_mode = erofs_ftype_to_dtype(ctx->de_ftype);
ditto.
Otherwise it looks good to me generally.
Thanks,
Gao Xiang