Skip to content

Commit

Permalink
open and close leaf vdevs when the provider changes
Browse files Browse the repository at this point in the history
this prevents writing to Z.I.A. vdevs that point to old providers since vdev open/close is not normally called
  • Loading branch information
calccrypto committed Mar 18, 2024
1 parent b025b3e commit cde5e7f
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 8 deletions.
1 change: 1 addition & 0 deletions include/sys/vdev_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ typedef struct vdev_file {

extern void vdev_file_init(void);
extern void vdev_file_fini(void);
extern mode_t vdev_file_open_mode(spa_mode_t spa_mode);

#ifdef __cplusplus
}
Expand Down
4 changes: 2 additions & 2 deletions include/sys/zia.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ void zia_prop_warn(boolean_t val, const char *name);
int zia_init(void);
int zia_fini(void);

void *zia_get_provider(const char *name);
void *zia_get_provider(const char *name, vdev_t *vdev);
const char *zia_get_provider_name(void *provider);
int zia_put_provider(void **provider);
int zia_put_provider(void **provider, vdev_t *vdev);

/*
* turn off offloading for this zio as well as
Expand Down
2 changes: 1 addition & 1 deletion module/os/linux/zfs/vdev_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ vdev_file_rele(vdev_t *vd)
ASSERT(vd->vdev_path != NULL);
}

static mode_t
mode_t
vdev_file_open_mode(spa_mode_t spa_mode)
{
mode_t mode = 0;
Expand Down
9 changes: 6 additions & 3 deletions module/zfs/spa.c
Original file line number Diff line number Diff line change
Expand Up @@ -2194,7 +2194,8 @@ spa_unload(spa_t *spa)
spa->spa_raidz_expand = NULL;

if (zia_get_props(spa)->provider != NULL) {
zia_put_provider(&zia_get_props(spa)->provider);
zia_put_provider(&zia_get_props(spa)->provider,
spa->spa_root_vdev);
}

spa_config_exit(spa, SCL_ALL, spa);
Expand Down Expand Up @@ -9498,8 +9499,10 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
case ZPOOL_PROP_ZIA_PROVIDER:
strval = fnvpair_value_string(elem);
if (zia_props->provider != NULL)
zia_put_provider(&zia_props->provider);
zia_props->provider = zia_get_provider(strval);
zia_put_provider(&zia_props->provider,
spa->spa_root_vdev);
zia_props->provider = zia_get_provider(strval,
spa->spa_root_vdev);
zia_props->can_offload = !!zia_props->provider;

/*
Expand Down
74 changes: 72 additions & 2 deletions module/zfs/zia.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include <sys/spa_impl.h>
#include <sys/vdev_impl.h>
#include <sys/vdev_disk.h>
#include <sys/vdev_file.h>
#include <sys/vdev_raidz_impl.h>
#include <sys/zia.h>
#include <sys/zia_cddl.h>
Expand Down Expand Up @@ -289,8 +290,39 @@ zia_fini(void)
return (ZIA_OK);
}

#ifdef ZIA
/* recursively find all leaf vdevs and open them */
static void zia_open_vdevs(vdev_t *vd) {
vdev_ops_t *ops = vd->vdev_ops;
if (ops->vdev_op_leaf) {
ASSERT(!vd->vdev_zia_handle);

const size_t len = strlen(ops->vdev_op_type);
if (len == 4) {
if (memcmp(ops->vdev_op_type, "file", 4) == 0) {
zia_file_open(vd, vd->vdev_path,
vdev_file_open_mode(spa_mode(vd->vdev_spa)),
0);
}
#ifdef _KERNEL
else if (memcmp(ops->vdev_op_type, "disk", 4) == 0) {
/* first member is struct block_device * */
void *disk = vd->vdev_tsd;
zia_disk_open(vd, vd->vdev_path, disk);
}
#endif
}
} else {
for (uint64_t i = 0; i < vd->vdev_children; i++) {
vdev_t *child = vd->vdev_child[i];
zia_open_vdevs(child);
}
}
}
#endif

void *
zia_get_provider(const char *name)
zia_get_provider(const char *name, vdev_t *vdev)
{
#ifdef ZIA
if (!dpusm) {
Expand All @@ -303,6 +335,11 @@ zia_get_provider(const char *name)
printk("Z.I.A. obtained handle to provider \"%s\" (%p)",
name, provider);
#endif

/* set up Z.I.A. for existing vdevs */
if (vdev) {
zia_open_vdevs(vdev);
}
return (provider);
#else
(void) name; (void) vdev;
Expand All @@ -324,14 +361,47 @@ zia_get_provider_name(void *provider)
#endif
}

#ifdef ZIA
/* recursively find all leaf vdevs and close them */
static void zia_close_vdevs(vdev_t *vd) {
vdev_ops_t *ops = vd->vdev_ops;
if (ops->vdev_op_leaf) {
const size_t len = strlen(ops->vdev_op_type);
if (len == 4) {
if (memcmp(ops->vdev_op_type, "file", 4) == 0) {
zia_file_close(vd);
}
#ifdef _KERNEL
else if (memcmp(ops->vdev_op_type, "disk", 4) == 0) {
zia_disk_close(vd);
}
#endif
}
} else {
for (uint64_t i = 0; i < vd->vdev_children; i++) {
vdev_t *child = vd->vdev_child[i];
zia_close_vdevs(child);
}
}
}
#endif

int
zia_put_provider(void **provider)
zia_put_provider(void **provider, vdev_t *vdev)
{
#ifdef ZIA
if (!dpusm || !provider || !*provider) {
return (ZIA_FALLBACK);
}

/*
* if the zpool is not going down, but the provider is going away,
* make sure the vdevs don't keep pointing to the invalid provider
*/
if (vdev) {
zia_close_vdevs(vdev);
}

#ifdef _KERNEL
const char *name = zia_get_provider_name(*provider);
#endif
Expand Down

0 comments on commit cde5e7f

Please sign in to comment.