Re: [PATCH 1/2] ublk: support ublk recovery
Gao Xiang <[email protected]>
| Newsgroups | org.ozlabs.lists.linux-erofs |
|---|---|
| Message-ID | <[email protected]> |
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