win-pvdrivers

changeset 1044:9f476ac2fbe1 0.11.0.399

Add proper support for vbd resize using unit attention.
author James Harper <james.harper@bendigoit.com.au>
date Mon Mar 04 14:26:41 2013 +1100 (2013-03-04)
parents 7a4113fe4caf
children f6a7b0654b9c
files xenvbd_common/common_miniport.h xenvbd_scsiport/common.h xenvbd_scsiport/xenvbd.c xenvbd_storport/xenvbd.h
line diff
     1.1 --- a/xenvbd_common/common_miniport.h	Sun Mar 03 17:19:24 2013 +1100
     1.2 +++ b/xenvbd_common/common_miniport.h	Mon Mar 04 14:26:41 2013 +1100
     1.3 @@ -143,8 +143,7 @@ decode_cdb_is_read(PSCSI_REQUEST_BLOCK s
     1.4  }
     1.5  
     1.6  static ULONG
     1.7 -XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
     1.8 -{
     1.9 +XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb) {
    1.10    PSENSE_DATA sd = srb->SenseInfoBuffer;
    1.11   
    1.12    UNREFERENCED_PARAMETER(xvdd);
    1.13 @@ -154,19 +153,30 @@ XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvd
    1.14    
    1.15    sd->ErrorCode = 0x70;
    1.16    sd->Valid = 1;
    1.17 -  sd->SenseKey = sense_key;
    1.18 +  sd->SenseKey = xvdd->last_sense_key;
    1.19    sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
    1.20 -  sd->AdditionalSenseCode = additional_sense_code;
    1.21 +  sd->AdditionalSenseCode = xvdd->last_additional_sense_code;
    1.22 +  sd->AdditionalSenseCodeQualifier = xvdd->last_additional_sense_code_qualifier;
    1.23 +  xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
    1.24 +  xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
    1.25 +  xvdd->last_additional_sense_code_qualifier = 0;
    1.26 +  xvdd->cac = FALSE;
    1.27    return sizeof(SENSE_DATA);
    1.28  }
    1.29  
    1.30  static VOID
    1.31 -XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
    1.32 -{
    1.33 -  if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
    1.34 +XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb) {
    1.35 +  if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE) {
    1.36      return;
    1.37 -  XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
    1.38 -  srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
    1.39 +  }
    1.40 +  srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
    1.41 +  if (srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) {
    1.42 +    /* because cac is set nothing will progress until sense is requested */
    1.43 +    xvdd->cac = TRUE;
    1.44 +    return;
    1.45 +  }
    1.46 +  XenVbd_MakeSense(xvdd, srb);
    1.47 +  srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID;
    1.48  }
    1.49  
    1.50  /* called with StartIo lock held */
    1.51 @@ -187,10 +197,10 @@ XenVbd_HandleEvent(PXENVBD_DEVICE_DATA x
    1.52      return;
    1.53    }
    1.54  
    1.55 -  while (more_to_do) {
    1.56 +  while (more_to_do && !xvdd->cac) {
    1.57      rp = xvdd->ring.sring->rsp_prod;
    1.58      KeMemoryBarrier();
    1.59 -    for (i = xvdd->ring.rsp_cons; i != rp; i++) {
    1.60 +    for (i = xvdd->ring.rsp_cons; i != rp && !xvdd->cac; i++) {
    1.61        rep = XenVbd_GetResponse(xvdd, i);
    1.62        shadow = &xvdd->shadows[rep->id & SHADOW_ID_ID_MASK];
    1.63        if (shadow->reset) {
    1.64 @@ -231,11 +241,9 @@ XenVbd_HandleEvent(PXENVBD_DEVICE_DATA x
    1.65          if (srb_entry->outstanding_requests == 0 && srb_entry->offset == srb_entry->length) {
    1.66            if (srb_entry->error) {
    1.67              srb->SrbStatus = SRB_STATUS_ERROR;
    1.68 -            srb->ScsiStatus = 0x02;
    1.69              xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
    1.70 -            xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
    1.71 -            XenVbd_MakeAutoSense(xvdd, srb);
    1.72            }
    1.73 +          XenVbd_MakeAutoSense(xvdd, srb);
    1.74            SxxxPortNotification(RequestComplete, xvdd, srb);
    1.75          }
    1.76        }
    1.77 @@ -657,7 +665,7 @@ XenVbd_ResetBus(PXENVBD_DEVICE_DATA xvdd
    1.78    /* send a notify to Dom0 just in case it was missed for some reason (which should _never_ happen normally but could in dump mode) */
    1.79    XnNotify(xvdd->handle, xvdd->event_channel);
    1.80  
    1.81 -  SxxxPortNotification(NextLuRequest, xvdd, 0, 0, 0);
    1.82 +  SxxxPortNotification(NextRequest, xvdd);
    1.83    FUNCTION_EXIT();
    1.84  
    1.85    return TRUE;
    1.86 @@ -681,14 +689,6 @@ XenVbd_ProcessSrbList(PXENVBD_DEVICE_DAT
    1.87    PSRB_IO_CONTROL sic;
    1.88    ULONG prev_offset;
    1.89  
    1.90 -  if (xvdd->device_state == DEVICE_STATE_ACTIVE) {
    1.91 -    if (xvdd->new_total_sectors == -1L)
    1.92 -      xvdd->new_total_sectors = xvdd->total_sectors;
    1.93 -    if (xvdd->new_total_sectors != xvdd->total_sectors) {
    1.94 -      xvdd->total_sectors = xvdd->new_total_sectors;
    1.95 -      SxxxPortNotification(BusChangeDetected, xvdd, 0);
    1.96 -    }
    1.97 -  }
    1.98    while(!xvdd->aligned_buffer_in_use && xvdd->shadow_free && (srb_entry = (srb_list_entry_t *)RemoveHeadList(&xvdd->srb_list)) != (srb_list_entry_t *)&xvdd->srb_list) {
    1.99      srb = srb_entry->srb;
   1.100      prev_offset = srb_entry->offset;
   1.101 @@ -699,7 +699,6 @@ XenVbd_ProcessSrbList(PXENVBD_DEVICE_DAT
   1.102        SxxxPortNotification(RequestComplete, xvdd, srb);
   1.103        continue;
   1.104      }
   1.105 -
   1.106      data_transfer_length = srb->DataTransferLength;
   1.107      srb_status = SRB_STATUS_PENDING;
   1.108      
   1.109 @@ -710,7 +709,23 @@ XenVbd_ProcessSrbList(PXENVBD_DEVICE_DAT
   1.110          InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
   1.111          break;
   1.112        }
   1.113 +      if (xvdd->new_total_sectors != xvdd->total_sectors) {
   1.114 +        if (xvdd->new_total_sectors == -1L) {
   1.115 +          xvdd->new_total_sectors = xvdd->total_sectors;
   1.116 +        } else {
   1.117 +          FUNCTION_MSG("Resize detected. Setting UNIT_ATTENTION\n");
   1.118 +          xvdd->total_sectors = xvdd->new_total_sectors;
   1.119 +          xvdd->last_sense_key = SCSI_SENSE_UNIT_ATTENTION;
   1.120 +          xvdd->last_additional_sense_code = SCSI_ADSENSE_PARAMETERS_CHANGED;
   1.121 +          xvdd->last_additional_sense_code_qualifier = 0x09; /* capacity changed */
   1.122 +        }
   1.123 +      }
   1.124        cdb = (PCDB)srb->Cdb;
   1.125 +      if (xvdd->cac && cdb->CDB6GENERIC.OperationCode != SCSIOP_REQUEST_SENSE) {
   1.126 +        FUNCTION_MSG("Waiting for REQUEST_SENSE\n");
   1.127 +        InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
   1.128 +        break;
   1.129 +      }
   1.130        switch(cdb->CDB6GENERIC.OperationCode) {
   1.131        case SCSIOP_TEST_UNIT_READY:
   1.132          if (dump_mode)
   1.133 @@ -993,7 +1008,7 @@ XenVbd_ProcessSrbList(PXENVBD_DEVICE_DAT
   1.134        case SCSIOP_REQUEST_SENSE:
   1.135          if (dump_mode)
   1.136            FUNCTION_MSG("Command = REQUEST_SENSE\n");
   1.137 -        data_transfer_length = XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
   1.138 +        data_transfer_length = XenVbd_MakeSense(xvdd, srb);
   1.139          srb_status = SRB_STATUS_SUCCESS;
   1.140          break;      
   1.141        case SCSIOP_READ_TOC:
   1.142 @@ -1054,6 +1069,8 @@ XenVbd_ProcessSrbList(PXENVBD_DEVICE_DAT
   1.143        default:
   1.144          FUNCTION_MSG("Unhandled EXECUTE_SCSI Command = %02X\n", srb->Cdb[0]);
   1.145          xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
   1.146 +        xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
   1.147 +        xvdd->last_additional_sense_code_qualifier = 0;
   1.148          srb_status = SRB_STATUS_ERROR;
   1.149          break;
   1.150        }
   1.151 @@ -1062,9 +1079,9 @@ XenVbd_ProcessSrbList(PXENVBD_DEVICE_DAT
   1.152          if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE) {
   1.153            xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
   1.154            xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
   1.155 +          xvdd->last_additional_sense_code_qualifier = 0;
   1.156          }
   1.157          srb->SrbStatus = srb_status;
   1.158 -        srb->ScsiStatus = 0x02;
   1.159          XenVbd_MakeAutoSense(xvdd, srb);
   1.160          SxxxPortNotification(RequestComplete, xvdd, srb);
   1.161        } else if (srb_status != SRB_STATUS_PENDING) {
   1.162 @@ -1072,16 +1089,14 @@ XenVbd_ProcessSrbList(PXENVBD_DEVICE_DAT
   1.163            FUNCTION_MSG("ScsiStatus = 0x%02x\n", srb->ScsiStatus);
   1.164          }
   1.165          if (data_transfer_length > srb->DataTransferLength)
   1.166 -          FUNCTION_MSG("data_transfer_length too big - %d > %d\n", data_transfer_length, srb->DataTransferLength);
   1.167 -        
   1.168 +          FUNCTION_MSG("data_transfer_length too big - %d > %d\n", data_transfer_length, srb->DataTransferLength);        
   1.169          if (srb_status == SRB_STATUS_SUCCESS && data_transfer_length < srb->DataTransferLength) {
   1.170            srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
   1.171            srb->DataTransferLength = data_transfer_length;
   1.172          } else {
   1.173            srb->SrbStatus = srb_status;
   1.174          }
   1.175 -        xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
   1.176 -        xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
   1.177 +        XenVbd_MakeAutoSense(xvdd, srb);
   1.178          SxxxPortNotification(RequestComplete, xvdd, srb);
   1.179        }
   1.180        break;
     2.1 --- a/xenvbd_scsiport/common.h	Sun Mar 03 17:19:24 2013 +1100
     2.2 +++ b/xenvbd_scsiport/common.h	Mon Mar 04 14:26:41 2013 +1100
     2.3 @@ -42,6 +42,8 @@ struct {
     2.4    grant_ref_t sring_gref; 
     2.5    UCHAR last_sense_key;
     2.6    UCHAR last_additional_sense_code;
     2.7 +  UCHAR last_additional_sense_code_qualifier;
     2.8 +  BOOLEAN cac;
     2.9    XENVBD_DEVICETYPE device_type;
    2.10    XENVBD_DEVICEMODE device_mode;
    2.11    ULONG bytes_per_sector; /* 512 for disk, 2048 for CDROM) */
     3.1 --- a/xenvbd_scsiport/xenvbd.c	Sun Mar 03 17:19:24 2013 +1100
     3.2 +++ b/xenvbd_scsiport/xenvbd.c	Mon Mar 04 14:26:41 2013 +1100
     3.3 @@ -72,6 +72,12 @@ XenVbd_NotificationNextLuRequest(PXENVBD
     3.4  }
     3.5  
     3.6  VOID
     3.7 +XenVbd_NotificationNextRequest(PXENVBD_DEVICE_DATA xvdd) {
     3.8 +  ScsiPortNotification(NextLuRequest, xvdd->xvsd);
     3.9 +}
    3.10 +
    3.11 +
    3.12 +VOID
    3.13  XenVbd_NotificationBusChangeDetected(PXENVBD_DEVICE_DATA xvdd, UCHAR PathId) {
    3.14    ScsiPortNotification(BusChangeDetected, xvdd->xvsd, PathId);
    3.15  }
     4.1 --- a/xenvbd_storport/xenvbd.h	Sun Mar 03 17:19:24 2013 +1100
     4.2 +++ b/xenvbd_storport/xenvbd.h	Mon Mar 04 14:26:41 2013 +1100
     4.3 @@ -83,6 +83,8 @@ struct {
     4.4    ULONG backend_state;
     4.5    UCHAR last_sense_key;
     4.6    UCHAR last_additional_sense_code;
     4.7 +  UCHAR last_additional_sense_code_qualifier;
     4.8 +  BOOLEAN cac;
     4.9    blkif_response_t tmp_rep;
    4.10    XENVBD_DEVICETYPE device_type;
    4.11    XENVBD_DEVICEMODE device_mode;