[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 3/6] Align blkif protocol values to 512B sectors


  • To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Tu Dinh <ngoc-tu.dinh@xxxxxxxxxx>
  • Date: Tue, 28 Apr 2026 11:03:32 +0200
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=vates.tech header.i="@vates.tech" header.h="From:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:In-Reply-To:References:Feedback-ID"
  • Cc: Tu Dinh <ngoc-tu.dinh@xxxxxxxxxx>, Owen Smith <owen.smith@xxxxxxxxxx>
  • Delivery-date: Tue, 28 Apr 2026 09:03:46 +0000
  • Feedback-id: default:8631fc262581453bbf619ec5b2062170:Sweego
  • List-id: Developer list for the Windows PV Drivers subproject <win-pv-devel.lists.xenproject.org>

With the deprecation of feature-large-sector-size, blkif.h now specifies
that all sector amounts in the protocol are in 512B units.

Signed-off-by: Tu Dinh <ngoc-tu.dinh@xxxxxxxxxx>
---
 src/xenvbd/frontend.c | 80 +++++++++++++++++++++++++++++--------------
 src/xenvbd/frontend.h | 10 +++++-
 src/xenvbd/ring.c     | 56 ++++++++++++++----------------
 src/xenvbd/target.c   | 13 +++----
 4 files changed, 97 insertions(+), 62 deletions(-)

diff --git a/src/xenvbd/frontend.c b/src/xenvbd/frontend.c
index 45a5f49..d8e3287 100644
--- a/src/xenvbd/frontend.c
+++ b/src/xenvbd/frontend.c
@@ -761,7 +761,7 @@ __Size(
     __in  PXENVBD_DISKINFO  Info
     )
 {
-    ULONG64                 MBytes = (Info->SectorSize * Info->SectorCount) >> 
20; // / (1024 * 1024);
+    ULONG64                 MBytes = Info->BlkifSectorCount >> (20 - 
BLKIF_SECTOR_SHIFT);
 
     if (MBytes < 10240)
         return (ULONG)MBytes;
@@ -773,7 +773,7 @@ __Units(
     __in  PXENVBD_DISKINFO  Info
     )
 {
-    ULONG64                 MBytes = (Info->SectorSize * Info->SectorCount) >> 
20; // / (1024 * 1024);
+    ULONG64                 MBytes = Info->BlkifSectorCount >> (20 - 
BLKIF_SECTOR_SHIFT);
 
     if (MBytes < 10240)
         return "MB";
@@ -856,46 +856,73 @@ FrontendReadDiskInfo(
     )
 {
     BOOLEAN                 Changed;
+    PXENVBD_DISKINFO        DiskInfo = &Frontend->DiskInfo;
 
     Changed = FrontendReadDiskValue32(Frontend,
                                       "info",
-                                      &Frontend->DiskInfo.DiskInfo);
+                                      &DiskInfo->DiskInfo);
     Changed |= FrontendReadDiskValue32(Frontend,
                                        "sector-size",
-                                       &Frontend->DiskInfo.SectorSize);
+                                       &DiskInfo->SectorSize);
     Changed |= FrontendReadDiskValue32(Frontend,
                                        "physical-sector-size",
-                                       &Frontend->DiskInfo.PhysSectorSize);
+                                       &DiskInfo->PhysSectorSize);
     Changed |= FrontendReadValue64(Frontend,
                                    "sectors",
-                                   &Frontend->DiskInfo.SectorCount);
+                                   &DiskInfo->BlkifSectorCount);
 
     if (!Changed)
         return;
 
