Author: mav
Date: Sat Jul 27 22:44:55 2013
New Revision: 253724
URL: http://svnweb.freebsd.org/changeset/base/253724

Log:
  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).

Modified:
  head/sys/cam/ata/ata_da.c
  head/sys/cam/scsi/scsi_da.c

Modified: head/sys/cam/ata/ata_da.c
==============================================================================
--- head/sys/cam/ata/ata_da.c   Sat Jul 27 22:23:32 2013        (r253723)
+++ head/sys/cam/ata/ata_da.c   Sat Jul 27 22:44:55 2013        (r253724)
@@ -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, unio
                        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;

Modified: head/sys/cam/scsi/scsi_da.c
==============================================================================
--- head/sys/cam/scsi/scsi_da.c Sat Jul 27 22:23:32 2013        (r253723)
+++ head/sys/cam/scsi/scsi_da.c Sat Jul 27 22:44:55 2013        (r253724)
@@ -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,
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to