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