mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-26 12:12:13 +03:00
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 <behlendorf1@llnl.gov> Reviewed-by: Serapheim Dimitropoulos <serapheim@delphix.com> Signed-off-by: Paul Dagnelie <pcd@delphix.com> Closes #9112
This commit is contained in:
committed by
Brian Behlendorf
parent
8e556c5ebc
commit
dc04a8c757
+10
-9
@@ -121,7 +121,7 @@ zfs_refcount_count(zfs_refcount_t *rc)
|
||||
}
|
||||
|
||||
int64_t
|
||||
zfs_refcount_add_many(zfs_refcount_t *rc, uint64_t number, void *holder)
|
||||
zfs_refcount_add_many(zfs_refcount_t *rc, uint64_t number, const void *holder)
|
||||
{
|
||||
reference_t *ref = NULL;
|
||||
int64_t count;
|
||||
@@ -143,13 +143,14 @@ zfs_refcount_add_many(zfs_refcount_t *rc, uint64_t number, void *holder)
|
||||
}
|
||||
|
||||
int64_t
|
||||
zfs_refcount_add(zfs_refcount_t *rc, void *holder)
|
||||
zfs_refcount_add(zfs_refcount_t *rc, const void *holder)
|
||||
{
|
||||
return (zfs_refcount_add_many(rc, 1, holder));
|
||||
}
|
||||
|
||||
int64_t
|
||||
zfs_refcount_remove_many(zfs_refcount_t *rc, uint64_t number, void *holder)
|
||||
zfs_refcount_remove_many(zfs_refcount_t *rc, uint64_t number,
|
||||
const void *holder)
|
||||
{
|
||||
reference_t *ref;
|
||||
int64_t count;
|
||||
@@ -197,7 +198,7 @@ zfs_refcount_remove_many(zfs_refcount_t *rc, uint64_t number, void *holder)
|
||||
}
|
||||
|
||||
int64_t
|
||||
zfs_refcount_remove(zfs_refcount_t *rc, void *holder)
|
||||
zfs_refcount_remove(zfs_refcount_t *rc, const void *holder)
|
||||
{
|
||||
return (zfs_refcount_remove_many(rc, 1, holder));
|
||||
}
|
||||
@@ -235,7 +236,7 @@ zfs_refcount_transfer(zfs_refcount_t *dst, zfs_refcount_t *src)
|
||||
|
||||
void
|
||||
zfs_refcount_transfer_ownership_many(zfs_refcount_t *rc, uint64_t number,
|
||||
void *current_holder, void *new_holder)
|
||||
const void *current_holder, const void *new_holder)
|
||||
{
|
||||
reference_t *ref;
|
||||
boolean_t found = B_FALSE;
|
||||
@@ -260,8 +261,8 @@ zfs_refcount_transfer_ownership_many(zfs_refcount_t *rc, uint64_t number,
|
||||
}
|
||||
|
||||
void
|
||||
zfs_refcount_transfer_ownership(zfs_refcount_t *rc, void *current_holder,
|
||||
void *new_holder)
|
||||
zfs_refcount_transfer_ownership(zfs_refcount_t *rc, const void *current_holder,
|
||||
const void *new_holder)
|
||||
{
|
||||
return (zfs_refcount_transfer_ownership_many(rc, 1, current_holder,
|
||||
new_holder));
|
||||
@@ -273,7 +274,7 @@ zfs_refcount_transfer_ownership(zfs_refcount_t *rc, void *current_holder,
|
||||
* might be held.
|
||||
*/
|
||||
boolean_t
|
||||
zfs_refcount_held(zfs_refcount_t *rc, void *holder)
|
||||
zfs_refcount_held(zfs_refcount_t *rc, const void *holder)
|
||||
{
|
||||
reference_t *ref;
|
||||
|
||||
@@ -301,7 +302,7 @@ zfs_refcount_held(zfs_refcount_t *rc, void *holder)
|
||||
* since the reference might not be held.
|
||||
*/
|
||||
boolean_t
|
||||
zfs_refcount_not_held(zfs_refcount_t *rc, void *holder)
|
||||
zfs_refcount_not_held(zfs_refcount_t *rc, const void *holder)
|
||||
{
|
||||
reference_t *ref;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user