[PATCH v2] erofs-utils: oci: add support for indexing by layer digest

Gao Xiang hsiangkao at linux.alibaba.com
Thu Sep 18 12:27:10 AEST 2025



On 2025/9/16 23:34, ChengyuZhu6 wrote:
> From: Chengyu Zhu <hudsonzhu at tencent.com>
> 
> Add support for indexing by layer_digest string for more precise
> and reliable OCI layer identification. This change affects both mkfs.erofs
> and mount.erofs tools.
> 
> Signed-off-by: Chengyu Zhu <hudsonzhu at tencent.com>
> ---
>   lib/liberofs_oci.h |   6 +-
>   lib/remotes/oci.c  |  89 +++++++++++++++++++------
>   mkfs/main.c        |  75 +++++++++++++--------
>   mount/main.c       | 160 +++++++++++++++++++++++++++++++++------------
>   4 files changed, 240 insertions(+), 90 deletions(-)
> 
> diff --git a/lib/liberofs_oci.h b/lib/liberofs_oci.h
> index aa41141..621eb2b 100644
> --- a/lib/liberofs_oci.h
> +++ b/lib/liberofs_oci.h
> @@ -21,7 +21,8 @@ struct erofs_importer;
>    * @platform: target platform in "os/arch" format (e.g., "linux/amd64")
>    * @username: username for authentication (optional)
>    * @password: password for authentication (optional)
> - * @layer_index: specific layer to extract (-1 for all layers)
> + * @layer_digest: specific layer digest to extract (NULL for all layers)
> + * @layer_index: specific layer index to extract (negative for all layers)
>    *
>    * Configuration structure for OCI image parameters including registry
>    * location, image identification, platform specification, and authentication
> @@ -32,6 +33,7 @@ struct ocierofs_config {
>   	char *platform;
>   	char *username;
>   	char *password;
> +	char *layer_digest;
>   	int layer_index;
>   };
>   
> @@ -51,7 +53,7 @@ struct ocierofs_ctx {
>   	char *tag;
>   	char *manifest_digest;
>   	struct ocierofs_layer_info **layers;
> -	int layer_index;
> +	char *layer_digest;
>   	int layer_count;
>   };
>   
> diff --git a/lib/remotes/oci.c b/lib/remotes/oci.c
> index 26aec27..d22aa2e 100644
> --- a/lib/remotes/oci.c
> +++ b/lib/remotes/oci.c
> @@ -898,6 +898,21 @@ static int ocierofs_prepare_auth(struct ocierofs_ctx *ctx,
>   	return 0;
>   }
>   
> +static int ocierofs_find_layer_by_digest(struct ocierofs_ctx *ctx, const char *digest)
> +{
> +	int i;
> +
> +	if (!digest || !ctx->layers)
> +		return -1;

It's an internal function, let's not check input argument validity (`digest`).
Or if users misuse an internal function, I'd rather to have a coredump instead
of slient failure.

In principle, `ctx->layers` won't be NULL here too (if ctx->layer_count > 0),
if it really needs to check, I suggest using `DBG_BUGON(!ctx->layers)` or
just get rid of this check.

> +
> +	for (i = 0; i < ctx->layer_count; i++) {

		DBG_BUGON(!ctx->layers[i]);
		DBG_BUGON(!ctx->layers[i]->digest);

		if (!strcmp(ctx->layers[i]->digest, digest))
			return i;


> +		if (ctx->layers[i] && ctx->layers[i]->digest &&
> +		    !strcmp(ctx->layers[i]->digest, digest))
> +			return i;
> +	}
> +	return -1;
> +}
> +
>   static int ocierofs_prepare_layers(struct ocierofs_ctx *ctx,
>   				   const struct ocierofs_config *config)
>   {
> @@ -925,16 +940,35 @@ static int ocierofs_prepare_layers(struct ocierofs_ctx *ctx,
>   		goto out_manifest;
>   	}
>   
> -	if (ctx->layer_index >= ctx->layer_count) {
> -		erofs_err("layer index %d exceeds available layers (%d)",
> -			  ctx->layer_index, ctx->layer_count);
> -		ret = -EINVAL;
> -		goto out_layers;
> +	if (config->layer_index >= 0) {
> +		if (config->layer_index >= ctx->layer_count) {
> +			erofs_err("layer index %d out of range (0..%d)",
> +				  config->layer_index, ctx->layer_count - 1);
> +			ret = -EINVAL;
> +			goto out_layers;
> +		}
> +		if (!ctx->layers[config->layer_index] ||
> +		    !ctx->layers[config->layer_index]->digest) {
> +			ret = -EINVAL;
> +			goto out_layers;
> +		}

		DBG_BUGON(!ctx->layers[config->layer_index]);
		DBG_BUGON(!ctx->layers[config->layer_index]->digest);

> +		ctx->layer_digest = strdup(ctx->layers[config->layer_index]->digest);
> +		if (!ctx->layer_digest) {
> +			ret = -ENOMEM;
> +			goto out_layers;
> +		}
> +	} else if (ctx->layer_digest) {
> +		if (ocierofs_find_layer_by_digest(ctx, ctx->layer_digest) < 0) {

	} else if (ctx->layer_digest &&
		   ocierofs_find_layer_by_digest(ctx, ctx->layer_digest) < 0) {

		erofs_err("layer digest %s not found in image layers",
			  ctx->layer_digest);
		ret = -ENOENT;
		goto out_layers;
	}


...

> -/* Parse input string in format: "image_ref platform layer [b64cred]" */
> +/* Parse input string in format: "image_ref platform layer [b64cred]"
> + * where layer is one of:
> + *   - "digest:<sha256...>" (layer_digest)
> + *   - "index:<N>"          (layer_index)
> + *   - ""                   (no specific layer)


can we just add another tag for this?
	OCI_LAYER and OCI_DIGEST

Thanks,
Gao Xiang


More information about the Linux-erofs mailing list