summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2011-12-18 12:27:45 +0000
committerpjd <pjd@FreeBSD.org>2011-12-18 12:27:45 +0000
commit952e2f20b5b7f292d040b0456988f2748e4a554f (patch)
tree112af611d7225166582bdded325e13ad89fb5819 /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
parent3c1d6d15932737a320fd0860781f16898f43ef5f (diff)
downloadFreeBSD-src-952e2f20b5b7f292d040b0456988f2748e4a554f.zip
FreeBSD-src-952e2f20b5b7f292d040b0456988f2748e4a554f.tar.gz
From time to time people report space map corruption resulting in panic
(ss == NULL) on pool import. I had such a panic recently. With current version of ZFS it is still possible to import the pool in readonly mode and backup all the data, but in case it is impossible for some reason add tunable vfs.zfs.space_map_last_hope, which when set to '1' will tell ZFS to remove colliding range and retry. This seems to have worked for me, but I consider it highly risky to use. MFC after: 1 week
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
index 1ce7b2a..a8df1c7 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
@@ -29,6 +29,13 @@
#include <sys/zio.h>
#include <sys/space_map.h>
+SYSCTL_DECL(_vfs_zfs);
+static int space_map_last_hope;
+TUNABLE_INT("vfs.zfs.space_map_last_hope", &space_map_last_hope);
+SYSCTL_INT(_vfs_zfs, OID_AUTO, space_map_last_hope, CTLFLAG_RDTUN,
+ &space_map_last_hope, 0,
+ "If kernel panic in space_map code on pool import, import the pool in readonly mode and backup all your data before trying this option.");
+
/*
* Space map routines.
* NOTE: caller is responsible for all locking.
@@ -93,7 +100,7 @@ space_map_add(space_map_t *sm, uint64_t start, uint64_t size)
VERIFY(sm->sm_space + size <= sm->sm_size);
VERIFY(P2PHASE(start, 1ULL << sm->sm_shift) == 0);
VERIFY(P2PHASE(size, 1ULL << sm->sm_shift) == 0);
-
+again:
ssearch.ss_start = start;
ssearch.ss_end = end;
ss = avl_find(&sm->sm_root, &ssearch, &where);
@@ -104,6 +111,23 @@ space_map_add(space_map_t *sm, uint64_t start, uint64_t size)
(longlong_t)start, (longlong_t)size);
return;
}
+ if (ss != NULL && space_map_last_hope) {
+ uint64_t sstart, ssize;
+
+ if (ss->ss_start > start)
+ sstart = ss->ss_start;
+ else
+ sstart = start;
+ if (ss->ss_end > end)
+ ssize = end - sstart;
+ else
+ ssize = ss->ss_end - sstart;
+ ZFS_LOG(0,
+ "Removing colliding space_map range (start=%ju end=%ju). Good luck!",
+ (uintmax_t)sstart, (uintmax_t)(sstart + ssize));
+ space_map_remove(sm, sstart, ssize);
+ goto again;
+ }
/* Make sure we don't overlap with either of our neighbors */
VERIFY(ss == NULL);
OpenPOWER on IntegriCloud