[PATCH] libata-eh: implement dev->ering
authorTejun Heo <htejun@gmail.com>
Mon, 15 May 2006 11:58:19 +0000 (20:58 +0900)
committerTejun Heo <htejun@gmail.com>
Mon, 15 May 2006 11:58:19 +0000 (20:58 +0900)
This patch implements ata_ering and uses it to define dev->ering.

ata_ering is a ring buffer which records libata errors - whether a
command was for normar IO request, err_mask and timestamp.  Errors are
recorded per-device in dev->ering.  This will be used by EH to
determine recovery actions.

Signed-off-by: Tejun Heo <htejun@gmail.com>
drivers/scsi/libata-eh.c
include/linux/libata.h

index 0803231f65779776e96383f4452a09adc16c0f42..71ad18b7cff6e3eda05b50d586dd976dc57edef5 100644 (file)
 
 static void __ata_port_freeze(struct ata_port *ap);
 
+static void ata_ering_record(struct ata_ering *ering, int is_io,
+                            unsigned int err_mask)
+{
+       struct ata_ering_entry *ent;
+
+       WARN_ON(!err_mask);
+
+       ering->cursor++;
+       ering->cursor %= ATA_ERING_SIZE;
+
+       ent = &ering->ring[ering->cursor];
+       ent->is_io = is_io;
+       ent->err_mask = err_mask;
+       ent->timestamp = get_jiffies_64();
+}
+
+static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering)
+{
+       struct ata_ering_entry *ent = &ering->ring[ering->cursor];
+       if (!ent->err_mask)
+               return NULL;
+       return ent;
+}
+
+static int ata_ering_map(struct ata_ering *ering,
+                        int (*map_fn)(struct ata_ering_entry *, void *),
+                        void *arg)
+{
+       int idx, rc = 0;
+       struct ata_ering_entry *ent;
+
+       idx = ering->cursor;
+       do {
+               ent = &ering->ring[idx];
+               if (!ent->err_mask)
+                       break;
+               rc = map_fn(ent, arg);
+               if (rc)
+                       break;
+               idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE;
+       } while (idx != ering->cursor);
+
+       return rc;
+}
+
 /**
  *     ata_scsi_timed_out - SCSI layer time out callback
  *     @cmd: timed out SCSI command
index 6fe5ed8eabf56275c540a64c668a41c3ffa1ba39..f5cea13599c339cdbb43a13ba3585778f6cab00f 100644 (file)
@@ -226,6 +226,9 @@ enum {
        ATA_PORT_PRIMARY        = (1 << 0),
        ATA_PORT_SECONDARY      = (1 << 1),
 
+       /* ering size */
+       ATA_ERING_SIZE          = 32,
+
        /* reset / recovery action types */
        ATA_EH_REVALIDATE       = (1 << 0),
        ATA_EH_SOFTRESET        = (1 << 1),
@@ -375,6 +378,17 @@ struct ata_host_stats {
        unsigned long           rw_reqbuf;
 };
 
+struct ata_ering_entry {
+       int                     is_io;
+       unsigned int            err_mask;
+       u64                     timestamp;
+};
+
+struct ata_ering {
+       int                     cursor;
+       struct ata_ering_entry  ring[ATA_ERING_SIZE];
+};
+
 struct ata_device {
        struct ata_port         *ap;
        u64                     n_sectors;      /* size of device, if ATA */
@@ -401,6 +415,9 @@ struct ata_device {
        u16                     cylinders;      /* Number of cylinders */
        u16                     heads;          /* Number of heads */
        u16                     sectors;        /* Number of sectors per track */
+
+       /* error history */
+       struct ata_ering        ering;
 };
 
 struct ata_port {