summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2013-07-27 22:44:55 +0000
committermav <mav@FreeBSD.org>2013-07-27 22:44:55 +0000
commit9932d6357cd2745b8b313b513e4c8711a63cb77c (patch)
tree8cb88e91b54234ba167c1801108f9f129e24cb26 /sys/cam
parent6b7d3341e2ee3a31dce13dd3c674e17647216275 (diff)
downloadFreeBSD-src-9932d6357cd2745b8b313b513e4c8711a63cb77c.zip
FreeBSD-src-9932d6357cd2745b8b313b513e4c8711a63cb77c.tar.gz
Synchronize device cache on close only if there were some write operations.
While these operations are not really needed otherwise, at least for SCSI they may cause extra errors if some other initiator holds write exclusive reservation on the LUN (SYNCHRONIZE CACHE handled as "write" operation).
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/ata/ata_da.c17
-rw-r--r--sys/cam/scsi/scsi_da.c17
2 files changed, 24 insertions, 10 deletions
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
index 6e9c462..3dac0ac 100644
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -86,7 +86,8 @@ typedef enum {
ADA_FLAG_SCTX_INIT = 0x0200,
ADA_FLAG_CAN_CFA = 0x0400,
ADA_FLAG_CAN_POWERMGT = 0x0800,
- ADA_FLAG_CAN_DMA48 = 0x1000
+ ADA_FLAG_CAN_DMA48 = 0x1000,
+ ADA_FLAG_DIRTY = 0x2000
} ada_flags;
typedef enum {
@@ -602,6 +603,7 @@ adaclose(struct disk *dp)
struct cam_periph *periph;
struct ada_softc *softc;
union ccb *ccb;
+ int error;
periph = (struct cam_periph *)dp->d_drv1;
cam_periph_lock(periph);
@@ -617,7 +619,8 @@ adaclose(struct disk *dp)
("adaclose\n"));
/* We only sync the cache if the drive is capable of it. */
- if ((softc->flags & ADA_FLAG_CAN_FLUSHCACHE) != 0 &&
+ if ((softc->flags & ADA_FLAG_DIRTY) != 0 &&
+ (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) != 0 &&
(periph->flags & CAM_PERIPH_INVALID) == 0) {
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
@@ -634,11 +637,13 @@ adaclose(struct disk *dp)
ata_48bit_cmd(&ccb->ataio, ATA_FLUSHCACHE48, 0, 0, 0);
else
ata_28bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0);
- cam_periph_runccb(ccb, adaerror, /*cam_flags*/0,
+ error = cam_periph_runccb(ccb, adaerror, /*cam_flags*/0,
/*sense_flags*/0, softc->disk->d_devstat);
- if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
+ if (error != 0)
xpt_print(periph->path, "Synchronize cache failed\n");
+ else
+ softc->flags &= ~ADA_FLAG_DIRTY;
xpt_release_ccb(ccb);
}
@@ -1479,8 +1484,10 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
tag_code = 1;
}
switch (bp->bio_cmd) {
- case BIO_READ:
case BIO_WRITE:
+ softc->flags |= ADA_FLAG_DIRTY;
+ /* FALLTHROUGH */
+ case BIO_READ:
{
uint64_t lba = bp->bio_pblkno;
uint16_t count = bp->bio_bcount / softc->params.secsize;
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index ae80b65..8d0f35e 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -89,7 +89,8 @@ typedef enum {
DA_FLAG_OPEN = 0x100,
DA_FLAG_SCTX_INIT = 0x200,
DA_FLAG_CAN_RC16 = 0x400,
- DA_FLAG_PROBED = 0x800
+ DA_FLAG_PROBED = 0x800,
+ DA_FLAG_DIRTY = 0x1000
} da_flags;
typedef enum {
@@ -1237,6 +1238,7 @@ daclose(struct disk *dp)
{
struct cam_periph *periph;
struct da_softc *softc;
+ int error;
periph = (struct cam_periph *)dp->d_drv1;
cam_periph_lock(periph);
@@ -1251,8 +1253,9 @@ daclose(struct disk *dp)
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
("daclose\n"));
- if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0
- && (softc->flags & DA_FLAG_PACK_INVALID) == 0) {
+ if ((softc->flags & DA_FLAG_DIRTY) != 0 &&
+ (softc->quirks & DA_Q_NO_SYNC_CACHE) == 0 &&
+ (softc->flags & DA_FLAG_PACK_INVALID) == 0) {
union ccb *ccb;
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
@@ -1266,9 +1269,11 @@ daclose(struct disk *dp)
SSD_FULL_SIZE,
5 * 60 * 1000);
- cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
+ error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_QUIET_IR,
softc->disk->d_devstat);
+ if (error == 0)
+ softc->flags &= ~DA_FLAG_DIRTY;
xpt_release_ccb(ccb);
}
@@ -2240,8 +2245,10 @@ skipstate:
}
switch (bp->bio_cmd) {
- case BIO_READ:
case BIO_WRITE:
+ softc->flags |= DA_FLAG_DIRTY;
+ /* FALLTHROUGH */
+ case BIO_READ:
scsi_read_write(&start_ccb->csio,
/*retries*/da_retry_count,
/*cbfcnp*/dadone,
OpenPOWER on IntegriCloud