summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorab-oe <[email protected]>2016-02-26 08:33:44 +0100
committerBrian Behlendorf <[email protected]>2016-02-29 09:07:27 -0800
commit513168abd267f84ebcb688b4e1d42a2abd4fedce (patch)
treee06741f3535e627968c944fe2c84dc7295e68608
parent9f500936c82137ef3a57c53013894f622dcec14e (diff)
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 <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #4116
-rw-r--r--module/zfs/zvol.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
index c90e4ec6b..034cf6a6a 100644
--- a/module/zfs/zvol.c
+++ b/module/zfs/zvol.c
@@ -276,6 +276,7 @@ zvol_update_volsize(uint64_t volsize, objset_t *os)
{
dmu_tx_t *tx;
int error;
+ uint64_t txg;
ASSERT(MUTEX_HELD(&zvol_state_lock));
@@ -287,11 +288,14 @@ zvol_update_volsize(uint64_t volsize, objset_t *os)
dmu_tx_abort(tx);
return (SET_ERROR(error));
}
+ txg = dmu_tx_get_txg(tx);
error = zap_update(os, ZVOL_ZAP_OBJ, "size", 8, 1,
&volsize, tx);
dmu_tx_commit(tx);
+ txg_wait_synced(dmu_objset_pool(os), txg);
+
if (error == 0)
error = dmu_free_long_range(os,
ZVOL_OBJ, volsize, DMU_OBJECT_END);