Panic in ZFS layer on 8.1-STABLE
Dan Nelson
dnelson at allantgroup.com
Wed Dec 15 23:08:16 UTC 2010
In the last episode (Dec 15), Andriy Gapon said:
> on 15/12/2010 10:28 Jeremie Le Hen said the following:
> > Hi,
> >
> > [ Please Cc: me when replying, as I'm not subscribed to -stable at . ]
> >
> > My filer at home runs FreeBSD. A single data RAID-1 zpool with 10~15
> > datasets, two of them using compression. Over the night, I got the
> > following panic:
>
> Thanks for the stack trace!
> But where is the promised panic message? :)
>
> I suspect that you ran out of kernel address space.
> You'd probably have to tune your system and/or add more memory.
> Please research this topic via mailing lists archives.
>
> > Tracing pid 0 tid 100111 td 0x86393a00
> > kdb_enter(809faa5b,809faa5b,80a12e84,cb114aec,0,...) at kdb_enter+0x3a
> > panic(80a12e84,1c000,2e3e8000,80a12e7e,7d0,...) at panic+0x131
> > kmem_malloc(8169008c,1c000,2,cb114b6c,80909a99,...) at kmem_malloc+0x285
> > page_alloc(0,1c000,cb114b5f,2,2f0c800,...) at page_alloc+0x27
> > uma_large_malloc(1c000,2,0,8609b3f0,30,...) at uma_large_malloc+0x4a
> > malloc(1c000,860b2120,2,cb114bb0,8601d36d,...) at malloc+0x7c
> > zfs_kmem_alloc(1c000,2,cb114bf0,8601f77b,1c000,...) at
> > zfs_kmem_alloc+0x20
> > zio_buf_alloc(1c000,cb114c30,86008817,92c33bd0,cb114bf0,...) at
> > zio_buf_alloc+0x44
> > zio_compress_data(3,b4264000,20000,0,cb114c58,...) at
> > zio_compress_data+0x8b
The following patch may help you. It helps me :) It converts the
zio_buf_alloc() call into a zio_buf_alloc_nowait(), so that if the alloc
fails, zio_compress_data() returns failure and zfs writes the block
uncompressed instead of panicing.
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c (revision 216418)
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c (working copy)
@@ -202,6 +202,20 @@ zio_buf_alloc(size_t size)
return (kmem_alloc(size, KM_SLEEP));
}
+void *
+zio_buf_alloc_nowait(size_t size)
+{
+#ifdef ZIO_USE_UMA
+ size_t c = (size - 1) >> SPA_MINBLOCKSHIFT;
+
+ ASSERT(c < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT);
+
+ return (kmem_cache_alloc(zio_buf_cache[c], KM_NOSLEEP));
+#else
+ return (kmem_alloc(size, KM_NOSLEEP));
+#endif
+}
+
/*
* Use zio_data_buf_alloc to allocate data. The data will not appear in a
* crashdump if the kernel panics. This exists so that we will limit the amount
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_compress.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_compress.c (revision 216418)
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_compress.c (working copy)
@@ -32,6 +32,12 @@
#include <sys/zio.h>
#include <sys/zio_compress.h>
+int panics_avoided_by_not_compressing = 0;
+SYSCTL_DECL(_vfs_zfs);
+SYSCTL_INT(_vfs_zfs, OID_AUTO, compression_panics_avoided, CTLFLAG_RD,
+ &panics_avoided_by_not_compressing, 0,
+ "kmem_map panics avoided by skipping compression when memory is low");
+
/*
* Compression vectors.
*/
@@ -109,7 +115,17 @@ zio_compress_data(int cpfunc, void *src, uint64_t
destbufsize = P2ALIGN(srcsize - (srcsize >> 3), SPA_MINBLOCKSIZE);
if (destbufsize == 0)
return (0);
+
+#if 1
+ dest = zio_buf_alloc_nowait(destbufsize);
+ if (dest == 0)
+ {
+ panics_avoided_by_not_compressing++;
+ return (0);
+ }
+#else
dest = zio_buf_alloc(destbufsize);
+#endif
ciosize = ci->ci_compress(src, dest, (size_t)srcsize,
(size_t)destbufsize, ci->ci_level);
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h (revision 216418)
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h (working copy)
@@ -398,6 +398,7 @@ extern zio_t *zio_unique_parent(zio_t *cio);
extern void zio_add_child(zio_t *pio, zio_t *cio);
extern void *zio_buf_alloc(size_t size);
+extern void *zio_buf_alloc_nowait(size_t size);
extern void zio_buf_free(void *buf, size_t size);
extern void *zio_data_buf_alloc(size_t size);
extern void zio_data_buf_free(void *buf, size_t size);
--
Dan Nelson
dnelson at allantgroup.com
More information about the freebsd-stable
mailing list