Gerrit Promises / 64620

LU-19548 lfs: update mirror split for EC support

64620 master PS23 merged LU-19548 · Maximilian Dilger · scanned 11 h ago

Export .md
6open
1in flight
2to check
2kept
2set aside
4in resolved threads

226 threads read, 118 from checkers only skipped, 1 duplicate folded in

Open 6

Open Free and re-fetch layout per file in multi-file mirror split/delete so resync decisions use the correct file's layout Marc Vef lustre/utils/lfs.c:6287 PS20 high resolved thread
AI check Still open PS23 vs master 550451c0e4 2026-09-28 $0.09

On master (550451c0e4b9), master/lustre/utils/lfs.c:6384-6388 still only fetches the layout when it is NULL ('if (!layout) layout = layout_get_by_name_or_fid(...)'), then feeds it to data_mirror_remains() and last_non_stale_mirror() for SO_MIRROR_SPLIT/SO_MIRROR_DELETE. Inside the per-file loop, the layout is only freed and reset under restripe (lfs.c:6246-6248) and in the auto-stripe migrate branch (lfs.c:6320-6321). So in a multi-file split or delete, files 2..N are still judged against file 1's layout. None of the candidate diffs (58229, 68697, 68696, 65921, 66672, 66113, 68278) touch last_non_stale_mirror or this layout fetch. Marc Vef deferred the fix to a separate patch, and I can't find that patch anywhere here.

Suggested action: In lfs_setstripe_internal's per-file loop, for SO_MIRROR_SPLIT/SO_MIRROR_DELETE (when no template is given), free the layout and fetch it again for each fname before calling data_mirror_remains()/last_non_stale_mirror(). Add a sanity-flr test that splits several files in one command, where only a later file needs the resync.

“this should be addressed but in a separate patch.”Marc Vef, PS20

Thread · 2 messages

