Skip to content

DAOS-19616 placement: derive CURRENT layouts from PRE and POST - #19088

Merged
mchaarawi merged 3 commits into
release/2.8from
liang/b2_8_cas_shard_move
Sep 17, 2026
Merged

mchaarawi merged 3 commits into
release/2.8from
liang/b2_8_cas_shard_move

Conversation

@gnailzenh

Copy link
Copy Markdown
Collaborator

Generating CURRENT directly can mis-handle cascading shard relocation. Build POST first and generate PRE only when transition state affects placement. Derive CURRENT from both layouts while preserving readable PRE targets. Add POST peers for drain, reintegration, and collateral relocation. Use POST directly for failed PRE targets and unaffected objects. Handle missing rebuild spares without invalid target lookups.

Steps for the author:

  • Commit message follows the guidelines.
  • Appropriate Features or Test-tag pragmas were used.
  • Appropriate Functional Test Stages were run.
  • At least two positive code reviews including at least one code owner from each category referenced in the PR.
  • Testing is complete. If necessary, forced-landing label added and a reason added in a comment.

After all prior steps are complete:

  • Gatekeeper requested (daos-gatekeeper added as a reviewer).

Generating CURRENT directly can mis-handle cascading shard relocation.
Build POST first and generate PRE only when transition state affects placement.
Derive CURRENT from both layouts while preserving readable PRE targets.
Add POST peers for drain, reintegration, and collateral relocation.
Use POST directly for failed PRE targets and unaffected objects.
Handle missing rebuild spares without invalid target lookups.

Signed-off-by: Liang Zhen <gnailzenh@gmail.com>
@github-actions

Copy link
Copy Markdown

Ticket title is 'FIO crc mismatch detected on 4x node IB config while running HSN cable pulls test'
Status is 'Open'
Job should run at elevated priority (1)
https://daosio.atlassian.net/browse/DAOS-19616

@github-actions github-actions Bot added the priority Ticket has high priority (automatically managed) label Sep 16, 2026
@daosbuild3

Copy link
Copy Markdown
Collaborator

@daosbuild3

Copy link
Copy Markdown
Collaborator

Test stage Unit Test with memcheck completed with status UNSTABLE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net/job/daos-stack/job/daos//view/change-requests/job/PR-19088/1/testReport/

The derived CURRENT layout keeps the readable PRE_REBUILD target of a
shard and adds the POST_REBUILD target as a write-only peer, so the
same target can legitimately be the readable primary of one shard and
the rebuild destination of another shard of the same object while an
extension is in flight: PRE remaps the shard from a reintegrating
target to a spare, and POST, placing on the extended map, picks the
same spare for a second, failed shard. The old code produced the same
pair, with the destination hidden as a peer behind a bogus primary.
PLACEMENT 18 now rejects readable duplicates only.

Port the placement UTs which pin the relocation behaviour:

  no_stale_read_source              cascading relocation on a spare
  extension_preserves_read_sources  NEW / new-UP extension, RP and EC
                                    classes, one or two groups, v1/v2
  no_hidden_peer_source             every migration destination is
                                    written, every readable target
                                    was written before the failure
  relocation_peer_alloc_failure     pl_map_extend() allocation failure
                                    is propagated (fault injection)

They assert that every healthy PRE_REBUILD read source stays in the
CURRENT write set, that no target is readable twice in a group and
that the single group layout matches. Test pool maps now give targets
fseq 1, as gen_pool_buf() does, so that a reintegrated target is not
mistaken for a freshly added one.

Build and run from the repository root:

  scons --config=force --jobs=16 \
    install/bin/jump_pl_map install/lib64/libdaos.so
  ./utils/run_utest.py --suite_filter='^placement$' --sudo=no

All 33 placement cases pass on top of the derived CURRENT layout with
no further placement change. Native sweeps over 985,600 random and
120,000 exhaustive/extension cases found no PRE read source missing
from the CURRENT write set.

Signed-off-by: Xuezhao Liu <xuezhao.liu@hpe.com>
Signed-off-by: Xuezhao Liu <xuezhao.liu@hpe.com>
@liuxuezhao
liuxuezhao requested review from a team as code owners September 16, 2026 14:29
@daosbuild3

Copy link
Copy Markdown
Collaborator

Comment thread src/placement/jump_map.c
};

static bool
comp_may_change_layout(const struct pool_component *comp)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the PR is refreshed, it may be worth adding the following comment. Returning false for DOWNOUT does not mean its remapped spare cannot differ between PRE and POST; another DOWN , DRAIN , or UP target can still change the remap sequence. This takes me sometime to think.

/*
 * Return true if this component can make PRE_REBUILD and POST_REBUILD
 * diverge.
 *
 * Returning false for DOWNOUT does not mean that a shard remapped from a
 * DOWNOUT target must have the same spare in both layouts. Its spare may
 * still change when another DOWN, DRAIN, or UP target affects the remap
 * sequence. Once such a transitional component is encountered, the complete
 * PRE_REBUILD and POST_REBUILD layouts, including DOWNOUT shards, must be
 * compared.
 */

Comment thread src/placement/jump_map.c
D_ASSERT(post_affected == NULL || gen_mode == POST_REBUILD);
layout->ol_ver = allow_version;
if (post_affected != NULL)
*post_affected = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor, post_affected the caller already init as false, so seems need not set it again here.

Comment thread src/placement/jump_map.c
static bool
comp_may_change_layout(const struct pool_component *comp)
{
return comp->co_status != PO_COMP_ST_UPIN && comp->co_status != PO_COMP_ST_DOWNOUT;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I read the code, was think about PO_COMP_ST_NEW status.
By checking some code, NEW cannot reach this func because it should be already filtered out.
But maybe it could be a little bit clearer to write as -
return comp->co_status == PO_COMP_ST_UP || comp->co_status == PO_COMP_ST_DOWN || comp->co_status == PO_COMP_ST_DRAIN;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we need to have some cleanups for the master version of this patch, for example, PL_HAS_PEER can be removed.
Let's keep the 2.8 version as now and see if it can pass CI.

@wangshilong
wangshilong requested a review from a team September 17, 2026 14:26
@mchaarawi
mchaarawi merged commit 0cb0e4d into release/2.8 Sep 17, 2026
45 of 46 checks passed
@mchaarawi
mchaarawi deleted the liang/b2_8_cas_shard_move branch September 17, 2026 19:20
@daltonbohning daltonbohning added the release-2.8.1 Targeted for release 2.8.1 label Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority Ticket has high priority (automatically managed) release-2.8.1 Targeted for release 2.8.1

Development

Successfully merging this pull request may close these issues.

6 participants