Hi Chengyu,

On 2026/6/19 12:19, Chengyu wrote:
From: Chengyu Zhu <[email protected]>

Enable ublk user recovery so erofsmount can reattach a daemon to a
recoverable ublk device after the previous userspace server exits.

Store the recovery source information in a ublk-specific runtime record,
create ublk devices with user recovery enabled, and add the mount-side
reattach path for existing recoverable ublk devices.

Also encode ublk IO uring command opcodes explicitly for non-legacy kernels,
and initialize the control ring before querying whether a ublk device is
recoverable.

Signed-off-by: Chengyu Zhu <[email protected]>
---
  lib/backends/ublk.c |  23 ++++++---
  mount/main.c        | 115 ++++++++++++++++++++++++++++++++++++++++----
  2 files changed, 122 insertions(+), 16 deletions(-)

diff --git a/lib/backends/ublk.c b/lib/backends/ublk.c
index a8ecad9..49191de 100644
--- a/lib/backends/ublk.c
+++ b/lib/backends/ublk.c
@@ -258,7 +258,16 @@ static unsigned int erofsublk_formalize_cmd_op(unsigned 
int op)
        DBG_BUGON(_IOC_DIR(op) != 0);
        DBG_BUGON(_IOC_SIZE(op) != 0);
- if (op < ARRAY_SIZE(ctrl_cmd_op) && !erofs_ublk_use_legacy_cmds)
+       if (erofs_ublk_use_legacy_cmds)
+               return op;
+
+       /* IO opcodes live above the ctrl table and need explicit encoding */
+       if (op == UBLK_IO_FETCH_REQ)
+               return UBLK_U_IO_FETCH_REQ;
+       if (op == UBLK_IO_COMMIT_AND_FETCH_REQ)
+               return UBLK_U_IO_COMMIT_AND_FETCH_REQ;
+
+       if (op < ARRAY_SIZE(ctrl_cmd_op))
                return ctrl_cmd_op[op];
        return op;

        if (!erofs_ublk_use_legacy_cmds) {
                if (op == UBLK_IO_FETCH_REQ)
                        return UBLK_U_IO_FETCH_REQ;
                if (op == UBLK_IO_COMMIT_AND_FETCH_REQ)
                        return UBLK_U_IO_COMMIT_AND_FETCH_REQ;
                if (op < ARRAY_SIZE(ctrl_cmd_op))
                        return ctrl_cmd_op[op];
        }
        return op;

?


  }
@@ -528,11 +537,6 @@ static inline unsigned int user_data_to_tag(u64 user_data)
        return user_data & 0xffff;
  }

..

+static int ublk_dev_id_from_path(const char *path);

Can we avoid forward declaration?

+
+static int erofsmount_ublk_reattach(int dev_id)
+{
+       struct erofsmount_nbd_ctx ctx = { .vd = &ctx._vd };
+       char *recp;
+       FILE *f;
+       int err;
+
+       if (!erofs_ublk_is_recoverable(dev_id))
+               return -EINVAL;
+
+       if (asprintf(&recp, EROFSMOUNT_UBLK_REC_FMT, dev_id) <= 0)
+               return -ENOMEM;
+
+       f = fopen(recp, "r");
+       if (!f) {
+               err = -errno;
+               free(recp);
+               return err;
+       }
+
+       err = erofsmount_open_recovery_source(&ctx, f);
+       if (err) {
+               free(recp);
+               return err;
+       }
+
+       if (fork() == 0) {
+               err = erofs_ublk_recover_dev(dev_id, erofsmount_ublk_handler,
+                                            ctx.vd);
+               if (err) {
+                       erofs_err("ublk recover dev %d failed: %s",
+                                 dev_id, strerror(-err));
+                       erofs_io_close(ctx.vd);
+                       exit(EXIT_FAILURE);
+               }
+               err = erofs_ublk_start(dev_id, -1);
+               erofs_ublk_destroy(dev_id);
+               erofs_io_close(ctx.vd);
+               (void)unlink(recp);
+               exit(err ? EXIT_FAILURE : EXIT_SUCCESS);
+       }
+
+       erofs_io_close(ctx.vd);
+       free(recp);
+       return 0;
+}
+
  static int erofsmount_reattach(const char *target)
  {
        struct erofsmount_nbd_ctx ctx = { .vd = &ctx._vd };
@@ -1450,6 +1528,10 @@ static int erofsmount_reattach(const char *target)
        if (err < 0)
                return -errno;
+ nbdnum = ublk_dev_id_from_path(target);
+       if (S_ISBLK(st.st_mode) && nbdnum >= 0)
+               return erofsmount_ublk_reattach(nbdnum);
+
        if (!S_ISBLK(st.st_mode) || major(st.st_rdev) != EROFS_NBD_MAJOR)
                return -ENOTBLK;

        if (!S_ISBLK(st.st_mode))
                return -ENOTBLK;

        nbdnum = ublk_dev_id_from_path(target);
        if (nbdnum >= 0)
                return erofsmount_ublk_reattach(nbdnum);

        if (major(st.st_rdev) != EROFS_NBD_MAJOR)
                return -ENOTBLK;

?


Thanks,
Gao Xiang

Reply via email to