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

[PATCH 6/6] xencrsh: 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:35 +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:48 +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/xencrsh/frontend.c |  25 ++++++----
 src/xencrsh/frontend.h |  10 +++-
 src/xencrsh/pdo.c      | 103 +++++++++++++++++++++++++++--------------
 3 files changed, 92 insertions(+), 46 deletions(-)

diff --git a/src/xencrsh/frontend.c b/src/xencrsh/frontend.c
index 32ba1df..0cb4dd6 100644
--- a/src/xencrsh/frontend.c
+++ b/src/xencrsh/frontend.c
@@ -523,22 +523,29 @@ __ReadDiskInfo(
     Status = StoreRead(NULL, Frontend->BackendPath, 
                         "sectors", &Buffer);
     if (NT_SUCCESS(Status)) {
-        Frontend->SectorCount = _strtoui64(Buffer, NULL, 10);
+        Frontend->BlkifSectorCount = _strtoui64(Buffer, NULL, 10);
         AustereFree(Buffer);
         Updated = TRUE;
     }
 
-    if (Frontend->SectorCount == 0) {
-        LogError("Invalid SectorCount!\n");
+    if (Frontend->BlkifSectorCount == 0) {
+        LogError("Invalid BlkifSectorCount!\n");
     }
-    if (Frontend->SectorSize == 0) {
+    if (Frontend->SectorSize < BLKIF_SECTOR_SIZE ||
+        (Frontend->SectorSize & (Frontend->SectorSize - 1)) != 0) {
         LogError("Invalid SectorSize!\n");
+        Frontend->SectorSize = BLKIF_SECTOR_SIZE;
     }
+    BitScanForward(&Frontend->SectorShift, Frontend->SectorSize);
+    Frontend->SectorShift -= BLKIF_SECTOR_SHIFT;
     if (Updated) {
-        LogVerbose("DiskInfo: %08x, %lld sectors of %d bytes (%lld KB or %lld 
MB)\n", 
-                    Frontend->DiskInfo, Frontend->SectorCount, 
Frontend->SectorSize, 
-                    (Frontend->SectorSize * Frontend->SectorCount) / 1024,
-                    (Frontend->SectorSize * Frontend->SectorCount) / (1024 * 
1024));
+        LogVerbose("DiskInfo: %llu %luB blocks, %luB logical sectors (2^%lu), "
+                   "info %08x\n",
+                   Frontend->BlkifSectorCount,
+                   BLKIF_SECTOR_SIZE,
+                   Frontend->SectorSize,
+                   Frontend->SectorShift,
+                   Frontend->DiskInfo);
     }
     if (Frontend->DiskInfo & VDISK_READONLY) {
         LogWarning("DiskInfo contains VDISK_READONLY flag!\n");
@@ -919,7 +926,7 @@ FrontendCreate(
     Frontend->TargetId = TargetId;
     Frontend->DeviceId = strtoul(DeviceId, NULL, 10);
     Frontend->State = XENVBD_INITIALIZED;
-    Frontend->SectorSize = 512; // default value
+    Frontend->SectorSize = BLKIF_SECTOR_SIZE; // default value
 
     Frontend->FrontendPath = DriverFormat("device/vbd/%s", DeviceId);
     if (Frontend->FrontendPath == NULL)
diff --git a/src/xencrsh/frontend.h b/src/xencrsh/frontend.h
index 2e2c305..5b0030a 100644
--- a/src/xencrsh/frontend.h
+++ b/src/xencrsh/frontend.h
@@ -39,6 +39,10 @@
 #include "pdo.h"
 #include "ring.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,
@@ -69,8 +73,12 @@ typedef struct _XENVBD_FRONTEND {
     BOOLEAN                     DumpFile;
 
     // Disk Info
+    // each "sector" here is of size BLKIF_SECTOR_SIZE
+    ULONG64                     BlkifSectorCount;
+    // logical sector size as used by Windows for addressing
     ULONG                       SectorSize;
-    ULONG64                     SectorCount;
+    // log2(sector size / BLKIF_SECTOR_SIZE)
+    ULONG                       SectorShift;
     ULONG                       DiskInfo;
 
     // Inquiry
diff --git a/src/xencrsh/pdo.c b/src/xencrsh/pdo.c
index 76c4d59..0335205 100644
--- a/src/xencrsh/pdo.c
+++ b/src/xencrsh/pdo.c
@@ -32,6 +32,8 @@
 
 #include "pdo.h"
 
+#include <limits.h>
+
 #include "driver.h"
 #include "fdo.h"
 #include "frontend.h"
@@ -53,6 +55,8 @@
 #include "assert.h"
 #include "util.h"
 
+#define SECTORS_PER_PAGE            ((ULONG)(PAGE_SIZE / BLKIF_SECTOR_SIZE))
+
 typedef struct _XENVBD_SG_INDEX {
     ULONG       Index;
     ULONG       Offset;
@@ -305,13 +309,6 @@ static FORCEINLINE ULONG __SectorSize(
     ASSERT3U(Pdo->Frontend.SectorSize, !=, 0);
     return Pdo->Frontend.SectorSize;
 }
-static FORCEINLINE ULONG __SectorsPerPage(
-    IN  ULONG                   SectorSize
-    )
-{
-    ASSERT3U(SectorSize, !=, 0);
-    return PAGE_SIZE / SectorSize;
-}
 static FORCEINLINE VOID
 __Operation(
     IN  UCHAR                   CdbOp,
@@ -402,12 +399,12 @@ PrepareReadWrite(
     PSTOR_SCATTER_GATHER_LIST   SGList;
     XENVBD_SG_INDEX             SGIndex;
 
-    PXENVBD_SRBEXT  SrbExt = GetSrbExt(Srb);
+    PXENVBD_FRONTEND            Frontend = &Pdo->Frontend;
+    PXENVBD_SRBEXT              SrbExt = GetSrbExt(Srb);
 
-    const ULONG64   StartSector     = Cdb_LogicalBlock(Srb);
-    const ULONG     NumSectors      = Cdb_TransferBlock(Srb);
+    const ULONG64   StartSector     = Cdb_LogicalBlock(Srb) << 
Frontend->SectorShift;
+    const ULONG     NumSectors      = Cdb_TransferBlock(Srb) << 
Frontend->SectorShift;
     const ULONG     SectorSize      = __SectorSize(Pdo);
-    const ULONG     SectorsPerPage  = __SectorsPerPage(SectorSize);
     __Operation(Cdb_OperationEx(Srb), &Operation, &ReadOnly);
 
     SGList = StorPortGetScatterGatherList(Pdo->Fdo, Srb);
@@ -439,13 +436,15 @@ PrepareReadWrite(
                 ULONG Type;
 
                 // get first sector, last sector and count
-                FirstSector = (__Offset(PhysAddr) + SectorSize - 1) / 
SectorSize;
-                SectorsNow  = __Min(NumSectors - SectorsDone, SectorsPerPage - 
FirstSector);
+                FirstSector = (__Offset(PhysAddr) + BLKIF_SECTOR_SIZE - 1) /
+                    BLKIF_SECTOR_SIZE;
+                SectorsNow  = __Min(NumSectors - SectorsDone,
+                                    SECTORS_PER_PAGE - FirstSector);
                 LastSector  = FirstSector + SectorsNow - 1;
 
-                ASSERT3U((PhysLen / SectorSize), ==, SectorsNow);
-                ASSERT3U((PhysLen & (SectorSize - 1)), ==, 0);
-               
+                ASSERT3U((PhysLen / BLKIF_SECTOR_SIZE), ==, SectorsNow);
+                ASSERT3U((PhysLen & (BLKIF_SECTOR_SIZE - 1)), ==, 0);
+
                 // simples - grab Pfn of PhysAddr
                 Pfn         = __Pfn(PhysAddr);
 
@@ -471,7 +470,7 @@ PrepareReadWrite(
 
                 // get first sector, last sector and count
                 FirstSector = 0;
-                SectorsNow  = __Min(NumSectors - SectorsDone, SectorsPerPage);
+                SectorsNow  = __Min(NumSectors - SectorsDone, 
SECTORS_PER_PAGE);
                 LastSector  = SectorsNow - 1;
 
                 // map PhysAddr to 1 or 2 pages and lock for VirtAddr
@@ -489,19 +488,19 @@ PrepareReadWrite(
                 Request->Segments[Index2].Pfn[0] = __Pfn(PhysAddr);
 #pragma warning(pop)
 
-                if (PhysLen < SectorsNow * SectorSize) {
+                if (PhysLen < SectorsNow * BLKIF_SECTOR_SIZE) {
                     __GetPhysAddr(SGList, &SGIndex, &PhysAddr, &PhysLen);
                     Mdl->Size       += sizeof(PFN_NUMBER);
                     Mdl->ByteCount  = Mdl->ByteCount + PhysLen;
                     Request->Segments[Index2].Pfn[1] = __Pfn(PhysAddr);
                 }
 
-                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));
+
                 Length = __Min(Mdl->ByteCount, PAGE_SIZE);
-                Buffer = MmMapLockedPagesSpecifyCache(Mdl, KernelMode, 
+                Buffer = MmMapLockedPagesSpecifyCache(Mdl, KernelMode,
                                         MmCached, NULL, FALSE, 
HighPagePriority);
                 if (!Buffer) {
                     Pdo->NeedsWake = TRUE;
@@ -585,7 +584,7 @@ PrepareSyncCache(
 
     Request->Operation      = Operation;
     Request->NrSegments     = 0;
-    Request->FirstSector    = Cdb_LogicalBlock(Srb);
+    Request->FirstSector    = Cdb_LogicalBlock(Srb) << 
Pdo->Frontend.SectorShift;
     Request->NrSectors      = 0;
 
     __UpdateStats(Pdo, Operation);
@@ -743,13 +742,27 @@ PdoCompleteSubmittedRequest(
 
 static FORCEINLINE BOOLEAN
 __ValidateSectors(
-    IN  ULONG64                 SectorCount,
-    IN  ULONG64                 Start,
-    IN  ULONG                   Length
+    _In_ PXENVBD_FRONTEND   Frontend,
+    _In_ ULONG64            StartLBA,
+    _In_ ULONG64            CountLBA
     )
 {
-    // Deal with overflow
-    return (Start < SectorCount) && ((Start + Length) < SectorCount);
+    ULONG64                 BlkifSectorStart;
+    ULONG64                 BlkifSectorEnd;
+
+    if (StartLBA > (ULLONG_MAX >> Frontend->SectorShift) ||
+        CountLBA > (ULLONG_MAX >> Frontend->SectorShift))
+        return FALSE;
+
+    BlkifSectorStart = StartLBA << Frontend->SectorShift;
+    BlkifSectorEnd = BlkifSectorStart + (CountLBA << Frontend->SectorShift);
+    if (BlkifSectorEnd < BlkifSectorStart)
+        return FALSE;
+
+    if (BlkifSectorEnd > Frontend->BlkifSectorCount)
+        return FALSE;
+
+    return TRUE;
 }
 static BOOLEAN
 PdoReadWrite(
@@ -765,8 +778,13 @@ PdoReadWrite(
         return TRUE;
     }
     // check valid sectors
-    if (!__ValidateSectors(Pdo->Frontend.SectorCount, Cdb_LogicalBlock(Srb), 
Cdb_TransferBlock(Srb))) {
-        LogTrace("Target[%d] : Invalid Sectors (%lld, %lld, %d)\n", 
Pdo->Frontend.TargetId, Pdo->Frontend.SectorCount, Cdb_LogicalBlock(Srb), 
Cdb_TransferBlock(Srb));
+    if (!__ValidateSectors(&Pdo->Frontend,
+                           Cdb_LogicalBlock(Srb),
+                           Cdb_TransferBlock(Srb))) {
+        LogTrace("Target[%lu] : Invalid Sectors (%llu, %lu)\n",
+                 Pdo->Frontend.TargetId,
+                 Cdb_LogicalBlock(Srb),
+                 Cdb_TransferBlock(Srb));
         Srb->ScsiStatus = 0x40; // SCSI_ABORT
         return TRUE; // Complete now
     }
@@ -791,7 +809,18 @@ PdoSyncCache(
         Srb->ScsiStatus = 0x40; // SCSI_ABORT;
         return TRUE;
     }
- 
+    // check valid sectors
+    if (!__ValidateSectors(&Pdo->Frontend,
+                           Cdb_LogicalBlock(Srb),
+                           Cdb_TransferBlock(Srb))) {
+        LogTrace("Target[%lu] : Invalid Sectors (%llu, %lu)\n",
+                 Pdo->Frontend.TargetId,
+                 Cdb_LogicalBlock(Srb),
+                 Cdb_TransferBlock(Srb));
+        Srb->ScsiStatus = 0x40; // SCSI_ABORT
+        return TRUE; // Complete now
+    }
+
     PrepareSyncCache(Pdo, Srb);
     PdoSubmitPrepared(Pdo);
     return FALSE;
@@ -964,13 +993,14 @@ PdoReadCapacity(
     IN  PSCSI_REQUEST_BLOCK     Srb
     )
 {
+    PXENVBD_FRONTEND        Frontend = &Pdo->Frontend;
     PREAD_CAPACITY_DATA     Capacity = Srb->DataBuffer;
     ULONG64                 SectorCount;
     ULONG                   SectorSize;
     ULONG                   LastBlock;
-    
-    SectorCount = Pdo->Frontend.SectorCount;
-    SectorSize = Pdo->Frontend.SectorSize;
+
+    SectorCount = Frontend->BlkifSectorCount >> Frontend->SectorShift;
+    SectorSize = Frontend->SectorSize;
 
     if (SectorCount == (ULONG)SectorCount)
         LastBlock = (ULONG)SectorCount - 1;
@@ -990,12 +1020,13 @@ PdoReadCapacity16(
     IN  PSCSI_REQUEST_BLOCK     Srb
     )
 {
+    PXENVBD_FRONTEND        Frontend = &Pdo->Frontend;
     PREAD_CAPACITY_DATA_EX  Capacity = Srb->DataBuffer;
     ULONG64                 SectorCount;
     ULONG                   SectorSize;
 
-    SectorCount = Pdo->Frontend.SectorCount;
-    SectorSize = Pdo->Frontend.SectorSize;
+    SectorCount = Frontend->BlkifSectorCount >> Frontend->SectorShift;
+    SectorSize = Frontend->SectorSize;
 
     if (Capacity) {
         Capacity->LogicalBlockAddress.QuadPart = _byteswap_uint64(SectorCount 
- 1);
-- 
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®.