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

Reply via email to