kern/182570: ZFS panic in receive

Keith White kwhite at site.uottawa.ca
Wed Oct 2 11:50:04 UTC 2013


>Number:         182570
>Category:       kern
>Synopsis:       ZFS panic in receive
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Oct 02 11:50:03 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Keith White
>Release:        current
>Organization:
EECS, University of Ottawa
>Environment:
FreeBSD freebsd10 10.0-ALPHA4 FreeBSD 10.0-ALPHA4 #0 r255937: Sun Sep 29 09:45:21 EDT 2013     kwhite at freebsd10:/usr/obj/usr/src/sys/GENERIC  amd64
>Description:
[previously sent to freebsd-current]

I get the following reproducible panic when doing a zfs send -R | zfs recv
of a well churned file system (snapshots of the ports tree before and
after libiconv update) running a recent current:

panic: solaris assert: dn->dn_maxblkid == 0 &&
(BP_IS_HOLE(&dn->dn_phys->dn_blkptr[0]) || dnode_block_freed(dn, 0)),
file:
/usr/src/sys/modules/zfs/../../cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c,
line: 598

coredump available.


# zfs list -t snapshot -r tank/ports
NAME                  USED  AVAIL  REFER  MOUNTPOINT
tank/ports at 20130915  72.5M      -  3.64G  -
tank/ports at 20130917      0      -  3.65G  -
tank/ports at 20130918      0      -  3.65G  -
tank/ports at 20130921  88.6M      -  3.66G  -
tank/ports at 20130928   352K      -  3.66G  -

# zpool list -v
NAME             SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
m_tank          1.81T   831G  1.00T    44%  1.00x  ONLINE  -
  ada4.nop.eli  1.81T   831G  1.00T         -
tank             928G   831G  96.9G    89%  1.00x  ONLINE  -
  ada3.nop.eli   928G   831G  96.9G         -

# zfs send -vR tank/ports at 20130928 | zfs recv -vF m_tank/xports
.. panic eventually ...

# cd /boot/kernel; kgdb kernel /var/crash/vmcore.last
..
(kgdb) up
#5  0xffffffff81d09735 in dnode_reallocate (dn=0xfffff8006dde3000,
ot=DMU_OT_PLAIN_FILE_CONTENTS, blocksize=1024, bonustype=DMU_OT_SA,
bonuslen=168, tx=0xfffff8006d7a2600)
    at
/usr/src/sys/modules/zfs/../../cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c:596


596                     ASSERT(dn->dn_maxblkid == 0 &&

(kgdb) p dn->dn_maxblkid
$1 = 2

So, no question about why the ASSERT failed.

Sorry, debugging this is *way* beyond me.  Any hints, patches to try?


>How-To-Repeat:
on a zpool called "tank" with non-existent tank/nobj and tank/xobj:

#!/bin/sh

zfs create tank/nobj
zfs snapshot tank/nobj at 0
__MAKECONF=/dev/null SRCCONF=/dev/null MAKEOBJDIRPREFIX=/tank/nobj make -j6 buildkernel
zfs snapshot tank/nobj at 1
find /tank/nobj -name '.h' -print | xargs rm
zfs snapshot tank/nobj at 2
rm -rf /tank/nobj/*
zfs snapshot tank/nobj at 3
__MAKECONF=/dev/null SRCCONF=/dev/null MAKEOBJDIRPREFIX=/tank/nobj make -j6 buildkernel
zfs snapshot tank/nobj at 4
rm -rf /tank/nobj/*
zfs snapshot tank/nobj at 5

zfs send -vR tank/nobj at 5 | zfs recv -vF tank/xobj

>Fix:
This will just avoid the panic, the received filesystem is not complete.  The "zfs recv" now terminates with "internal error: File too large":


Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c      (revision 255986)
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c      (working copy)
@@ -592,10 +592,16 @@
        rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
        dnode_setdirty(dn, tx);
        if (dn->dn_datablksz != blocksize) {
+#if 1
+               if (dn->dn_maxblkid != 0) {
+                       printf("ZFS should panic here since dn->dn_maxblkid is %lu instead of 0\n...but we'll continue\n", dn->dn_maxblkid);
+               }
+#else
                /* change blocksize */
                ASSERT(dn->dn_maxblkid == 0 &&
                    (BP_IS_HOLE(&dn->dn_phys->dn_blkptr[0]) ||
                    dnode_block_freed(dn, 0)));
+#endif
                dnode_setdblksz(dn, blocksize);
                dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = blocksize;
        }


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list