]> granicus.if.org Git - zfs/commitdiff
Make zvol update volsize operation synchronous.
authorab-oe <arkadiusz.bubala@open-e.com>
Fri, 26 Feb 2016 07:33:44 +0000 (08:33 +0100)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 29 Feb 2016 17:07:27 +0000 (09:07 -0800)
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

module/zfs/zvol.c

index c90e4ec6b97905f9d557683e4973acdf946b6018..034cf6a6a95d3720e1560ba457781bfc4c978f7a 100644 (file)
@@ -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);