Skip to content

Commit

Permalink
US1533 replacing disk in a pool
Browse files Browse the repository at this point in the history
Signed-off-by: Jan Kryl <[email protected]>
  • Loading branch information
Jan Kryl committed May 20, 2018
1 parent b7b28b8 commit dd0383e
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 53 deletions.
78 changes: 42 additions & 36 deletions module/zfs/zfs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2021,7 +2021,41 @@ zfs_ioc_vdev_remove(zfs_cmd_t *zc)
return (error);
}

#if defined(_KERNEL)
static int
zfs_ioc_vdev_attach(zfs_cmd_t *zc)
{
spa_t *spa;
int replacing = zc->zc_cookie;
nvlist_t *config;
int error;

if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
return (error);

if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
zc->zc_iflags, &config)) == 0) {
error = spa_vdev_attach(spa, zc->zc_guid, config, replacing);
nvlist_free(config);
}

spa_close(spa, FTAG);
return (error);
}

static int
zfs_ioc_vdev_detach(zfs_cmd_t *zc)
{
spa_t *spa;
int error;

if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
return (error);

error = spa_vdev_detach(spa, zc->zc_guid, 0, B_FALSE);

spa_close(spa, FTAG);
return (error);
}

static int
zfs_ioc_vdev_set_state(zfs_cmd_t *zc)
Expand Down Expand Up @@ -2066,41 +2100,7 @@ zfs_ioc_vdev_set_state(zfs_cmd_t *zc)
return (error);
}

static int
zfs_ioc_vdev_attach(zfs_cmd_t *zc)
{
spa_t *spa;
int replacing = zc->zc_cookie;
nvlist_t *config;
int error;

if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
return (error);

if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
zc->zc_iflags, &config)) == 0) {
error = spa_vdev_attach(spa, zc->zc_guid, config, replacing);
nvlist_free(config);
}

spa_close(spa, FTAG);
return (error);
}

static int
zfs_ioc_vdev_detach(zfs_cmd_t *zc)
{
spa_t *spa;
int error;

if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
return (error);

error = spa_vdev_detach(spa, zc->zc_guid, 0, B_FALSE);

spa_close(spa, FTAG);
return (error);
}
#if defined(_KERNEL)

static int
zfs_ioc_vdev_split(zfs_cmd_t *zc)
Expand Down Expand Up @@ -7279,6 +7279,12 @@ uzfs_handle_ioctl(const char *pool, zfs_cmd_t *zc, uzfs_info_t *ucmd_info)
return (zfs_ioc_vdev_add(zc));
case ZFS_IOC_VDEV_REMOVE:
return (zfs_ioc_vdev_remove(zc));
case ZFS_IOC_VDEV_ATTACH:
return (zfs_ioc_vdev_attach(zc));
case ZFS_IOC_VDEV_DETACH:
return (zfs_ioc_vdev_detach(zc));
case ZFS_IOC_VDEV_SET_STATE:
return (zfs_ioc_vdev_set_state(zc));
}
return (err);
}
Expand Down
119 changes: 102 additions & 17 deletions tests/cbtest/gtest/test_zrepl_prot.cc
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,17 @@ static void graceful_close(int sockfd)
close(sockfd);
}

