Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 09 Feb 2002 19:20:18 -0500 (EST)
From:      John Baldwin <jhb@FreeBSD.org>
To:        Mikhail Teterin <mi@aldan.algebra.com>
Cc:        current@FreeBSD.org
Subject:   RE: panic: bdwrite: buffer is not busy
Message-ID:  <20020212021234.8C1189F382@okeeffe.bestweb.net>

next in thread | raw e-mail | index | archive | help

On 09-Feb-02 Mikhail Teterin wrote:
> While attempting to ``fdisk fd0.1440''. Or ``fdisk fd0''. Or
> ``newfs_msdos fd0.1440'' with or without the floppy inside :-\
> With todays or Jan 3rd kernel (my previous upgrade).

Only use fdisk on hard disks.  Still it shouldn't panic.  The bdwrite is just
extra garbage, the real panic is due to a NULL pointer dereference:

> IdlePTD at phsyical address 0x004ed000
> initial pcb at physical address 0x00411560
> panicstr: bdwrite: buffer is not busy
> panic messages:
> ---
> Fatal trap 12: page fault while in kernel mode
> cpuid = 1; lapic.id = 00000000
> fault virtual address   = 0x1c
> fault code              = supervisor read, page not present
> instruction pointer     = 0x8:0xc022d923
> stack pointer           = 0x10:0xce9c0b10
> frame pointer           = 0x10:0xce9c0b24
> code segment            = base 0x0, limit 0xfffff, type 0x1b
>                         = DPL 0, pres 1, def32 1, gran 1
> processor eflags        = interrupt enabled, resume, IOPL = 0
> current process         = 405 (fdisk)
> trap number             = 12
> panic: page fault
> cpuid = 1; lapic.id = 00000000
> boot() called on cpu#1
> 
> syncing disks... panic: bdwrite: buffer is not busy
> cpuid = 1; lapic.id = 00000000
> boot() called on cpu#1
> Uptime: 1m40s
> pfs_vncache_unload(): 1 entries remaining
> 
> (kgdb) where
>#0  dumpsys () at /ccd/src/sys/kern/kern_shutdown.c:504
>#1  0xc021cee8 in boot (howto=260) at /ccd/src/sys/kern/kern_shutdown.c:336
>#2  0xc021d3d9 in panic (fmt=0xc03728c1 "bdwrite: buffer is not busy")
>     at /ccd/src/sys/kern/kern_shutdown.c:646
>#3  0xc0253583 in bdwrite (bp=0xc7cb7af4) at /ccd/src/sys/kern/vfs_bio.c:856
>#4  0xc02d28ee in ffs_update (vp=0xce8657a0, waitfor=0)
>     at /ccd/src/sys/ufs/ffs/ffs_inode.c:120
>#5  0xc02dff6e in ffs_fsync (ap=0xce9c09cc)
>     at /ccd/src/sys/ufs/ffs/ffs_vnops.c:292
>#6  0xc02de386 in ffs_sync (mp=0xc16cbe00, waitfor=2, cred=0xc1026b00, 
>     td=0xc03cf2c0) at vnode_if.h:441
>#7  0xc026034a in sync (td=0xc03cf2c0, uap=0x0)
>     at /ccd/src/sys/kern/vfs_syscalls.c:669
>#8  0xc021cb14 in boot (howto=256) at /ccd/src/sys/kern/kern_shutdown.c:245
>#9  0xc021d3d9 in panic (fmt=0xc03914de "%s")
>     at /ccd/src/sys/kern/kern_shutdown.c:646
>#10 0xc03299e2 in trap_fatal (frame=0xce9c0ad0, eva=28)
>     at /ccd/src/sys/i386/i386/trap.c:842
>#11 0xc0329709 in trap_pfault (frame=0xce9c0ad0, usermode=0, eva=28)
>     at /ccd/src/sys/i386/i386/trap.c:756
>#12 0xc0329147 in trap (frame={tf_fs = 24, tf_es = -828637168, 
>       tf_ds = -1071513584, tf_edi = -1049875456, tf_esi = 0, 
>       tf_ebp = -828634332, tf_isp = -828634372, tf_ebx = -942596204, 
>       tf_esp = -942596204, tf_ss = -1049268480})
>     at /ccd/src/sys/i386/i386/trap.c:426

^^ Here's the page fault for the NULL deref, so the next frame is where it
happened:

>#13 0xc022d923 in readdisklabel (dev=0xc1756f00, lp=0xc16c2c00)
>     at /ccd/src/sys/kern/subr_disklabel.c:220

In my subr_disklabel.c, line 220 is the DEV_STRATEGY:

        bp = geteblk((int)lp->d_secsize);
        bp->b_dev = dev;
        bp->b_blkno = LABELSECTOR * ((int)lp->d_secsize/DEV_BSIZE);
        bp->b_bcount = lp->d_secsize;
        bp->b_flags &= ~B_INVAL;
        bp->b_iocmd = BIO_READ;
        DEV_STRATEGY(bp, 1);

Hmm, DEV_STRATEGY is:

#define DEV_STRATEGY(bp, dummy)                                         \
        do {                                                            \
        if ((bp)->b_flags & B_PHYS)                                     \
                (bp)->b_io.bio_offset = (bp)->b_offset;                 \
        else                                                            \
                (bp)->b_io.bio_offset = dbtob((bp)->b_blkno);           \
        (bp)->b_io.bio_done = bufdonebio;                               \
        (bp)->b_io.bio_caller2 = (bp);                                  \
        BIO_STRATEGY(&(bp)->b_io, dummy);                               \
        } while (0)

I think we can assume the buf is not null as we would have panic'd earlier, so
that leaves BIO_STRATEGY maybe:

#define BIO_STRATEGY(bp, dummy)                                         \
        do {                                                            \
        if ((!(bp)->bio_cmd) || ((bp)->bio_cmd & ((bp)->bio_cmd - 1)))  \
                Debugger("bio_cmd botch");                              \
        (*devsw((bp)->bio_dev)->d_strategy)(bp);                        \
        } while (0)

I'm guessing that devsw() is returning NULL here.  You could add a KASSERT() to
this macro just before the call to d_strategy() along the lines of

        KASSERT(devsw((bp)->bio_dev) != NULL, ("no devsw for bio"));    \

To see if this is indeed the case.  

-- 

John Baldwin <jhb@FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve!"  -  http://www.FreeBSD.org/

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020212021234.8C1189F382>