[PATCH] libata-eh: implement dev->ering
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>
This commit is contained in:
parent
9be1e979f2
commit
0c247c559c
@ -46,6 +46,51 @@
|
|||||||
|
|
||||||
static void __ata_port_freeze(struct ata_port *ap);
|
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
|
* ata_scsi_timed_out - SCSI layer time out callback
|
||||||
* @cmd: timed out SCSI command
|
* @cmd: timed out SCSI command
|
||||||
|
@ -226,6 +226,9 @@ enum {
|
|||||||
ATA_PORT_PRIMARY = (1 << 0),
|
ATA_PORT_PRIMARY = (1 << 0),
|
||||||
ATA_PORT_SECONDARY = (1 << 1),
|
ATA_PORT_SECONDARY = (1 << 1),
|
||||||
|
|
||||||
|
/* ering size */
|
||||||
|
ATA_ERING_SIZE = 32,
|
||||||
|
|
||||||
/* reset / recovery action types */
|
/* reset / recovery action types */
|
||||||
ATA_EH_REVALIDATE = (1 << 0),
|
ATA_EH_REVALIDATE = (1 << 0),
|
||||||
ATA_EH_SOFTRESET = (1 << 1),
|
ATA_EH_SOFTRESET = (1 << 1),
|
||||||
@ -375,6 +378,17 @@ struct ata_host_stats {
|
|||||||
unsigned long rw_reqbuf;
|
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_device {
|
||||||
struct ata_port *ap;
|
struct ata_port *ap;
|
||||||
u64 n_sectors; /* size of device, if ATA */
|
u64 n_sectors; /* size of device, if ATA */
|
||||||
@ -401,6 +415,9 @@ struct ata_device {
|
|||||||
u16 cylinders; /* Number of cylinders */
|
u16 cylinders; /* Number of cylinders */
|
||||||
u16 heads; /* Number of heads */
|
u16 heads; /* Number of heads */
|
||||||
u16 sectors; /* Number of sectors per track */
|
u16 sectors; /* Number of sectors per track */
|
||||||
|
|
||||||
|
/* error history */
|
||||||
|
struct ata_ering ering;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ata_port {
|
struct ata_port {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user