From ef35240304518887c0472fda71a672a0c29be0f2 Mon Sep 17 00:00:00 2001 From: Alex Hornung Date: Tue, 13 Apr 2010 16:32:08 +0000 Subject: [PATCH 1/1] nata - Drop pending requests on dump * Drop all pending requests in the ata queue when we are about to dump. * This should solve issues that have been appearing lately causing a TAILQ_NEXT panic on dumps with nata under heavy I/O. Reported-by: Jan Lentfer (lentferj@), Antonio Huete (tuxillo@) Obtained-from: FreeBSD --- sys/dev/disk/nata/ata-all.h | 1 + sys/dev/disk/nata/ata-disk.c | 1 + sys/dev/disk/nata/ata-queue.c | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/sys/dev/disk/nata/ata-all.h b/sys/dev/disk/nata/ata-all.h index f5f6045973..3f6a4c088c 100644 --- a/sys/dev/disk/nata/ata-all.h +++ b/sys/dev/disk/nata/ata-all.h @@ -565,6 +565,7 @@ int ata_limit_mode(device_t dev, int mode, int maxmode); /* ata-queue.c: */ int ata_controlcmd(device_t dev, u_int8_t command, u_int16_t feature, u_int64_t lba, u_int16_t count); int ata_atapicmd(device_t dev, u_int8_t *ccb, caddr_t data, int count, int flags, int timeout); +void ata_drop_requests(device_t dev); void ata_queue_init(struct ata_channel *ch); void ata_queue_request(struct ata_request *request); void ata_start(device_t dev); diff --git a/sys/dev/disk/nata/ata-disk.c b/sys/dev/disk/nata/ata-disk.c index 960536b68c..a1ae6cc829 100644 --- a/sys/dev/disk/nata/ata-disk.c +++ b/sys/dev/disk/nata/ata-disk.c @@ -377,6 +377,7 @@ ad_dump(struct dev_dump_args *ap) struct ata_device *atadev = device_get_softc(dev); struct ata_request request; + ata_drop_requests(dev); /* * 0 length means flush buffers and return */ diff --git a/sys/dev/disk/nata/ata-queue.c b/sys/dev/disk/nata/ata-queue.c index 5186c99143..8b8ffe6ba3 100644 --- a/sys/dev/disk/nata/ata-queue.c +++ b/sys/dev/disk/nata/ata-queue.c @@ -56,6 +56,24 @@ ata_queue_init(struct ata_channel *ch) ch->transition = NULL; } +/* + * Rudely drop all requests queued to the channel of specified device. + * XXX: The requests are leaked, use only in fatal case. + */ +void +ata_drop_requests(device_t dev) +{ + struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_request *request, *tmp; + + spin_lock_wr(&ch->queue_mtx); + TAILQ_FOREACH_MUTABLE(request, &ch->ata_queue, chain, tmp) { + TAILQ_REMOVE(&ch->ata_queue, request, chain); + request->result = ENXIO; + } + spin_unlock_wr(&ch->queue_mtx); +} + void ata_queue_request(struct ata_request *request) { -- 2.41.0