mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-30 04:22:44 +00:00
Fix zfsd with the device_removal pool feature.
Previously zfsd would crash in the presence of a pool with a
top-level-vdev that had previously been removed. The crash happened
because the configuration nvlist of such a TLV contains an empty
ZPOOL_CONFIG_CHILDREN array, which led to a pop_front from an empty
list, which has undefined behavior.
The crash only happened in stable/14 and later, probably do to
differences in libcxx, but the change should be MFCed anyway.
PR: 273663
Reported by: Marek Zarychta <zarychtam@plan-b.pwste.edu.pl>
Sponsored by: Axcient
Reviewed by: mav
Differential Revision: https://reviews.freebsd.org/D41818
(cherry picked from commit 0b294a386d
)
This commit is contained in:
parent
d5dbed2f1e
commit
b2dff90c0b
@ -768,3 +768,40 @@ TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_five)
|
||||
delete CaseFile4;
|
||||
delete CaseFile5;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test VdevIterator
|
||||
*/
|
||||
class VdevIteratorTest : public ::testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
bool VdevIteratorTestCB(Vdev &vdev, void *cbArg) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
/*
|
||||
* VdevIterator::Next should not crash when run on a pool that has a previously
|
||||
* removed vdev. Regression for
|
||||
* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=273663
|
||||
*/
|
||||
TEST_F(VdevIteratorTest, VdevRemoval)
|
||||
{
|
||||
nvlist_t* poolConfig, *rootVdev;
|
||||
|
||||
ASSERT_EQ(0, nvlist_alloc(&rootVdev, NV_UNIQUE_NAME, 0));
|
||||
ASSERT_EQ(0, nvlist_add_uint64(rootVdev, ZPOOL_CONFIG_GUID, 0x5678));
|
||||
/*
|
||||
* Note: pools with previously-removed top-level VDEVs will contain a
|
||||
* TLV in their labels that has 0 children.
|
||||
*/
|
||||
ASSERT_EQ(0, nvlist_add_nvlist_array(rootVdev, ZPOOL_CONFIG_CHILDREN,
|
||||
NULL, 0));
|
||||
ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0));
|
||||
ASSERT_EQ(0, nvlist_add_uint64(poolConfig,
|
||||
ZPOOL_CONFIG_POOL_GUID, 0x1234));
|
||||
ASSERT_EQ(0, nvlist_add_nvlist(poolConfig, ZPOOL_CONFIG_VDEV_TREE,
|
||||
rootVdev));
|
||||
|
||||
VdevIterator(poolConfig).Each(VdevIteratorTestCB, NULL);
|
||||
}
|
||||
|
@ -101,10 +101,7 @@ VdevIterator::Next()
|
||||
{
|
||||
nvlist_t *vdevConfig;
|
||||
|
||||
if (m_vdevQueue.empty())
|
||||
return (NULL);
|
||||
|
||||
for (;;) {
|
||||
for (vdevConfig = NULL; !m_vdevQueue.empty();) {
|
||||
nvlist_t **vdevChildren;
|
||||
int result;
|
||||
u_int numChildren;
|
||||
|
Loading…
Reference in New Issue
Block a user