Gerrit AI review for Lustre · 2026-08-29 14:41 · PS20 · resolved
(defect) `layout` is a function-scope variable that is only freed and reset inside this loop under `restripe` and in the auto-stripe migrate branch, neither of which applies to SO_MIRROR_SPLIT/SO_MIRROR_DELETE. So on a multi-file command it is fetched from the first file and reused for every later one, and the resync decision for file 2..N is made against file 1's layout. This predates the patch, but the new `data_mirror_remains()` call is a second consumer of it, and sanity-flr test_44f added here splits 40 files in one command, so the path is now routinely exercised. Concretely, if file1 has two healthy data mirrors then `last_non_stale_mirror()` returns false and the resync is skipped for file2 as well, even when the mirror being split is file2's only non-stale copy. Should the layout be freed and re-fetched per file here?
Marc Vef · 2026-08-31 11:01
this was raised before. This should be addressed but in a separate patch. The issue predates this patch and was introduced by 81481104fdc ("LU-13720 lfs: resync file if needed before mirror_split()", Dec 2024.

Code at the comment

    6282: 			 * that split, and resyncing first would recompute
    6283: 			 * parity over the whole file only for it to fail.
    6284: 			 */
    6285: 			result = 0;
    6286: 			if (!layout)
>>> 6287: 				layout = layout_get_by_name_or_fid(template ?:
    6288: 						fname, fname, 0, O_RDONLY);
    6289: 			if (data_mirror_remains(layout, mirror_id) &&
    6290: 			    last_non_stale_mirror(mirror_id, layout)) {
    6291: 				struct ll_ioc_lease *ioc = NULL;
    6292: 
Comment in Gerrit ↗ 64620-6d081ddf
Open Resolve mirror id once for -I/--pool paths so collect_mirror_id() doesn't wrongly count the mirror being split as a surviving copy Marc Vef lustre/utils/lfs.c:6289 PS20 high resolved thread
AI check Still open PS23 vs master 550451c0e4 2026-09-28 $0.10

The follow-up Marc Vef promised has not been done anywhere I can see. On master (master/lustre/utils/lfs.c:6364-6369), the split/delete branch only sets MF_COMP_POOL, or MF_COMP_ID, or copies mirror_id into comp_id. It never works out mirror_id for the -I or --pool paths. So at lines 6387-6388, data_mirror_remains(layout, mirror_id) and last_non_stale_mirror(mirror_id, layout) are still called with mirror_id == 0 unless --mirror-id was given. That means the mirror being split can still be counted as a surviving good copy. The current patchset has the same code (change/lustre/utils/lfs.c:6385-6386). The history files contain only this change's own commit, which adds data_mirror_remains and still passes the raw mirror_id. A search of the candidate diffs for last_non_stale_mirror, data_mirror_remains and find_mirror_id_by_pool found nothing. None of the NEW follow-ups (58229, 68697, 68696, 65921, 66672) or the MERGED ones (66113, 68278) touch this code. The reviewer's point holds: the author agreed the --pool case is a real bug and did not withdraw it. The author also said -d cannot be combined with -I, but the resync check still runs with mirror_id 0 for plain -I splits, so that does not settle it.

Suggested action: In the SO_MIRROR_SPLIT/SO_MIRROR_DELETE branch of lfs_setstripe_internal(), when mirror_id is 0, work out the target mirror id before the resync check, the same way mirror_split() does. Use find_comp_id plus mirror_id_of for -I, and find_mirror_id_by_pool for --pool. Pass that resolved id to both data_mirror_remains() and last_non_stale_mirror(). Add a sanity-ec test: take a file with an in-sync EC data mirror plus parity and a stale mirror, delete it with --pool and with -I, and check that the file keeps a non-stale data copy.

“the `-p` issue is correct but predates this patch and will be addressed in a follow-up”Marc Vef, PS20

Thread · 2 messages

Gerrit AI review for Lustre · 2026-08-29 14:41 · PS20 · resolved
(defect) `mirror_id` here is still 0 unless `--mirror-id` was given: the branch just above sets `comp_id` or `MF_COMP_POOL` for `-I` and `--pool` and leaves `mirror_id` alone. Both helpers then run with `cid_exclude == 0`, and no mirror has id 0, so `collect_mirror_id()` also collects the mirror that is about to be split and counts it as a surviving good copy. Take {D1 in-sync EC data, P1 its parity, D2 stale} and lfs mirror delete --pool ssd FILE (or -I <D1 comp id>) `last_non_stale_mirror(0, layout)` finds D1 non-stale, returns false, and the resync is skipped. mirror_split() then resolves the mirror itself, co-splits D1+P1, and the file is left with only stale D2 - the same loss the `--mirror-id` path is being fixed for. Could the mirror id be resolved once (as mirror_split() does with find_comp_id/find_mirror_id_by_pool) and passed to both helpers?
Marc Vef · 2026-08-31 11:01
this comment was raised before. (1) -d is mutually exclusive with -I and refused on arg parsing. (2) the `-p` issue is correct but predates this patch and will be addressed in a follow-up

Code at the comment

    6284: 			 */
    6285: 			result = 0;
    6286: 			if (!layout)
    6287: 				layout = layout_get_by_name_or_fid(template ?:
    6288: 						fname, fname, 0, O_RDONLY);
>>> 6289: 			if (data_mirror_remains(layout, mirror_id) &&
    6290: 			    last_non_stale_mirror(mirror_id, layout)) {
    6291: 				struct ll_ioc_lease *ioc = NULL;
    6292: 
    6293: 				ioc = calloc(1, sizeof(*ioc) +
    6294: 						sizeof(__u32) * IOC_IDS_MAX);
Comment in Gerrit ↗ 64620-4fd76819
Open Support merging data+parity split victim in mirror extend follow-up patch Maximilian Dilger Documentation/man1/lfs-mirror-split.1:85 PS15 med resolved thread
AI check Still open PS23 vs master 550451c0e4 2026-09-28 $0.18

Nothing I can see has done the promised work. The merge check that rejects any source file with mirrors is still there on master (master/lustre/lod/lod_object.c:3435-3437 in lod_declare_layout_merge(): `if (le16_to_cpu(merge_lcm->lcm_mirror_count)) RETURN(-EBUSY)`). So after `lfs mirror split -f` moves a data mirror and its parity mirror into NEW_FILE, `lfs mirror extend -f NEW_FILE` still fails with EBUSY. The man page doesn't mention this either: master/Documentation/man1/lfs-mirror-split.1:97-108 says the data+parity pair is moved to NEW_FILE and that splitting a parity mirror alone is refused, but says nothing about EBUSY on a later extend. The 'mirror extend patch' Maximilian pointed to is change 65921, which is still NEW. It adds only `--ec`, `--mirror-id` and auto-attach of parity. It refuses `--ec` together with `-f` (candidates/65921.diff:204-208 and 2312-2320). Its lod_object.c hunk (lines 506-571) only links merged parity components to their data mirror and leaves the mirror_count EBUSY check alone. 58229 (no match for lcm_mirror_count or EBUSY in its diff) and 68697 (refuses to split a parity mirror into its own file) don't cover it either. Andreas argued that re-merging a data+parity pair isn't needed, since a resync is required anyway, so the merge itself can reasonably be dropped. But he said the man page note 'would be useful', and that note was never added.

Suggested action: In lfs-mirror-split.1 (-f NEW_FILE) and lfs-mirror-extend.1 (-f), state that a NEW_FILE holding an EC data+parity pair cannot be merged back with 'lfs mirror extend -f' (it fails with EBUSY). Tell users to merge a plain data mirror instead and then add parity with 'lfs mirror extend --ec'. Optionally, have lfs detect a mirrored victim and print a clear error before the MDS returns EBUSY.

“as said, will be fixed in a follow up patch.”Maximilian Dilger, PS15

Thread · 7 messages

Gerrit AI review for Lustre · 2026-08-18 07:12 · PS15 · resolved
(minor) The victim now gets two mirrors, and lod_declare_layout_merge() rejects any merge source that has more than one: if (le16_to_cpu(merge_lcm->lcm_mirror_count)) RETURN(-EBUSY); So `lfs mirror extend -N -f NEW_FILE` (documented in lfs-mirror-extend.1) fails with EBUSY on a file produced this way, unlike every other split victim. Should this paragraph say so, until extend learns to merge a data+parity pair?
Andreas Dilger · 2026-08-20 16:46
Updating the man page to explain this would be useful, but I don't think re-merging a data mirror+parity into an existing file is a necessary operation. Since the mirror+EC would need to be resync'd anyway, it is not more efficient than just creating a new mirror on the target file and resyncing that, or merging a plain data mirror and then adding another EC.
Marc Vef · 2026-08-20 16:55
This is fine and will be addressed in the follow-up patch.
Marc Vef · 2026-08-20 17:19
Looks like we commented at the same time. This is a good point and would simplify things for mirror extend. Since we need to resync anyway, it would be enough to add an EC mirror to the extended data mirror. This way, the same `--ec` configuration is automatically used on the target file. I guess this could be done from user space, we don't need to modify the merge layout functionality on the mds. I'll reflect on that further later
Maximilian Dilger · 2026-08-21 02:53
as said, will be fixed in a follow up patch.
Andreas Dilger · 2026-08-22 06:20
To clarify, does that mean functionality added in this patch would be removed in a later patch? That is bad form, as it makes the code and history more complex, and often leaves cruft behind (or is never removed). Better to not add the unnecessary functionality in the first place.
Maximilian Dilger · 2026-08-24 20:35
no, none of what's being added by this patch should need to be removed later. this patch is still being followed by the mirror extend patch and i think the comment left by the bot originally isn't taking that into account.

Code at the comment

      80: .BI -f " NEW_FILE"
      81: This option indicates the layout of the split mirror will be stored into
      82: .IR NEW_FILE .
      83: If the split mirror is an EC data mirror, both the data and its associated
      84: parity mirror will be moved to
>>>   85: .IR NEW_FILE .
      86: .P
      87: This option cannot be used on encrypted files when the encryption key is not
      88: available. It will result in
      89: .BR -ENOKEY .
      90: .SH EXAMPLES
Comment in Gerrit ↗ 64620-5e9e1c38
Open Document --no-warn option in commit message if refreshed Gerrit AI review for Lustre COMMIT_MSG:28 PS22 low
AI check Still open PS23 vs master 550451c0e4 2026-09-28 $0.12

The promise was to mention the option if the patch was refreshed. It was refreshed from PS22 to PS23, and PS23 merged as commit 2e591389646c. Its commit message (history/f152f03c_0ad701c1.txt:264-303) covers the parity pair split/destroy, the split refusals, the resync fixes and the endian bugs, but never mentions `--no-warn` or the new default warning when destroying parity removes the last redundant copy. The option itself did land in that commit: the lfs-mirror-delete/split man pages (history:320-462) and lfs.c (history:1362-1371, 1782, 1827). No follow-up in candidates/ mentions `--no-warn` (grep found nothing), including 66113, which merged afterwards as c8fe1ced8f20. So a `git log --grep=no-warn` search still finds nothing, which is the gap the comment pointed at. The commit message of a merged change can't be amended now.

Suggested action: The merged commit message can't be changed, so name `--no-warn` for `lfs mirror split`/`lfs mirror delete`, and the default warning when a parity destroy removes the last redundant copy, in the commit message of the next related LU-19548 follow-up (e.g. 65921 or 68697), so it can be found with `git log --grep`. Otherwise close the item as not fixable for 64620.

“If the patch is refreshed, a sentence in the second paragraph would cover it.”Gerrit AI review for Lustre, PS22

Thread · 1 message

Gerrit AI review for Lustre · 2026-09-09 22:10 · PS22
(minor) The body doesn't mention the new `--no-warn` option or the warning it suppresses, yet both are new user-visible behaviour: `lfs mirror split` and `lfs mirror delete` gain the option, a warning is now printed by default when a parity destroy takes away the last redundant copy, and two man pages are updated for it. The house rule is that the message should name the new command/parameter so it is findable via `git log` grep later. If the patch is refreshed, a sentence in the second paragraph would cover it.
Comment in Gerrit ↗ 64620-f152f03c
Open Update man page synopsis to show -d/-f as mutually exclusive Gerrit AI review for Lustre Documentation/man1/lfs-mirror-split.1:14 PS22 low
AI check Still open PS23 vs master 550451c0e4 2026-09-28 $0.11

The comment is correct. On master (550451c0e4b9, which contains the merged commit 2e591389646c), lustre/utils/lfs.c rejects the two options in both orders: about line 5139 prints "-d cannot be used with -f" and line 5280 prints "-f cannot be used with -d". But master/Documentation/man1/lfs-mirror-split.1:14-17 still lists .RB [ --destroy | -d ] and .RB [ -f NEW_FILE ] as separate optional items. The -d text in OPTIONS (lines 86-91) and the -f text (lines 97-113) don't say the two can't be combined either. The history file only has 2e591389646c, which added --no-warn but didn't touch this. No candidate diff changes lfs-mirror-split.1, and the replies don't withdraw the item.

Suggested action: In Documentation/man1/lfs-mirror-split.1, merge the separate [--destroy|-d] and [-f NEW_FILE] synopsis entries into one alternation, e.g. .RB [ --destroy | -d | -f .IR NEW_FILE ]. Also add a sentence to both the -d and -f OPTIONS entries saying they are mutually exclusive.

Thread · 1 message

Gerrit AI review for Lustre · 2026-09-09 22:10 · PS22
(minor) The synopsis shows `[--destroy|-d]` and `[-f NEW_FILE]` as independently optional, but this patch makes them mutually exclusive in both orders - `case 'f'` now rejects `-f` once MF_DESTROY is set, and `case 'd'` already rejected `-d` after `-f`. Worth folding them into one alternation, and saying so in the OPTIONS text for `-d`, so the page matches what the parser accepts.

Code at the comment

       9: .BR --component-id | --comp-id | -I
      10: .I COMP_ID
      11: |
      12: .B --pool
      13: .IR POOL }
>>>   14: .RB [ --destroy | -d ]
      15: .RB [ --no-warn ]
      16: .RB [ -f
      17: .IR NEW_FILE ]
      18: .I MIRRORED_FILE
      19: .YS
Comment in Gerrit ↗ 64620-3a10ec1d
Open Decide whether multi-mirror split should iterate instead of erroring, possibly in follow-on patch wc-checkpatch lustre/lod/lod_object.c:3759 PS18 low resolved thread
AI check Still open PS23 vs master 550451c0e4 2026-09-28 $0.05

Split still rejects requests for more than one mirror. The check `if (comp_v1->lcm_mirror_count > 1)` with CERROR "cannot purge %u mirrors at once" and -EINVAL is unchanged at master/lustre/lod/lod_object.c:3757-3762 and at the same lines in change/ PS23. On the client, lfs mirror_split() (master/lustre/utils/lfs.c:2752, called at :6406) still takes a single mirror id and does not loop over several mirrors. None of the candidate diffs change this check or add iteration; a grep for lcm_mirror_count, mirror_split and 'cannot purge' finds nothing relevant. Only 65921.diff:577 matches lcm_mirror_count, and that line is unrelated mirror-extend code. Andreas deferred this to a follow-on patch, and no such patch is visible. Marking the thread resolved did not implement it.

Suggested action: In lfs mirror split, when the user asks to split several mirrors (e.g. -N 2 or several mirror ids), loop and split them one at a time instead of failing with -EINVAL. Also decide whether the lod_object.c check is a usage error or just a current implementation limit, and make the CERROR message say which.

Thread · 2 messages

wc-checkpatch · 2026-08-25 15:02 · PS18 · resolved
(style) Review error messages to ensure they are useful, and not just status/debug
Andreas Dilger · 2026-08-25 18:16
Do you think this is a usage error if the user requests splitting multiple mirrors, or just a limitation in the current implementation? IMHO it would be more convenient for the user to just iterate over all the mirrors one-at-a-time (possibly by `lfs` on the client rather than on the server) instead of returning an error, especially in the case of -N=2 or similar removing multiple mirrors that were added to a file for caching or by accident. That could be done in a follow-on patch, to avoid delaying this one.

Code at the comment

    3754: 	/* from now on, @buf contains cpu endian data */
    3755: 
    3756: 	/* Allow purging a single mirror, or a data + parity mirror pair */
    3757: 	if (comp_v1->lcm_mirror_count > 1) {
    3758: 		rc = -EINVAL;
>>> 3759: 		CERROR("%s: cannot purge %u mirrors at once from "DFID": rc = %d\n",
    3760: 		       lod2obd(d)->obd_name, comp_v1->lcm_mirror_count + 1,
    3761: 		       PFID(lu_object_fid(&dt->do_lu)), rc);
    3762: 		RETURN(rc);
    3763: 	}
    3764: 
Comment in Gerrit ↗ 64620-0c53ebe8

In flight 1

In flight Enforce on MDS that a parity-only victim file cannot be created Marc Vef lustre/mdd/mdd_object.c:2042 PS19 med in flight: 68697
AI check Unclear PS23 vs master 550451c0e4 2026-09-28 $0.07

Kept in change 68697 — LU-19548 mdd: refuse to split a parity mirror to a victim (NEW) passes has_victim (mrd_obj != NULL) to mdd_split_ea() and returns -EINVAL for a parity target

Master (550451c0e4b9) still has no MDS check. In master/lustre/mdd/mdd_object.c, target_is_parity is set around lines 1910-1945, but it only feeds the link_id pairing logic. It never causes a victim split of a parity mirror to be refused, and the only uses of mrd_obj (lines 2127 and 2327) pick the victim object. candidates/68697.diff adds a has_victim && target_is_parity check to mdd_split_ea() that logs CERROR 'cannot split parity mirror ... into a file of its own' and returns -EINVAL. It also changes lfs.c so lfs no longer takes the old-MDS volatile fallback for a parity target. 68697 is still NEW, so this is not landed yet.

Suggested action: Land 68697. Add a sanity-ec test that asks the MDS directly (without lfs's client-side check) to split a parity mirror into a victim file, and check that it fails with -EINVAL.

In flight: 68697 new LU-19548 mdd: refuse to split a parity mirror to a victim found by the check · turns into kept when it merges
“Addressed in https://review.whamcloud.com/c/fs/lustre-release/+/68697”Marc Vef, PS19

Possible follow-ups — found in Gerrit, not confirmed

Thread · 5 messages

Gerrit AI review for Lustre · 2026-08-28 13:56 · PS19 · resolved
(minor) Keeping LCME_FL_PARITY on the victim entries means a direct parity split now hands a victim file whose only component is parity. Nothing on the MDS refuses that - data_remains only protects the source - so the "a file containing only a parity mirror cannot be read" rule documented in lfs-mirror-split.1 lives solely in mirror_split(), and any other client (or an unpatched lfs) can still create such a file. mdd_xattr_split() already knows whether a victim object exists (mrd->mrd_obj), so this could be enforced here too. Was that deliberate?
Marc Vef · 2026-08-31 11:34
Agreed. For belt and suspenders, this should be added on the MDS side (`mrd_obj != NULL`). Reasonable if the patch is refreshed, in a follow-up otherwise.
Marc Vef · 2026-09-07 14:34
Done
Marc Vef · 2026-09-07 15:19
Reopening this. This warants another patch because it depends on another unrelated bug on master I need to investigate. I will push a separate patch
Marc Vef · 2026-09-07 19:52
Addressed in https://review.whamcloud.com/c/fs/lustre-release/+/68697

Code at the comment

    2037: 			vic = true;
    2038: 
    2039: 		/* copy component entry */
    2040: 		if (vic) {
    2041: 			memcpy(entry_vic, entry, sizeof(*entry));
>>> 2042: 			entry_vic->lcme_flags &= cpu_to_le32(vic_flag_mask);
    2043: 			if (vic_parity_stale && parity_id && mid == parity_id)
    2044: 				entry_vic->lcme_flags |=
    2045: 					cpu_to_le32(LCME_FL_STALE);
    2046: 			entry_vic->lcme_offset = cpu_to_le32(offset_vic);
    2047: 			/* If the paired mirror stays behind (a direct parity
Comment in Gerrit ↗ 64620-a08dac95

To check 2

Unclear File small follow-up patch for remaining issue Keguang Xu (change-level) PS20 low
AI check Unclear PS23 vs master 550451c0e4 2026-09-28 $0.30

Keguang Xu's PS20 comment only says "still one issue left" and never names it. No code context was captured, and Marc Vef's reply ("Agreed") does not name it either. The change merged as 2e591389646c. The only later master commit touching these files is c8fe1ced8f20 (66113, `lfs getstripe --ec-map`), which adds new output and does not fix anything in mirror split. Two open follow-ups from Marc Vef touch this code: 68697 enforces in the MDS (mdd_split_ea() with has_victim) the rule that a lone parity mirror cannot be split into a file of its own. 68696 declares the layout split before the purge in mdd_xattr_split(), which stops the -EINVAL fallback to a volatile file. Either could be the issue Keguang meant, but nothing here ties either one to his comment. Merged 68278 only changes the OST count in sanity-ec test_7d.

Suggested action: Ask Keguang Xu which issue he meant on PS20 of change 64620. Then check whether open changes 68697 or 68696 fix it, or file a small LU-19548 follow-up if neither does.

“Maybe another small patch to fix it?”Keguang Xu, PS20

Thread · 2 messages

Keguang Xu · 2026-09-02 01:12 · PS20 · resolved
@mvef@whamcloud.com, approve +1, but still one issue left. Maybe another small patch to fix it?
Marc Vef · 2026-09-02 07:36
Agreed, many thanks Keguang.
Comment in Gerrit ↗ 64620-da097ab4
Unclear Fix minor link-id handling issues in follow-up patch Marc Vef (change-level) PS19 low
AI check Unclear PS23 vs master 550451c0e4 2026-09-28 $0.09

The PS19 change-level comment says only that there are 'a few minor issues' with link-id handling. It does not list them; they were probably in inline comments that were not captured. The link-id code merged in 2e591389646c adds mdd_lcme_link_id, mdd_ec_pair_linked and mdd_lcme_clear_link_id, plus parity_mirror_link in lfs (history/80d744ff_f21809c1.txt:503-782, 1396-1765). Since then, master has only c8fe1ced8f20 (LU-20036 --ec-map), which reads lcme_mirror_link_id but does not change split handling. Among the NEW candidates, 68697 (refuse to split a parity mirror to a victim) and 68696 are in this area, but I can't match either one to issues that were never named.

Suggested action: Get Marc Vef's list of minor link-id issues from PS19 (inline comments or his notes). Check each one against master 2e591389646c and candidates 68697 and 68696, then fix whatever is still open in a follow-up.

“There are a few minor issues that are worthwhile to fix if refreshed or otherwise in a follow-up.”Marc Vef, PS19

Thread · 1 message

Marc Vef · 2026-08-27 22:09 · PS19 · resolved
The patch and the link id handling look correct. There are a few minor issues that are worthwhile to fix if refreshed or otherwise in a follow-up. In any case, I put them on my list so we don't forget later
Comment in Gerrit ↗ 64620-80d744ff

Kept 2

Kept Fix resync-stale-mirror-before-delete-last-copy before final release Andreas Dilger (change-level) PS18 low +1 repeat
AI check Kept PS23 vs master 550451c0e4 2026-09-28 $0.08

Kept in patchset 23 — The resync step now runs only when data_mirror_remains() is true, so a stale mirror is no longer resynced before a split that will be refused.

In change/lustre/utils/lfs.c:6385 (and master/lustre/utils/lfs.c:6387), the resync is gated on `data_mirror_remains(layout, mirror_id) && last_non_stale_mirror(mirror_id, layout)`. The comment above it (master lfs.c:6377-6382) says the resync is skipped when no data mirror would remain because mirror_split() will refuse that split. mirror_split() rejects it at change lfs.c:2883 / master lfs.c:2885 with the error 'it is the only data mirror'. So when someone asks to delete the last data copy, the stale parity mirror is no longer resynced before the command fails. The commented-on behavior is fixed in the merged patchset.

“The "resync stale mirror before refusing to delete the last data copy" could potentially be fixed before final release”Andreas Dilger, PS18

Also raised in 1 other thread — Both are about fixing the resync-before-delete-last-copy check order (data_mirror_remains) so a stale mirror isn't resynced/read before rejecting deletion of the last data copy

lustre/utils/lfs.c:2641 PS17 Gerrit AI review for Lustre: (suggestion) Skipping parity here is right, but it also makes last_non_stale_mirror() return true for a file whose only remaining mirror is
Gerrit AI review for Lustre · 2026-08-25 11:24 · PS17
(suggestion) Skipping parity here is right, but it also makes last_non_stale_mirror() return true for a file whose only remaining mirror is parity - i.e. exactly the case mirror_split() is about to reject with "it is the only data mirror". lfs_setstripe_internal() runs the resync before mirror_split(): if (last_non_stale_mirror(mirror_id, layout)) result = lfs_mirror_resync_file(...); if (!result) result = mirror_split(...); With nothing stale, lfs_mirror_resync_file() falls through to lfs_mirror_verify_file(), which recomputes parity over the whole file. So `lfs mirror delete --mirror-id DATA` on a lone data+parity pair reads the entire file before failing. Could the data_mirror_remains() check move ahead of the resync (the tests only hit this with 0-length files, so it doesn't show up there)?
Andreas Dilger · 2026-08-25 18:16
This seems unlikely to happen in practice. On the one hand resyncing the parity mirror isn't terrible, so I don't see this as a blocker. On the other hand, it is usually best if commands do what they are asked, so resyncing the stale parity mirror when being asked to delete the data mirror is a bit surprising for the user, but not "dangerous" per se. It would make sense to fix, either if the patch is refreshed or in a follow-on patch, but

Thread · 1 message

Andreas Dilger · 2026-08-25 18:16 · PS18 · resolved
Some improvements possible, but I don't think anything show-stopping. The "resync stale mirror before refusing to delete the last data copy" could potentially be fixed before final release, but this seems unlikely to happen frequently, and resyncing a stale parity mirror for the last data copy isn't a terrible thing either.
Comment in Gerrit ↗ 64620-bd8c919f
Kept Add a -q option to quiet the parity-split warning Andreas Dilger lustre/tests/sanity-ec.sh:2203 PS15 low
AI check Kept PS23 vs master 550451c0e4 2026-09-28 $0.14

Kept in patchset 23 — A --no-warn option (not -q) was added to lfs mirror split and lfs mirror delete. It sets MF_NO_WARN, which turns off the parity-mirror redundancy warning.

In change/lustre/utils/lfs.c, MF_NO_WARN is defined at lines 1829-1840. The long option "no-warn" is registered at lines 4761-4762 and sets MF_NO_WARN at line 4926. At lines 3061-3066, the warning 'removing parity mirror %u leaves data mirror %u without a redundant copy' is printed only when !(mflags & MF_NO_WARN). The usage text at lines 286/301 lists [--no-warn] for split and delete, and lines 5927-5930 reject it for any other command. The option is also documented in Documentation/man1/lfs-mirror-split.1:64 and lfs-mirror-delete.1:39. master/lustre/utils/lfs.c:3062 and :4928 contain the same code, so it has landed. It is spelled --no-warn rather than the suggested -q, but it does what was asked. One gap: no test uses --no-warn (a grep of master/lustre/tests finds nothing).

Suggested action: Optionally add a sanity-ec test that runs 'lfs mirror split'/'mirror delete --no-warn' on a parity mirror and checks that the warning is not printed.

“Not critical for this patch, but nice to have in the future.”Andreas Dilger, PS15

Thread · 3 messages

Andreas Dilger · 2026-08-20 16:46 · PS15 · resolved
(minor) Is there a `-q` option or similar that quiets this warning? It could get annoying in a hurry if someone is splitting the parity from thousands or millions of files for some reason (e.g. EC is broken for some reason).
Maximilian Dilger · 2026-08-21 02:53
not at the moment, but could be added in a later patch (unless you think it should be added to this one as a feature).
Andreas Dilger · 2026-08-22 06:20
Not critical for this patch, but nice to have in the future.

Code at the comment

    2198: 		error "parity mirror $ec_parity_id still links to '$link'"
    2199: 
    2200: 	$LFS mirror extend -N -c1 $victim || error "mirror extend failed"
    2201: 
    2202: 	$LFS mirror delete --mirror-id $ec_parity_id $victim 2>&1 |
>>> 2203: 		grep -q "removes EC protection" &&
    2204: 		error "unlinked parity mirror should not claim EC protection"
    2205: 	verify_mirror_count $victim 1
    2206: }
    2207: run_test 7f "split parity mirror -f to file works with warning"
    2208: 
Comment in Gerrit ↗ 64620-b0c0df4a

Set aside 2

Not needed Document new -f/-d usage-error interaction in commit message Andreas Dilger COMMIT_MSG:28 PS17 low
AI check Not needed PS23 vs master 550451c0e4 2026-09-28 $0.05

The code the AI reviewer described did land: master/lustre/utils/lfs.c:5280-5283 has the new check in case 'f' ('if (mirror_flags & MF_DESTROY)', printing '-f cannot be used with -d'). So 'lfs mirror split -d -f VICTIM FILE' is now a usage error. The request was only to add a sentence about this to the commit message. Andreas Dilger, the maintainer, replied 'Not critical.', which declined the request rather than promising to do it, and the thread is resolved. The change is merged at PS23, so its commit message can no longer be edited. change/ has no COMMIT_MSG file to check, and no later commit or candidate follow-up could add the note either. The behavior was never wrong; only the documentation was, and the maintainer judged that unnecessary.

“Not critical.”Andreas Dilger, PS17

Thread · 2 messages

Gerrit AI review for Lustre · 2026-08-25 11:24 · PS17 · resolved
(minor) One user-visible hunk isn't covered here: `case 'f'` in lfs_setstripe_internal() now rejects `-f` when MF_DESTROY is already set. Before this, only `case 'd'` looked at has_m_file, so `lfs mirror split -d -f VICTIM FILE` was accepted when -d came first and is now a usage error. Worth a sentence alongside the other mirror_split() fixes so the hunk isn't a surprise.
Andreas Dilger · 2026-08-25 18:16
Not critical.
Comment in Gerrit ↗ 64620-0dd5bb1a
Not needed Add --force-no-ec functionality back in future patch if needed Maximilian Dilger Documentation/man1/lfs-mirror-delete.1:64 PS14 low
AI check Not needed PS23 vs master 550451c0e4 2026-09-28 $0.03

A grep for 'force-no-ec' or 'force_no_ec' finds nothing in change/ (PS23), master/ (550451c0e4b9), history/ or any candidate diff. The option was fully removed from lfs-mirror-delete.1 and lfs.c, which is what Andreas's comment suggested if there was no good use case. The author only offered to bring it back 'if needed later', and no need has come up in the thread or in any follow-up. The concern was resolved by removing the option, so there is no outstanding work to track.

“removed --force-no-ec, can make a future patch with this function if needed later.”Maximilian Dilger, PS14

Thread · 2 messages

Andreas Dilger · 2026-08-12 18:49 · PS14 · resolved
(minor) Is there a good reason for users to ever use this option, or to delete the data mirror but leave the parity mirror? If yes, that should be mentioned here, otherwise write something like `This is mostly needed for test/debug and should not normally be used.` or if the goal is to extract only the data mirror then the better approach would be to split the data and EC mirrors together, then delete the EC mirror from that file.
Maximilian Dilger · 2026-08-17 20:41
removed --force-no-ec, can make a future patch with this function if needed later.

Code at the comment

      59: The pool storing a component contained within a mirror.
      60: .TP
      61: .B --force-no-ec
      62: When deleting an EC data mirror, delete only the data mirror and leave its
      63: associated parity mirror behind, instead of deleting both mirrors together.
>>>   64: The parity mirror left behind no longer protects any data: its link to the
      65: data mirror is cleared, and
      66: .B lfs mirror verify
      67: and
      68: .B lfs mirror resync
      69: skip it. A warning naming the
Comment in Gerrit ↗ 64620-1f2910f6

92 judged not a promise, 2 not read by Claude yet.

COMMIT_MSG:28 **[AI review - opus]** Marc Vef · not read yet Gerrit ↗
(change-level) Confirm single-step split of data and EC mirrors works Andreas Dilger · resolved Gerrit ↗
(change-level) Rebase note Marc Vef · resolved Gerrit ↗
(change-level) Partial review note Marc Vef · resolved Gerrit ↗
(change-level) Rebase note Marc Vef · resolved Gerrit ↗
(change-level) Build chatter Maximilian Dilger · resolved Gerrit ↗
(change-level) Rebase build dependency note Andreas Dilger · resolved Gerrit ↗
(change-level) Ping reviewer Andreas Dilger · resolved Gerrit ↗
(change-level) Ping reviewers Maximilian Dilger · resolved Gerrit ↗
(change-level) Decision to drop --force-no-ec option Andreas Dilger · resolved Gerrit ↗
(change-level) Suggestion to split --force-no-ec into separate patch (superseded by removal) Andreas Dilger · resolved Gerrit ↗
(change-level) Review vote comment Andreas Dilger · resolved Gerrit ↗
(change-level) Partial review note Marc Vef · resolved Gerrit ↗
(change-level) Design complexity question Andreas Dilger · resolved Gerrit ↗
(change-level) Ping reviewers after rebase Maximilian Dilger · resolved Gerrit ↗
(change-level) Discussion of tooling to track deferred issues Andreas Dilger · resolved Gerrit ↗
(change-level) Ping reviewers Marc Vef · resolved Gerrit ↗
(change-level) Fix ENOSPC test failures in zfs testing Oleg Drokin · resolved Gerrit ↗
(change-level) Maloo voting chatter Marc Vef · resolved Gerrit ↗
(change-level) Test results chatter Marc Vef · resolved Gerrit ↗
Documentation/man1/lfs-mirror-split.1:48 **[AI review - opus]** Marc Vef · not read yet Gerrit ↗
lustre/utils/lfs.c:2720 N/A Gerrit AI review for Lustre Gerrit ↗
COMMIT_MSG:7 Reword commit summary to imperative mood Gerrit AI review for Lustre · resolved Gerrit ↗
COMMIT_MSG:15 Fix commit message force-no-ec description inconsistency Marc Vef · resolved Gerrit ↗
COMMIT_MSG:17 Trim verbose commit message Marc Vef · resolved Gerrit ↗
COMMIT_MSG:24 Clarify commit message on -d requirement removal and mirror delete opc Gerrit AI review for Lustre · resolved Gerrit ↗
COMMIT_MSG:24 Document unaccounted hunks in commit message Gerrit AI review for Lustre · resolved Gerrit ↗
COMMIT_MSG:24 Mention LCME_FL_NOSYNC fix in commit message Gerrit AI review for Lustre · resolved Gerrit ↗
COMMIT_MSG:43 Remove stale commentary from commit message Andreas Dilger · resolved Gerrit ↗
COMMIT_MSG:50 Mention new sanity-ec tests in commit message Gerrit AI review for Lustre · resolved Gerrit ↗
COMMIT_MSG:60 Add Fixes: trailer for endian bug Gerrit AI review for Lustre · resolved Gerrit ↗
COMMIT_MSG:103 Add Fixes: trailer for stack overflow bug Gerrit AI review for Lustre · resolved Gerrit ↗
Documentation/man1/lfs-mirror-delete.1:82 Fix man page example for lfs mirror delete Gerrit AI review for Lustre · resolved Gerrit ↗
Documentation/man1/lfs-mirror-split.1:1 Bump man page date Gerrit AI review for Lustre · resolved Gerrit ↗
Documentation/man1/lfs-mirror-split.1:45 Add anti-nag option for warning Andreas Dilger · resolved Gerrit ↗
Documentation/man1/lfs-mirror-split.1:50 Fix man page description of parity split restrictions Gerrit AI review for Lustre · resolved Gerrit ↗
Documentation/man1/lfs-mirror-split.1:60 Add --no-warn flag and adjust warning logic Andreas Dilger · resolved Gerrit ↗
Documentation/man1/lfs-mirror-split.1:88 Fix man page describing --force-no-ec behaviour Marc Vef · resolved Gerrit ↗
Documentation/man1/lfs-mirror-split.1:101 Fix man page description (duplicate) Andreas Dilger · resolved Gerrit ↗
Documentation/man1/lfs-mirror-split.1:139 Fix man page example inconsistency Marc Vef · resolved Gerrit ↗
include/uapi/linux/lustre/lustre_user.h:1149 Address wire compatibility of overloaded mirror id bit Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/lod/lod_object.c:3758 Use consistent rc in error messages wc-checkpatch · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1823 Handle mirror_link_id dangling ids on split Marc Vef · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1835 Fix function comment style kg.xu · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1836 Verify reverse data->EC mirror link isn't broken by another in-flight patch Andreas Dilger · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1850 Fix typo 'a EC mirror' Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1876 Update kernel-doc for mdd split function Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1880 Fix mirror pairing to use mirror_link_id instead of adjacency assumption Marc Vef · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1895 Rename count variable for readability Marc Vef · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1909 Add guard for splitting both data and parity mirrors Marc Vef · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1919 Refuse/warn split leaving only parity mirrors (data corruption risk) Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1919 Remove leftover commentary Marc Vef · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1935 Handle orphan parity mirror after force-no-ec split Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1948 Carry over stale flag to victim to avoid stale-parity read Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1949 N/A Marc Vef · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1961 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1965 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1981 N/A kg.xu · resolved Gerrit ↗
lustre/mdd/mdd_object.c:1992 N/A wc-checkpatch · resolved Gerrit ↗
lustre/tests/sanity-ec.sh:1454 N/A Andreas Dilger · resolved Gerrit ↗
lustre/tests/sanity-ec.sh:1462 N/A Andreas Dilger · resolved Gerrit ↗
lustre/tests/sanity-ec.sh:1463 N/A Andreas Dilger · resolved Gerrit ↗
lustre/tests/sanity-ec.sh:1486 N/A Andreas Dilger · resolved Gerrit ↗
lustre/tests/sanity-ec.sh:1489 N/A Andreas Dilger · resolved Gerrit ↗
lustre/tests/sanity-ec.sh:1501 N/A Andreas Dilger · resolved Gerrit ↗
lustre/tests/sanity-ec.sh:1530 N/A Andreas Dilger · resolved Gerrit ↗
lustre/tests/sanity-ec.sh:1537 N/A Andreas Dilger · resolved Gerrit ↗
lustre/tests/sanity-ec.sh:2076 N/A Marc Vef · resolved Gerrit ↗
lustre/tests/sanity-ec.sh:2194 N/A Andreas Dilger · resolved Gerrit ↗
lustre/tests/sanity-ec.sh:2295 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/lfs.c:2548 N/A Andreas Dilger · resolved Gerrit ↗
lustre/utils/lfs.c:2641 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/lfs.c:2645 N/A kg.xu · resolved Gerrit ↗
lustre/utils/lfs.c:2664 N/A Andreas Dilger · resolved Gerrit ↗
lustre/utils/lfs.c:2694 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/lfs.c:2698 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/lfs.c:2752 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/lfs.c:2753 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/lfs.c:2788 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/lfs.c:2791 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/lfs.c:2835 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/lfs.c:2862 N/A Andreas Dilger · resolved Gerrit ↗
lustre/utils/lfs.c:2875 N/A Andreas Dilger · resolved Gerrit ↗
lustre/utils/lfs.c:2966 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/lfs.c:2982 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/lfs.c:5824 N/A Andreas Dilger · resolved Gerrit ↗
lustre/utils/lfs.c:5878 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/liblustreapi_layout.c:2482 N/A Andreas Dilger · resolved Gerrit ↗
lustre/utils/liblustreapi_layout.c:2498 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/liblustreapi_layout.c:5332 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/liblustreapi_layout.c:5334 N/A Marc Vef · resolved Gerrit ↗
lustre/utils/liblustreapi_layout.c:5334 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/liblustreapi_layout.c:5334 N/A Gerrit AI review for Lustre · resolved Gerrit ↗
lustre/utils/liblustreapi_layout.c:5731 N/A Keguang Xu · resolved Gerrit ↗

Verdicts are AI output, checked against the commits they cite — verify before acting on one.