Fix zvol_state_t->zv_open_count race
authorLOLi <loli10K@users.noreply.github.com>
Thu, 15 Jun 2017 18:08:45 +0000 (20:08 +0200)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 15 Jun 2017 18:08:45 +0000 (11:08 -0700)
commit97f8d7961e0b6e282f5296c20d5af9746c9db688
treed918cc250518319a419942c159fa784e02bc6af7
parent627791f3c0f27322d7d5dd99630f03759278d824
Fix zvol_state_t->zv_open_count race

5559ba0 added zv_state_lock to protect zvol_state_t internal data:
this, however, doesn't guard zv->zv_open_count and
zv->zv_disk->private_data in zvol_remove_minors_impl().

Fix this by taking zv->zv_state_lock before we check its zv_open_count.

P1 (z_zvol)                       P2 (systemd-udevd)
---                               ---
zvol_remove_minors_impl()
: zv->zv_open_count==0
                                  zvol_open()
                                  ->mutex_enter(zv_state_lock)
                                  : zv->zv_open_count++
                                  ->mutex_exit(zv_state_lock)
->mutex_enter(zv->zv_state_lock)
->zvol_remove(zv)
->mutex_exit(zv->zv_state_lock)
: zv->zv_disk->private_data = NULL
->zvol_free()
-->ASSERT(zv->zv_open_count==0) *
                                  zvol_release()
                                  : zv = disk->private_data
                                  ->ASSERT(zv && zv->zv_open_count>0) *
---                               ---
* ASSERT() fails

Reviewed by: Boris Protopopov <bprotopopov@hotmail.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov
Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
Closes #6213
module/zfs/zvol.c