[PATCH v1] erofs-utils:mount: add OCI recovery support for NBD reattach

Gao Xiang hsiangkao at linux.alibaba.com
Tue Sep 9 18:46:16 AEST 2025



On 2025/9/9 15:09, ChengyuZhu6 wrote:
> From: Chengyu Zhu <hudsonzhu at tencent.com>
> 
> This commit implements recovery support for OCI-based NBD mounts,
> allowing the system to properly reattach NBD devices after
> NBD disconnection.
> 
> Signed-off-by: Chengyu Zhu <hudsonzhu at tencent.com>
> ---
>   mount/main.c | 100 ++++++++++++++++++++++++++++++++++++++-------------
>   1 file changed, 75 insertions(+), 25 deletions(-)
> 
> diff --git a/mount/main.c b/mount/main.c
> index c52ac3b..37e9f6d 100644
> --- a/mount/main.c
> +++ b/mount/main.c
> @@ -401,12 +401,14 @@ out_closefd:
>   	return err;
>   }
>   
> -static char *erofsmount_write_recovery_info(const char *source)
> +static char *erofsmount_write_recovery_info(struct erofs_nbd_source *source)
>   {
>   	char recp[] = "/var/run/erofs/mountnbd_XXXXXX";
>   	char *realp;
>   	int fd, err;
>   	FILE *f;
> +	char *content = NULL;
> +	int ret;
>   
>   	fd = mkstemp(recp);
>   	if (fd < 0 && errno == ENOENT) {
> @@ -424,15 +426,32 @@ static char *erofsmount_write_recovery_info(const char *source)
>   		return ERR_PTR(-errno);
>   	}
>   
> -	realp = realpath(source, NULL);
> -	if (!realp) {
> -		fclose(f);
> -		return ERR_PTR(-errno);
> +	if (source->type == EROFSNBD_SOURCE_OCI) {

Could we just split this block into:
	erofsmount_write_recovery_oci(f, source);

> +		ret = asprintf(&content, "%s %s %s %s %d",
> +			       source->ocicfg.image_ref ?: "",
> +			       source->ocicfg.platform ?: "",
> +			       source->ocicfg.username ?: "",
> +			       source->ocicfg.password ?: "",

Could we just encode username:password into base64?

> +			       source->ocicfg.layer_index);
> +		if (ret < 0) {
> +			fclose(f);
> +			return ERR_PTR(-ENOMEM);
> +		}
> +		err = fprintf(f, "OCI_LAYER %s\n", content) < 0;
> +		free(content);
> +	} else {

and this into:
	erofsmount_write_recovery_local(f, source);

> +		realp = realpath(source->device_path, NULL);
> +		if (!realp) {
> +			fclose(f);
> +			return ERR_PTR(-errno);
> +		}
> +
> +		/* TYPE<LOCAL> <SOURCE PATH>\n(more..) */
> +		err = fprintf(f, "LOCAL %s\n", realp) < 0;
> +		free(realp);
>   	}
> -	/* TYPE<LOCAL> <SOURCE PATH>\n(more..) */
> -	err = fprintf(f, "LOCAL %s\n", realp) < 0;
> +
>   	fclose(f);
> -	free(realp);
>   	if (err)
>   		return ERR_PTR(-ENOMEM);
>   	return strdup(recp) ?: ERR_PTR(-ENOMEM);
> @@ -491,15 +510,10 @@ static int erofsmount_startnbd_nl(pid_t *pid, struct erofs_nbd_source *source)
>   				exit(EXIT_FAILURE);
>   			ctx.vd.fd = err;
>   		}
> -
> -		if (source->type == EROFSNBD_SOURCE_LOCAL) {
> -			recp = erofsmount_write_recovery_info(source->device_path);
> -			if (IS_ERR(recp)) {
> -				erofs_io_close(&ctx.vd);
> -				exit(EXIT_FAILURE);
> -			}
> -		} else {
> -			recp = NULL;
> +		recp = erofsmount_write_recovery_info(source);
> +		if (IS_ERR(recp)) {
> +			erofs_io_close(&ctx.vd);
> +			exit(EXIT_FAILURE);
>   		}
>   
>   		num = -1;
> @@ -595,19 +609,55 @@ static int erofsmount_reattach(const char *target)
>   		*(source++) = '\0';
>   	}
>   
> -	if (strcmp(line, "LOCAL")) {
> +	if (!strcmp(line, "LOCAL")) {
> +		err = open(source, O_RDONLY);
> +		if (err < 0) {
> +			err = -errno;
> +			goto err_line;
> +		}
> +		ctx.vd.fd = err;
> +	} else if (!strcmp(line, "OCI_LAYER")) {
> +		struct ocierofs_config oci_cfg = {};
> +		char *platform, *username, *password, *layer_str;
> +		int layer_index;
> +
> +		platform = strchr(source, ' ');
> +		if (platform) {
> +			*platform++ = '\0';
> +			oci_cfg.image_ref = source;
> +			oci_cfg.platform = platform;
> +		} else {
> +			oci_cfg.image_ref = source;
> +		}
> +
> +		username = strchr(platform ?: source, ' ');
> +		if (username) {
> +			*username++ = '\0';
> +			oci_cfg.username = username;
> +		}
> +
> +		password = strchr(username ?: (platform ?: source), ' ');
> +		if (password) {
> +			*password++ = '\0';
> +			oci_cfg.password = password;
> +		}
> +
> +		layer_str = strchr(password ?: (username ?: (platform ?: source)), ' ');
> +		if (layer_str) {
> +			*layer_str++ = '\0';
> +			layer_index = atoi(layer_str);
> +			oci_cfg.layer_index = layer_index;
> +		}

Move those into erofsmount_parse_recovery_ocilayer(&oci_cfg, source)?

Thanks,
Gao Xiang


More information about the Linux-erofs mailing list