win-pvdrivers

changeset 799:213306951ec5

Stall the xenvbd queue if we detect a write that overlaps a write already in the pipe. This prevents warnings with drbd and has no measurable loss of performance during normal use.
author James Harper <james.harper@bendigoit.com.au>
date Sat May 22 20:39:27 2010 +1000 (2010-05-22)
parents b4f77023ac84
children 1d06ba3917d2
files xenvbd/xenvbd.c
line diff
     1.1 --- a/xenvbd/xenvbd.c	Fri May 21 16:30:53 2010 +1000
     1.2 +++ b/xenvbd/xenvbd.c	Sat May 22 20:39:27 2010 +1000
     1.3 @@ -356,12 +356,14 @@ XenVbd_PutQueuedSrbsOnRing(PXENVBD_DEVIC
     1.4  {
     1.5    PSCSI_REQUEST_BLOCK srb;
     1.6    srb_list_entry_t *srb_entry;
     1.7 +  ULONGLONG sector_number;
     1.8    ULONG block_count;
     1.9    blkif_shadow_t *shadow;
    1.10    ULONG remaining, offset, length;
    1.11    grant_ref_t gref;
    1.12    PUCHAR ptr;
    1.13    int notify;
    1.14 +  int i;
    1.15  
    1.16    //FUNCTION_ENTER();
    1.17  
    1.18 @@ -373,14 +375,63 @@ XenVbd_PutQueuedSrbsOnRing(PXENVBD_DEVIC
    1.19      srb = srb_entry->srb;
    1.20      block_count = decode_cdb_length(srb);;
    1.21      block_count *= xvdd->bytes_per_sector / 512;
    1.22 +    sector_number = decode_cdb_sector(srb);
    1.23 +    sector_number *= xvdd->bytes_per_sector / 512;
    1.24 +    
    1.25 +    /* look for pending writes that overlap this one */
    1.26 +    /* we get warnings from drbd if we don't */
    1.27 +    for (i = 0; i < MAX_SHADOW_ENTRIES; i++)
    1.28 +    {
    1.29 +      PSCSI_REQUEST_BLOCK srb2;
    1.30 +      ULONGLONG sector_number2;
    1.31 +      ULONG block_count2;
    1.32 +      
    1.33 +      srb2 = xvdd->shadows[i].srb;
    1.34 +      if (!srb2)
    1.35 +        continue;
    1.36 +      if (decode_cdb_is_read(srb2))
    1.37 +        continue;
    1.38 +      block_count2 = decode_cdb_length(srb2);;
    1.39 +      block_count2 *= xvdd->bytes_per_sector / 512;
    1.40 +      sector_number2 = decode_cdb_sector(srb2);
    1.41 +      sector_number2 *= xvdd->bytes_per_sector / 512;
    1.42 +      
    1.43 +      if (sector_number < sector_number2 && sector_number + block_count <= sector_number2)
    1.44 +        continue;
    1.45 +      if (sector_number2 < sector_number && sector_number2 + block_count2 <= sector_number)
    1.46 +        continue;
    1.47 +
    1.48 +#if 0
    1.49 +      /* check if the data being written is identical to the data in the pipe */
    1.50 +      {
    1.51 +        PUCHAR buf, buf2;
    1.52 +        ULONG byte_count;
    1.53 +        int j;
    1.54 +
    1.55 +        buf = (PUCHAR)srb->DataBuffer + (max(sector_number, sector_number2) - sector_number) * xvdd->bytes_per_sector;
    1.56 +        buf2 = (PUCHAR)srb2->DataBuffer + (max(sector_number, sector_number2) - sector_number2) * xvdd->bytes_per_sector;
    1.57 +        byte_count = (ULONG)(min(sector_number + block_count, sector_number2 + block_count2) - max(sector_number, sector_number2)) * xvdd->bytes_per_sector;
    1.58 +        for (j = 0; j < (int)byte_count; j++)
    1.59 +        {
    1.60 +          if (buf[j] != buf2[j])
    1.61 +            break;
    1.62 +        }
    1.63 +      }
    1.64 +#endif
    1.65 +
    1.66 +      KdPrint((__DRIVER_NAME "     Concurrent outstanding write detected (%I64d, %d) (%I64d, %d)\n",
    1.67 +        sector_number, block_count, sector_number2, block_count2));
    1.68 +      /* put the srb back at the start of the queue */
    1.69 +      InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
    1.70 +      return; /* stall the queue */
    1.71 +    }
    1.72 +
    1.73      remaining = block_count * 512;
    1.74 -
    1.75      shadow = get_shadow_from_freelist(xvdd);
    1.76      ASSERT(shadow);
    1.77      ASSERT(!shadow->aligned_buffer_in_use);
    1.78      ASSERT(!shadow->srb);
    1.79 -    shadow->req.sector_number = decode_cdb_sector(srb);
    1.80 -    shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
    1.81 +    shadow->req.sector_number = sector_number;
    1.82      shadow->req.handle = 0;
    1.83      shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
    1.84      shadow->req.nr_segments = 0;