fix deadlock-prone code in getzfsvfs()
authoravg <avg@FreeBSD.org>
Thu, 23 Jun 2016 07:01:54 +0000 (07:01 +0000)
committeravg <avg@FreeBSD.org>
Thu, 23 Jun 2016 07:01:54 +0000 (07:01 +0000)
commit6efa34305bb5e56714c708e0ea703023b0c8cfd1
treea0d8dd9bd34c8447871bf78044c098510f444a5c
parentdb5b889e7a94fff893bfa972be9e32514b42f2a2
fix deadlock-prone code in getzfsvfs()

getzfsvfs() called vfs_busy() in the waiting mode while having a hold on
a pool (via a call to dmu_objset_hold).  In other words,
dp_config_rwlock was held in the shared mode while a thread could be
sleeping in vfs_busy().
The pool's txg sync thread needs to take dp_config_rwlock in the
exclusive mode for some actions, e.g., for executing sync tasks.  If the
sync thread gets blocked, then any thread waiting for its sync task to
get executed is also blocked.  Which, in turn, could mean that
vfs_busy() will keep waiting indefinitely.

The solution is to use vfs_ref() in the locked section and to call
vfs_busy() only after dropping other locks.
Note that a reference on a struct mount object does not prevent an
associated zfsvfs_t object from being destroyed.  So, we have to be
careful to operate only on the struct mount object until we successfully
vfs_busy it.

Approved by: re (gjb)
MFC after: 2 weeks
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c