zvol_os: Keep better track of open count in close

zvol_geom_close gets a count of the number of close operations to do.

Make sure we're always using this count to check if this will be the
last close operation performed on the zvol.

Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Matt Macy <mmacy@FreeBSD.org>
Signed-off-by: Ryan Moeller <ryan@iXsystems.com>
Closes #11117
This commit is contained in:
Ryan Moeller 2020-10-21 17:46:48 +00:00 committed by Brian Behlendorf
parent 00a27515f0
commit ef525e0841
1 changed files with 6 additions and 4 deletions

View File

@ -332,6 +332,7 @@ zvol_geom_close(struct g_provider *pp, int flag, int count)
{ {
zvol_state_t *zv; zvol_state_t *zv;
boolean_t drop_suspend = B_TRUE; boolean_t drop_suspend = B_TRUE;
int new_open_count;
rw_enter(&zvol_state_lock, ZVOL_RW_READER); rw_enter(&zvol_state_lock, ZVOL_RW_READER);
zv = pp->private; zv = pp->private;
@ -359,13 +360,15 @@ zvol_geom_close(struct g_provider *pp, int flag, int count)
* (hold zv_suspend_lock) and respect proper lock acquisition * (hold zv_suspend_lock) and respect proper lock acquisition
* ordering - zv_suspend_lock before zv_state_lock * ordering - zv_suspend_lock before zv_state_lock
*/ */
if ((zv->zv_open_count - count) == 0) { new_open_count = zv->zv_open_count - count;
if (new_open_count == 0) {
if (!rw_tryenter(&zv->zv_suspend_lock, ZVOL_RW_READER)) { if (!rw_tryenter(&zv->zv_suspend_lock, ZVOL_RW_READER)) {
mutex_exit(&zv->zv_state_lock); mutex_exit(&zv->zv_state_lock);
rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER); rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER);
mutex_enter(&zv->zv_state_lock); mutex_enter(&zv->zv_state_lock);
/* check to see if zv_suspend_lock is needed */ /* check to see if zv_suspend_lock is needed */
if (zv->zv_open_count != 1) { new_open_count = zv->zv_open_count - count;
if (new_open_count != 0) {
rw_exit(&zv->zv_suspend_lock); rw_exit(&zv->zv_suspend_lock);
drop_suspend = B_FALSE; drop_suspend = B_FALSE;
} }
@ -380,8 +383,7 @@ zvol_geom_close(struct g_provider *pp, int flag, int count)
/* /*
* You may get multiple opens, but only one close. * You may get multiple opens, but only one close.
*/ */
zv->zv_open_count -= count; zv->zv_open_count = new_open_count;
if (zv->zv_open_count == 0) { if (zv->zv_open_count == 0) {
ASSERT(ZVOL_RW_READ_HELD(&zv->zv_suspend_lock)); ASSERT(ZVOL_RW_READ_HELD(&zv->zv_suspend_lock));
zvol_last_close(zv); zvol_last_close(zv);