aboutsummaryrefslogtreecommitdiffstats
path: root/include/sys
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2022-01-04 16:46:32 -0800
committerGitHub <[email protected]>2022-01-04 16:46:32 -0800
commit3c80e0742a8fa012d5f2048e362a6235f8ec2304 (patch)
tree33aab52e98af6c3bb12f220911cae407de3bd03a /include/sys
parent1135d0a5fff42ab9a79a1117faa8481d55976a1e (diff)
Verify dRAID empty sectors
Verify that all empty sectors are zero filled before using them to calculate parity. Failure to do so can result in incorrect parity columns being generated and written to disk if the contents of an empty sector are non-zero. This was possible because the checksum only protects the data portions of the buffer, not the empty sector padding. This issue has been addressed by updating raidz_parity_verify() to check that all dRAID empty sectors are zero filled. Any sectors which are non-zero will be fixed, repair IO issued, and a checksum error logged. They can then be safely used to verify the parity. This specific type of damage is unlikely to occur since it requires a disk to have silently returned bad data, for an empty sector, while performing a scrub. However, if a pool were to have been damaged in this way, scrubbing the pool with this change applied will repair both the empty sector and parity columns as long as the data checksum is valid. Checksum errors will be reported in the `zpool status` output for any repairs which are made. Reviewed-by: Tony Hutter <[email protected]> Reviewed-by: Mark Maybee <[email protected]> Reviewed-by: Brian Atkinson <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #12857
Diffstat (limited to 'include/sys')
-rw-r--r--include/sys/vdev_draid.h1
-rw-r--r--include/sys/vdev_raidz.h2
2 files changed, 3 insertions, 0 deletions
diff --git a/include/sys/vdev_draid.h b/include/sys/vdev_draid.h
index 52ce4ba16..dd334acba 100644
--- a/include/sys/vdev_draid.h
+++ b/include/sys/vdev_draid.h
@@ -96,6 +96,7 @@ extern boolean_t vdev_draid_readable(vdev_t *, uint64_t);
extern boolean_t vdev_draid_missing(vdev_t *, uint64_t, uint64_t, uint64_t);
extern uint64_t vdev_draid_asize_to_psize(vdev_t *, uint64_t);
extern void vdev_draid_map_alloc_empty(zio_t *, struct raidz_row *);
+extern int vdev_draid_map_verify_empty(zio_t *, struct raidz_row *);
extern nvlist_t *vdev_draid_read_config_spare(vdev_t *);
/* Functions for dRAID distributed spares. */
diff --git a/include/sys/vdev_raidz.h b/include/sys/vdev_raidz.h
index ee597eb0d..c7cf0af6d 100644
--- a/include/sys/vdev_raidz.h
+++ b/include/sys/vdev_raidz.h
@@ -32,6 +32,7 @@ extern "C" {
#endif
struct zio;
+struct raidz_col;
struct raidz_row;
struct raidz_map;
#if !defined(_KERNEL)
@@ -49,6 +50,7 @@ void vdev_raidz_generate_parity(struct raidz_map *);
void vdev_raidz_reconstruct(struct raidz_map *, const int *, int);
void vdev_raidz_child_done(zio_t *);
void vdev_raidz_io_done(zio_t *);
+void vdev_raidz_checksum_error(zio_t *, struct raidz_col *, abd_t *);
extern const zio_vsd_ops_t vdev_raidz_vsd_ops;