The problem is that g_access() must be called with the GEOM topology lock held.
And that gives a false impression that the lock is indeed held across the call.
But this isn't always true because many classes, ZVOL being one of the many,
need to perform I/O on the first open. So, they must drop and pick up the
topology lock in their access method.
That, of course, can break many assumptions. Specifically, g_slice_access()
adds an extra exclusive count on the first open. As described above, an
underlying geom may drop the topology lock and that would open a race with
another thread that would also request another extra exclusive count.
The workaround is to check whether this thread won or lost the first-open race
after calling g_access(). The losing thread decrements the exclusive count.
Ideally, the race should be eliminated or accounted for in the GEOM design.
There could be other bad consequences.