mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-17 18:11:00 +03:00
zvol_remove_minors do parallel zvol_free
On some kernel version, blk_cleanup_queue and put_disk will wait for more then 10ms. So a pool with a lot of zvols will easily wait for more then 1 min if we do zvol_free sequentially. Signed-off-by: Chunwei Chen <david.chen@osnexus.com> Requires-spl: refs/pull/588/head
This commit is contained in:
parent
7ac557cef1
commit
899662e344
@ -1036,7 +1036,7 @@ zvol_open(struct block_device *bdev, fmode_t flag)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Obtain a copy of private_data under the lock to make sure
|
* Obtain a copy of private_data under the lock to make sure
|
||||||
* that either the result of zvol_freeg() setting
|
* that either the result of zvol_free() setting
|
||||||
* bdev->bd_disk->private_data to NULL is observed, or zvol_free()
|
* bdev->bd_disk->private_data to NULL is observed, or zvol_free()
|
||||||
* is not called on this zv because of the positive zv_open_count.
|
* is not called on this zv because of the positive zv_open_count.
|
||||||
*/
|
*/
|
||||||
@ -1316,12 +1316,13 @@ out_kmem:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cleanup then free a zvol_state_t which was created by zvol_alloc().
|
* Used for taskq, if used out side zvol_state_lock, you need to clear
|
||||||
|
* zv_disk->private_data inside lock first.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
zvol_free(zvol_state_t *zv)
|
zvol_free_impl(void *arg)
|
||||||
{
|
{
|
||||||
ASSERT(MUTEX_HELD(&zvol_state_lock));
|
zvol_state_t *zv = arg;
|
||||||
ASSERT(zv->zv_open_count == 0);
|
ASSERT(zv->zv_open_count == 0);
|
||||||
|
|
||||||
zfs_rlock_destroy(&zv->zv_range_lock);
|
zfs_rlock_destroy(&zv->zv_range_lock);
|
||||||
@ -1336,6 +1337,16 @@ zvol_free(zvol_state_t *zv)
|
|||||||
kmem_free(zv, sizeof (zvol_state_t));
|
kmem_free(zv, sizeof (zvol_state_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cleanup then free a zvol_state_t which was created by zvol_alloc().
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
zvol_free(zvol_state_t *zv)
|
||||||
|
{
|
||||||
|
ASSERT(MUTEX_HELD(&zvol_state_lock));
|
||||||
|
zvol_free_impl(zv);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a block device minor node and setup the linkage between it
|
* Create a block device minor node and setup the linkage between it
|
||||||
* and the specified volume. Once this function returns the block
|
* and the specified volume. Once this function returns the block
|
||||||
@ -1691,6 +1702,7 @@ zvol_remove_minors_impl(const char *name)
|
|||||||
{
|
{
|
||||||
zvol_state_t *zv, *zv_next;
|
zvol_state_t *zv, *zv_next;
|
||||||
int namelen = ((name) ? strlen(name) : 0);
|
int namelen = ((name) ? strlen(name) : 0);
|
||||||
|
taskqid_t t, tid = TASKQID_INVALID;
|
||||||
|
|
||||||
if (zvol_inhibit_dev)
|
if (zvol_inhibit_dev)
|
||||||
return;
|
return;
|
||||||
@ -1710,11 +1722,22 @@ zvol_remove_minors_impl(const char *name)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
zvol_remove(zv);
|
zvol_remove(zv);
|
||||||
zvol_free(zv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* clear this so zvol_open won't open it */
|
||||||
|
zv->zv_disk->private_data = NULL;
|
||||||
|
|
||||||
|
/* try parallel zv_free, if failed do it in place */
|
||||||
|
t = taskq_dispatch(system_taskq, zvol_free_impl, zv,
|
||||||
|
TQ_SLEEP);
|
||||||
|
if (t == TASKQID_INVALID)
|
||||||
|
zvol_free(zv);
|
||||||
|
else
|
||||||
|
tid = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
mutex_exit(&zvol_state_lock);
|
mutex_exit(&zvol_state_lock);
|
||||||
|
if (tid != TASKQID_INVALID)
|
||||||
|
taskq_wait_outstanding(system_taskq, tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove minor for this specific snapshot only */
|
/* Remove minor for this specific snapshot only */
|
||||||
|
Loading…
Reference in New Issue
Block a user