diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml
index c0cf1c5257b..108c764f81a 100644
--- a/.github/workflows/ossf-scorecard.yml
+++ b/.github/workflows/ossf-scorecard.yml
@@ -33,12 +33,12 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: "Run analysis"
- uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
+ uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
@@ -71,6 +71,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
+ uses: github/codeql-action/upload-sarif@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
with:
sarif_file: results.sarif
diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml
index dd8b3c3db7c..f2ca5ef18bc 100644
--- a/.github/workflows/trivy.yml
+++ b/.github/workflows/trivy.yml
@@ -23,7 +23,7 @@ jobs:
security-events: write
steps:
- name: Checkout code
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Run Trivy vulnerability scanner in filesystem mode (table format)
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1
@@ -58,7 +58,7 @@ jobs:
trivy-config: 'utils/trivy/trivy.yaml'
- name: Upload Trivy scan results to GitHub Security tab
- uses: github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
+ uses: github/codeql-action/upload-sarif@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
with:
sarif_file: 'trivy-results.sarif'
diff --git a/.gitignore b/.gitignore
index 0960ff64e30..cdef98717dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,3 +65,4 @@ utils/githooks/*.d/*-user-*
.vscode
src/include/daos_version.h
utils/rpms/mock.cfg
+trivy-report-daos.txt
diff --git a/Jenkinsfile b/Jenkinsfile
index 078cc2e8c0b..8b996b2c659 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -291,10 +291,10 @@ pipeline {
defaultValue: true,
description: 'Run the Functional on EL 8 test stage')
booleanParam(name: 'CI_FUNCTIONAL_el9_TEST',
- defaultValue: true,
+ defaultValue: false,
description: 'Run the Functional on EL 9 test stage')
booleanParam(name: 'CI_FUNCTIONAL_leap15_TEST',
- defaultValue: true,
+ defaultValue: false,
description: 'Run the Functional on Leap 15 test stage' +
' Requires CI_MORE_FUNCTIONAL_PR_TESTS')
booleanParam(name: 'CI_FUNCTIONAL_ubuntu20_TEST',
@@ -311,7 +311,7 @@ pipeline {
defaultValue: false,
description: 'Run the Functional Hardware Medium MD on SSD test stage')
booleanParam(name: 'CI_medium_vmd_TEST',
- defaultValue: true,
+ defaultValue: false,
description: 'Run the Functional Hardware Medium VMD test stage')
booleanParam(name: 'CI_medium_verbs_provider_TEST',
defaultValue: false,
diff --git a/ci/provisioning/post_provision_config_nodes_LEAP.sh b/ci/provisioning/post_provision_config_nodes_LEAP.sh
index 4e6dc3e4e41..5a2a553e56f 100644
--- a/ci/provisioning/post_provision_config_nodes_LEAP.sh
+++ b/ci/provisioning/post_provision_config_nodes_LEAP.sh
@@ -9,7 +9,7 @@ bootstrap_dnf() {
rm -rf "$REPOS_DIR"
ln -s ../zypp/repos.d "$REPOS_DIR"
dnf -y remove lua54 lua-lmod
- dnf -y --nogpgcheck install lua-lmod '--repo=*lua*' --repo '*network-cluster*'
+ dnf -y --nogpgcheck install lua-lmod --repo '*lua*' --repo '*network-cluster*' --repo '*oss-proxy*'
}
group_repo_post() {
diff --git a/src/cart/crt_iv.c b/src/cart/crt_iv.c
index c1d9c9e85cb..9913686e5f1 100644
--- a/src/cart/crt_iv.c
+++ b/src/cart/crt_iv.c
@@ -1843,11 +1843,10 @@ crt_hdlr_iv_sync_aux(void *arg)
grp_ver = ivns_internal->cii_grp_priv->gp_membs_ver;
D_RWLOCK_UNLOCK(&ivns_internal->cii_grp_priv->gp_rwlock);
if (grp_ver != input->ivs_grp_ver) {
- D_DEBUG(DB_ALL,
- "Group (%s) version mismatch. Local: %d Remote :%d\n",
- ivns_id.ii_group_name, grp_ver,
- input->ivs_grp_ver);
- D_GOTO(exit, rc = -DER_GRPVER);
+ rc = -DER_GRPVER;
+ DL_INFO(rc, "Group (%s) version mismatch. Local: %d Remote :%d",
+ ivns_id.ii_group_name, grp_ver, input->ivs_grp_ver);
+ goto exit;
}
iv_ops = crt_iv_ops_get(ivns_internal, input->ivs_class_id);
@@ -1922,7 +1921,7 @@ crt_hdlr_iv_sync_aux(void *arg)
if (need_put && iv_ops)
iv_ops->ivo_on_put(ivns_internal, NULL, user_priv);
- output->rc = rc;
+ output->ivs_rc = rc;
crt_reply_send(rpc_req);
/* ADDREF done in lookup above */
@@ -2002,7 +2001,7 @@ crt_hdlr_iv_sync(crt_rpc_t *rpc_req)
IVNS_DECREF(ivns_internal);
return;
exit:
- output->rc = rc;
+ output->ivs_rc = rc;
crt_reply_send(rpc_req);
if (ivns_internal) {
@@ -2022,9 +2021,9 @@ crt_iv_sync_corpc_aggregate(crt_rpc_t *source, crt_rpc_t *result, void *arg)
output_result = crt_reply_get(result);
/* Only set new rc if so far rc is 0 */
- if (output_result->rc == 0) {
- if (output_source->rc != 0)
- output_result->rc = output_source->rc;
+ if (output_result->ivs_rc == 0) {
+ if (output_source->ivs_rc != 0)
+ output_result->ivs_rc = output_source->ivs_rc;
}
return 0;
@@ -2163,14 +2162,16 @@ handle_ivsync_response(const struct crt_cb_info *cb_info)
{
struct iv_sync_cb_info *iv_sync = cb_info->cci_arg;
struct crt_iv_ops *iv_ops;
+ crt_rpc_t *rpc = cb_info->cci_rpc;
+ struct crt_iv_sync_out *output = crt_reply_get(rpc);
if (iv_sync->isc_bulk_hdl != CRT_BULK_NULL)
crt_bulk_free(iv_sync->isc_bulk_hdl);
/* do_callback is set based on sync value specified */
if (iv_sync->isc_do_callback) {
- if (cb_info->cci_rc != 0)
- iv_sync->isc_update_rc = cb_info->cci_rc;
+ if (cb_info->cci_rc || output->ivs_rc)
+ iv_sync->isc_update_rc = cb_info->cci_rc ? cb_info->cci_rc : output->ivs_rc;
iv_sync->isc_update_comp_cb(iv_sync->isc_ivns_internal,
iv_sync->isc_class_id,
@@ -2412,7 +2413,7 @@ finalize_transfer_back(struct update_cb_info *cb_info, int rc)
struct crt_iv_update_out *child_output;
child_output = crt_reply_get(cb_info->uci_child_rpc);
- child_output->rc = rc;
+ child_output->ivo_rc = rc;
ivns = cb_info->uci_ivns_internal;
crt_reply_send(cb_info->uci_child_rpc);
@@ -2528,15 +2529,15 @@ handle_ivupdate_response(const struct crt_cb_info *cb_info)
if (iv_info->uci_bulk_hdl == CRT_BULK_NULL)
d_sgl_buf_copy(&iv_info->uci_iv_value, &output->ivo_iv_sgl);
iv_ops->ivo_on_refresh(iv_info->uci_ivns_internal, &input->ivu_key, 0,
- &iv_info->uci_iv_value, false, cb_info->cci_rc ?: output->rc,
- iv_info->uci_user_priv);
+ &iv_info->uci_iv_value, false,
+ cb_info->cci_rc ?: output->ivo_rc, iv_info->uci_user_priv);
if (input->ivu_iv_value_bulk == CRT_BULK_NULL &&
iv_info->uci_child_rpc != NULL) {
child_output = crt_reply_get(iv_info->uci_child_rpc);
child_output->ivo_iv_sgl = iv_info->uci_iv_value;
}
- transfer_back_to_child(&input->ivu_key, iv_info, cb_info->cci_rc ?: output->rc);
+ transfer_back_to_child(&input->ivu_key, iv_info, cb_info->cci_rc ?: output->ivo_rc);
D_GOTO(exit, 0);
}
@@ -2549,10 +2550,10 @@ handle_ivupdate_response(const struct crt_cb_info *cb_info)
iv_ops->ivo_on_put(iv_info->uci_ivns_internal, &iv_info->uci_iv_value,
iv_info->uci_user_priv);
- child_output->rc = output->rc;
+ child_output->ivo_rc = output->ivo_rc;
if (cb_info->cci_rc != 0)
- child_output->rc = cb_info->cci_rc;
+ child_output->ivo_rc = cb_info->cci_rc;
/* Respond back to child; might fail if child is not alive */
if (crt_reply_send(iv_info->uci_child_rpc) != DER_SUCCESS)
@@ -2568,7 +2569,7 @@ handle_ivupdate_response(const struct crt_cb_info *cb_info)
else
tmp_iv_value = &iv_info->uci_iv_value;
- rc = output->rc;
+ rc = output->ivo_rc;
if (cb_info->cci_rc != 0)
rc = cb_info->cci_rc;
@@ -2897,7 +2898,7 @@ bulk_update_transfer_done_aux(const struct crt_bulk_cb_info *info)
D_GOTO(exit, rc);
}
rc = crt_bulk_free(cb_info->buc_bulk_hdl);
- output->rc = rc;
+ output->ivo_rc = rc;
iv_ops->ivo_on_put(ivns_internal, &cb_info->buc_iv_value, cb_info->buc_user_priv);
crt_reply_send(info->bci_bulk_desc->bd_rpc);
@@ -2913,7 +2914,7 @@ bulk_update_transfer_done_aux(const struct crt_bulk_cb_info *info)
send_error:
/* send back whatever error got us here */
- output->rc = rc;
+ output->ivo_rc = rc;
rc = crt_bulk_free(cb_info->buc_bulk_hdl);
if (rc != 0)
DL_ERROR(rc, "crt_bulk_free() failed");
@@ -3016,7 +3017,7 @@ bulk_update_transfer_done(const struct crt_bulk_cb_info *info)
return rc;
send_error:
- output->rc = rc;
+ output->ivo_rc = rc;
crt_reply_send(info->bci_bulk_desc->bd_rpc);
crt_bulk_free(cb_info->buc_bulk_hdl);
@@ -3121,7 +3122,7 @@ crt_iv_update_inline_hdlr(crt_rpc_t *rpc, struct crt_ivns_internal *ivns_interna
D_GOTO(exit, rc);
}
} else if (rc == 0) {
- output->rc = rc;
+ output->ivo_rc = rc;
crt_reply_send(rpc);
iv_ops->ivo_on_put(ivns_internal, &iv_value, user_priv);
} else {
@@ -3136,7 +3137,7 @@ crt_iv_update_inline_hdlr(crt_rpc_t *rpc, struct crt_ivns_internal *ivns_interna
iv_ops->ivo_on_put(ivns_internal, &iv_value, user_priv);
send_error:
- output->rc = rc;
+ output->ivo_rc = rc;
crt_reply_send(rpc);
if (update_cb_info)
D_FREE(update_cb_info);
@@ -3270,7 +3271,7 @@ crt_hdlr_iv_update(crt_rpc_t *rpc_req)
}
} else if (rc == 0) {
- output->rc = rc;
+ output->ivo_rc = rc;
rc = crt_reply_send(rpc_req);
} else {
D_GOTO(send_error, rc);
@@ -3340,7 +3341,7 @@ crt_hdlr_iv_update(crt_rpc_t *rpc_req)
return;
send_error:
- output->rc = rc;
+ output->ivo_rc = rc;
crt_reply_send(rpc_req);
if (put_needed)
diff --git a/src/cart/crt_rpc.h b/src/cart/crt_rpc.h
index 904ca89dc40..f55a608974f 100644
--- a/src/cart/crt_rpc.h
+++ b/src/cart/crt_rpc.h
@@ -513,7 +513,7 @@ CRT_RPC_DECLARE(crt_iv_fetch, CRT_ISEQ_IV_FETCH, CRT_OSEQ_IV_FETCH)
((uint32_t) (padding) CRT_VAR)
#define CRT_OSEQ_IV_UPDATE /* output fields */ \
- ((uint64_t) (rc) CRT_VAR) \
+ ((uint64_t) (ivo_rc) CRT_VAR) \
((d_sg_list_t) (ivo_iv_sgl) CRT_VAR)
CRT_RPC_DECLARE(crt_iv_update, CRT_ISEQ_IV_UPDATE, CRT_OSEQ_IV_UPDATE)
@@ -532,7 +532,7 @@ CRT_RPC_DECLARE(crt_iv_update, CRT_ISEQ_IV_UPDATE, CRT_OSEQ_IV_UPDATE)
((uint32_t) (ivs_class_id) CRT_VAR) \
#define CRT_OSEQ_IV_SYNC /* output fields */ \
- ((int32_t) (rc) CRT_VAR)
+ ((int32_t) (ivs_rc) CRT_VAR)
CRT_RPC_DECLARE(crt_iv_sync, CRT_ISEQ_IV_SYNC, CRT_OSEQ_IV_SYNC)
diff --git a/src/client/dfuse/dfuse.h b/src/client/dfuse/dfuse.h
index 47725aaed71..eaa527eff1f 100644
--- a/src/client/dfuse/dfuse.h
+++ b/src/client/dfuse/dfuse.h
@@ -1,6 +1,7 @@
/**
* (C) Copyright 2016-2024 Intel Corporation.
* (C) Copyright 2025 Google LLC
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -28,6 +29,12 @@ struct dfuse_info {
struct fuse_session *di_session;
char *di_group;
char *di_mountpoint;
+ char *di_handles_file;
+ bool di_dump_handles;
+ bool di_read_handles;
+ daos_handle_t di_poh;
+ daos_handle_t di_coh;
+ dfs_t *di_dfs;
int32_t di_thread_count;
uint32_t di_eq_count;
bool di_foreground;
diff --git a/src/client/dfuse/dfuse_core.c b/src/client/dfuse/dfuse_core.c
index 77bce41bd04..55e49d89f97 100644
--- a/src/client/dfuse/dfuse_core.c
+++ b/src/client/dfuse/dfuse_core.c
@@ -500,14 +500,24 @@ dfuse_pool_connect(struct dfuse_info *dfuse_info, const char *label, struct dfus
if (label) {
daos_pool_info_t p_info = {};
- rc = daos_pool_connect(label, dfuse_info->di_group, DAOS_PC_RO, &dfp->dfp_poh,
- &p_info, NULL);
- if (rc) {
- if (rc == -DER_NO_PERM || rc == -DER_NONEXIST)
- DHL_INFO(dfp, rc, "daos_pool_connect() failed");
- else
- DHL_ERROR(dfp, rc, "daos_pool_connect() failed");
- D_GOTO(err_free, rc = daos_der2errno(rc));
+ /** if we read the pool handle, query for the info */
+ if (dfuse_info->di_read_handles) {
+ dfp->dfp_poh = dfuse_info->di_poh;
+ rc = daos_pool_query(dfp->dfp_poh, NULL, &p_info, NULL, NULL);
+ if (rc) {
+ DHL_ERROR(dfp, rc, "daos_pool_query() failed");
+ D_GOTO(err_free, rc = daos_der2errno(rc));
+ }
+ } else {
+ rc = daos_pool_connect(label, dfuse_info->di_group, DAOS_PC_RO,
+ &dfp->dfp_poh, &p_info, NULL);
+ if (rc) {
+ if (rc == -DER_NO_PERM || rc == -DER_NONEXIST)
+ DHL_INFO(dfp, rc, "daos_pool_connect() failed");
+ else
+ DHL_ERROR(dfp, rc, "daos_pool_connect() failed");
+ D_GOTO(err_free, rc = daos_der2errno(rc));
+ }
}
uuid_copy(dfp->dfp_uuid, p_info.pi_uuid);
@@ -848,17 +858,23 @@ dfuse_cont_open(struct dfuse_info *dfuse_info, struct dfuse_pool *dfp, const cha
int dfs_flags = O_RDWR;
dfc->dfs_ops = &dfuse_dfs_ops;
- if (dfuse_info->di_read_only) {
- dfs_flags = O_RDONLY;
- rc = daos_cont_open(dfp->dfp_poh, label, DAOS_COO_RO, &dfc->dfs_coh,
- &c_info, NULL);
+
+ if (dfuse_info->di_read_handles) {
+ dfc->dfs_coh = dfuse_info->di_coh;
+ rc = daos_cont_query(dfc->dfs_coh, &c_info, NULL, NULL);
} else {
- rc = daos_cont_open(dfp->dfp_poh, label, DAOS_COO_RW, &dfc->dfs_coh,
- &c_info, NULL);
- if (rc == -DER_NO_PERM) {
+ if (dfuse_info->di_read_only) {
dfs_flags = O_RDONLY;
rc = daos_cont_open(dfp->dfp_poh, label, DAOS_COO_RO, &dfc->dfs_coh,
&c_info, NULL);
+ } else {
+ rc = daos_cont_open(dfp->dfp_poh, label, DAOS_COO_RW, &dfc->dfs_coh,
+ &c_info, NULL);
+ if (rc == -DER_NO_PERM) {
+ dfs_flags = O_RDONLY;
+ rc = daos_cont_open(dfp->dfp_poh, label, DAOS_COO_RO,
+ &dfc->dfs_coh, &c_info, NULL);
+ }
}
}
if (rc != -DER_SUCCESS) {
@@ -869,10 +885,14 @@ dfuse_cont_open(struct dfuse_info *dfuse_info, struct dfuse_pool *dfp, const cha
D_GOTO(err_free, rc = daos_der2errno(rc));
}
- rc = dfs_mount(dfp->dfp_poh, dfc->dfs_coh, dfs_flags, &dfc->dfs_ns);
- if (rc) {
- DHS_ERROR(dfc, rc, "dfs mount() failed");
- D_GOTO(err_close, rc);
+ if (dfuse_info->di_read_handles)
+ dfc->dfs_ns = dfuse_info->di_dfs;
+ else {
+ rc = dfs_mount(dfp->dfp_poh, dfc->dfs_coh, dfs_flags, &dfc->dfs_ns);
+ if (rc) {
+ DHS_ERROR(dfc, rc, "dfs mount() failed");
+ D_GOTO(err_close, rc);
+ }
}
uuid_copy(dfc->dfc_uuid, c_info.ci_uuid);
diff --git a/src/client/dfuse/dfuse_main.c b/src/client/dfuse/dfuse_main.c
index 6c0611b48a8..4587b08e2d1 100644
--- a/src/client/dfuse/dfuse_main.c
+++ b/src/client/dfuse/dfuse_main.c
@@ -292,6 +292,10 @@ show_help(char *name)
"\n"
" --multi-user Run dfuse in multi user mode\n"
" --read-only Mount dfuse read-only\n"
+ " --dump-handles=file Serialize and dump the pool, container, and dfs handles"
+ " to file using the local2global DAOS functionality\n"
+ " --read-handles=file Read the deserialize the pool, cont, and dfs handles,"
+ " and use them instead of connecting to the server\n"
"\n"
" -h --help Show this help\n"
" -v --version Show version\n"
@@ -368,6 +372,11 @@ show_help(char *name)
" The default is --enable-wb-cache.\n"
"* If --disable-caching and --enable-wb-cache are both specified,\n"
" the --enable-wb-cache option is ignored and no caching is performed.\n"
+ "* If --dump-handles is used from one dfuse mount and --read-handles is used for\n"
+ " starting other dfuse mounts, the dfuse mount that dumps the handles cannot be\n"
+ " umounted before the others, otherwise the other mounts will become inaccessible\n"
+ " since the g2l & l2g method for sharing DAOS handles requires the main process\n"
+ " that establishes the pool and container connections to keep those alive.\n"
"\n"
"Version: %s\n",
name, DAOS_VERSION);
@@ -431,6 +440,8 @@ main(int argc, char **argv)
{"enable-wb-cache", no_argument, 0, 'F'},
{"disable-caching", no_argument, 0, 'A'},
{"disable-wb-cache", no_argument, 0, 'B'},
+ {"dump-handles", required_argument, 0, 'D'},
+ {"read-handles", required_argument, 0, 'R'},
{"read-only", no_argument, 0, 'r'},
{"options", required_argument, 0, 'o'},
{"version", no_argument, 0, 'v'},
@@ -450,6 +461,8 @@ main(int argc, char **argv)
dfuse_info->di_caching = true;
dfuse_info->di_wb_cache = true;
dfuse_info->di_eq_count = 1;
+ dfuse_info->di_dump_handles = false;
+ dfuse_info->di_read_handles = false;
while (1) {
c = getopt_long(argc, argv, "Mm:t:o:fhe:v", long_options, NULL);
@@ -484,6 +497,14 @@ main(int argc, char **argv)
case 'm':
dfuse_info->di_mountpoint = optarg;
break;
+ case 'D':
+ dfuse_info->di_handles_file = optarg;
+ dfuse_info->di_dump_handles = true;
+ break;
+ case 'R':
+ dfuse_info->di_handles_file = optarg;
+ dfuse_info->di_read_handles = true;
+ break;
case 'M':
dfuse_info->di_multi_user = true;
break;
@@ -540,17 +561,16 @@ main(int argc, char **argv)
}
}
- if (!dfuse_info->di_foreground && d_isenv_def("PMIX_RANK")) {
- DFUSE_TRA_WARNING(dfuse_info,
- "Not running in background under orterun");
- dfuse_info->di_foreground = true;
- }
-
if (!dfuse_info->di_mountpoint) {
printf("Mountpoint is required\n");
show_help(argv[0]);
D_GOTO(out_debug, rc = -DER_INVAL);
}
+ if (dfuse_info->di_dump_handles && dfuse_info->di_read_handles) {
+ printf("Cannot dump and read handles file at the same time\n");
+ show_help(argv[0]);
+ D_GOTO(out_debug, rc = -DER_INVAL);
+ }
/* If the number of threads has been specified on the command line then use that, otherwise
* check CPU binding. If bound to a number of cores then launch that number of threads,
@@ -698,6 +718,91 @@ main(int argc, char **argv)
D_GOTO(out_daos, rc = daos_errno2der(rc));
}
+ /** if user passes a handle file, read it and store the serialized handles */
+ if (dfuse_info->di_read_handles && dfuse_info->di_handles_file) {
+ d_iov_t pool_hdl = {NULL, 0, 0};
+ d_iov_t cont_hdl = {NULL, 0, 0};
+ d_iov_t dfs_hdl = {NULL, 0, 0};
+ char *buf = NULL;
+ daos_size_t buf_size;
+ size_t sizes[3];
+ FILE *fp;
+ int dfs_flags = O_RDWR;
+
+ fp = fopen(dfuse_info->di_handles_file, "rb");
+ if (!fp) {
+ rc = errno;
+ DHL_ERROR(dfuse_info, daos_errno2der(rc), "Failed to open file %s",
+ dfuse_info->di_handles_file);
+ D_GOTO(out_daos, rc = daos_errno2der(rc));
+ }
+
+ /** read the 3 size_t values for the 3 handles */
+ if (fread(sizes, sizeof(size_t), 3, fp) != 3) {
+ rc = errno;
+ DHL_ERROR(dfuse_info, daos_errno2der(rc), "Failed to read file %s",
+ dfuse_info->di_handles_file);
+ fclose(fp);
+ D_GOTO(out_daos, rc = daos_errno2der(rc));
+ }
+ pool_hdl.iov_buf_len = pool_hdl.iov_len = sizes[0];
+ cont_hdl.iov_buf_len = cont_hdl.iov_len = sizes[1];
+ dfs_hdl.iov_buf_len = dfs_hdl.iov_len = sizes[2];
+
+ buf_size = sizes[0] + sizes[1] + sizes[2];
+ D_ALLOC(buf, buf_size);
+ if (buf == NULL) {
+ fclose(fp);
+ D_GOTO(out_daos, rc = -DER_NOMEM);
+ }
+
+ if (fread(buf, 1, buf_size, fp) != buf_size) {
+ rc = errno;
+ DHL_ERROR(dfuse_info, daos_errno2der(rc), "Failed to read file %s",
+ dfuse_info->di_handles_file);
+ fclose(fp);
+ D_FREE(buf);
+ D_GOTO(out_daos, rc = daos_errno2der(rc));
+ }
+
+ pool_hdl.iov_buf = buf;
+ cont_hdl.iov_buf = buf + pool_hdl.iov_buf_len;
+ dfs_hdl.iov_buf = buf + pool_hdl.iov_buf_len + cont_hdl.iov_buf_len;
+
+ rc = daos_pool_global2local(pool_hdl, &dfuse_info->di_poh);
+ if (rc) {
+ fclose(fp);
+ D_FREE(buf);
+ DHL_ERROR(dfuse_info, rc, "daos_pool_global2local() failed");
+ D_GOTO(out_daos, rc);
+ }
+
+ rc = daos_cont_global2local(dfuse_info->di_poh, cont_hdl, &dfuse_info->di_coh);
+ if (rc) {
+ fclose(fp);
+ D_FREE(buf);
+ daos_pool_disconnect(dfuse_info->di_poh, NULL);
+ DHL_ERROR(dfuse_info, rc, "daos_cont_global2local() failed");
+ D_GOTO(out_daos, rc);
+ }
+
+ if (dfuse_info->di_read_only)
+ dfs_flags = O_RDONLY;
+ rc = dfs_global2local(dfuse_info->di_poh, dfuse_info->di_coh, dfs_flags, dfs_hdl,
+ &dfuse_info->di_dfs);
+ if (rc) {
+ fclose(fp);
+ D_FREE(buf);
+ daos_cont_close(dfuse_info->di_coh, NULL);
+ daos_pool_disconnect(dfuse_info->di_poh, NULL);
+ DHL_ERROR(dfuse_info, rc, "dfs_global2local() failed");
+ D_GOTO(out_daos, rc);
+ }
+
+ fclose(fp);
+ D_FREE(buf);
+ }
+
/* Connect to a pool */
rc = dfuse_pool_connect(dfuse_info, pool_name[0] ? pool_name : NULL, &dfp);
if (rc != 0) {
@@ -711,6 +816,91 @@ main(int argc, char **argv)
D_GOTO(out_pool, rc = daos_errno2der(rc));
}
+ /** if user asked to dump the handles, serialize them and write them to the file */
+ if (dfuse_info->di_dump_handles && dfuse_info->di_handles_file) {
+ d_iov_t pool_hdl = {NULL, 0, 0};
+ d_iov_t cont_hdl = {NULL, 0, 0};
+ d_iov_t dfs_hdl = {NULL, 0, 0};
+ char *buf = NULL;
+ daos_size_t buf_size;
+ FILE *fp;
+
+ rc = daos_pool_local2global(dfp->dfp_poh, &pool_hdl);
+ if (rc) {
+ DHL_ERROR(dfuse_info, rc, "daos_pool_local2global() failed");
+ goto out_cont;
+ }
+ rc = daos_cont_local2global(dfs->dfs_coh, &cont_hdl);
+ if (rc) {
+ DHL_ERROR(dfuse_info, rc, "daos_cont_local2global() failed");
+ goto out_cont;
+ }
+ rc = dfs_local2global(dfs->dfs_ns, &dfs_hdl);
+ if (rc) {
+ DHL_ERROR(dfuse_info, rc, "dfs_local2global() failed");
+ goto out_cont;
+ }
+
+ buf_size = pool_hdl.iov_buf_len + cont_hdl.iov_buf_len + dfs_hdl.iov_buf_len;
+ D_ALLOC(buf, buf_size);
+ if (buf == NULL)
+ D_GOTO(out_cont, rc = -DER_NOMEM);
+
+ pool_hdl.iov_buf = buf;
+ cont_hdl.iov_buf = buf + pool_hdl.iov_buf_len;
+ dfs_hdl.iov_buf = buf + pool_hdl.iov_buf_len + cont_hdl.iov_buf_len;
+
+ rc = daos_pool_local2global(dfp->dfp_poh, &pool_hdl);
+ if (rc) {
+ DHL_ERROR(dfuse_info, rc, "daos_pool_local2global() failed");
+ D_FREE(buf);
+ goto out_cont;
+ }
+ rc = daos_cont_local2global(dfs->dfs_coh, &cont_hdl);
+ if (rc) {
+ DHL_ERROR(dfuse_info, rc, "daos_cont_local2global() failed");
+ D_FREE(buf);
+ goto out_cont;
+ }
+ rc = dfs_local2global(dfs->dfs_ns, &dfs_hdl);
+ if (rc) {
+ DHL_ERROR(dfuse_info, rc, "dfs_local2global() failed");
+ D_FREE(buf);
+ goto out_cont;
+ }
+
+ fp = fopen(dfuse_info->di_handles_file, "wb+");
+ if (!fp) {
+ rc = errno;
+ DHL_ERROR(dfuse_info, daos_errno2der(rc), "Failed to open file %s",
+ dfuse_info->di_handles_file);
+ D_FREE(buf);
+ D_GOTO(out_cont, rc = daos_errno2der(rc));
+ }
+
+ size_t sizes[3] = {pool_hdl.iov_buf_len, cont_hdl.iov_buf_len, dfs_hdl.iov_buf_len};
+
+ if (fwrite(sizes, sizeof(size_t), 3, fp) != 3) {
+ rc = errno;
+ fclose(fp);
+ D_FREE(buf);
+ DHL_ERROR(dfuse_info, daos_errno2der(rc), "Failed to write file %s",
+ dfuse_info->di_handles_file);
+ D_GOTO(out_cont, rc = daos_errno2der(rc));
+ }
+
+ if (fwrite(buf, 1, buf_size, fp) != buf_size) {
+ rc = errno;
+ fclose(fp);
+ D_FREE(buf);
+ DHL_ERROR(dfuse_info, daos_errno2der(rc), "Failed to write file %s",
+ dfuse_info->di_handles_file);
+ D_GOTO(out_cont, rc = daos_errno2der(rc));
+ }
+ fclose(fp);
+ D_FREE(buf);
+ }
+
rc = dfuse_fs_start(dfuse_info, dfs);
if (rc != -DER_SUCCESS)
D_GOTO(out_cont, rc);
diff --git a/src/client/java/daos-java/pom.xml b/src/client/java/daos-java/pom.xml
index 6b26378ac6f..b6d6b6996f3 100644
--- a/src/client/java/daos-java/pom.xml
+++ b/src/client/java/daos-java/pom.xml
@@ -41,7 +41,7 @@
io.netty
netty-buffer
- 4.1.115.Final
+ 4.1.125.Final
com.google.code.findbugs
diff --git a/src/client/java/hadoop-daos/pom.xml b/src/client/java/hadoop-daos/pom.xml
index 1bba3428580..28576e3ec63 100644
--- a/src/client/java/hadoop-daos/pom.xml
+++ b/src/client/java/hadoop-daos/pom.xml
@@ -15,7 +15,7 @@
jar
- 3.4.0
+ 3.4.2
${project.basedir}/build
${project.basedir}/install
diff --git a/src/common/misc.c b/src/common/misc.c
index e5dddf0a64e..1a7abbf2025 100644
--- a/src/common/misc.c
+++ b/src/common/misc.c
@@ -220,15 +220,17 @@ daos_sgl_merge(d_sg_list_t *dst, d_sg_list_t *src)
}
daos_size_t
-daos_sgl_data_len(d_sg_list_t *sgl)
+daos_sgl_data_len(d_sg_list_t *sgl, bool out)
{
daos_size_t len;
- int i;
+ uint32_t sg_nr;
+ uint32_t i;
if (sgl == NULL || sgl->sg_iovs == NULL)
return 0;
- for (i = 0, len = 0; i < sgl->sg_nr; i++)
+ sg_nr = out ? sgl->sg_nr_out : sgl->sg_nr;
+ for (i = 0, len = 0; i < sg_nr; i++)
len += sgl->sg_iovs[i].iov_len;
return len;
diff --git a/src/common/tests_lib.c b/src/common/tests_lib.c
index 9cb2ebbcb95..7ee661f4c6a 100644
--- a/src/common/tests_lib.c
+++ b/src/common/tests_lib.c
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2015-2022 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -279,7 +280,7 @@ td_init(struct test_data *td, uint32_t iod_nr, struct td_init_args args)
/* Initialize and create some data */
dts_sgl_generate(sgl, 1, args.ca_data_size, 0xAB);
- D_ASSERT(daos_sgl_data_len(sgl) == data_len);
+ D_ASSERT(daos_sgl_data_len(sgl, false) == data_len);
iod->iod_type = iod_types[i];
dts_iov_alloc_str(&iod->iod_name, "akey");
diff --git a/src/container/cli.c b/src/container/cli.c
index a0dc96fec00..18b6a75a590 100644
--- a/src/container/cli.c
+++ b/src/container/cli.c
@@ -190,6 +190,7 @@ dup_cont_create_props(daos_handle_t poh, daos_prop_t **prop_out,
int rc = 0;
uid_t uid = geteuid();
gid_t gid = getegid();
+ uint32_t co_ver = 0;
entries = (prop_in == NULL) ? 0 : prop_in->dpp_nr;
@@ -224,6 +225,10 @@ dup_cont_create_props(daos_handle_t poh, daos_prop_t **prop_out,
entries++;
}
+ if (!daos_prop_has_entry(prop_in, DAOS_PROP_CO_OBJ_VERSION)) {
+ co_ver = DAOS_POOL_OBJ_VERSION_2;
+ entries++;
+ }
if (!daos_prop_has_entry(prop_in, DAOS_PROP_CO_ROOTS)) {
uint64_t rf;
@@ -294,6 +299,11 @@ dup_cont_create_props(daos_handle_t poh, daos_prop_t **prop_out,
roots = NULL; /* prop is responsible for it now */
idx++;
}
+ if (co_ver != 0) {
+ final_prop->dpp_entries[idx].dpe_type = DAOS_PROP_CO_OBJ_VERSION;
+ final_prop->dpp_entries[idx].dpe_val = co_ver;
+ idx++;
+ }
}
*prop_out = final_prop;
@@ -999,7 +1009,7 @@ dc_cont_open(tse_task_t *task)
if (tpriv->cont == NULL)
D_GOTO(err_pool, rc = -DER_NOMEM);
uuid_generate(tpriv->cont->dc_cont_hdl);
- tpriv->cont->dc_capas = args->flags;
+ tpriv->cont->dc_capas = args->flags | DAOS_COO_NEW_LAYOUT;
}
D_DEBUG(DB_MD, DF_UUID ":%s: opening: hdl=" DF_UUIDF " flags=%x\n", DP_UUID(pool->dp_pool),
diff --git a/src/container/container_iv.c b/src/container/container_iv.c
index 43d024d02a5..a063c685b9c 100644
--- a/src/container/container_iv.c
+++ b/src/container/container_iv.c
@@ -449,6 +449,7 @@ cont_iv_ent_fetch(struct ds_iv_entry *entry, struct ds_iv_key *key,
d_sg_list_t *dst, void **priv)
{
struct cont_iv_entry *src_iv;
+ struct cont_iv_entry iv_entry = {0};
daos_handle_t root_hdl;
d_iov_t key_iov;
d_iov_t val_iov;
@@ -496,7 +497,6 @@ cont_iv_ent_fetch(struct ds_iv_entry *entry, struct ds_iv_key *key,
rc1 = ds_cont_hdl_rdb_lookup(entry->ns->iv_pool_uuid,
civ_key->cont_uuid, &chdl);
if (rc1 == 0) {
- struct cont_iv_entry iv_entry = { 0 };
daos_prop_t *prop = NULL;
struct daos_prop_entry *prop_entry;
struct daos_co_status stat = { 0 };
@@ -546,8 +546,38 @@ cont_iv_ent_fetch(struct ds_iv_entry *entry, struct ds_iv_key *key,
} else {
rc = -DER_NONEXIST;
}
+ } else if (class_id == IV_CONT_AGG_EPOCH_BOUNDRY) {
+ uint64_t ec_agg_eph;
+
+ rc = ds_cont_ec_agg_eph_rdb_lookup(entry->ns->iv_pool_uuid,
+ civ_key->cont_uuid, &ec_agg_eph);
+ if (rc == 0) {
+ uuid_copy(iv_entry.cont_uuid, civ_key->cont_uuid);
+ iv_entry.iv_agg_eph.eph = ec_agg_eph;
+ iv_entry.iv_agg_eph.rank = dss_self_rank();
+ d_iov_set(&val_iov, &iv_entry, sizeof(iv_entry));
+ rc = dbtree_update(root_hdl, &key_iov, &val_iov);
+ DL_CDEBUG(
+ rc != 0, DLOG_ERR, DB_MD, rc,
+ DF_CONT ": dbtree_update ec_agg_eph " DF_X64,
+ DP_CONT(entry->ns->iv_pool_uuid, civ_key->cont_uuid),
+ ec_agg_eph);
+ if (rc)
+ goto failed;
+ /* on master node will not trigger on_refresh callback,
+ * so need to explicitly refresh its own cont child's
+ * sc_ec_agg_eph_boundary especially for the case of
+ * restart that the value is zero.
+ */
+ rc = ds_cont_tgt_refresh_agg_eph(entry->ns->iv_pool_uuid,
+ civ_key->cont_uuid,
+ ec_agg_eph);
+ if (rc == 0)
+ goto again;
+ }
}
}
+failed:
D_DEBUG(DB_MGMT, DF_CONT "lookup cont: rc " DF_RC "\n",
DP_CONT(entry->ns->iv_pool_uuid, civ_key->cont_uuid), DP_RC(rc));
D_GOTO(out, rc);
@@ -653,8 +683,15 @@ cont_iv_ent_update(struct ds_iv_entry *entry, struct ds_iv_key *key,
} else if (entry->iv_class->iv_class_id ==
IV_CONT_AGG_EPOCH_BOUNDRY) {
rc = cont_iv_ent_agg_eph_refresh(entry, key, src);
- if (rc)
+ if (rc) {
+ if (rc == -DER_NONEXIST) {
+ DL_INFO(
+ rc, DF_CONT " cont_iv_ent_agg_eph_refresh ignore",
+ DP_CONT(entry->ns->iv_pool_uuid, civ_key->cont_uuid));
+ rc = 0;
+ }
D_GOTO(out, rc);
+ }
}
}
@@ -1116,8 +1153,7 @@ cont_iv_ec_agg_eph_update(void *ns, uuid_t cont_uuid, daos_epoch_t eph)
int
cont_iv_ec_agg_eph_refresh(void *ns, uuid_t cont_uuid, daos_epoch_t eph)
{
- return cont_iv_ec_agg_eph_update_internal(ns, cont_uuid, eph,
- 0, CRT_IV_SYNC_LAZY,
+ return cont_iv_ec_agg_eph_update_internal(ns, cont_uuid, eph, 0, CRT_IV_SYNC_EAGER,
IV_CONT_AGG_EPOCH_BOUNDRY);
}
diff --git a/src/container/srv_container.c b/src/container/srv_container.c
index 5dc44e2758d..0971752888e 100644
--- a/src/container/srv_container.c
+++ b/src/container/srv_container.c
@@ -702,10 +702,12 @@ cont_create_prop_prepare(struct ds_pool_hdl *pool_hdl,
}
break;
case DAOS_PROP_CO_GLOBAL_VERSION:
- case DAOS_PROP_CO_OBJ_VERSION:
- D_ERROR("container global/obj %u version could be not set\n",
- entry->dpe_type);
+ D_ERROR("container global %u version could be not set\n", entry->dpe_type);
return -DER_INVAL;
+ case DAOS_PROP_CO_OBJ_VERSION:
+ /* this is a walkaround for 2.6 only */
+ entry_def->dpe_val = entry->dpe_val;
+ break;
default:
D_ASSERTF(0, "bad dpt_type %d.\n", entry->dpe_type);
break;
@@ -760,8 +762,9 @@ cont_create_prop_prepare(struct ds_pool_hdl *pool_hdl,
/* inherit object version from pool*/
entry_def = daos_prop_entry_get(prop_def, DAOS_PROP_CO_OBJ_VERSION);
- if (entry_def)
+ if (entry_def && entry_def->dpe_val == 0)
entry_def->dpe_val = pool_hdl->sph_obj_ver;
+
/* for new container set HEALTHY status with current pm ver */
entry_def = daos_prop_entry_get(prop_def, DAOS_PROP_CO_STATUS);
D_ASSERT(entry_def != NULL);
@@ -1688,6 +1691,7 @@ cont_ec_agg_alloc(struct cont_svc *cont_svc, uuid_t cont_uuid,
uuid_copy(ec_agg->ea_cont_uuid, cont_uuid);
ec_agg->ea_servers_num = rank_nr;
ec_agg->ea_current_eph = 0;
+ ec_agg->ea_rdb_eph = 0;
for (i = 0; i < rank_nr; i++) {
ec_agg->ea_server_ephs[i].rank = doms[i].do_comp.co_rank;
ec_agg->ea_server_ephs[i].eph = 0;
@@ -1802,6 +1806,7 @@ cont_refresh_vos_agg_eph_one(void *data)
if (cont_child->sc_ec_agg_eph_boundary < arg->min_eph)
cont_child->sc_ec_agg_eph_boundary = arg->min_eph;
+ cont_child->sc_ec_agg_eph_valid = 1;
ds_cont_child_put(cont_child);
return rc;
}
@@ -1811,6 +1816,8 @@ ds_cont_tgt_refresh_agg_eph(uuid_t pool_uuid, uuid_t cont_uuid,
daos_epoch_t eph)
{
struct refresh_vos_agg_eph_arg arg;
+ static uint64_t cnt;
+ static uint64_t gap = 1;
int rc;
uuid_copy(arg.pool_uuid, pool_uuid);
@@ -1820,116 +1827,286 @@ ds_cont_tgt_refresh_agg_eph(uuid_t pool_uuid, uuid_t cont_uuid,
rc = ds_pool_task_collective(pool_uuid, PO_COMP_ST_NEW | PO_COMP_ST_DOWN |
PO_COMP_ST_DOWNOUT, cont_refresh_vos_agg_eph_one,
&arg, DSS_ULT_FL_PERIODIC);
+ if (rc) {
+ DL_ERROR(rc, DF_CONT ": refresh ec_agg_eph " DF_X64 " failed.",
+ DP_CONT(pool_uuid, cont_uuid), eph);
+ } else {
+ if (cnt++ % gap == 0) {
+ D_INFO(DF_CONT ": refresh ec_agg_eph " DF_X64,
+ DP_CONT(pool_uuid, cont_uuid), eph);
+ if (gap <= 256)
+ gap <<= 1;
+ } else {
+ D_DEBUG(DB_MD, DF_CONT ": refresh ec_agg_eph " DF_X64,
+ DP_CONT(pool_uuid, cont_uuid), eph);
+ }
+ }
return rc;
}
-#define EC_AGG_EPH_INTV (10ULL * 1000) /* seconds interval to check*/
-static void
-cont_agg_eph_leader_ult(void *arg)
+static int
+cont_agg_eph_load(struct cont_svc *svc, uuid_t cont_uuid, uint64_t *ec_agg_eph)
{
- struct cont_svc *svc = arg;
- struct ds_pool *pool = svc->cs_pool;
- struct cont_ec_agg *ec_agg;
- struct cont_ec_agg *tmp;
- uint64_t cur_eph, new_eph;
- int rc = 0;
+ struct rdb_tx tx;
+ struct cont *cont = NULL;
+ uint64_t agg_eph;
+ d_iov_t value;
+ int rc;
- if (svc->cs_ec_leader_ephs_req == NULL)
+ D_ASSERT(dss_get_module_info()->dmi_xs_id == 0);
+ rc = rdb_tx_begin(svc->cs_rsvc->s_db, svc->cs_rsvc->s_term, &tx);
+ if (rc != 0) {
+ DL_CDEBUG(rc != -DER_NOTLEADER, DLOG_ERR, DB_MD, rc,
+ DF_CONT ": Failed to start rdb tx.",
+ DP_CONT(svc->cs_pool_uuid, cont_uuid));
+ return rc;
+ }
+
+ ABT_rwlock_rdlock(svc->cs_lock);
+ rc = cont_lookup(&tx, svc, cont_uuid, &cont);
+ if (rc != 0) {
+ D_ERROR(DF_CONT ": Failed to look container: %d\n",
+ DP_CONT(svc->cs_pool_uuid, cont_uuid), rc);
+ D_GOTO(out_lock, rc);
+ }
+
+ d_iov_set(&value, &agg_eph, sizeof(agg_eph));
+ rc = rdb_tx_lookup(&tx, &cont->c_prop, &ds_cont_prop_ec_agg_eph, &value);
+ DL_CDEBUG(rc != 0 && rc != -DER_NONEXIST && rc != -DER_NOTLEADER, DLOG_ERR, DB_MD, rc,
+ DF_CONT ": rdb_tx_lookup ec_agg_eph " DF_X64,
+ DP_CONT(svc->cs_pool_uuid, cont_uuid), agg_eph);
+ if (rc == -DER_NONEXIST) {
+ agg_eph = 0;
+ rc = 0;
+ }
+ if (rc == 0)
+ *ec_agg_eph = agg_eph;
+ cont_put(cont);
+
+out_lock:
+ ABT_rwlock_unlock(svc->cs_lock);
+ rdb_tx_end(&tx);
+ return rc;
+}
+
+int
+ds_cont_ec_agg_eph_rdb_lookup(uuid_t pool_uuid, uuid_t cont_uuid, uint64_t *ec_agg_eph)
+{
+ struct cont_svc *svc;
+ int rc;
+
+ rc = cont_svc_lookup_leader(pool_uuid, 0 /* id */, &svc, NULL);
+ if (rc != 0) {
+ DL_ERROR(rc, DF_CONT ": find leader failed.", DP_CONT(pool_uuid, cont_uuid));
+ return rc;
+ }
+
+ rc = cont_agg_eph_load(svc, cont_uuid, ec_agg_eph);
+ cont_svc_put_leader(svc);
+ if (rc)
+ DL_ERROR(rc, DF_CONT ": cont_agg_eph_load failed.", DP_CONT(pool_uuid, cont_uuid));
+ return rc;
+}
+
+static int
+cont_agg_eph_store(struct cont_svc *svc, uuid_t cont_uuid, uint64_t ec_agg_eph, uint64_t *rdb_eph)
+{
+ struct rdb_tx tx;
+ struct cont *cont = NULL;
+ d_iov_t value;
+ uint64_t old_eph;
+ int rc;
+
+ D_ASSERT(dss_get_module_info()->dmi_xs_id == 0);
+ rc = rdb_tx_begin(svc->cs_rsvc->s_db, svc->cs_rsvc->s_term, &tx);
+ if (rc != 0) {
+ DL_CDEBUG(rc != -DER_NOTLEADER, DLOG_ERR, DB_MD, rc,
+ DF_CONT ": Failed to start rdb tx.",
+ DP_CONT(svc->cs_pool_uuid, cont_uuid));
+ return rc;
+ }
+
+ ABT_rwlock_wrlock(svc->cs_lock);
+ rc = cont_lookup(&tx, svc, cont_uuid, &cont);
+ if (rc != 0) {
+ D_ERROR(DF_CONT ": Failed to look container: %d\n",
+ DP_CONT(svc->cs_pool_uuid, cont_uuid), rc);
+ D_GOTO(out_lock, rc);
+ }
+
+ d_iov_set(&value, &old_eph, sizeof(old_eph));
+ rc = rdb_tx_lookup(&tx, &cont->c_prop, &ds_cont_prop_ec_agg_eph, &value);
+ if (rc == -DER_NONEXIST) {
+ rc = 0;
+ old_eph = 0;
+ }
+ if (rc != 0)
goto out;
- while (!dss_ult_exiting(svc->cs_ec_leader_ephs_req)) {
- d_rank_list_t fail_ranks = { 0 };
+ *rdb_eph = old_eph;
+ if (ec_agg_eph > old_eph) {
+ d_iov_set(&value, &ec_agg_eph, sizeof(ec_agg_eph));
+ rc = rdb_tx_update(&tx, &cont->c_prop, &ds_cont_prop_ec_agg_eph, &value);
+ if (rc == 0)
+ rc = rdb_tx_commit(&tx);
+ if (rc == 0)
+ *rdb_eph = ec_agg_eph;
+ } else {
+ D_DEBUG(DB_MD,
+ DF_CONT ": bypass rdb update ec_agg_eph " DF_X64 ", in rdb eph " DF_X64,
+ DP_CONT(svc->cs_pool_uuid, cont_uuid), ec_agg_eph, old_eph);
+ }
+
+out:
+ DL_CDEBUG(rc != 0 && rc != -DER_NOTLEADER, DLOG_ERR, DB_MD, rc,
+ DF_CONT ": rdb_tx_update ec_agg_eph " DF_X64,
+ DP_CONT(svc->cs_pool_uuid, cont_uuid), ec_agg_eph);
+ cont_put(cont);
+out_lock:
+ ABT_rwlock_unlock(svc->cs_lock);
+ rdb_tx_end(&tx);
+ return rc;
+}
+
+static void
+cont_agg_eph_sync(struct ds_pool *pool, struct cont_svc *svc)
+{
+ d_rank_list_t fail_ranks = {0};
+ struct cont_ec_agg *ec_agg;
+ struct cont_ec_agg *tmp;
+ daos_epoch_t cur_eph, new_eph;
+ daos_epoch_t min_eph;
+ d_rank_t rank;
+ int i;
+ int rc;
+
+ rc = map_ranks_init(pool->sp_map, PO_COMP_ST_DOWNOUT | PO_COMP_ST_DOWN, &fail_ranks);
+ if (rc) {
+ D_ERROR(DF_UUID ": ranks init failed: %d\n", DP_UUID(pool->sp_uuid), rc);
+ return;
+ }
- if (pool->sp_rebuilding) {
- D_DEBUG(DB_MD, DF_UUID "skip during rebuilding.\n",
- DP_UUID(pool->sp_uuid));
- goto yield;
+ d_list_for_each_entry_safe(ec_agg, tmp, &svc->cs_ec_agg_list, ea_list) {
+ if (ec_agg->ea_deleted) {
+ d_list_del(&ec_agg->ea_list);
+ D_FREE(ec_agg->ea_server_ephs);
+ D_FREE(ec_agg);
+ continue;
}
- rc = map_ranks_init(pool->sp_map, PO_COMP_ST_DOWNOUT | PO_COMP_ST_DOWN,
- &fail_ranks);
- if (rc) {
- D_ERROR(DF_UUID": ranks init failed: %d\n",
- DP_UUID(pool->sp_uuid), rc);
- goto yield;
+ if (ec_agg->ea_rdb_eph == 0) {
+ rc = cont_agg_eph_load(svc, ec_agg->ea_cont_uuid, &ec_agg->ea_rdb_eph);
+ if (rc)
+ DL_ERROR(rc, DF_CONT ": cont_agg_eph_load failed.",
+ DP_CONT(svc->cs_pool_uuid, ec_agg->ea_cont_uuid));
}
- d_list_for_each_entry_safe(ec_agg, tmp, &svc->cs_ec_agg_list, ea_list) {
- daos_epoch_t min_eph = DAOS_EPOCH_MAX;
- int i;
+ min_eph = DAOS_EPOCH_MAX;
+ for (i = 0; i < ec_agg->ea_servers_num; i++) {
+ rank = ec_agg->ea_server_ephs[i].rank;
- if (ec_agg->ea_deleted) {
- d_list_del(&ec_agg->ea_list);
- D_FREE(ec_agg->ea_server_ephs);
- D_FREE(ec_agg);
+ if (d_rank_in_rank_list(&fail_ranks, rank)) {
+ D_DEBUG(DB_MD, DF_CONT " skip %u\n",
+ DP_CONT(svc->cs_pool_uuid, ec_agg->ea_cont_uuid), rank);
continue;
}
- for (i = 0; i < ec_agg->ea_servers_num; i++) {
- d_rank_t rank = ec_agg->ea_server_ephs[i].rank;
+ if (ec_agg->ea_server_ephs[i].eph < min_eph)
+ min_eph = ec_agg->ea_server_ephs[i].eph;
+ }
- if (d_rank_in_rank_list(&fail_ranks, rank)) {
- D_DEBUG(DB_MD, DF_CONT" skip %u\n",
- DP_CONT(svc->cs_pool_uuid,
- ec_agg->ea_cont_uuid),
- rank);
- continue;
- }
+ /* for reboot case the ea_rdb_eph possibly higher than min_eph */
+ if (min_eph < ec_agg->ea_rdb_eph)
+ min_eph = ec_agg->ea_rdb_eph;
- if (ec_agg->ea_server_ephs[i].eph < min_eph)
- min_eph = ec_agg->ea_server_ephs[i].eph;
- }
+ if (min_eph == ec_agg->ea_current_eph)
+ continue;
- if (min_eph == ec_agg->ea_current_eph)
- continue;
+ /**
+ * NB: during extending or reintegration, the new
+ * server might cause the minimum epoch is less than
+ * ea_current_eph.
+ */
+ D_DEBUG(DB_MD, DF_CONT " minimum " DF_U64 " current " DF_X64 "\n",
+ DP_CONT(svc->cs_pool_uuid, ec_agg->ea_cont_uuid), min_eph,
+ ec_agg->ea_current_eph);
+
+ cur_eph = d_hlc2sec(ec_agg->ea_current_eph);
+ new_eph = d_hlc2sec(min_eph);
+ if (cur_eph && new_eph > cur_eph && (new_eph - cur_eph) >= 600)
+ D_WARN(DF_CONT ": Sluggish EC boundary reporting. "
+ "cur:" DF_U64 " new:" DF_U64 " gap:" DF_U64 "\n",
+ DP_CONT(svc->cs_pool_uuid, ec_agg->ea_cont_uuid), cur_eph, new_eph,
+ new_eph - cur_eph);
+
+ if (min_eph > ec_agg->ea_rdb_eph) {
+ rc = cont_agg_eph_store(svc, ec_agg->ea_cont_uuid, min_eph,
+ &ec_agg->ea_rdb_eph);
+ if (rc)
+ DL_ERROR(rc,
+ DF_CONT ": rdb_tx_update ec_agg_eph " DF_X64 " failed.",
+ DP_CONT(svc->cs_pool_uuid, ec_agg->ea_cont_uuid), min_eph);
+ }
- /**
- * NB: during extending or reintegration, the new
- * server might cause the minimum epoch is less than
- * ea_current_eph.
- */
- D_DEBUG(DB_MD, DF_CONT" minimum "DF_U64" current "DF_X64"\n",
- DP_CONT(svc->cs_pool_uuid, ec_agg->ea_cont_uuid),
- min_eph, ec_agg->ea_current_eph);
-
- cur_eph = d_hlc2sec(ec_agg->ea_current_eph);
- new_eph = d_hlc2sec(min_eph);
- if (cur_eph && new_eph > cur_eph && (new_eph - cur_eph) >= 600)
- D_WARN(DF_CONT": Sluggish EC boundary reporting. "
- "cur:"DF_U64" new:"DF_U64" gap:"DF_U64"\n",
- DP_CONT(svc->cs_pool_uuid, ec_agg->ea_cont_uuid),
- cur_eph, new_eph, new_eph - cur_eph);
-
- rc = cont_iv_ec_agg_eph_refresh(pool->sp_iv_ns,
- ec_agg->ea_cont_uuid,
- min_eph);
- if (rc) {
- DL_CDEBUG(rc == -DER_NONEXIST, DLOG_INFO, DLOG_ERR, rc,
- DF_CONT ": refresh failed",
- DP_CONT(svc->cs_pool_uuid, ec_agg->ea_cont_uuid));
-
- /* If there are network error or pool map inconsistency,
- * let's skip the following eph sync, which will fail
- * anyway.
- */
- if (daos_crt_network_error(rc) || rc == -DER_GRPVER) {
- D_INFO(DF_UUID": skip refresh due to: "DF_RC"\n",
- DP_UUID(svc->cs_pool_uuid), DP_RC(rc));
- break;
- }
+ rc = cont_iv_ec_agg_eph_refresh(pool->sp_iv_ns, ec_agg->ea_cont_uuid, min_eph);
+ if (rc) {
+ DL_CDEBUG(rc == -DER_NONEXIST, DLOG_INFO, DLOG_ERR, rc,
+ DF_CONT ": refresh failed",
+ DP_CONT(svc->cs_pool_uuid, ec_agg->ea_cont_uuid));
- continue;
- }
- ec_agg->ea_current_eph = min_eph;
- if (pool->sp_rebuilding)
+ /* If there are network error or pool map inconsistency,
+ * let's skip the following eph sync, which will fail
+ * anyway.
+ */
+ if (daos_crt_network_error(rc) || rc == -DER_GRPVER) {
+ D_INFO(DF_UUID ": skip refresh due to: " DF_RC "\n",
+ DP_UUID(svc->cs_pool_uuid), DP_RC(rc));
break;
+ }
+
+ continue;
}
+ ec_agg->ea_current_eph = min_eph;
+ }
+
+ map_ranks_fini(&fail_ranks);
+}
+
+int
+ds_cont_svc_refresh_agg_eph(uuid_t pool_uuid)
+{
+ struct cont_svc *svc;
+ int rc;
+
+ rc = cont_svc_lookup_leader(pool_uuid, 0 /* id */, &svc, NULL /* hint */);
+ if (rc != 0)
+ return rc;
- map_ranks_fini(&fail_ranks);
+ cont_agg_eph_sync(svc->cs_pool, svc);
+
+ cont_svc_put_leader(svc);
+ return 0;
+}
+
+#define EC_AGG_EPH_INTV (10ULL * 1000) /* seconds interval to check*/
+static void
+cont_agg_eph_leader_ult(void *arg)
+{
+ struct cont_svc *svc = arg;
+ struct ds_pool *pool = svc->cs_pool;
+ struct cont_ec_agg *ec_agg;
+ struct cont_ec_agg *tmp;
+ int rc = 0;
+
+ if (svc->cs_ec_leader_ephs_req == NULL)
+ goto out;
+
+ while (!dss_ult_exiting(svc->cs_ec_leader_ephs_req)) {
+ cont_agg_eph_sync(pool, svc);
if (dss_ult_exiting(svc->cs_ec_leader_ephs_req))
break;
-yield:
+
sched_req_sleep(svc->cs_ec_leader_ephs_req, EC_AGG_EPH_INTV);
}
@@ -2272,6 +2449,17 @@ cont_open(struct rdb_tx *tx, struct ds_pool_hdl *pool_hdl, struct cont *cont, cr
D_GOTO(out, rc);
D_ASSERT(prop != NULL);
D_ASSERT(prop->dpp_nr <= CONT_PROP_NUM);
+ if (!(flags & DAOS_COO_NEW_LAYOUT)) {
+ struct daos_prop_entry *entry;
+
+ entry = daos_prop_entry_get(prop, DAOS_PROP_CO_OBJ_VERSION);
+ if (entry && entry->dpe_val >= DAOS_POOL_OBJ_VERSION_2) {
+ D_ERROR(DF_CONT ": refusing attempt to open with new layout: " DF_X64 "\n",
+ DP_CONT(cont->c_svc->cs_pool_uuid, cont->c_uuid), entry->dpe_val);
+ rc = -DER_NOTSUPPORTED;
+ D_GOTO(out, rc);
+ }
+ }
get_cont_prop_access_info(prop, &owner, &acl);
@@ -4612,7 +4800,7 @@ upgrade_cont_cb(daos_handle_t ih, d_iov_t *key, d_iov_t *val, void *varg)
}
if (DAOS_FAIL_CHECK(DAOS_FORCE_OBJ_UPGRADE)) {
- obj_ver = DS_POOL_OBJ_VERSION;
+ obj_ver = DAOS_POOL_OBJ_VERSION;
d_iov_set(&value, &obj_ver, sizeof(obj_ver));
rc = rdb_tx_update(ap->tx, &cont->c_prop,
&ds_cont_prop_cont_obj_version, &value);
@@ -4707,9 +4895,9 @@ upgrade_cont_cb(daos_handle_t ih, d_iov_t *key, d_iov_t *val, void *varg)
entry = daos_prop_entry_get(prop, DAOS_PROP_CO_OBJ_VERSION);
D_ASSERT(entry != NULL);
- entry->dpe_val = DS_POOL_OBJ_VERSION;
+ entry->dpe_val = DAOS_POOL_OBJ_VERSION;
entry->dpe_flags &= ~DAOS_PROP_ENTRY_NOT_SET;
- obj_ver = DS_POOL_OBJ_VERSION;
+ obj_ver = DAOS_POOL_OBJ_VERSION;
d_iov_set(&value, &obj_ver, sizeof(obj_ver));
rc = rdb_tx_update(ap->tx, &cont->c_prop, &ds_cont_prop_cont_obj_version, &value);
if (rc) {
diff --git a/src/container/srv_internal.h b/src/container/srv_internal.h
index ae5e5ec8a75..bb257a73212 100644
--- a/src/container/srv_internal.h
+++ b/src/container/srv_internal.h
@@ -67,10 +67,11 @@ struct ec_eph {
struct cont_ec_agg {
uuid_t ea_cont_uuid;
daos_epoch_t ea_current_eph;
+ daos_epoch_t ea_rdb_eph;
struct ec_eph *ea_server_ephs;
d_list_t ea_list;
int ea_servers_num;
- uint32_t ea_deleted:1;
+ uint32_t ea_deleted : 1;
};
/*
@@ -310,4 +311,7 @@ int cont_child_gather_oids(struct ds_cont_child *cont, uuid_t coh_uuid,
int ds_cont_hdl_rdb_lookup(uuid_t pool_uuid, uuid_t cont_hdl_uuid,
struct container_hdl *chdl);
+int
+ds_cont_ec_agg_eph_rdb_lookup(uuid_t pool_uuid, uuid_t cont_uuid, uint64_t *ec_agg_eph);
+
#endif /* __CONTAINER_SRV_INTERNAL_H__ */
diff --git a/src/container/srv_layout.c b/src/container/srv_layout.c
index 35bb16e0b71..ae1b16b3ae2 100644
--- a/src/container/srv_layout.c
+++ b/src/container/srv_layout.c
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2017-2023 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -54,6 +55,7 @@ RDB_STRING_KEY(ds_cont_prop_, scrubber_disabled);
RDB_STRING_KEY(ds_cont_prop_, co_md_times);
RDB_STRING_KEY(ds_cont_prop_, cont_obj_version);
RDB_STRING_KEY(ds_cont_prop_, nhandles);
+RDB_STRING_KEY(ds_cont_prop_, ec_agg_eph);
/* dummy value for container roots, avoid malloc on demand */
static struct daos_prop_co_roots dummy_roots;
diff --git a/src/container/srv_layout.h b/src/container/srv_layout.h
index d4f2622aba2..7f10d948368 100644
--- a/src/container/srv_layout.h
+++ b/src/container/srv_layout.h
@@ -1,5 +1,6 @@
/*
* (C) Copyright 2016-2023 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -137,6 +138,7 @@ extern d_iov_t ds_cont_prop_co_md_times; /* co_md_times */
extern d_iov_t ds_cont_prop_cont_obj_version; /* uint32_t */
extern d_iov_t ds_cont_prop_nhandles; /* uint32_t */
extern d_iov_t ds_cont_prop_oit_oids; /* snapshot OIT OID KVS */
+extern d_iov_t ds_cont_prop_ec_agg_eph; /* uint64_t */
/* Please read the IMPORTANT notes above before adding new keys. */
struct co_md_times {
diff --git a/src/include/daos/common.h b/src/include/daos/common.h
index 082c64484b1..e8b599e2ce8 100644
--- a/src/include/daos/common.h
+++ b/src/include/daos/common.h
@@ -388,7 +388,10 @@ int daos_sgl_copy_data(d_sg_list_t *dst, d_sg_list_t *src);
int daos_sgl_alloc_copy_data(d_sg_list_t *dst, d_sg_list_t *src);
int daos_sgls_alloc(d_sg_list_t *dst, d_sg_list_t *src, int nr);
int daos_sgl_merge(d_sg_list_t *dst, d_sg_list_t *src);
-daos_size_t daos_sgl_data_len(d_sg_list_t *sgl);
+daos_size_t
+daos_sgl_data_len(d_sg_list_t *sgl, bool out);
+daos_size_t
+ daos_sgl_out_data_len(d_sg_list_t *sgl);
daos_size_t daos_sgl_buf_size(d_sg_list_t *sgl);
daos_size_t daos_sgls_buf_size(d_sg_list_t *sgls, int nr);
daos_size_t daos_sgls_packed_size(d_sg_list_t *sgls, int nr,
diff --git a/src/include/daos/object.h b/src/include/daos/object.h
index feb59d24d0c..bdd7abb2cc7 100644
--- a/src/include/daos/object.h
+++ b/src/include/daos/object.h
@@ -653,6 +653,8 @@ enum daos_io_flags {
DIOF_RECX_REVERSE = 0x800,
/* Use for rebuild fetch epoch selection */
DIOF_FETCH_EPOCH_EC_AGG_BOUNDARY = 0x1000,
+ /* Do not degrade enumeration/fetch if data shard failed */
+ DIOF_EC_NO_DEGRADE = 0x2000,
};
/**
diff --git a/src/include/daos/pool.h b/src/include/daos/pool.h
index c98ce1a19b0..036122133f2 100644
--- a/src/include/daos/pool.h
+++ b/src/include/daos/pool.h
@@ -1,6 +1,7 @@
/*
* (C) Copyright 2016-2024 Intel Corporation.
* (C) Copyright 2025 Google LLC
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -86,6 +87,16 @@
*/
#define DAOS_POOL_GLOBAL_VERSION 3
+/**
+ * Each individual object layout format, like oid layout, dkey to group,
+ * dkey to EC group start.
+ */
+enum {
+ DAOS_POOL_OBJ_VERSION_1 = 1,
+ DAOS_POOL_OBJ_VERSION_2 = 2,
+ DAOS_POOL_OBJ_VERSION = DAOS_POOL_OBJ_VERSION_2,
+};
+
int dc_pool_init(void);
void dc_pool_fini(void);
diff --git a/src/include/daos_cont.h b/src/include/daos_cont.h
index 632eafe8130..6e6e5b98adc 100644
--- a/src/include/daos_cont.h
+++ b/src/include/daos_cont.h
@@ -1,5 +1,6 @@
/*
* (C) Copyright 2020-2024 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -73,8 +74,15 @@ extern "C" {
*/
#define DAOS_COO_EVICT_ALL (1U << 6)
+/**
+ * When clients attempt to open a container using the new hash layout,
+ * the server will reject the request if this flag is not set,
+ * even if the container is already in the new layout format.
+ */
+#define DAOS_COO_NEW_LAYOUT (1U << 7)
+
/** Number of bits in the container open mode flag, DAOS_COO_ bits */
-#define DAOS_COO_NBITS (7)
+#define DAOS_COO_NBITS (8)
/** Mask for all of the bits in the container open mode flag, DAOS_COO_ bits */
#define DAOS_COO_MASK ((1U << DAOS_COO_NBITS) - 1)
diff --git a/src/include/daos_srv/container.h b/src/include/daos_srv/container.h
index 5beea88fe1f..ccd5b43e0a0 100644
--- a/src/include/daos_srv/container.h
+++ b/src/include/daos_srv/container.h
@@ -37,6 +37,8 @@ void ds_cont_svc_step_down(struct cont_svc *svc);
int
ds_cont_svc_set_prop(uuid_t pool_uuid, const char *cont_id, d_rank_list_t *ranks,
daos_prop_t *prop);
+int
+ ds_cont_svc_refresh_agg_eph(uuid_t pool_uuid);
int ds_cont_list(uuid_t pool_uuid, struct daos_pool_cont_info **conts, uint64_t *ncont);
int ds_cont_filter(uuid_t pool_uuid, daos_pool_cont_filter_t *filt,
struct daos_pool_cont_info2 **conts, uint64_t *ncont);
@@ -72,7 +74,9 @@ struct ds_cont_child {
sc_dtx_delay_reset : 1, sc_dtx_registered : 1, sc_props_fetched : 1, sc_stopping : 1,
sc_destroying : 1, sc_vos_agg_active : 1, sc_ec_agg_active : 1,
/* flag of CONT_CAPA_READ_DATA/_WRITE_DATA disabled */
- sc_rw_disabled : 1, sc_scrubbing : 1, sc_rebuilding : 1;
+ sc_rw_disabled : 1, sc_scrubbing : 1, sc_rebuilding : 1,
+ /* flag of sc_ec_agg_eph_boundary valid */
+ sc_ec_agg_eph_valid : 1;
/* Tracks the schedule request for aggregation ULT */
struct sched_request *sc_agg_req;
diff --git a/src/include/daos_srv/pool.h b/src/include/daos_srv/pool.h
index aa602ef7aeb..8d0b1450a32 100644
--- a/src/include/daos_srv/pool.h
+++ b/src/include/daos_srv/pool.h
@@ -35,12 +35,6 @@ struct ds_pool_svc;
error from the server in the case there is fault injection to return such an error.*/
extern __thread bool firewall_blocking_flag;
-/**
- * Each individual object layout format, like oid layout, dkey to group,
- * dkey to EC group start.
- */
-#define DS_POOL_OBJ_VERSION 1
-
/* age of an entry in svc_ops KVS before it may be evicted */
#define DEFAULT_SVC_OPS_ENTRY_AGE_SEC_MAX 300ULL
diff --git a/src/include/daos_srv/rebuild.h b/src/include/daos_srv/rebuild.h
index 4799b78b693..96e2911903a 100644
--- a/src/include/daos_srv/rebuild.h
+++ b/src/include/daos_srv/rebuild.h
@@ -102,7 +102,8 @@ int ds_rebuild_query(uuid_t pool_uuid,
struct daos_rebuild_status *status);
void ds_rebuild_running_query(uuid_t pool_uuid, uint32_t opc, uint32_t *rebuild_ver,
daos_epoch_t *current_eph, uint32_t *rebuild_gen);
-int ds_rebuild_regenerate_task(struct ds_pool *pool, daos_prop_t *prop);
+int
+ ds_rebuild_regenerate_task(struct ds_pool *pool, daos_prop_t *prop, uint64_t delay_sec);
void ds_rebuild_leader_stop_all(void);
void ds_rebuild_abort(uuid_t pool_uuid, unsigned int version, uint32_t rebuild_gen,
uint64_t term);
diff --git a/src/object/cli_ec.c b/src/object/cli_ec.c
index 2a6ee7409f2..73897d51abe 100644
--- a/src/object/cli_ec.c
+++ b/src/object/cli_ec.c
@@ -1885,7 +1885,9 @@ obj_ec_fetch_set_sgl(struct dc_object *obj, struct obj_reasb_req *reasb_req,
uiod = &uiods[i];
riod = &riods[i];
usgl = &usgls[i];
- usgl->sg_nr_out = 0;
+ /* for data recovery case, the sg_nr_out possibly already set by obj_ec_sgl_copy */
+ if (!reasb_req->orr_recov_data)
+ usgl->sg_nr_out = 0;
tail_hole_size = 0;
size_in_iod = daos_iods_len(uiod, 1);
if (uiod->iod_size == 0)
@@ -1933,7 +1935,7 @@ obj_ec_fetch_set_sgl(struct dc_object *obj, struct obj_reasb_req *reasb_req,
* is set by obj_ec_recov_fill_back().
*/
if (!reasb_req->orr_recov_data ||
- (size_in_iod - tail_hole_size) > daos_sgl_data_len(usgl))
+ (size_in_iod - tail_hole_size) > daos_sgl_data_len(usgl, true))
dc_sgl_out_set(usgl, size_in_iod - tail_hole_size);
return;
@@ -2677,6 +2679,11 @@ obj_ec_sgl_copy(d_sg_list_t *sgl, uint64_t off, void *buf, uint64_t size)
/* to copy data from [buf, buf + size) to sgl */
rc = daos_sgl_processor(sgl, true, &sgl_idx, size, oes_copy, &arg);
D_ASSERT(rc == 0);
+ if (sgl_idx.iov_offset == 0)
+ sgl->sg_nr_out = sgl_idx.iov_idx;
+ else
+ sgl->sg_nr_out = sgl_idx.iov_idx + 1;
+ ;
}
/* copy the recovered data back to missed (to be recovered) recx list */
diff --git a/src/object/cli_obj.c b/src/object/cli_obj.c
index 9cf67485cd6..c0de8cd4a18 100644
--- a/src/object/cli_obj.c
+++ b/src/object/cli_obj.c
@@ -5075,49 +5075,48 @@ obj_dup_sgls_free(struct obj_auxi_args *obj_auxi)
d_sg_list_t *sg_orig = &ctx->sgls_orig[i];
uint32_t dup_sg_idx = 0;
uint32_t dup_buf_size = 0;
- uint32_t sg_nr_out = 0;
+ uint32_t dup_data_len = 0;
char *dup_buf;
if (!ctx->alloc_bitmaps || !ctx->alloc_bitmaps[i])
continue;
D_ASSERT(ctx->merged_bitmaps[i] != NULL);
- for (j = 0; j < sg_orig->sg_nr && dup_sg_idx < sg_dup->sg_nr_out;) {
+ for (j = 0; j < sg_orig->sg_nr && dup_sg_idx < sg_dup->sg_nr_out; j++) {
iov = &sg_orig->sg_iovs[j];
iov_dup = &sg_dup->sg_iovs[dup_sg_idx];
- if (skip_sgl_iov(false, iov)) {
- j++;
+ if (skip_sgl_iov(false, iov))
continue;
- }
/* Direct copy if entry wasn't modified */
if (!isset_range((uint8_t *)ctx->merged_bitmaps[i], j, j)) {
*iov = *iov_dup;
- D_ASSERT(dup_buf_size == 0);
- j++;
- sg_nr_out++;
+ D_ASSERT(dup_data_len == 0);
dup_sg_idx++;
continue;
}
- if (dup_buf_size == 0) {
+ if (dup_data_len == 0) {
+ dup_data_len = iov_dup->iov_len;
dup_buf_size = iov_dup->iov_buf_len;
dup_buf = (char *)iov_dup->iov_buf;
}
+ /* Update iov_len for short read */
+ if (dup_data_len < iov->iov_len)
+ iov->iov_len = dup_data_len;
/* Copy data from duplicate buffer to original buffer */
- D_ASSERT(dup_buf_size >= iov->iov_buf_len);
- memcpy((char *)iov->iov_buf, dup_buf, iov->iov_buf_len);
- dup_buf_size -= iov->iov_buf_len;
- dup_buf += iov->iov_buf_len;
- sg_nr_out++;
- j++;
+ D_ASSERT(dup_buf_size >= iov->iov_len);
+ memcpy((char *)iov->iov_buf, dup_buf, iov->iov_len);
+ dup_data_len -= iov->iov_len;
+ dup_buf += iov->iov_len;
+ dup_buf_size -= iov->iov_len;
/* When current duplicate buffer is exhausted, get next entry */
- if (dup_buf_size == 0)
+ if (dup_data_len == 0)
dup_sg_idx++;
}
- sg_orig->sg_nr_out = sg_nr_out;
+ sg_orig->sg_nr_out = j;
}
}
@@ -5142,7 +5141,8 @@ obj_reasb_io_fini(struct obj_auxi_args *obj_auxi, bool retry)
}
obj_bulk_fini(obj_auxi);
obj_auxi_free_failed_tgt_list(obj_auxi);
- obj_dup_sgls_free(obj_auxi);
+ if (!retry)
+ obj_dup_sgls_free(obj_auxi);
obj_reasb_req_fini(&obj_auxi->reasb_req, obj_auxi->iod_nr);
obj_auxi->req_reasbed = false;
@@ -5914,6 +5914,12 @@ obj_ec_fetch_shards_get(struct dc_object *obj, daos_obj_fetch_t *args, unsigned
if (likely(ec_deg_tgt == tgt_idx))
continue;
+ if (args->extra_flags & DIOF_EC_NO_DEGRADE) {
+ D_WARN(DF_OID "have to degraded fetch for %u => %u, but sponsor forbid.\n",
+ DP_OID(obj->cob_md.omd_id), tgt_idx, ec_deg_tgt);
+ D_GOTO(out, rc = -DER_IO);
+ }
+
if (obj_auxi->ec_in_recov) {
D_DEBUG(DB_IO, DF_OID " shard %d failed recovery.\n",
DP_OID(obj->cob_md.omd_id), grp_start + tgt_idx);
diff --git a/src/object/cli_shard.c b/src/object/cli_shard.c
index 9f385b98f52..d6f85a71bf1 100644
--- a/src/object/cli_shard.c
+++ b/src/object/cli_shard.c
@@ -921,16 +921,18 @@ dc_rw_cb(tse_task_t *task, void *arg)
orwo->orw_rels.ca_arrays,
orwo->orw_rels.ca_count);
if (rc) {
- D_ERROR(DF_UOID " obj_ec_parity_check failed, " DF_RC "\n",
- DP_UOID(orw->orw_oid), DP_RC(rc));
+ DL_ERROR(rc, DF_CONT ", " DF_UOID " obj_ec_parity_check failed",
+ DP_CONT(orw->orw_pool_uuid, orw->orw_co_uuid),
+ DP_UOID(orw->orw_oid));
goto out;
}
}
rc = dc_shard_update_size(rw_args, 0);
if (rc) {
- D_ERROR(DF_UOID " dc_shard_update_size failed, " DF_RC "\n",
- DP_UOID(orw->orw_oid), DP_RC(rc));
+ DL_ERROR(rc, DF_CONT ", " DF_UOID " dc_shard_update_size failed",
+ DP_CONT(orw->orw_pool_uuid, orw->orw_co_uuid),
+ DP_UOID(orw->orw_oid));
goto out;
}
diff --git a/src/object/obj_class.c b/src/object/obj_class.c
index f37ff1e6ee7..654a316efe0 100644
--- a/src/object/obj_class.c
+++ b/src/object/obj_class.c
@@ -812,9 +812,22 @@ dc_set_oclass(uint32_t rf, int domain_nr, int target_nr, enum daos_otype_t otype
}
break;
case DAOS_PROP_CO_REDUN_RF3:
- /** EC not supported here */
- *ord = OR_RP_4;
- grp_size = 4;
+ if ((rdd == DAOS_OCH_RDD_EC || (rdd == 0 && daos_is_array_type(otype))) &&
+ domain_nr >= 10) {
+ if (domain_nr >= 22) {
+ *ord = OR_RS_16P3;
+ grp_size = 19;
+ } else if (domain_nr >= 14) {
+ *ord = OR_RS_8P3;
+ grp_size = 11;
+ } else {
+ *ord = OR_RS_4P3;
+ grp_size = 7;
+ }
+ } else {
+ *ord = OR_RP_4;
+ grp_size = 4;
+ }
break;
case DAOS_PROP_CO_REDUN_RF4:
/** EC not supported here */
diff --git a/src/object/obj_verify.c b/src/object/obj_verify.c
index beffd5744ab..46df0b6c93d 100644
--- a/src/object/obj_verify.c
+++ b/src/object/obj_verify.c
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2019-2023 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -31,9 +32,9 @@ dc_obj_verify_list(struct dc_obj_verify_args *dova)
memset(dova->kds, 0, sizeof(daos_key_desc_t) * DOVA_NUM);
memset(dova->list_buf, 0, dova->list_buf_len);
- dova->list_sgl.sg_nr = 1;
- dova->list_sgl.sg_nr_out = 1;
- dova->list_sgl.sg_iovs = &dova->list_iov;
+ dova->list_sgl.sg_nr = 1;
+ dova->list_sgl.sg_nr_out = 0;
+ dova->list_sgl.sg_iovs = &dova->list_iov;
dova->size = 0;
dova->num = DOVA_NUM;
@@ -113,9 +114,9 @@ dc_obj_verify_fetch(struct dc_obj_verify_args *dova)
dova->fetch_iov.iov_buf = dova->fetch_buf;
dova->fetch_iov.iov_buf_len = dova->fetch_buf_len;
- dova->fetch_sgl.sg_nr = 1;
- dova->fetch_sgl.sg_nr_out = 1;
- dova->fetch_sgl.sg_iovs = &dova->fetch_iov;
+ dova->fetch_sgl.sg_nr = 1;
+ dova->fetch_sgl.sg_nr_out = 0;
+ dova->fetch_sgl.sg_iovs = &dova->fetch_iov;
shard = dc_obj_anchor2shard(&dova->dkey_anchor);
rc = dc_obj_fetch_task_create(dova->oh, dova->th, 0, &cursor->dkey, 1,
@@ -677,18 +678,18 @@ dc_obj_verify_ec_cb(struct dc_obj_enum_unpack_io *io, void *arg)
D_GOTO(out, rc = -DER_NOMEM);
d_iov_set(&iovs[idx], data, size);
- sgls[idx].sg_nr = 1;
- sgls[idx].sg_nr_out = 1;
- sgls[idx].sg_iovs = &iovs[idx];
+ sgls[idx].sg_nr = 1;
+ sgls[idx].sg_nr_out = 0;
+ sgls[idx].sg_iovs = &iovs[idx];
D_ALLOC(data_verify, size);
if (data_verify == NULL)
D_GOTO(out, rc = -DER_NOMEM);
d_iov_set(&iovs_verify[idx], data_verify, size);
- sgls_verify[idx].sg_nr = 1;
- sgls_verify[idx].sg_nr_out = 1;
- sgls_verify[idx].sg_iovs = &iovs_verify[idx];
+ sgls_verify[idx].sg_nr = 1;
+ sgls_verify[idx].sg_nr_out = 0;
+ sgls_verify[idx].sg_iovs = &iovs_verify[idx];
if (iod->iod_type == DAOS_IOD_ARRAY) {
rc = obj_recx_ec2_daos(obj_get_oca(obj), tgt_off, &iod->iod_recxs, NULL,
&iod->iod_nr, true);
@@ -705,10 +706,13 @@ dc_obj_verify_ec_cb(struct dc_obj_enum_unpack_io *io, void *arg)
return 0;
}
- /* Fetch by specific shard */
- rc = dc_obj_fetch_task_create(dova->oh, dova->th, 0, &io->ui_dkey, idx,
- 0, iods, sgls, NULL, &shard, NULL, NULL, NULL,
- &task);
+ /*
+ * NOTE: Fetch data from data shard (including current one). The EC fetch task may touch
+ * multiple data shards. That is no matter as long as it does not trigger degraded
+ * fetch. Using DIOF_EC_NO_DEGRADE flag for such purpose.
+ */
+ rc = dc_obj_fetch_task_create(dova->oh, dova->th, 0, &io->ui_dkey, idx, DIOF_EC_NO_DEGRADE,
+ iods, sgls, NULL, &shard, NULL, NULL, NULL, &task);
if (rc != 0) {
D_ERROR(DF_OID" sgl num %u shard "DF_U64"\n",
DP_OID(obj->cob_md.omd_id), idx, shard);
@@ -731,10 +735,9 @@ dc_obj_verify_ec_cb(struct dc_obj_enum_unpack_io *io, void *arg)
D_GOTO(out, rc);
}
- daos_fail_loc_set(DAOS_OBJ_FORCE_DEGRADE | DAOS_FAIL_ONCE);
rc = dc_obj_fetch_task_create(dova->oh, dova->th, 0, &io->ui_dkey, idx,
- 0, iods, sgls_verify, NULL, &shard, NULL, NULL,
- NULL, &verify_task);
+ DIOF_FOR_FORCE_DEGRADE, iods, sgls_verify, NULL, &shard, NULL,
+ NULL, NULL, &verify_task);
if (rc != 0) {
D_ERROR(DF_OID" sgl num %u shard "DF_U64"\n",
DP_OID(obj->cob_md.omd_id), idx, shard);
@@ -756,7 +759,6 @@ dc_obj_verify_ec_cb(struct dc_obj_enum_unpack_io *io, void *arg)
io->ui_iods[i].iod_size, DP_RC(rc));
D_GOTO(out, rc);
}
- daos_fail_loc_set(0);
for (i = 0; i < idx; i++) {
if (sgls[i].sg_iovs[0].iov_len != sgls_verify[i].sg_iovs[0].iov_len ||
@@ -810,10 +812,10 @@ dc_obj_verify_ec_rdg(struct dc_object *obj, struct dc_obj_verify_args *dova,
dc_obj_shard2anchor(&dova->dkey_anchor, start + i);
daos_anchor_set_flags(&dova->dkey_anchor, DIOF_TO_SPEC_SHARD |
DIOF_WITH_SPEC_EPOCH);
- dova->th = th;
- dova->eof = 0;
- dova->non_exist = 0;
- dova->current_shard = i;
+ dova->th = th;
+ dova->eof = 0;
+ dova->non_exist = 0;
+ dova->current_shard = start + i;
memset(cursor, 0, sizeof(*cursor));
cursor->iod.iod_nr = 1;
cursor->iod.iod_recxs = &cursor->recx;
diff --git a/src/object/srv_ec_aggregate.c b/src/object/srv_ec_aggregate.c
index 9af73b918a6..b6fee91c619 100644
--- a/src/object/srv_ec_aggregate.c
+++ b/src/object/srv_ec_aggregate.c
@@ -1075,7 +1075,7 @@ agg_update_parity(struct ec_agg_entry *entry, uint8_t *bit_map,
buf = entry->ae_sgl.sg_iovs[AGG_IOV_DATA].iov_buf;
diff = entry->ae_sgl.sg_iovs[AGG_IOV_DIFF].iov_buf;
- for (i = 0, j = 0; i < cell_cnt; i++) {
+ for (i = 0, j = 0; i < cell_cnt; i++, j++) {
old = &obuf[i * cell_bytes];
new = &buf[i * cell_bytes];
vects[0] = old;
@@ -1086,6 +1086,7 @@ agg_update_parity(struct ec_agg_entry *entry, uint8_t *bit_map,
goto out;
while (!isset(bit_map, j))
j++;
+ D_ASSERTF(j < k, "bad cell_idx %d, number of data shards %d\n", j, k);
agg_diff_preprocess(entry, diff, j);
ec_encode_data_update(cell_bytes, k, p, j,
entry->ae_codec->ec_gftbls, diff,
@@ -1951,15 +1952,15 @@ agg_process_stripe(struct ec_agg_param *agg_param, struct ec_agg_entry *entry)
/* offload of ds_obj_update to push remote parity */
rc = agg_peer_update(entry, write_parity);
if (rc)
- D_ERROR("agg_peer_update fail: "DF_RC"\n",
- DP_RC(rc));
+ DL_ERROR(rc, "agg_peer_update failed, write_parity %d",
+ write_parity);
}
if (rc == 0) {
rc = agg_update_vos(agg_param, entry, write_parity);
if (rc)
- D_ERROR("agg_update_vos failed: "DF_RC"\n",
- DP_RC(rc));
+ DL_ERROR(rc, "agg_update_vos failed, write_parity %d",
+ write_parity);
}
}
diff --git a/src/object/srv_obj.c b/src/object/srv_obj.c
index c80f68630c2..620e63aef65 100644
--- a/src/object/srv_obj.c
+++ b/src/object/srv_obj.c
@@ -1389,6 +1389,25 @@ obj_rw_recx_list_post(struct obj_rw_in *orw, struct obj_rw_out *orwo, uint8_t *s
return rc;
}
+struct ec_agg_boundary_arg {
+ struct ds_pool *eab_pool;
+ uuid_t eab_co_uuid;
+};
+
+static int
+obj_fetch_ec_agg_boundary(void *data)
+{
+ struct ec_agg_boundary_arg *arg = data;
+ int rc;
+
+ rc = ds_cont_fetch_ec_agg_boundary(arg->eab_pool->sp_iv_ns, arg->eab_co_uuid);
+ if (rc)
+ DL_ERROR(rc, DF_CONT ", ds_cont_fetch_ec_agg_boundary failed.",
+ DP_CONT(arg->eab_pool->sp_uuid, arg->eab_co_uuid));
+
+ return rc;
+}
+
static int
obj_local_rw_internal(crt_rpc_t *rpc, struct obj_io_context *ioc, daos_iod_t *iods,
struct dcs_iod_csums *iod_csums, uint64_t *offs, uint8_t *skips,
@@ -1509,6 +1528,32 @@ obj_local_rw_internal(crt_rpc_t *rpc, struct obj_io_context *ioc, daos_iod_t *io
get_parity_list = ec_recov && is_parity_shard &&
((orw->orw_flags & ORF_EC_RECOV_SNAP) == 0);
}
+ if ((ec_deg_fetch || (ec_recov && get_parity_list)) &&
+ ioc->ioc_coc->sc_ec_agg_eph_valid == 0) {
+ struct ec_agg_boundary_arg arg;
+
+ arg.eab_pool = ioc->ioc_coc->sc_pool->spc_pool;
+ uuid_copy(arg.eab_co_uuid, ioc->ioc_coc->sc_uuid);
+ rc = dss_ult_execute(obj_fetch_ec_agg_boundary, &arg, NULL, NULL,
+ DSS_XS_SYS, 0, 0);
+ if (rc) {
+ DL_ERROR(rc, DF_CONT ", " DF_UOID " fetch ec_agg_boundary failed.",
+ DP_CONT(ioc->ioc_coc->sc_pool_uuid, ioc->ioc_coc->sc_uuid),
+ DP_UOID(orw->orw_oid));
+ goto out;
+ }
+ if (ioc->ioc_coc->sc_ec_agg_eph_valid == 0) {
+ rc = -DER_FETCH_AGAIN;
+ DL_INFO(rc, DF_CONT ", " DF_UOID " zero ec_agg_boundary.",
+ DP_CONT(ioc->ioc_coc->sc_pool_uuid, ioc->ioc_coc->sc_uuid),
+ DP_UOID(orw->orw_oid));
+ goto out;
+ }
+ D_DEBUG(DB_IO,
+ DF_CONT ", " DF_UOID " fetched ec_agg_eph_boundary " DF_X64 "\n",
+ DP_CONT(ioc->ioc_coc->sc_pool_uuid, ioc->ioc_coc->sc_uuid),
+ DP_UOID(orw->orw_oid), ioc->ioc_coc->sc_ec_agg_eph_boundary);
+ }
if (get_parity_list) {
D_ASSERT(!ec_deg_fetch);
fetch_flags |= VOS_OF_FETCH_RECX_LIST;
diff --git a/src/object/srv_obj_migrate.c b/src/object/srv_obj_migrate.c
index 7772bcdd4e0..2a91c7f1722 100644
--- a/src/object/srv_obj_migrate.c
+++ b/src/object/srv_obj_migrate.c
@@ -764,7 +764,7 @@ mrone_obj_fetch_internal(struct migrate_one *mrone, daos_handle_t oh, d_sg_list_
retry:
rc = dsc_obj_fetch(oh, eph, &mrone->mo_dkey, iod_num, iods, sgls, NULL, flags, extra_arg,
csum_iov_fetch);
- if (rc == -DER_TIMEDOUT &&
+ if ((rc == -DER_TIMEDOUT || rc == -DER_FETCH_AGAIN) &&
tls->mpt_version + 1 >= tls->mpt_pool->spc_map_version) {
if (tls->mpt_fini) {
DL_ERROR(rc, DF_RB ": dsc_obj_fetch " DF_UOID "failed when mpt_fini",
diff --git a/src/pipeline/cli_pipeline.c b/src/pipeline/cli_pipeline.c
index b30d8366b79..9d76456f331 100644
--- a/src/pipeline/cli_pipeline.c
+++ b/src/pipeline/cli_pipeline.c
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2021-2023 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -544,7 +545,7 @@ shard_task_sched(tse_task_t *task, void *arg)
static int
pipeline_create_layout(daos_handle_t coh, struct dc_pool *pool, struct daos_obj_md *obj_md,
- struct pl_obj_layout **layout)
+ struct pl_obj_layout **layout, uint16_t layout_gl_version)
{
int rc = 0;
struct pl_map *map;
@@ -555,7 +556,7 @@ pipeline_create_layout(daos_handle_t coh, struct dc_pool *pool, struct daos_obj_
D_GOTO(out, rc = -DER_INVAL);
}
- rc = pl_obj_place(map, 0, obj_md, 0, NULL, layout);
+ rc = pl_obj_place(map, layout_gl_version, obj_md, 0, NULL, layout);
pl_map_decref(map);
if (rc != 0) {
D_DEBUG(DB_PL, "Failed to generate object layout\n");
@@ -609,6 +610,7 @@ dc_pipeline_run(tse_task_t *api_task)
int total_replicas;
int shard;
struct pipeline_comp_cb_args comp_cb_args;
+ uint16_t layout_gl_ver;
coh = dc_obj_hdl2cont_hdl(api_args->oh);
rc = dc_obj_hdl2obj_md(api_args->oh, &obj_md);
@@ -629,7 +631,8 @@ dc_pipeline_run(tse_task_t *api_task)
/** get layout */
- rc = pipeline_create_layout(coh, pool, &obj_md, &layout);
+ layout_gl_ver = dc_obj_hdl2layout_ver(api_args->oh);
+ rc = pipeline_create_layout(coh, pool, &obj_md, &layout, layout_gl_ver);
dc_pool_put(pool);
if (rc != 0)
D_GOTO(out, rc);
@@ -687,7 +690,7 @@ dc_pipeline_run(tse_task_t *api_task)
/** object id */
oid.id_pub = obj_md.omd_id;
oid.id_shard = shard;
- oid.id_layout_ver = dc_obj_hdl2layout_ver(api_args->oh);
+ oid.id_layout_ver = layout_gl_ver;
oid.id_padding = 0;
/** queue shard task */
diff --git a/src/placement/jump_map.c b/src/placement/jump_map.c
index 179a3788ea5..70057d8e7d8 100644
--- a/src/placement/jump_map.c
+++ b/src/placement/jump_map.c
@@ -1,6 +1,7 @@
/**
*
* (C) Copyright 2016-2024 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -46,7 +47,7 @@ jm_obj_placement_fini(struct jm_obj_placement *jmop)
#define LOCAL_PD_ARRAY_SIZE (4)
static int
jm_obj_pd_init(struct pl_jump_map *jmap, struct daos_obj_md *md, struct pool_domain *root,
- struct jm_obj_placement *jmop)
+ struct jm_obj_placement *jmop, uint32_t layout_ver)
{
struct pool_domain *pds, *pd;
uint8_t *pd_used = NULL;
@@ -114,9 +115,9 @@ jm_obj_pd_init(struct pl_jump_map *jmap, struct daos_obj_md *md, struct pool_dom
}
oid = md->omd_id;
- key = oid.hi ^ oid.lo;
+ key = jm_oid_hash(layout_ver, oid);
for (i = 0; i < jmop->jmop_pd_nr; i++) {
- key = crc(key, i);
+ key = (layout_ver <= 1) ? crc(key, i) : jm_crc(key, i, 0xcafebabe);
selected_pd = d_hash_jump(key, jmap->jmp_pd_nr);
do {
selected_pd = selected_pd % jmap->jmp_pd_nr;
@@ -242,8 +243,8 @@ layout_find_diff(struct pl_jump_map *jmap, struct pl_obj_layout *original,
*/
static int
jm_obj_placement_init(struct pl_jump_map *jmap, struct daos_obj_md *md,
- struct daos_obj_shard_md *shard_md,
- struct jm_obj_placement *jmop)
+ struct daos_obj_shard_md *shard_md, struct jm_obj_placement *jmop,
+ uint32_t layout_ver)
{
struct daos_oclass_attr *oc_attr;
struct pool_domain *root;
@@ -305,7 +306,7 @@ jm_obj_placement_init(struct pl_jump_map *jmap, struct daos_obj_md *md,
D_ASSERT(jmop->jmop_grp_nr > 0);
D_ASSERT(jmop->jmop_grp_size > 0);
- rc = jm_obj_pd_init(jmap, md, root, jmop);
+ rc = jm_obj_pd_init(jmap, md, root, jmop, layout_ver);
if (rc == 0)
D_DEBUG(DB_PL, "obj="DF_OID"/ grp_size=%u grp_nr=%d, pd_nr=%u pd_grp_size=%u\n",
DP_OID(oid), jmop->jmop_grp_size, jmop->jmop_grp_nr,
@@ -404,7 +405,7 @@ obj_remap_shards(struct pl_jump_map *jmap, uint32_t layout_ver, struct daos_obj_
current = remap_list->next;
spare_tgt = NULL;
oid = md->omd_id;
- key = oid.hi ^ oid.lo;
+ key = jm_oid_hash(layout_ver, oid);
spares_left = count_available_spares(jmap, layout, failed_in_layout);
rc = pool_map_find_domain(jmap->jmp_map.pl_poolmap, PO_COMP_TP_ROOT,
@@ -435,13 +436,16 @@ obj_remap_shards(struct pl_jump_map *jmap, uint32_t layout_ver, struct daos_obj_
dgu = f_shard->fs_data;
D_ASSERT(dgu != NULL);
- rebuild_key = crc(key, f_shard->fs_shard_idx);
+ if (layout_ver <= 1)
+ rebuild_key = crc(key, crc(key, f_shard->fs_shard_idx));
+ else /* hash OID differently so we don't land to the same target */
+ rebuild_key = jm_crc(oid.lo, oid.hi, 0xDead2Bad);
+
curr_pd = jm_obj_shard_pd(jmop, shard_id);
- get_target(root, curr_pd, layout_ver, &spare_tgt, &spare_dom,
- crc(key, rebuild_key), dom_used, dom_full,
- dgu->dgu_used, dgu->dgu_real, tgts_used,
- shard_id, allow_version, gen_mode, fdom_lvl,
- jmop->jmop_grp_size, &spares_left, &spare_avail);
+ get_target(root, curr_pd, layout_ver, &spare_tgt, &spare_dom, rebuild_key,
+ dom_used, dom_full, dgu->dgu_used, dgu->dgu_real, tgts_used,
+ shard_id, allow_version, gen_mode, fdom_lvl, jmop->jmop_grp_size,
+ &spares_left, &spare_avail);
if (layout_ver > 0) {
/*
* After 2.4 (layout_ver > 0), it will always assign each shard
@@ -644,7 +648,8 @@ get_object_layout(struct pl_jump_map *jmap, uint32_t layout_ver, struct pl_obj_l
D_GOTO(out, rc = -DER_NOMEM);
oid = md->omd_id;
- key = oid.hi ^ oid.lo;
+ key = jm_oid_hash(layout_ver, oid);
+
if (daos_obj_is_srank(oid))
spec_oid = true;
@@ -1012,7 +1017,7 @@ jump_map_obj_place(struct pl_map *map, uint32_t layout_version, struct daos_obj_
D_DEBUG(DB_PL, "Determining location for object: "DF_OID", ver: %d, pda %u\n",
DP_OID(oid), md->omd_ver, md->omd_pda);
- rc = jm_obj_placement_init(jmap, md, shard_md, &jmop);
+ rc = jm_obj_placement_init(jmap, md, shard_md, &jmop, layout_version);
if (rc) {
D_ERROR("jm_obj_placement_init failed, rc "DF_RC"\n", DP_RC(rc));
return rc;
@@ -1115,7 +1120,7 @@ jump_map_obj_find_diff(struct pl_map *map, uint32_t layout_ver, struct daos_obj_
}
jmap = pl_map2jmap(map);
- rc = jm_obj_placement_init(jmap, md, shard_md, &jop);
+ rc = jm_obj_placement_init(jmap, md, shard_md, &jop, layout_ver);
if (rc) {
D_ERROR("jm_obj_placement_init failed, rc %d.\n", rc);
return rc;
diff --git a/src/placement/jump_map.h b/src/placement/jump_map.h
index 1fd39d3ce58..330872d842f 100644
--- a/src/placement/jump_map.h
+++ b/src/placement/jump_map.h
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2022-2023 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -61,4 +62,22 @@ get_target(struct pool_domain *root, struct pool_domain *curr_pd, uint32_t layou
uint8_t *dom_full, uint8_t *dom_cur_grp_used, uint8_t *dom_cur_grp_real,
uint8_t *tgts_used, int shard_num, uint32_t allow_version, enum layout_gen_mode gen_mode,
pool_comp_type_t fdom_lvl, uint32_t grp_size, uint32_t *spare_left, bool *spare_avail);
+
+static inline uint64_t
+jm_crc(uint64_t val0, uint64_t val1, uint64_t val2)
+{
+ uint64_t data[3];
+
+ data[0] = val0;
+ data[1] = val1;
+ data[2] = val2;
+ return crc64_ecma_refl(0xbabecafe, (uint8_t *)data, 24);
+}
+
+static inline uint64_t
+jm_oid_hash(uint32_t layout_ver, daos_obj_id_t oid)
+{
+ return layout_ver <= 1 ? (oid.hi ^ oid.lo) : jm_crc(oid.hi, oid.lo, 0xbabeface);
+}
+
#endif /* __JUMP_MAP_H__ */
diff --git a/src/placement/jump_map_versions.c b/src/placement/jump_map_versions.c
index b943949ad6a..f817ed96b04 100644
--- a/src/placement/jump_map_versions.c
+++ b/src/placement/jump_map_versions.c
@@ -1,6 +1,7 @@
/**
*
* (C) Copyright 2016-2024 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -414,6 +415,216 @@ __get_target_v1(struct pool_domain *root_pos, struct pool_domain *curr_pd,
} while (!found_target);
}
+/**
+ * This function is identical to __get_target_v1, except how they call CRC functions,
+ * the V1 function may cause a large number of hash collisions in certain cases.
+ *
+ * Search for jm_crc() and crc() to see how they differ.
+ */
+static void
+__get_target_v2(struct pool_domain *root_pos, struct pool_domain *curr_pd,
+ struct pool_target **target, struct pool_domain **dom, uint64_t obj_key,
+ uint8_t *dom_used, uint8_t *dom_full, uint8_t *dom_cur_grp_used, uint8_t *tgts_used,
+ int shard_num, uint32_t allow_version, enum layout_gen_mode gen_mode,
+ pool_comp_type_t fdom_lvl, uint32_t grp_size, bool *pd_ignored)
+{
+ int range_set;
+ uint8_t found_target = 0;
+ struct pool_domain *curr_dom;
+ struct pool_domain *dom_stack[MAX_STACK] = {0};
+ int top = -1;
+
+ curr_dom = curr_pd;
+ do {
+ uint32_t avail_doms;
+ uint64_t key;
+
+ /* Retrieve number of nodes in this domain */
+ avail_doms = get_num_domains(curr_dom, allow_version, gen_mode, fdom_lvl);
+
+ /* If choosing target (lowest fault domain level) */
+ if (curr_dom->do_comp.co_type == fdom_lvl) {
+ uint32_t fail_num = 0;
+ uint32_t tgt_idx;
+ uint32_t start_tgt;
+ uint32_t end_tgt;
+ uint32_t selected_tgt;
+
+ start_tgt = curr_dom->do_targets - root_pos->do_targets;
+ end_tgt = start_tgt + (curr_dom->do_target_nr - 1);
+
+ range_set = tgt_isset_range(root_pos->do_targets, tgts_used, start_tgt,
+ end_tgt, allow_version, gen_mode);
+ if (range_set) {
+ /* Used up all targets in this domain */
+ D_ASSERT(top != -1);
+ curr_dom = dom_stack[top--]; /* try parent */
+ continue;
+ }
+
+ /*
+ * Must crc key because jump consistent hash
+ * requires an even distribution or it will
+ * not work
+ */
+ key = jm_crc(obj_key, shard_num, fail_num++);
+ /* Get target for shard */
+ selected_tgt = d_hash_jump(key, avail_doms);
+ do {
+ selected_tgt = selected_tgt % avail_doms;
+ /* Retrieve actual target using index */
+ *target =
+ _get_target(curr_dom, selected_tgt, allow_version, gen_mode);
+ /* Get target id to check if target used */
+ tgt_idx = *target - root_pos->do_targets;
+ selected_tgt++;
+ } while (isset(tgts_used, tgt_idx));
+
+ setbit(tgts_used, tgt_idx);
+ D_DEBUG(DB_PL, "selected tgt %d\n", tgt_idx);
+ D_ASSERTF(isclr(dom_full, (uint32_t)(curr_dom - root_pos)),
+ "selected_tgt %u\n", (uint32_t)(curr_dom - root_pos));
+ range_set = tgt_isset_range(root_pos->do_targets, tgts_used, start_tgt,
+ end_tgt, allow_version, gen_mode);
+ if (range_set) {
+ /* Used up all targets in this domain */
+ setbit(dom_full, curr_dom - root_pos);
+ D_DEBUG(DB_PL, "dom %d used up\n", (int)(curr_dom - root_pos));
+ /* Check and set if all of its parent are full */
+ while (top != -1) {
+ if (is_dom_full(dom_stack[top], root_pos, dom_full,
+ allow_version, gen_mode)) {
+ uint32_t off = dom_stack[top] - root_pos;
+
+ D_DEBUG(DB_PL, "dom %u used up\n", off);
+ setbit(dom_full, off);
+ }
+ --top;
+ }
+ }
+ *dom = curr_dom;
+ /* Found target (which may be available or not) */
+ found_target = 1;
+ } else {
+ uint32_t selected_dom;
+ uint32_t fail_num = 0;
+ uint32_t start_dom;
+ uint32_t end_dom;
+
+ start_dom = (curr_dom->do_children) - root_pos;
+ end_dom = start_dom + (curr_dom->do_child_nr - 1);
+
+ D_DEBUG(DB_TRACE, "start_dom %u end_dom %u\n", start_dom, end_dom);
+ /* Check if all targets under the domain range has been
+ * used up (occupied), go back to its parent if it does.
+ */
+ range_set =
+ is_dom_full(curr_dom, root_pos, dom_full, allow_version, gen_mode);
+ if (range_set) {
+ if (top == -1) {
+ if (curr_pd != root_pos) {
+ /* all domains within the PD are full, ignore the
+ * PD restrict.
+ */
+ D_DEBUG(DB_PL,
+ "PD[%d] all doms are full, weak the "
+ "PD restrict\n",
+ (int)(curr_dom - root_pos));
+ curr_pd = root_pos;
+ curr_dom = curr_pd;
+ *pd_ignored = true;
+ continue;
+ }
+ /* shard nr > target nr, no extra target for the shard */
+ *target = NULL;
+ return;
+ }
+ setbit(dom_full, curr_dom - root_pos);
+ D_DEBUG(DB_PL, "used up dom %d\n", (int)(curr_dom - root_pos));
+ setbit(dom_cur_grp_used, curr_dom - root_pos);
+ curr_dom = dom_stack[top--];
+ continue;
+ }
+
+ /* Check if all children has been used for the current group or full */
+ range_set = dom_isset_2ranges(root_pos, dom_full, dom_cur_grp_used,
+ start_dom, end_dom, allow_version, gen_mode);
+ if (range_set) {
+ if (top == -1) {
+ if (curr_pd != root_pos && grp_size > 1) {
+ /* All domains within the PD are full, ignore the
+ * PD restrict. For non-replica (grp_size 1) case,
+ * keep the PD restrict until all targets under the
+ * domain range has been used up (see above check
+ * for dom_full bitmap).
+ */
+ D_DEBUG(DB_PL,
+ "PD[%d] all doms are full, weak the "
+ "PD restrict\n",
+ (int)(curr_dom - root_pos));
+ curr_pd = root_pos;
+ curr_dom = curr_pd;
+ *pd_ignored = true;
+ continue;
+ }
+ *target = NULL;
+ return;
+ }
+ setbit(dom_cur_grp_used, curr_dom - root_pos);
+ D_DEBUG(DB_PL, "set grp_used %d\n", (int)(curr_dom - root_pos));
+ curr_dom = dom_stack[top--];
+ continue;
+ }
+
+ /* Check if all children has been used for the current group or the
+ * object.
+ */
+ range_set = dom_isset_2ranges(root_pos, dom_used, dom_cur_grp_used,
+ start_dom, end_dom, allow_version, gen_mode);
+ if (range_set) {
+ int idx;
+
+ for (idx = start_dom; idx <= end_dom; ++idx)
+ if (!isset(dom_full, idx)) {
+ clrbit(dom_used, idx);
+ D_DEBUG(DB_PL, "clrbit dom_used %d\n", idx);
+ }
+ if (top == -1)
+ curr_dom = curr_pd;
+ else
+ curr_dom = dom_stack[top--];
+ continue;
+ }
+
+ /* Keep choosing the new domain until the one has not been used. */
+ do {
+ struct pool_domain *_dom;
+
+ key = jm_crc(obj_key, shard_num, fail_num++);
+ selected_dom = d_hash_jump(key, avail_doms);
+ _dom = _get_dom(curr_dom, selected_dom, allow_version, gen_mode);
+ if (_dom != NULL)
+ selected_dom = _dom - curr_dom->do_children;
+ } while (isset(dom_used, start_dom + selected_dom) ||
+ isset(dom_cur_grp_used, start_dom + selected_dom));
+
+ D_ASSERTF(isclr(dom_full, start_dom + selected_dom), "selected_dom %u\n",
+ selected_dom);
+ /* Mark this domain as used */
+ if (curr_dom == curr_pd && curr_pd != root_pos)
+ setbit(dom_used, (int)(curr_dom - root_pos));
+ D_DEBUG(DB_PL, "selected dom %d\n", start_dom + selected_dom);
+ setbit(dom_used, start_dom + selected_dom);
+ setbit(dom_cur_grp_used, start_dom + selected_dom);
+ D_ASSERT(top < MAX_STACK - 1);
+ top++;
+ dom_stack[top] = curr_dom;
+ curr_dom = &curr_dom->do_children[selected_dom];
+ obj_key = jm_crc(obj_key, curr_dom->do_comp.co_id, 0xbabecafe);
+ }
+ } while (!found_target);
+}
+
/* Only reset all used dom/tgts bits if all domain has been used. */
static void
dom_reset_bit(struct pool_domain *dom, uint8_t *dom_bits, struct pool_domain *root,
@@ -604,11 +815,11 @@ reset_dom_cur_grp_v1(struct pool_domain *root, struct pool_domain *curr_pd,
}
static void
-get_target_v1(struct pool_domain *root, struct pool_domain *curr_pd, struct pool_target **target,
- struct pool_domain **dom, uint64_t key, uint8_t *dom_used, uint8_t *dom_full,
- uint8_t *dom_cur_grp_used, uint8_t *dom_cur_grp_real, uint8_t *tgts_used,
- int shard_num, uint32_t allow_version, enum layout_gen_mode gen_mode,
- pool_comp_type_t fdom_lvl, uint32_t grp_size)
+get_target_new(struct pool_domain *root, struct pool_domain *curr_pd, uint32_t layout_ver,
+ struct pool_target **target, struct pool_domain **dom, uint64_t key,
+ uint8_t *dom_used, uint8_t *dom_full, uint8_t *dom_cur_grp_used,
+ uint8_t *dom_cur_grp_real, uint8_t *tgts_used, int shard_num, uint32_t allow_version,
+ enum layout_gen_mode gen_mode, pool_comp_type_t fdom_lvl, uint32_t grp_size)
{
struct pool_target *found = NULL;
bool pd_ignored;
@@ -622,9 +833,17 @@ get_target_v1(struct pool_domain *root, struct pool_domain *curr_pd, struct pool
*/
while (found == NULL) {
pd_ignored = false;
- __get_target_v1(root, curr_pd, &found, dom, key, dom_used, dom_full,
- dom_cur_grp_used, tgts_used, shard_num, allow_version, gen_mode,
- fdom_lvl, grp_size, &pd_ignored);
+ if (layout_ver == 1) {
+ __get_target_v1(root, curr_pd, &found, dom, key, dom_used, dom_full,
+ dom_cur_grp_used, tgts_used, shard_num, allow_version,
+ gen_mode, fdom_lvl, grp_size, &pd_ignored);
+ } else { /* Fix CRC calls */
+ D_ASSERT(layout_ver == 2);
+ __get_target_v2(root, curr_pd, &found, dom, key, dom_used, dom_full,
+ dom_cur_grp_used, tgts_used, shard_num, allow_version,
+ gen_mode, fdom_lvl, grp_size, &pd_ignored);
+ }
+
if (found == NULL) {
if (pd_ignored)
reset_dom_cur_grp_v1(root, root, dom_cur_grp_used, dom_cur_grp_real,
@@ -901,14 +1120,15 @@ get_target(struct pool_domain *root, struct pool_domain *curr_pd, uint32_t layou
}
break;
case 1:
+ case 2:
/**
* New layout(>= 1) will always try to assign target to the shard due to the high
* overhead of the EC degraded fetch, so it might put multiple shards in the
* same target, i.e. it will never check the spare target here.
*/
- get_target_v1(root, curr_pd, target, dom, key, dom_used, dom_full, dom_cur_grp_used,
- dom_cur_grp_real, tgts_used, shard_num, allow_version, gen_mode,
- fdom_lvl, grp_size);
+ get_target_new(root, curr_pd, layout_ver, target, dom, key, dom_used, dom_full,
+ dom_cur_grp_used, dom_cur_grp_real, tgts_used, shard_num,
+ allow_version, gen_mode, fdom_lvl, grp_size);
if (spare_avail)
*spare_avail = true;
break;
diff --git a/src/placement/tests/jump_map_place_obj.c b/src/placement/tests/jump_map_place_obj.c
index 8e257aad82f..b2e5e1d21e7 100644
--- a/src/placement/tests/jump_map_place_obj.c
+++ b/src/placement/tests/jump_map_place_obj.c
@@ -1196,10 +1196,10 @@ down_back_to_up_in_same_order(void **state)
* healthy targets because of the retry/collision mechanism of the jump
* map algorithm.
* Due to layout colocation, if the oid has been changed, then it could
- * be 2 or even 3 as well, with current oid setting, this is 1.
+ * be 2 or even 3 as well, with current oid setting, this is 2.
*/
- assert_int_equal(1, ctx.reint.out_nr);
- jtc_assert_rebuild_reint_new(ctx, 1, 0, 1, 1);
+ assert_int_equal(2, ctx.reint.out_nr);
+ jtc_assert_rebuild_reint_new(ctx, 2, 0, 2, 2);
/* Take second downed target up */
jtc_set_status_on_target(&ctx, UP, orig_shard_targets[1]);
@@ -1674,14 +1674,14 @@ placement_handles_multiple_states_with_addition(void **state)
rebuilding = jtc_get_layout_rebuild_count(&ctx);
/* 1 each for down, up, new ... maybe? */
- assert_true(rebuilding == 2 || rebuilding == 3);
+ assert_true(rebuilding == 2 || rebuilding == 3 || rebuilding == 4);
/* Both DOWN and UP target will be remapped during remap */
- assert_int_equal(ctx.rebuild.out_nr, 2);
+ assert_int_equal(ctx.rebuild.out_nr, 3);
/* Adding new targets might make original shard to be remapped
* to new location.
*/
- assert_true(ctx.reint.out_nr == 1 || ctx.reint.out_nr == 2);
+ assert_true(ctx.reint.out_nr == 1 || ctx.reint.out_nr == 2 || ctx.reint.out_nr == 3);
/* JCH might cause multiple shards remap to the new target */
assert_true(ctx.new.out_nr >= 1);
diff --git a/src/placement/tests/place_obj_common.h b/src/placement/tests/place_obj_common.h
index 537c02a8de7..537fbe963a2 100644
--- a/src/placement/tests/place_obj_common.h
+++ b/src/placement/tests/place_obj_common.h
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2016-2023 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -28,7 +29,7 @@ extern bool g_verbose;
#define is_true assert_true
#define is_false assert_false
-#define PLT_LAYOUT_VERSION 1
+#define PLT_LAYOUT_VERSION 2
extern bool fail_domain_node;
void
print_layout(struct pl_obj_layout *layout);
diff --git a/src/pool/srv_layout.c b/src/pool/srv_layout.c
index dbddb92ef6f..1456cbeaf46 100644
--- a/src/pool/srv_layout.c
+++ b/src/pool/srv_layout.c
@@ -1,5 +1,6 @@
/*
* (C) Copyright 2017-2023 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -133,7 +134,7 @@ struct daos_prop_entry pool_prop_entries_default[DAOS_PROP_PO_NUM] = {
},
{
.dpe_type = DAOS_PROP_PO_OBJ_VERSION,
- .dpe_val = DS_POOL_OBJ_VERSION,
+ .dpe_val = DAOS_POOL_OBJ_VERSION,
},
{
.dpe_type = DAOS_PROP_PO_PERF_DOMAIN,
diff --git a/src/pool/srv_pool.c b/src/pool/srv_pool.c
index 4e0f5db7e4f..96b3729a2cd 100644
--- a/src/pool/srv_pool.c
+++ b/src/pool/srv_pool.c
@@ -666,7 +666,7 @@ pool_prop_write(struct rdb_tx *tx, const rdb_path_t *kvs, daos_prop_t *prop)
rc = rdb_tx_update(tx, kvs, &ds_pool_prop_svc_redun_fac, &value);
break;
case DAOS_PROP_PO_OBJ_VERSION:
- if (entry->dpe_val > DS_POOL_OBJ_VERSION) {
+ if (entry->dpe_val > DAOS_POOL_OBJ_VERSION) {
rc = -DER_INVAL;
break;
}
@@ -2352,7 +2352,7 @@ pool_svc_step_up_cb(struct ds_rsvc *rsvc)
struct pool_iv_conns *iv_hdls = NULL;
bool cont_svc_up = false;
bool events_initialized = false;
- d_rank_t rank = dss_self_rank();
+ d_rank_t rank = dss_self_rank();
int rc;
D_ASSERTF(svc->ps_error == 0, "ps_error: " DF_RC "\n", DP_RC(svc->ps_error));
@@ -2461,7 +2461,7 @@ pool_svc_step_up_cb(struct ds_rsvc *rsvc)
if (rc != 0)
goto out;
- rc = ds_rebuild_regenerate_task(svc->ps_pool, prop);
+ rc = ds_rebuild_regenerate_task(svc->ps_pool, prop, 0);
if (rc != 0)
goto out;
@@ -6126,7 +6126,7 @@ __ds_pool_mark_upgrade_completed(uuid_t pool_uuid, struct pool_svc *svc, int rc)
obj_version = (uint32_t)fail_val;
} else {
- obj_version = DS_POOL_OBJ_VERSION;
+ obj_version = DAOS_POOL_OBJ_VERSION;
}
d_iov_set(&value, &obj_version, sizeof(obj_version));
@@ -6187,10 +6187,9 @@ pool_check_upgrade_object_layout(struct rdb_tx *tx, struct pool_svc *svc,
else if (rc == -DER_NONEXIST)
current_layout_ver = 0;
- if (current_layout_ver < DS_POOL_OBJ_VERSION) {
- rc = ds_rebuild_schedule(svc->ps_pool, svc->ps_pool->sp_map_version,
- upgrade_eph, DS_POOL_OBJ_VERSION, NULL,
- RB_OP_UPGRADE, 0);
+ if (current_layout_ver < DAOS_POOL_OBJ_VERSION) {
+ rc = ds_rebuild_schedule(svc->ps_pool, svc->ps_pool->sp_map_version, upgrade_eph,
+ DAOS_POOL_OBJ_VERSION, NULL, RB_OP_UPGRADE, 0);
if (rc == 0)
*scheduled_layout_upgrade = true;
}
diff --git a/src/pool/srv_target.c b/src/pool/srv_target.c
index 082bab6cb40..46c7fadaeb4 100644
--- a/src/pool/srv_target.c
+++ b/src/pool/srv_target.c
@@ -2441,8 +2441,13 @@ cont_discard_cb(daos_handle_t ih, vos_iter_entry_t *entry,
put:
ds_cont_child_put(cont);
+ /* don't destroy vos container, to avoid ds_cont_tgt_refresh_agg_eph() failure,
+ * later depend on container recovery process to handle it.
+ */
+#if 0
if (rc == 0)
rc = ds_cont_child_destroy(arg->tgt_discard->pool_uuid, entry->ie_couuid);
+#endif
return rc;
}
@@ -2603,7 +2608,7 @@ ds_pool_task_collective(uuid_t pool_uuid, uint32_t ex_status, int (*coll_func)(v
}
/* Discard the objects by epoch in this pool */
-static void
+static int
ds_pool_tgt_discard_ult(void *data)
{
struct ds_pool *pool;
@@ -2630,6 +2635,7 @@ ds_pool_tgt_discard_ult(void *data)
ds_pool_put(pool);
free:
tgt_discard_arg_free(arg);
+ return rc;
}
void
@@ -2662,7 +2668,7 @@ ds_pool_tgt_discard_handler(crt_rpc_t *rpc)
pool->sp_need_discard = 1;
pool->sp_discard_status = 0;
- rc = dss_ult_create(ds_pool_tgt_discard_ult, arg, DSS_XS_SYS, 0, 0, NULL);
+ rc = dss_ult_execute(ds_pool_tgt_discard_ult, arg, NULL, NULL, DSS_XS_SYS, 0, 0);
ds_pool_put(pool);
out:
diff --git a/src/rebuild/srv.c b/src/rebuild/srv.c
index 76971149ef8..817dda33ac4 100644
--- a/src/rebuild/srv.c
+++ b/src/rebuild/srv.c
@@ -1601,8 +1601,7 @@ rebuild_task_ult(void *arg)
cur_ts = daos_gettime_coarse();
D_ASSERT(task->dst_schedule_time != (uint64_t)-1);
if (cur_ts < task->dst_schedule_time) {
- D_DEBUG(DB_REBUILD, "rebuild task sleep "DF_U64" second\n",
- task->dst_schedule_time - cur_ts);
+ D_INFO("rebuild task sleep " DF_U64 " second\n", task->dst_schedule_time - cur_ts);
dss_sleep((task->dst_schedule_time - cur_ts) * 1000);
}
@@ -1613,6 +1612,13 @@ rebuild_task_ult(void *arg)
D_GOTO(out_task, rc = -DER_NONEXIST);
}
+ rc = ds_cont_svc_refresh_agg_eph(task->dst_pool_uuid);
+ if (rc) {
+ D_ERROR(DF_UUID ": ds_cont_svc_refresh_agg_eph failed, " DF_RC "\n",
+ DP_UUID(task->dst_pool_uuid), DP_RC(rc));
+ goto out_pool;
+ }
+
while (1) {
/* Check if the leader pool map has been synced to all other targets
* to avoid -DER_GRP error.
@@ -2180,7 +2186,7 @@ regenerate_task_of_type(struct ds_pool *pool, pool_comp_state_t match_states, ui
/* Regenerate the rebuild tasks when changing the leader. */
int
-ds_rebuild_regenerate_task(struct ds_pool *pool, daos_prop_t *prop)
+ds_rebuild_regenerate_task(struct ds_pool *pool, daos_prop_t *prop, uint64_t delay_sec)
{
struct daos_prop_entry *entry;
char *env;
@@ -2206,12 +2212,13 @@ ds_rebuild_regenerate_task(struct ds_pool *pool, daos_prop_t *prop)
entry = daos_prop_entry_get(prop, DAOS_PROP_PO_SELF_HEAL);
D_ASSERT(entry != NULL);
if (entry->dpe_val & (DAOS_SELF_HEAL_AUTO_REBUILD | DAOS_SELF_HEAL_DELAY_REBUILD)) {
- rc = regenerate_task_of_type(pool, PO_COMP_ST_DOWN,
- entry->dpe_val & DAOS_SELF_HEAL_DELAY_REBUILD ? -1 : 0);
+ rc = regenerate_task_of_type(
+ pool, PO_COMP_ST_DOWN,
+ entry->dpe_val & DAOS_SELF_HEAL_DELAY_REBUILD ? -1 : delay_sec);
if (rc != 0)
return rc;
- rc = regenerate_task_of_type(pool, PO_COMP_ST_DRAIN, 0);
+ rc = regenerate_task_of_type(pool, PO_COMP_ST_DRAIN, delay_sec);
if (rc != 0)
return rc;
} else {
@@ -2229,7 +2236,7 @@ ds_rebuild_regenerate_task(struct ds_pool *pool, daos_prop_t *prop)
* discarding on an empty targets is harmless. So it is ok to use REINT to
* do EXTEND here.
*/
- rc = regenerate_task_of_type(pool, PO_COMP_ST_UP, 0);
+ rc = regenerate_task_of_type(pool, PO_COMP_ST_UP, delay_sec);
if (rc != 0)
return rc;
diff --git a/src/tests/ftest/pool/create_capacity.yaml b/src/tests/ftest/pool/create_capacity.yaml
index 9ba2c5652fe..1eee1e71e6a 100644
--- a/src/tests/ftest/pool/create_capacity.yaml
+++ b/src/tests/ftest/pool/create_capacity.yaml
@@ -9,7 +9,7 @@ timeouts:
server_config:
name: daos_server
engines_per_host: 2
- restart_duration: 120
+ restart_duration: 140
engines:
0:
pinned_numa_node: 0
diff --git a/src/tests/suite/daos_obj_array.c b/src/tests/suite/daos_obj_array.c
index 00742f54991..858b70e6ff2 100644
--- a/src/tests/suite/daos_obj_array.c
+++ b/src/tests/suite/daos_obj_array.c
@@ -1729,6 +1729,83 @@ array_recx_write_mixed_iov_read_single(void **state)
daos_obj_close(oh, NULL);
}
+#define ONE_KB (1024)
+#define TWO_MB (2 * 1024 * 1024)
+
+void
+test_sgl_merge_short_read(void **state)
+{
+ test_arg_t *arg = *state;
+ daos_obj_id_t oid;
+ daos_handle_t oh;
+ d_iov_t dkey;
+ d_sg_list_t sgl;
+ daos_iod_t iod;
+ daos_recx_t recx;
+ char *wbuf, *rbuf;
+ d_iov_t *sg_iovs = NULL;
+ int total_iovs = TWO_MB / ONE_KB;
+ int data_offset = 0;
+ int rc, i;
+
+ oid = daos_test_oid_gen(arg->coh, OC_SX, 0, 0, arg->myrank);
+ rc = daos_obj_open(arg->coh, oid, DAOS_OO_RW, &oh, NULL);
+ assert_rc_equal(rc, 0);
+
+ /* Buffer allocation with guard pages */
+ wbuf = malloc(ONE_MB);
+ assert_true(wbuf != NULL);
+ dts_buf_render(wbuf, ONE_MB);
+
+ /* Allocate 2MB read buffer with guard pages */
+ rbuf = calloc(1, TWO_MB + FOUR_KB);
+ assert_true(rbuf != NULL);
+
+ /* Build scatter-gather list for 1KB chunks */
+ sg_iovs = calloc(total_iovs, sizeof(d_iov_t));
+ assert_true(sg_iovs != NULL);
+
+ /* 1MB data read in 1KB chunks */
+ for (i = 0; i < total_iovs; i++) {
+ d_iov_set(&sg_iovs[data_offset], rbuf + i * ONE_KB, ONE_KB);
+ data_offset++;
+ }
+
+ /* Configure scatter-gather list */
+ sgl = (d_sg_list_t){.sg_nr = total_iovs, .sg_nr_out = 0, .sg_iovs = sg_iovs};
+
+ /* Prepare I/O descriptor */
+ d_iov_set(&dkey, "short_key", 9);
+ d_iov_set(&iod.iod_name, "big_akey", 8);
+ iod.iod_nr = 1;
+ iod.iod_size = 1;
+ iod.iod_type = DAOS_IOD_ARRAY;
+ iod.iod_recxs = &recx;
+ recx.rx_idx = 0;
+ recx.rx_nr = ONE_MB - 4;
+
+ /* Write initial data with single IOV */
+ d_sg_list_t write_sgl = {
+ .sg_nr = 1,
+ .sg_iovs = &(d_iov_t){.iov_buf = wbuf, .iov_len = ONE_MB - 4, .iov_buf_len = ONE_MB}};
+ rc = daos_obj_update(oh, DAOS_TX_NONE, 0, &dkey, 1, &iod, &write_sgl, NULL);
+ assert_rc_equal(rc, 0);
+
+ /* Read back using 1KB chunks */
+ rc = daos_obj_fetch(oh, DAOS_TX_NONE, 0, &dkey, 1, &iod, &sgl, NULL, NULL);
+ assert_rc_equal(rc, 0);
+ assert_rc_equal(sgl.sg_nr_out, 1024);
+ assert_rc_equal(sg_iovs[1023].iov_len, 1020);
+
+ /* Verify only 1MB - 4 was read successfully */
+ assert_memory_equal(wbuf, rbuf, ONE_MB - 4);
+
+ free(wbuf);
+ free(rbuf);
+ free(sg_iovs);
+ daos_obj_close(oh, NULL);
+}
+
static const struct CMUnitTest array_tests[] = {
{"ARRAY0: small_sgl", small_sgl, NULL, test_case_teardown},
{"ARRAY1: byte array with buffer on stack", byte_array_simple_stack, NULL, test_case_teardown},
@@ -1759,6 +1836,7 @@ static const struct CMUnitTest array_tests[] = {
{"ARRAY20: recx read mixed iov", array_recx_read_mixed_iov, NULL, test_case_teardown},
{"ARRAY21: recx write mixed iov", array_recx_write_mixed_iov_read_single, NULL,
test_case_teardown},
+ {"ARRAY22: recx short read", test_sgl_merge_short_read, NULL, test_case_teardown},
};
static int
diff --git a/src/tests/suite/daos_rebuild_common.c b/src/tests/suite/daos_rebuild_common.c
index 799b52fede8..18017191280 100644
--- a/src/tests/suite/daos_rebuild_common.c
+++ b/src/tests/suite/daos_rebuild_common.c
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2016-2023 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -624,19 +625,24 @@ void make_buffer(char *buffer, char start, int total)
static void
write_ec(struct ioreq *req, int index, char *data, daos_off_t off, int size)
{
- char key[32];
- daos_recx_t recx;
- int i;
- char single_data[LARGE_SINGLE_VALUE_SIZE];
+ char key[32];
+ daos_recx_t recx;
+ int small_size = 5;
+ int i;
+ char *single_data;
+
+ assert_true(small_size <= size);
+
+ D_ALLOC(single_data, LARGE_SINGLE_VALUE_SIZE);
+ assert_non_null(single_data);
for (i = 0; i < KEY_NR; i++) {
req->iod_type = DAOS_IOD_ARRAY;
sprintf(key, "dkey_small_%d", index);
- recx.rx_nr = 5;
+ recx.rx_nr = small_size;
recx.rx_idx = off + i * 10485760;
- insert_recxs(key, "a_key", 1, DAOS_TX_NONE, &recx, 1,
- data, size, req);
+ insert_recxs(key, "a_key", 1, DAOS_TX_NONE, &recx, 1, data, small_size, req);
sprintf(key, "dkey_%d", index);
recx.rx_nr = size;
@@ -658,6 +664,8 @@ write_ec(struct ioreq *req, int index, char *data, daos_off_t off, int size)
insert_single(key, "a_key", 0, single_data,
LARGE_SINGLE_VALUE_SIZE, DAOS_TX_NONE, req);
}
+
+ D_FREE(single_data);
}
static void
diff --git a/src/tests/suite/dfs_unit_test.c b/src/tests/suite/dfs_unit_test.c
index 84c77453e88..cb2ad322f89 100644
--- a/src/tests/suite/dfs_unit_test.c
+++ b/src/tests/suite/dfs_unit_test.c
@@ -2475,6 +2475,58 @@ dfs_test_oclass_hints(void **state)
rc = daos_cont_destroy(arg->pool.poh, "oc_cont2", 0, NULL);
assert_success(rc);
+ /** create container with RF = 3 */
+ print_message("DFS object class hints with container RF3:\n");
+ prop->dpp_entries[0].dpe_type = DAOS_PROP_CO_REDUN_FAC;
+ prop->dpp_entries[0].dpe_val = DAOS_PROP_CO_REDUN_RF3;
+ rc = dfs_cont_create_with_label(arg->pool.poh, "oc_cont3", &dattr, NULL, &coh, &dfs_l);
+ assert_int_equal(rc, 0);
+
+ /** set the expect EC object class ID based on domain nr */
+ if (attr.pa_domain_nr >= 22)
+ ecidx = OC_EC_16P3GX;
+ else if (attr.pa_domain_nr >= 14)
+ ecidx = OC_EC_8P3GX;
+ else if (attr.pa_domain_nr >= 10)
+ ecidx = OC_EC_4P3GX;
+ else
+ ecidx = OC_RP_4GX;
+
+ rc = dfs_suggest_oclass(dfs_l, "file:single", &cid);
+ assert_int_equal(rc, 0);
+ daos_oclass_id2name(cid, oclass_name);
+ print_message("oclass suggested for \"file:single\" = %s\n", oclass_name);
+ rc = compare_oclass(coh, cid, OC_RP_4G1);
+ assert_rc_equal(rc, 0);
+
+ rc = dfs_suggest_oclass(dfs_l, "File:max", &cid);
+ assert_int_equal(rc, 0);
+ daos_oclass_id2name(cid, oclass_name);
+ print_message("oclass suggested for \"File:max\" = %s\n", oclass_name);
+ rc = compare_oclass(coh, cid, ecidx);
+ assert_rc_equal(rc, 0);
+
+ rc = dfs_suggest_oclass(dfs_l, "dir:single", &cid);
+ assert_int_equal(rc, 0);
+ daos_oclass_id2name(cid, oclass_name);
+ print_message("oclass suggested for \"dir:single\" = %s\n", oclass_name);
+ rc = compare_oclass(coh, cid, OC_RP_4G1);
+ assert_rc_equal(rc, 0);
+
+ rc = dfs_suggest_oclass(dfs_l, "Directory:max", &cid);
+ assert_int_equal(rc, 0);
+ daos_oclass_id2name(cid, oclass_name);
+ print_message("oclass suggested for \"Directory:max\" = %s\n", oclass_name);
+ rc = compare_oclass(coh, cid, OC_RP_4GX);
+ assert_rc_equal(rc, 0);
+
+ rc = dfs_umount(dfs_l);
+ assert_int_equal(rc, 0);
+ rc = daos_cont_close(coh, NULL);
+ assert_success(rc);
+ rc = daos_cont_destroy(arg->pool.poh, "oc_cont3", 0, NULL);
+ assert_success(rc);
+
daos_prop_free(prop);
}
diff --git a/src/vos/vos_io.c b/src/vos/vos_io.c
index 8615fb56b47..1b25ffb1015 100644
--- a/src/vos/vos_io.c
+++ b/src/vos/vos_io.c
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2018-2024 Intel Corporation.
+ * (C) Copyright 2025 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
@@ -1007,14 +1008,44 @@ akey_fetch_recx(daos_handle_t toh, const daos_epoch_range_t *epr,
holes += lo - index;
}
- /* Hole extent, with_shadow case only used for EC obj */
- if (bio_addr_is_hole(&ent->en_addr) ||
- (with_shadow && (ent->en_epoch < shadow_ep))) {
+ if ((with_shadow && (ent->en_epoch < shadow_ep))) {
index = lo + nr;
holes += nr;
continue;
}
+ /* Hole extent, with_shadow case only used for EC obj */
+ if (bio_addr_is_hole(&ent->en_addr)) {
+ if (with_shadow) {
+ if (holes != 0) {
+ /* process the prev hole */
+ rc = save_recx(ioc, lo - holes, holes, shadow_ep, inob,
+ DRT_SHADOW);
+ if (rc != 0)
+ goto failed;
+ biov_set_hole(&biov, holes * inob);
+ /* skip the hole */
+ rc = iod_fetch(ioc, &biov);
+ if (rc != 0)
+ goto failed;
+ holes = 0;
+ }
+ /* process this punch ext, for degraded fetch just skip it */
+ index = lo + nr;
+ holes = nr;
+ biov_set_hole(&biov, holes * inob);
+ /* skip the hole */
+ rc = iod_fetch(ioc, &biov);
+ if (rc != 0)
+ goto failed;
+ holes = 0;
+ } else {
+ index = lo + nr;
+ holes += nr;
+ }
+ continue;
+ }
+
if (holes != 0) {
if (with_shadow) {
rc = save_recx(ioc, lo - holes, holes,
diff --git a/utils/node_local_test.py b/utils/node_local_test.py
index 62271c25fe6..03d31d940ab 100755
--- a/utils/node_local_test.py
+++ b/utils/node_local_test.py
@@ -1309,7 +1309,8 @@ class DFuse():
# pylint: disable-next=too-many-arguments
def __init__(self, daos, conf, pool=None, container=None, mount_path=None, uns_path=None,
- caching=True, wbcache=True, multi_user=False, ro=False):
+ caching=True, wbcache=True, multi_user=False, ro=False, dump_h=False,
+ read_h=False, file_h=None):
if mount_path:
self.dir = mount_path
else:
@@ -1334,6 +1335,9 @@ def __init__(self, daos, conf, pool=None, container=None, mount_path=None, uns_p
self.log_mask = None
self.log_file = None
self._ro = ro
+ self.dump_h = dump_h
+ self.read_h = read_h
+ self.file_h = file_h
self.valgrind = None
if not os.path.exists(self.dir):
@@ -1406,6 +1410,11 @@ def start(self, v_hint=None, use_oopt=False):
if not self.wbcache:
cmd.append('--disable-wb-cache')
+ if self.dump_h:
+ cmd.extend(['--dump-handles', self.file_h])
+ if self.read_h:
+ cmd.extend(['--read-handles', self.file_h])
+
if self._ro:
cmd.append('--read-only')
@@ -2408,15 +2417,29 @@ def test_pre_read(self):
def test_two_mounts(self):
"""Create two mounts, and check that a file created in one can be read from the other"""
+
+ try:
+ fd, tmpfile = tempfile.mkstemp(prefix="my_temp_file_", dir="/tmp")
+ print(f"Created temp file: {tmpfile}")
+ os.close(fd)
+
+ except OSError as e:
+ print(f"mkstemp failed: {e}", file=sys.stderr)
+ sys.exit(1)
+
dfuse0 = DFuse(self.server,
self.conf,
caching=False,
+ dump_h=True,
+ file_h=tmpfile,
container=self.container)
dfuse0.start(v_hint='two_0')
dfuse1 = DFuse(self.server,
self.conf,
caching=True,
+ read_h=True,
+ file_h=tmpfile,
container=self.container)
dfuse1.start(v_hint='two_1')
@@ -2432,10 +2455,10 @@ def test_two_mounts(self):
with open(file0, 'w') as fd:
fd.write('test')
- if dfuse0.stop():
- self.fatal_errors = True
if dfuse1.stop():
self.fatal_errors = True
+ if dfuse0.stop():
+ self.fatal_errors = True
def test_cache_expire(self):
"""Check that data and readdir cache expire correctly
diff --git a/utils/trivy/.trivyignore b/utils/trivy/.trivyignore
index 2a44fd66369..c3452b8f4fa 100644
--- a/utils/trivy/.trivyignore
+++ b/utils/trivy/.trivyignore
@@ -1,34 +1,12 @@
-## Ignored hadoop 3.3.6 related CVE
-## CVE-2023-52428,MEDIUM,,"Denial of Service in Connect2id Nimbus JOSE+JWT","com.nimbusds:nimbus-jose-jwt","9.8.1","9.37.2",https://avd.aquasec.com/nvd/cve-2023-52428
-CVE-2023-52428
-## CVE-2023-39410,HIGH,7.5,"apache-avro: Apache Avro Java SDK: Memory when deserializing untrusted data in Avro Java SDK","org.apache.avro:avro","1.7.7","1.11.3",https://avd.aquasec.com/nvd/cve-2023-39410
-CVE-2023-39410
-## CVE-2024-25710,HIGH,5.5,"commons-compress: Denial of service caused by an infinite loop for a corrupted DUMP file","org.apache.commons:commons-compress","1.21","1.26.0",https://avd.aquasec.com/nvd/cve-2024-25710
-CVE-2024-25710
-## CVE-2024-26308,HIGH,5.5,"commons-compress: OutOfMemoryError unpacking broken Pack200 file","org.apache.commons:commons-compress","1.21","1.26.0",https://avd.aquasec.com/nvd/cve-2024-26308
-CVE-2024-26308
-## CVE-2024-29131,MEDIUM,,"commons-configuration: StackOverflowError adding property in AbstractListDelimiterHandler.flattenIterator()","org.apache.commons:commons-configuration2","2.8.0","2.10.1",https://avd.aquasec.com/nvd/cve-2024-29131
-CVE-2024-29131
-## CVE-2024-29133,MEDIUM,,"commons-configuration: StackOverflowError calling ListDelimiterHandler.flatten(Object, int) with a cyclical object tree","org.apache.commons:commons-configuration2","2.8.0","2.10.1",https://avd.aquasec.com/nvd/cve-2024-29133
-CVE-2024-29133
-## CVE-2024-25638,HIGH,,"dnsjava: Improper response validation allowing DNSSEC bypass","dnsjava:dnsjava","2.1.7","3.6.0",https://avd.aquasec.com/nvd/cve-2024-25638
-CVE-2024-25638
+### Ignored hadoop 3.4.2 related CVEs
+## CVE-2025-52999,HIGH,,"com.fasterxml.jackson.core/jackson-core: jackson-core Potential StackoverflowError","com.fasterxml.jackson.core:jackson-core","2.10.2","2.15.0",https://avd.aquasec.com/nvd/cve-2025-52999
+CVE-2025-52999
-## Ignored hadoop 3.4.0 related CVE
-## CVE-2024-47561,CRITICAL,,"apache-avro: Schema parsing may trigger Remote Code Execution (RCE)","org.apache.avro:avro","1.9.2","1.11.4",https://avd.aquasec.com/nvd/cve-2024-47561
-CVE-2024-47561
-## CVE-2023-33201,MEDIUM,5.3,"bouncycastle: potential blind LDAP injection attack using a self-signed certificate","org.bouncycastle:bcprov-jdk15on","1.70","",https://avd.aquasec.com/nvd/cve-2023-33201
-CVE-2023-33201
-## CVE-2024-29857,MEDIUM,,"org.bouncycastle: Importing an EC certificate with crafted F2m parameters may lead to Denial of Service","org.bouncycastle:bcprov-jdk15on","1.70","1.78",https://avd.aquasec.com/nvd/cve-2024-29857
-CVE-2024-29857
-## CVE-2024-30171,MEDIUM,,"bc-java: BouncyCastle vulnerable to a timing variant of Bleichenbacher (Marvin Attack)","org.bouncycastle:bcprov-jdk15on","1.70","1.78",https://avd.aquasec.com/nvd/cve-2024-30171
-CVE-2024-30171
-## CVE-2024-30172,MEDIUM,,"org.bouncycastle:bcprov-jdk18on: Infinite loop in ED25519 verification in the ScalarUtil class","org.bouncycastle:bcprov-jdk15on","1.70","1.78",https://avd.aquasec.com/nvd/cve-2024-30172
-CVE-2024-30172
+## CVE-2025-53864,MEDIUM,,"com.nimbusds/nimbus-jose-jwt: Uncontrolled recursion in Connect2id Nimbus JOSE + JWT","com.nimbusds:nimbus-jose-jwt","9.37.2","10.0.2",https://avd.aquasec.com/nvd/cve-2025-53864
+CVE-2025-53864
-## Ignored io.netty:netty-buffer:4.1.115.Final and hadoop-common:3.4.0 CVE
-## CVE-2025-25193,MEDIUM,,"Netty, an asynchronous, event-driven network application framework, ha ...","io.netty:netty-common","4.1.115.Final","",https://avd.aquasec.com/nvd/cve-2025-25193
-CVE-2025-25193
-## Ignored hadoop 3.4.0 related CVE
-## CVE-2025-24970,HIGH,,"io.netty:netty-handler: SslHandler doesn't correctly validate packets which can lead to native crash when using native SSLEngine","io.netty:netty-handler","4.1.100.Final","4.1.118.Final",https://avd.aquasec.com/nvd/cve-2025-24970
-CVE-2025-24970
+## CVE-2025-48924,MEDIUM,,"commons-lang/commons-lang: org.apache.commons/commons-lang3: Uncontrolled Recursion vulnerability in Apache Commons Lang","org.apache.commons:commons-lang3","3.12.0","3.18.0",https://avd.aquasec.com/nvd/cve-2025-48924
+CVE-2025-48924
+
+## CVE-2025-58057,MEDIUM,7.5,"netty-codec: netty-codec-compression: Netty's BrotliDecoder is vulnerable to DoS via zip bomb style attack","io.netty:netty-codec","4.1.100.Final","4.1.125.Final",https://avd.aquasec.com/nvd/cve-2025-58057
+CVE-2025-58057
diff --git a/utils/trivy/trivy.yaml b/utils/trivy/trivy.yaml
index c6d9974456d..5ac0b5a86c7 100644
--- a/utils/trivy/trivy.yaml
+++ b/utils/trivy/trivy.yaml
@@ -19,7 +19,7 @@ db:
no-progress: false
repository: ghcr.io/aquasecurity/trivy-db
skip-update: false
-debug: true
+debug: false
dependency-tree: true
exit-code: 0
generate-default-config: false
@@ -228,6 +228,7 @@ scan:
# ignore all hadoop dependencies
skip-dirs:
./src/client/java/hadoop-daos
+ ./build
skip-files: []
show-suppressed: true
secret: