aboutsummaryrefslogtreecommitdiff
path: root/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
diff options
context:
space:
mode:
authorPawel Jakub Dawidek <pjd@FreeBSD.org>2009-12-05 14:33:11 +0000
committerPawel Jakub Dawidek <pjd@FreeBSD.org>2009-12-05 14:33:11 +0000
commit6468cb2ce0b62aaa418910f11909e0d739f50e7d (patch)
tree6d0833834ed9ee6af4c611ae73a9cddb17d6dda6 /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
parentccba8269770f4960779ffd8541b95402d8210b6d (diff)
downloadsrc-6468cb2ce0b62aaa418910f11909e0d739f50e7d.tar.gz
src-6468cb2ce0b62aaa418910f11909e0d739f50e7d.zip
Fix deadlock when ZVOLs are present and we are replacing dead component or
calling scrub when pool is in a degraded state. It will try to taste ZVOLs, which will lead to deadlock, as ZVOL will try to acquire the same locks as replace/scrub is holding already. We can't simply skip provider based on their GEOM class, because ZVOL can have providers build on top of it and we need to skip those as well. We do it by asking for ZFS::iszvol attribute. Any ZVOL-based provider will give us positive answer and we have to skip those providers. This way we remove possibility to create ZFS pools on top of ZVOLs, but it is not very useful anyway. I believe deadlock is still possible in some very complex situations like when we have MD provider on top of UFS file on top of ZVOL. When we try to replace dead component in the pool mentioned ZVOL is based on, there might be a deadlock when ZFS will try to taste MD provider. There is no easy way to detect that, but it isn't very common. MFC after: 1 week
Notes
Notes: svn path=/head/; revision=200126
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
index e7440016b3c4..5cc5f37d889a 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
@@ -293,11 +293,16 @@ vdev_geom_read_guid(struct g_consumer *cp)
uint64_t psize;
off_t offset, size;
uint64_t guid;
- int l, len;
+ int error, l, len, iszvol;
g_topology_assert_not();
pp = cp->provider;
+ ZFS_LOG(1, "Reading guid from %s...", pp->name);
+ if (g_getattr("ZFS::iszvol", cp, &iszvol) == 0 && iszvol) {
+ ZFS_LOG(1, "Skipping ZVOL-based provider %s.", pp->name);
+ return (0);
+ }
psize = pp->mediasize;
psize = P2ALIGN(psize, (uint64_t)sizeof(vdev_label_t));