static std::string getPoolState(std::string pname)
{
std::string s;

s = execCmd("zpool", std::string("list -Ho health ") + pname);
// Trim white space at the end of string
s.erase(std::find_if(s.rbegin(), s.rend(),
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return (s);
}

/*
* zrepl program wrapper.
*
Expand Down Expand Up @@ -566,23 +577,13 @@ class Target {
int m_listenfd;
};

/*
* Class simplifying test zfs pool creation and creation of zvols on it.
* Automatic pool destruction takes place when object goes out of scope.
*/
class TestPool {
class Vdev {
public:
TestPool(std::string poolname) {
m_name = poolname;
m_path = std::string("/tmp/") + m_name;
Vdev(std::string name) {
m_path = std::string("/tmp/") + name;
}

~TestPool() {
//try {
execCmd("zpool", std::string("destroy -f ") + m_name);
//} catch (std::runtime_error re) {
//;
//}
~Vdev() {
unlink(m_path.c_str());
}

Expand All @@ -599,8 +600,35 @@ class TestPool {
if (rc != 0)
throw std::system_error(errno, std::system_category(),
"Cannot truncate vdev file");
}

std::string m_path;
};

/*
* Class simplifying test zfs pool creation and creation of zvols on it.
* Automatic pool destruction takes place when object goes out of scope.
*/
class TestPool {
public:
TestPool(std::string poolname) {
m_name = poolname;
m_vdev = new Vdev(std::string("disk-for-") + poolname);
}

~TestPool() {
//try {
execCmd("zpool", std::string("destroy -f ") + m_name);
//} catch (std::runtime_error re) {
//;
//}
delete m_vdev;
}

void create() {
m_vdev->create();
execCmd("zpool", std::string("create ") + m_name + " " +
m_path);
m_vdev->m_path);
}

void import() {
Expand All @@ -621,8 +649,8 @@ class TestPool {
return (m_name + "/" + name);
}

Vdev *m_vdev;
std::string m_name;
std::string m_path;
};

class ZreplHandshakeTest : public testing::Test {
Expand Down Expand Up @@ -1338,7 +1366,6 @@ class ZreplBlockSizeTest : public testing::Test {
protected:
/*
* Shared setup hook for all zrepl block size tests - called just once.
* Creates a zvol with 4k block size.
*/
static void SetUpTestCase() {
zvol_io_hdr_t hdr_out, hdr_in;
Expand Down Expand Up @@ -1434,3 +1461,61 @@ TEST_F(ZreplBlockSizeTest, SetDifferentMetaBlockSizes) {
do_data_connection(m_data_fd, m_host, m_port, m_zvol_name, 512, 120,
ZVOL_OP_STATUS_FAILED);
}

/*
* Test disk replacement
*/
TEST(DiskReplaceTest, SpareReplacement) {
Zrepl zrepl;
Target target;
int rc, data_fd, control_fd;
std::string host;
uint16_t port;
int ioseq;
Vdev vdev2("vdev2");
Vdev spare("spare");
TestPool pool("rplcpool");

zrepl.start();
vdev2.create();
spare.create();
pool.create();
pool.createZvol("vol", "-o io.openebs:targetip=127.0.0.1");

rc = target.listen();
ASSERT_GE(rc, 0);
control_fd = target.accept(-1);
ASSERT_GE(control_fd, 0);
do_handshake(pool.getZvolName("vol"), host, port, NULL, control_fd,
ZVOL_OP_STATUS_OK);
do_data_connection(data_fd, host, port, pool.getZvolName("vol"));
write_data_and_verify_resp(data_fd, ioseq, 0, 10);

// construct mirrored pool with a spare
execCmd("zpool", std::string("attach ") + pool.m_name + " " +
pool.m_vdev->m_path + " " + vdev2.m_path);
write_data_and_verify_resp(data_fd, ioseq, 0, 10);
execCmd("zpool", std::string("add ") + pool.m_name + " spare " +
spare.m_path);
write_data_and_verify_resp(data_fd, ioseq, 0, 10);
ASSERT_STREQ(getPoolState(pool.m_name).c_str(), "ONLINE");

// fail one of the disks in the mirror
execCmd("zpool", std::string("offline ") + pool.m_name + " " +
vdev2.m_path);
write_data_and_verify_resp(data_fd, ioseq, 0, 10);
ASSERT_STREQ(getPoolState(pool.m_name).c_str(), "DEGRADED");

// replace failed disk by the spare and remove it from mirror
execCmd("zpool", std::string("replace ") + pool.m_name + " " +
vdev2.m_path + " " + spare.m_path);
write_data_and_verify_resp(data_fd, ioseq, 0, 10);
execCmd("zpool", std::string("detach ") + pool.m_name + " " +
vdev2.m_path);
ASSERT_STREQ(getPoolState(pool.m_name).c_str(), "ONLINE");

//std::cout << execCmd("zpool", std::string("status ") + pool.m_name);

graceful_close(data_fd);
graceful_close(control_fd);
}

0 comments on commit dd0383e

Please sign in to comment.