aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPaul Dagnelie <[email protected]>2019-08-13 20:24:43 -0700
committerBrian Behlendorf <[email protected]>2019-08-13 21:24:43 -0600
commitdc04a8c757d7df91efbca05491174112540f6e7a (patch)
treea7f13ef90ddddd8c64e5af6f0ac9a4470ec4c27e /include
parent8e556c5ebc7b66caf2cdcc561b6644f9f8437a6d (diff)
Prevent race in blkptr_verify against device removal
When we check the vdev of the blkptr in zfs_blkptr_verify, we can run into a race condition where that vdev is temporarily unavailable. This happens when a device removal operation and the old vdev_t has been removed from the array, but the new indirect vdev has not yet been inserted. We hold the spa_config_lock while doing our sensitive verification. To ensure that we don't deadlock, we only grab the lock if we don't have config_writer held. In addition, I had to const the tags of the refcounts and the spa_config_lock arguments. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Serapheim Dimitropoulos <[email protected]> Signed-off-by: Paul Dagnelie <[email protected]> Closes #9112
Diffstat (limited to 'include')
-rw-r--r--include/sys/refcount.h19
-rw-r--r--include/sys/spa.h5
2 files changed, 12 insertions, 12 deletions
diff --git a/include/sys/refcount.h b/include/sys/refcount.h
index e982faeba..c8f586230 100644
--- a/include/sys/refcount.h
+++ b/include/sys/refcount.h
@@ -44,7 +44,7 @@ extern "C" {
#ifdef ZFS_DEBUG
typedef struct reference {
list_node_t ref_link;
- void *ref_holder;
+ const void *ref_holder;
uint64_t ref_number;
uint8_t *ref_removed;
} reference_t;
@@ -70,16 +70,17 @@ void zfs_refcount_destroy(zfs_refcount_t *);
void zfs_refcount_destroy_many(zfs_refcount_t *, uint64_t);
int zfs_refcount_is_zero(zfs_refcount_t *);
int64_t zfs_refcount_count(zfs_refcount_t *);
-int64_t zfs_refcount_add(zfs_refcount_t *, void *);
-int64_t zfs_refcount_remove(zfs_refcount_t *, void *);
-int64_t zfs_refcount_add_many(zfs_refcount_t *, uint64_t, void *);
-int64_t zfs_refcount_remove_many(zfs_refcount_t *, uint64_t, void *);
+int64_t zfs_refcount_add(zfs_refcount_t *, const void *);
+int64_t zfs_refcount_remove(zfs_refcount_t *, const void *);
+int64_t zfs_refcount_add_many(zfs_refcount_t *, uint64_t, const void *);
+int64_t zfs_refcount_remove_many(zfs_refcount_t *, uint64_t, const void *);
void zfs_refcount_transfer(zfs_refcount_t *, zfs_refcount_t *);
-void zfs_refcount_transfer_ownership(zfs_refcount_t *, void *, void *);
+void zfs_refcount_transfer_ownership(zfs_refcount_t *, const void *,
+ const void *);
void zfs_refcount_transfer_ownership_many(zfs_refcount_t *, uint64_t,
- void *, void *);
-boolean_t zfs_refcount_held(zfs_refcount_t *, void *);
-boolean_t zfs_refcount_not_held(zfs_refcount_t *, void *);
+ const void *, const void *);
+boolean_t zfs_refcount_held(zfs_refcount_t *, const void *);
+boolean_t zfs_refcount_not_held(zfs_refcount_t *, const void *);
void zfs_refcount_init(void);
void zfs_refcount_fini(void);
diff --git a/include/sys/spa.h b/include/sys/spa.h
index e64313783..494326843 100644
--- a/include/sys/spa.h
+++ b/include/sys/spa.h
@@ -1007,8 +1007,8 @@ extern int spa_import_progress_set_state(uint64_t pool_guid,
/* Pool configuration locks */
extern int spa_config_tryenter(spa_t *spa, int locks, void *tag, krw_t rw);
-extern void spa_config_enter(spa_t *spa, int locks, void *tag, krw_t rw);
-extern void spa_config_exit(spa_t *spa, int locks, void *tag);
+extern void spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw);
+extern void spa_config_exit(spa_t *spa, int locks, const void *tag);
extern int spa_config_held(spa_t *spa, int locks, krw_t rw);
/* Pool vdev add/remove lock */
@@ -1123,7 +1123,6 @@ extern boolean_t spa_has_checkpoint(spa_t *spa);
extern boolean_t spa_importing_readonly_checkpoint(spa_t *spa);
extern boolean_t spa_suspend_async_destroy(spa_t *spa);
extern uint64_t spa_min_claim_txg(spa_t *spa);
-extern void zfs_blkptr_verify(spa_t *spa, const blkptr_t *bp);
extern boolean_t zfs_dva_valid(spa_t *spa, const dva_t *dva,
const blkptr_t *bp);
typedef void (*spa_remap_cb_t)(uint64_t vdev, uint64_t offset, uint64_t size,