Skip to content

Fix safeguard against deleting the last disk in a mirror - #305

Open
mwilck wants to merge 2 commits into
md-raid-utilities:mainfrom
mwilck:last-fail-fix
Open

mwilck wants to merge 2 commits into
md-raid-utilities:mainfrom
mwilck:last-fail-fix

Conversation

@mwilck

@mwilck mwilck commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

(This goes on top of #303, which it currently includes)

fc6fd40 ("Manage: Block unsafe member failing") was meant as a safeguard against users shooting themselves into the foot by removing the last up-to-date leg of a RAID mirror. But it works only if the RAID members are disks, not for partitions, and fails for set-A / set-B operations, too.

Add a test for this feature (which fails in the first place), and a fix that makes the test succeed.

Since commit fc6fd40 ("Manage: Block unsafe member failing"), mdadm
has a safeguard against failing the last leg of an error by accident.

Add tests for this feature.

The tests involving partitions as component devices and using
set-A / set-B are currently broken. They will be fixed with the
next commit.

Signed-off-by: Martin Wilck <mwilck@suse.com>
devnm2devid() works only for disk devices (/sys/block/$DEVNAME/dev),
but not for partitions (sys/block/$DISK/$PART/dev). This causes
is_remove_safe() to falsely return true if the last leg of a mirror
that is failed is a partition. The safeguard that commit fc6fd40
("Manage: Block unsafe member failing") was supposed to provide is
not effective in these cases. It also fails for "--fail set-X" in
RAID10 setups.

Moreover, in Manage_subdevs(), we already determine the device correctly,
there is no need to determine it again; we just need to pass the rdev
to is_remove_safe().

Fixes: fc6fd40 ("Manage: Block unsafe member failing")
Suggested-by: Shinkichi Yamazaki <shinkichi.yamazaki@suse.com>
Signed-off-by: Martin Wilck <mwilck@suse.com>
@mwilck

mwilck commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Modified; based directly on main now, not on #303.

Comment thread tests/01r1faillast
@@ -0,0 +1,39 @@
# create a RAID1 from partitions, try to fail both legs.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Kernel failfast feature is something else. We have name conflict I think.

Comment thread tests/01r1faillast
SEP=p
fi

mdadm -CR $md0 -l1 -n2 --assume-clean $dev2 $dev3

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

R1 and R10 covered, what about r5 or any from raid456?

Comment thread tests/01r10faillast
mdadm -S "$md0"

for d in $dev0 $dev1 $dev2 $dev3; do
sfdisk $d <<EOF

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

two cases are covered here:

  • bug for partitions
  • mdadm owned faulty state verification

Codex told me:

That exact partition-based example appears in [test line 195. Each expanded --disks= argument is 
collected into the device array at test line 346) then assigned to $dev0 through $dev13 in
tests/func.sh line 262

I found exactly one test under tests/ that creates partitions: [tests/07autodetect line 3.
It creates two partitionable MD arrays, runs sfdisk on those MD devices, and then uses ${mdp0}p1 and ${mdp1}p1.
It does not repartition the physical devices passed through --disks; the partition table is created inside
the MD arrays. No other test script uses sfdisk, fdisk, parted, partprobe, or kpartx.

I would prefer to not include partitions directly assuming that this defect will not appear in this form anymore and we should focus on executing this whole test suite on partitions and block devices as a two separate jobs.

Executing on partitions is very important case for MD stacked device. I know we have no working CI yet, but this should be our direction.

If I missed something, please let me know.

Comment thread Manage.c
* Return: True if array will be operational, false otherwise.
*/
bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const int verbose)
static bool is_remove_safe(mdu_array_info_t *array, const int fd, dev_t devid, const int verbose)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

description is not updated. When, updating please include why correct devid is important to be used here. You can mention the bug you discovered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants