Make zvol update volsize operation synchronous.

There is a race condition when new transaction group is added
to dp->dp_dirty_datasets list by the zap_update in the zvol_update_volsize.
Meanwhile, before these dirty data are synchronized, the receive process
can cause that dmu_recv_end_sync is executed. Then finally dirty data
are going to be synchronized but the synchronization ends with the NULL
pointer dereference error.

Signed-off-by: ab-oe <arkadiusz.bubala@open-e.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #4116
This commit is contained in:
ab-oe 2016-02-26 08:33:44 +01:00 committed by Brian Behlendorf
parent 9f500936c8
commit 513168abd2
1 changed files with 4 additions and 0 deletions

View File

@ -276,6 +276,7 @@ zvol_update_volsize(uint64_t volsize, objset_t *os)
{ {
dmu_tx_t *tx; dmu_tx_t *tx;
int error; int error;
uint64_t txg;
ASSERT(MUTEX_HELD(&zvol_state_lock)); ASSERT(MUTEX_HELD(&zvol_state_lock));
@ -287,11 +288,14 @@ zvol_update_volsize(uint64_t volsize, objset_t *os)
dmu_tx_abort(tx); dmu_tx_abort(tx);
return (SET_ERROR(error)); return (SET_ERROR(error));
} }
txg = dmu_tx_get_txg(tx);
error = zap_update(os, ZVOL_ZAP_OBJ, "size", 8, 1, error = zap_update(os, ZVOL_ZAP_OBJ, "size", 8, 1,
&volsize, tx); &volsize, tx);
dmu_tx_commit(tx); dmu_tx_commit(tx);
txg_wait_synced(dmu_objset_pool(os), txg);
if (error == 0) if (error == 0)
error = dmu_free_long_range(os, error = dmu_free_long_range(os,
ZVOL_OBJ, volsize, DMU_OBJECT_END); ZVOL_OBJ, volsize, DMU_OBJECT_END);