nata - Drop pending requests on dump
authorAlex Hornung <ahornung@gmail.com>
Tue, 13 Apr 2010 16:32:08 +0000 (16:32 +0000)
committerAlex Hornung <ahornung@gmail.com>
Tue, 13 Apr 2010 16:35:06 +0000 (16:35 +0000)
* 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
sys/dev/disk/nata/ata-disk.c
sys/dev/disk/nata/ata-queue.c

index f5f6045..3f6a4c0 100644 (file)
@@ -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);
index 960536b..a1ae6cc 100644 (file)
@@ -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
         */
index 5186c99..8b8ffe6 100644 (file)
@@ -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)
 {