tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: panic: ffs_valloc: dup alloc



> Does stuffing a couple sync calls somewhere before it starts
> suspending devices (wherever that is, I don't know) make the problems
> go away?

I use ACPI S3 sleep, and sys_sync() is called in pmf_system_suspend()
from acpi_enter_sleep_state().  I'm not sure if it is late enough.

> You're right.  When a disk driver is suspended, it should exit from
> its strategy/start routine early, without error.  It looks to me like
> sdstrategy() and wdstrategy() may each get this wrong.

I was running a kernel with the following diff.  I saw
"strategy_in_suspend = 0" on every resume, but still, I encountered
a crash today.
I couldn't see the panicstr or get a crash dump this time.

-- 
KAMADA Ken'ichi <kamada%nanohz.org@localhost>
Index: dev/ata/wd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/wd.c,v
retrieving revision 1.384
diff -p -u -r1.384 wd.c
--- dev/ata/wd.c        24 Feb 2010 22:37:57 -0000      1.384
+++ dev/ata/wd.c        14 Apr 2010 19:05:08 -0000
@@ -127,8 +127,11 @@ void       wdperror(const struct wd_softc *);
 
 static int     wdlastclose(device_t);
 static bool    wd_suspend(device_t, const pmf_qual_t *);
+static bool    wd_resume(device_t, const pmf_qual_t *);
 static int     wd_standby(struct wd_softc *, int);
 
+static int strategy_in_suspend;
+
 CFATTACH_DECL3_NEW(wd, sizeof(struct wd_softc),
     wdprobe, wdattach, wddetach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
 
@@ -389,7 +392,7 @@ wdattach(device_t parent, device_t self,
        /* Discover wedges on this disk. */
        dkwedge_discover(&wd->sc_dk);
 
-       if (!pmf_device_register1(self, wd_suspend, NULL, wd_shutdown))
+       if (!pmf_device_register1(self, wd_suspend, wd_resume, wd_shutdown))
                aprint_error_dev(self, "couldn't establish power handler\n");
 }
 
@@ -398,11 +401,22 @@ wd_suspend(device_t dv, const pmf_qual_t
 {
        struct wd_softc *sc = device_private(dv);
 
+       sc->suspended = 1;
        wd_flushcache(sc, AT_WAIT);
        wd_standby(sc, AT_WAIT);
        return true;
 }
 
+static bool
+wd_resume(device_t dv, const pmf_qual_t *qual)
+{
+       struct wd_softc *sc = device_private(dv);
+
+       sc->suspended = 0;
+       printf("strategy_in_suspend = %d\n", strategy_in_suspend);
+       return true;
+}
+
 int
 wddetach(device_t self, int flags)
 {
@@ -553,7 +567,10 @@ wdstrategy(struct buf *bp)
        /* Queue transfer on drive, activate drive and controller if idle. */
        s = splbio();
        bufq_put(wd->sc_q, bp);
-       wdstart(wd);
+       if (wd->suspended)
+               strategy_in_suspend++;
+       else
+               wdstart(wd);
        splx(s);
        return;
 done:
Index: dev/ata/wdvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/wdvar.h,v
retrieving revision 1.38
diff -p -u -r1.38 wdvar.h
--- dev/ata/wdvar.h     17 Dec 2009 21:03:10 -0000      1.38
+++ dev/ata/wdvar.h     14 Apr 2010 19:05:08 -0000
@@ -69,6 +69,7 @@ struct wd_softc {
 #if NRND > 0
        rndsource_element_t     rnd_source;
 #endif
+       int suspended;
 };
 
 #define sc_drive sc_wdc_bio.drive


Home | Main Index | Thread Index | Old Index