-    if (Frontend->DiskInfo.DiskInfo & VDISK_READONLY) {
-        Warning("Target[%d] : DiskInfo contains VDISK_READONLY flag!\n", 
Frontend->TargetId);
+    if (DiskInfo->DiskInfo & VDISK_READONLY) {
+        Warning("Target[%d] : DiskInfo contains VDISK_READONLY flag!\n",
+                Frontend->TargetId);
     }
-    if (Frontend->DiskInfo.DiskInfo & VDISK_CDROM) {
-        Warning("Target[%d] : DiskInfo contains VDISK_CDROM flag!\n", 
Frontend->TargetId);
+    if (DiskInfo->DiskInfo & VDISK_CDROM) {
+        Warning("Target[%d] : DiskInfo contains VDISK_CDROM flag!\n",
+                Frontend->TargetId);
     }
-    if (Frontend->DiskInfo.SectorSize == 0) {
-        Error("Target[%d] : Invalid SectorSize!\n", Frontend->TargetId);
+    if (DiskInfo->SectorSize < BLKIF_SECTOR_SIZE ||
+        (DiskInfo->SectorSize & (DiskInfo->SectorSize - 1)) != 0) {
+        Error("Target[%d] : Invalid SectorSize %lu, defaulting to %u!\n",
+              Frontend->TargetId,
+              DiskInfo->SectorSize,
+              BLKIF_SECTOR_SIZE);
+        DiskInfo->SectorSize = BLKIF_SECTOR_SIZE;
     }
-    if (Frontend->DiskInfo.SectorCount == 0) {
-        Error("Target[%d] : Invalid SectorCount!\n", Frontend->TargetId);
+    // infallible due to check above
+    BitScanForward(&DiskInfo->SectorShift, DiskInfo->SectorSize);
+    DiskInfo->SectorShift -= BLKIF_SECTOR_SHIFT;
+    if (DiskInfo->PhysSectorSize < DiskInfo->SectorSize ||
+        DiskInfo->PhysSectorSize % DiskInfo->SectorSize != 0) {
+        Error("Target[%d] : Invalid PhysSectorSize %lu, defaulting to %lu!\n",
+              Frontend->TargetId,
+              DiskInfo->PhysSectorSize,
+              DiskInfo->SectorSize);
+        DiskInfo->PhysSectorSize = DiskInfo->SectorSize;
     }
-    if (Frontend->DiskInfo.PhysSectorSize == 0) {
-        Frontend->DiskInfo.PhysSectorSize = Frontend->DiskInfo.SectorSize;
+    if (DiskInfo->BlkifSectorCount == 0 ||
+        DiskInfo->BlkifSectorCount % (DiskInfo->PhysSectorSize >>
+                                               DiskInfo->SectorShift) != 0) {
+        Error("Target[%d] : Invalid BlkifSectorCount %llu!\n",
+              Frontend->TargetId,
+              DiskInfo->BlkifSectorCount);
     }
 
     // dump actual values
-    Trace("Target[%d] : %lld sectors of %d bytes (%d)\n", Frontend->TargetId,
-          Frontend->DiskInfo.SectorCount, Frontend->DiskInfo.SectorSize,
-          Frontend->DiskInfo.PhysSectorSize);
-    Trace("Target[%d] : %d %s (%08x)\n", Frontend->TargetId,
-          __Size(&Frontend->DiskInfo), __Units(&Frontend->DiskInfo),
-          Frontend->DiskInfo.DiskInfo);
+    Trace("Target[%d] : %llu %luB blocks, %luB logical sectors (2^%lu), "
+          "%luB physical sectors\n",
+          Frontend->TargetId,
+          DiskInfo->BlkifSectorCount,
+          BLKIF_SECTOR_SIZE,
+          DiskInfo->SectorSize,
+          DiskInfo->SectorShift,
+          DiskInfo->PhysSectorSize);
+    Trace("Target[%d] : %d %s (%08x)\n",
+          Frontend->TargetId,
+          __Size(&Frontend->DiskInfo),
+          __Units(&Frontend->DiskInfo),
+          DiskInfo->DiskInfo);
 }
 
 static FORCEINLINE VOID
@@ -1590,9 +1617,12 @@ FrontendDebugCallback(
 
     XENBUS_DEBUG(Printf,
                  &Frontend->DebugInterface,
-                 "DiskInfo: %llu @ %u (%u) %08x\n",
-                 Frontend->DiskInfo.SectorCount,
+                 "DiskInfo: %llu %luB blocks, %luB logical sectors (2^%lu), "
+                 "%luB physical sectors, info %08x\n",
+                 Frontend->DiskInfo.BlkifSectorCount,
+                 BLKIF_SECTOR_SIZE,
                  Frontend->DiskInfo.SectorSize,
+                 Frontend->DiskInfo.SectorShift,
                  Frontend->DiskInfo.PhysSectorSize,
                  Frontend->DiskInfo.DiskInfo);
 }
@@ -1814,7 +1844,7 @@ FrontendCreate(
     Frontend->TargetId = TargetId;
     Frontend->DeviceId = strtoul(DeviceId, NULL, 10);
     Frontend->State = XENVBD_INITIALIZED;
-    Frontend->DiskInfo.SectorSize = 512; // default sector size
+    Frontend->DiskInfo.SectorSize = BLKIF_SECTOR_SIZE; // default sector size
     Frontend->BackendDomain = DOMID_INVALID;
 
     Frontend->MaxQueues = DriverGetMaxQueues();
diff --git a/src/xenvbd/frontend.h b/src/xenvbd/frontend.h
index dc7b55f..3c304f0 100644
--- a/src/xenvbd/frontend.h
+++ b/src/xenvbd/frontend.h
@@ -35,6 +35,10 @@
 
 #include <ntddk.h>
 
+// This is the fixed size, in bytes, of a sector used in the blkif protocol.
+#define BLKIF_SECTOR_SHIFT      9
+#define BLKIF_SECTOR_SIZE       (1U << BLKIF_SECTOR_SHIFT)
+
 typedef enum _XENVBD_STATE {
     XENVBD_STATE_INVALID,
     XENVBD_INITIALIZED, // -> { CLOSED }
@@ -65,8 +69,12 @@ typedef struct _XENVBD_FEATURES {
 } XENVBD_FEATURES, *PXENVBD_FEATURES;
 
 typedef struct _XENVBD_DISKINFO {
-    ULONG64                     SectorCount;
+    // each "sector" here is of size BLKIF_SECTOR_SIZE
+    ULONG64                     BlkifSectorCount;
+    // logical sector size as used by Windows for addressing
     ULONG                       SectorSize;
+    // log2(sector size / BLKIF_SECTOR_SIZE)
+    ULONG                       SectorShift;
     ULONG                       PhysSectorSize;
     ULONG                       DiskInfo;
 } XENVBD_DISKINFO, *PXENVBD_DISKINFO;
diff --git a/src/xenvbd/ring.c b/src/xenvbd/ring.c
index 1e8f761..2a4eb56 100644
--- a/src/xenvbd/ring.c
+++ b/src/xenvbd/ring.c
@@ -125,6 +125,8 @@ struct _XENVBD_RING {
 #define RING_POOL_TAG               'gnRX'
 #define XEN_IO_PROTO_ABI            "x86_64-abi"
 
+#define SECTORS_PER_PAGE            ((ULONG)(PAGE_SIZE / BLKIF_SECTOR_SIZE))
+
 static FORCEINLINE PVOID
 __RingAllocate(
     IN  ULONG                       Length
@@ -181,15 +183,6 @@ __StatName(
     }
 }
 
-static FORCEINLINE ULONG
-__SectorsPerPage(
-    IN  ULONG   SectorSize
-    )
-{
-    ASSERT3U(SectorSize, != , 0);
-    return PAGE_SIZE / SectorSize;
-}
-
 static FORCEINLINE VOID
 __Operation(
     IN  UCHAR       CdbOp,
@@ -213,7 +206,6 @@ __Operation(
 
 static FORCEINLINE ULONG
 __UseIndirect(
-    IN  ULONG           SectorsPerPage,
     IN  ULONG           MaxIndirectSegs,
     IN  ULONG           SectorsLeft
     )
@@ -221,7 +213,7 @@ __UseIndirect(
     if (MaxIndirectSegs <= BLKIF_MAX_SEGMENTS_PER_REQUEST)
         return BLKIF_MAX_SEGMENTS_PER_REQUEST; // not supported
 
-    if (SectorsLeft < BLKIF_MAX_SEGMENTS_PER_REQUEST * SectorsPerPage)
+    if (SectorsLeft < BLKIF_MAX_SEGMENTS_PER_REQUEST * SECTORS_PER_PAGE)
         return BLKIF_MAX_SEGMENTS_PER_REQUEST; // first into a single 
BLKIF_OP_{READ/WRITE}
 
     return MaxIndirectSegs;
@@ -646,7 +638,6 @@ BlkifRingPrepareSegment(
     PXENVBD_ADAPTER         Adapter = TargetGetAdapter(Target);
 
     const ULONG             SectorSize = 
FrontendGetDiskInfo(Ring->Frontend)->SectorSize;
-    const ULONG             SectorsPerPage = __SectorsPerPage(SectorSize);
 
     Pfn = AdapterGetNextSGEntry(Adapter,
                                 SrbExt,
@@ -658,11 +649,11 @@ BlkifRingPrepareSegment(
         InterlockedIncrement(&Ring->Stats[XENVBD_STAT_SEGMENTS_GRANTED]);
 
         // get first sector, last sector and count
-        Segment->FirstSector = (UCHAR)((Offset + SectorSize - 1) / SectorSize);
-        *SectorsNow = __min(SectorsLeft, SectorsPerPage - 
Segment->FirstSector);
+        Segment->FirstSector = (UCHAR)((Offset + BLKIF_SECTOR_SIZE - 1) / 
BLKIF_SECTOR_SIZE);
+        *SectorsNow = __min(SectorsLeft, SECTORS_PER_PAGE - 
Segment->FirstSector);
         Segment->LastSector = (UCHAR)(Segment->FirstSector + *SectorsNow - 1);
 
-        ASSERT3U((Length / SectorSize), == , *SectorsNow);
+        ASSERT3U((Length / BLKIF_SECTOR_SIZE), == , *SectorsNow);
     } else {
         PXENVBD_BOUNCE      Bounce;
         PMDL                Mdl;
@@ -672,7 +663,7 @@ BlkifRingPrepareSegment(
 
         // get first sector, last sector and count
         Segment->FirstSector = 0;
-        *SectorsNow = __min(SectorsLeft, SectorsPerPage);
+        *SectorsNow = __min(SectorsLeft, SECTORS_PER_PAGE);
         Segment->LastSector = (UCHAR)(*SectorsNow - 1);
 
         Bounce = AdapterGetBounce(Adapter);
@@ -693,7 +684,7 @@ BlkifRingPrepareSegment(
         Mdl->ByteOffset = Offset;
         Bounce->SourcePfn[0] = Pfn;
 
-        if (Length < *SectorsNow * SectorSize) {
+        if (Length < *SectorsNow * BLKIF_SECTOR_SIZE) {
             Pfn = AdapterGetNextSGEntry(Adapter,
                                         SrbExt,
                                         Length,
@@ -705,9 +696,9 @@ BlkifRingPrepareSegment(
         }
 #pragma warning(pop)
 
-        ASSERT((Mdl->ByteCount & (SectorSize - 1)) == 0);
+        ASSERT((Mdl->ByteCount & (BLKIF_SECTOR_SIZE - 1)) == 0);
         ASSERT3U(Mdl->ByteCount, <= , PAGE_SIZE);
-        ASSERT3U(*SectorsNow, == , (Mdl->ByteCount / SectorSize));
+        ASSERT3U(*SectorsNow, == , (Mdl->ByteCount / BLKIF_SECTOR_SIZE));
 
         Bounce->SourcePtr = MmMapLockedPagesSpecifyCache(Mdl,
                                                          KernelMode,
@@ -753,15 +744,13 @@ BlkifRingPrepareReadWrite(
     PXENVBD_RING            Ring = BlkifRing->Ring;
     PXENVBD_FRONTEND        Frontend = Ring->Frontend;
     PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
-    ULONG64                 SectorStart = Cdb_LogicalBlock(Srb);
-    ULONG                   SectorsLeft = Cdb_TransferBlock(Srb);
     UCHAR                   Operation;
     BOOLEAN                 ReadOnly;
     LIST_ENTRY              List;
-
-    const ULONG             SectorSize = 
FrontendGetDiskInfo(Frontend)->SectorSize;
-    const ULONG             SectorsPerPage = __SectorsPerPage(SectorSize);
     const ULONG             MaxIndirect = 
FrontendGetFeatures(Frontend)->Indirect;
+    const ULONG             SectorShift = 
FrontendGetDiskInfo(Frontend)->SectorShift;
+    ULONG64                 SectorStart = Cdb_LogicalBlock(Srb) << SectorShift;
+    ULONG                   SectorsLeft = Cdb_TransferBlock(Srb) << 
SectorShift;
 
     InitializeListHead(&List);
 
@@ -784,9 +773,7 @@ BlkifRingPrepareReadWrite(
 
         Request->SrbExt = SrbExt;
 
-        MaxSegments = __UseIndirect(SectorsPerPage,
-                                    MaxIndirect,
-                                    SectorsLeft);
+        MaxSegments = __UseIndirect(MaxIndirect, SectorsLeft);
 
         Request->Operation = Operation;
         Request->NrSegments = 0;
@@ -857,11 +844,14 @@ BlkifRingPrepareUnmap(
     IN  PXENVBD_SRBEXT      SrbExt
     )
 {
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_FRONTEND        Frontend = Ring->Frontend;
     PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
     PUNMAP_LIST_HEADER      Unmap = Srb->DataBuffer;
     ULONG                   Count;
     ULONG                   Index;
     LIST_ENTRY              List;
+    const ULONG             SectorShift = 
FrontendGetDiskInfo(Frontend)->SectorShift;
 
     InitializeListHead(&List);
 
@@ -873,6 +863,8 @@ BlkifRingPrepareUnmap(
     for (Index = 0; Index < Count; ++Index) {
         PUNMAP_BLOCK_DESCRIPTOR Descr = &Unmap->Descriptors[Index];
         PXENVBD_REQUEST         Request;
+        ULONG64                 FirstSector;
+        ULONG                   NrSectors;
 
         Request = BlkifRingGetRequest(BlkifRing);
         if (Request == NULL)
@@ -880,10 +872,13 @@ BlkifRingPrepareUnmap(
         InsertTailList(&List, &Request->ListEntry);
         SrbExt->RequestCount++;
 
+        FirstSector = _byteswap_uint64(*(PULONG64)Descr->StartingLba) << 
SectorShift;
+        NrSectors = _byteswap_ulong(*(PULONG)Descr->LbaCount) << SectorShift;
+
         Request->SrbExt = SrbExt;
         Request->Operation = BLKIF_OP_DISCARD;
-        Request->FirstSector = _byteswap_uint64(*(PULONG64)Descr->StartingLba);
-        Request->NrSectors = _byteswap_ulong(*(PULONG)Descr->LbaCount);
+        Request->FirstSector = FirstSector;
+        Request->NrSectors = NrSectors;
         Request->Flags = 0;
     }
 
@@ -909,6 +904,7 @@ BlkifRingPrepareSyncCache(
     PXENVBD_REQUEST         Request;
     UCHAR                   Operation;
     LIST_ENTRY              List;
+    const ULONG             SectorShift = 
FrontendGetDiskInfo(Frontend)->SectorShift;
 
     InitializeListHead(&List);
     Srb->SrbStatus = SRB_STATUS_PENDING;
@@ -928,7 +924,7 @@ BlkifRingPrepareSyncCache(
 
     Request->SrbExt = SrbExt;
     Request->Operation = Operation;
-    Request->FirstSector = Cdb_LogicalBlock(Srb);
+    Request->FirstSector = Cdb_LogicalBlock(Srb) << SectorShift;
 
     BlkifRingQueueRequests(BlkifRing, &List);
     return STATUS_SUCCESS;
diff --git a/src/xenvbd/target.c b/src/xenvbd/target.c
index 102e8b8..128ae63 100644
--- a/src/xenvbd/target.c
+++ b/src/xenvbd/target.c
@@ -218,6 +218,7 @@ TargetReadWrite(
     PXENVBD_SRBEXT          SrbExt = Srb->SrbExtension;
     PXENVBD_FRONTEND        Frontend = Target->Frontend;
     PXENVBD_RING            Ring = FrontendGetRing(Frontend);
+    PXENVBD_DISKINFO        DiskInfo = FrontendGetDiskInfo(Target->Frontend);
     ULONG64                 SectorCount;
     ULONG64                 SectorStart;
     ULONG                   NumSectors;
@@ -227,14 +228,14 @@ TargetReadWrite(
         goto fail1;
 
     // disallow writes to read-only disks
-    if (FrontendGetDiskInfo(Frontend)->DiskInfo & VDISK_READONLY &&
+    if (DiskInfo->DiskInfo & VDISK_READONLY &&
         Cdb_OperationEx(Srb) == SCSIOP_WRITE)
         goto fail2;
 
     // check Sectors requested is on the disk
-    SectorCount = FrontendGetDiskInfo(Frontend)->SectorCount;
-    SectorStart = Cdb_LogicalBlock(Srb);
-    NumSectors = Cdb_TransferBlock(Srb);
+    SectorCount = DiskInfo->BlkifSectorCount;
+    SectorStart = Cdb_LogicalBlock(Srb) << DiskInfo->SectorShift;
+    NumSectors = Cdb_TransferBlock(Srb) << DiskInfo->SectorShift;
 
     if (SectorStart >= SectorCount)
         goto fail3;
@@ -560,7 +561,7 @@ TargetReadCapacity(
     if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0)
         goto fail3;
 
-    SectorCount = DiskInfo->SectorCount;
+    SectorCount = DiskInfo->BlkifSectorCount >> DiskInfo->SectorShift;
     SectorSize = DiskInfo->SectorSize;
 
     if (SectorCount == (ULONG)SectorCount)
@@ -611,7 +612,7 @@ TargetReadCapacity16(
     if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0)
         goto fail3;
 
-    SectorCount = DiskInfo->SectorCount;
+    SectorCount = DiskInfo->BlkifSectorCount >> DiskInfo->SectorShift;
     SectorSize = DiskInfo->SectorSize;
     PhysSectorSize = DiskInfo->PhysSectorSize;
 
-- 
2.54.0.windows.1



--
Ngoc Tu Dinh | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.