From 0099190e7f18e890185e36c5a657e9ce95179bc8 Mon Sep 17 00:00:00 2001 From: zhongtao Date: Fri, 1 Mar 2024 15:04:09 +0800 Subject: [PATCH 17/43] bugfix for the concurrency competition between the reuse layer and the creation layer Signed-off-by: zhongtao --- src/daemon/modules/image/oci/oci_load.c | 9 ++++++++- src/daemon/modules/image/oci/registry/registry.c | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/daemon/modules/image/oci/oci_load.c b/src/daemon/modules/image/oci/oci_load.c index 534e2647..85127f35 100644 --- a/src/daemon/modules/image/oci/oci_load.c +++ b/src/daemon/modules/image/oci/oci_load.c @@ -680,6 +680,12 @@ static int oci_load_set_layers_info(load_image_t *im, const image_manifest_items char *parent_chain_id_sha256 = ""; char *id = NULL; char *parent_chain_id = NULL; + // exist_flag is used to mark whether a non-existent layer has been encountered during this layer reuse process. + // 1.exist_flag is true if the layers are currently reusable; + // 2.exist_flag is false if encounter an uncreated layer that cannot be reused + // Prevent concurrent competition between the creation layer function + // and the reuse layer function on the im -> layer_of_hold_refs variable + bool exist_flag = true; if (im == NULL || manifest == NULL || dstdir == NULL) { ERROR("Invalid input params image or manifest is null"); @@ -761,7 +767,7 @@ static int oci_load_set_layers_info(load_image_t *im, const image_manifest_items goto out; } - if (storage_inc_hold_refs(id) == 0) { + if (exist_flag && storage_inc_hold_refs(id) == 0) { free(im->layer_of_hold_refs); im->layer_of_hold_refs = util_strdup_s(id); if (parent_chain_id != NULL && storage_dec_hold_refs(parent_chain_id) != 0) { @@ -781,6 +787,7 @@ static int oci_load_set_layers_info(load_image_t *im, const image_manifest_items continue; } + exist_flag = false; if (check_and_set_digest_from_tarball(im->layers[i], conf->rootfs->diff_ids[i]) != 0) { ERROR("Check layer digest failed"); ret = -1; diff --git a/src/daemon/modules/image/oci/registry/registry.c b/src/daemon/modules/image/oci/registry/registry.c index aed3057a..66fa0076 100644 --- a/src/daemon/modules/image/oci/registry/registry.c +++ b/src/daemon/modules/image/oci/registry/registry.c @@ -1516,6 +1516,12 @@ static int fetch_all(pull_descriptor *desc) struct layer_list *list = NULL; pthread_t tid = 0; struct timespec ts = { 0 }; + // exist_flag is used to mark whether a non-existent layer has been encountered during this layer reuse process. + // 1.exist_flag is true if the layers are currently reusable; + // 2.exist_flag is false if encounter an uncreated layer that cannot be reused + // Prevent concurrent competition between the creation layer function + // and the reuse layer function on the im -> layer_of_hold_refs variable + bool exist_flag = true; if (desc == NULL) { ERROR("Invalid NULL param"); @@ -1547,7 +1553,7 @@ static int fetch_all(pull_descriptor *desc) // Skip layer that already exist in local store list = storage_layers_get_by_compress_digest(desc->layers[i].digest); - if (list != NULL) { + if (exist_flag && list != NULL) { for (j = 0; j < list->layers_len; j++) { if ((list->layers[j]->parent == NULL && i == 0) || (parent_chain_id != NULL && list->layers[j]->parent != NULL && @@ -1579,6 +1585,7 @@ static int fetch_all(pull_descriptor *desc) continue; } } + exist_flag = false; // parent_chain_id = NULL means no parent chain match from now on, so no longer need // to get layers by compressed digest to reuse layer. -- 2.34.1