Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c247c55 authored by Tejun Heo's avatar Tejun Heo
Browse files

[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: default avatarTejun Heo <htejun@gmail.com>
parent 9be1e979
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -46,6 +46,51 @@

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
+17 −0
Original line number Diff line number Diff line
@@ -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 {