diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
index 36527a523f28..decd4418af3d 100644
--- a/OvmfPkg/Include/Library/VirtioLib.h
+++ b/OvmfPkg/Include/Library/VirtioLib.h
@@ -2,7 +2,7 @@
 
   Declarations of utility functions used by virtio device drivers.
 
-  Copyright (C) 2012, Red Hat, Inc.
+  Copyright (C) 2012-2016, Red Hat, Inc.
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -167,6 +167,12 @@ VirtioAppendDesc (
                           Indices->HeadDescIdx identifies the head descriptor
                           of the descriptor chain.
 
+  @param[out] UsedLen     On success, the total number of bytes, consecutively
+                          across the buffers linked by the descriptor chain,
+                          that the host wrote. May be NULL if the caller
+                          doesn't care, or can compute the same information
+                          from device-specific request structures linked by the
+                          descriptor chain.
 
   @return              Error code from VirtIo->SetQueueNotify() if it fails.
 
@@ -179,7 +185,8 @@ VirtioFlush (
   IN     VIRTIO_DEVICE_PROTOCOL *VirtIo,
   IN     UINT16                 VirtQueueId,
   IN OUT VRING                  *Ring,
-  IN     DESC_INDICES           *Indices
+  IN     DESC_INDICES           *Indices,
+  OUT    UINT32                 *UsedLen    OPTIONAL
   );
 
 #endif // _VIRTIO_LIB_H_
diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
index 54cf225c9885..4b1d78b5a03e 100644
--- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
+++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
@@ -2,7 +2,7 @@
 
   Utility functions used by virtio device drivers.
 
-  Copyright (C) 2012, Red Hat, Inc.
+  Copyright (C) 2012-2016, Red Hat, Inc.
   Portion of Copyright (C) 2013, ARM Ltd.
 
   This program and the accompanying materials are licensed and made available
@@ -249,6 +249,12 @@ VirtioAppendDesc (
                           Indices->HeadDescIdx identifies the head descriptor
                           of the descriptor chain.
 
+  @param[out] UsedLen     On success, the total number of bytes, consecutively
+                          across the buffers linked by the descriptor chain,
+                          that the host wrote. May be NULL if the caller
+                          doesn't care, or can compute the same information
+                          from device-specific request structures linked by the
+                          descriptor chain.
 
   @return              Error code from VirtIo->SetQueueNotify() if it fails.
 
@@ -261,10 +267,12 @@ VirtioFlush (
   IN     VIRTIO_DEVICE_PROTOCOL *VirtIo,
   IN     UINT16                 VirtQueueId,
   IN OUT VRING                  *Ring,
-  IN     DESC_INDICES           *Indices
+  IN     DESC_INDICES           *Indices,
+  OUT    UINT32                 *UsedLen    OPTIONAL
   )
 {
   UINT16     NextAvailIdx;
+  UINT16     LastUsedIdx;
   EFI_STATUS Status;
   UINTN      PollPeriodUsecs;
 
@@ -276,6 +284,11 @@ VirtioFlush (
   // head descriptor of any given descriptor chain.
   //
   NextAvailIdx = *Ring->Avail.Idx;
+  //
+  // (Due to our lock-step progress, this is where the host will produce the
+  // used element with the head descriptor's index in it.)
+  //
+  LastUsedIdx = NextAvailIdx;
   Ring->Avail.Ring[NextAvailIdx++ % Ring->QueueSize] =
     Indices->HeadDescIdx % Ring->QueueSize;
 
@@ -315,5 +328,14 @@ VirtioFlush (
   }
 
   MemoryFence();
+
+  if (UsedLen != NULL) {
+    volatile CONST VRING_USED_ELEM *UsedElem;
+
+    UsedElem = &Ring->Used.UsedElem[LastUsedIdx % Ring->QueueSize];
+    ASSERT (UsedElem->Id == Indices->HeadDescIdx);
+    *UsedLen = UsedElem->Len;
+  }
+
   return EFI_SUCCESS;
 }
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index 75f85ca6e09a..50511a1e446b 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -324,7 +324,8 @@ SynchronousRequest (
   //
   // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
   //
-  if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&
+  if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices,
+        NULL) == EFI_SUCCESS &&
       HostStatus == VIRTIO_BLK_S_OK) {
     return EFI_SUCCESS;
   }
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
index e1e12039b359..f5f412a32e9b 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
@@ -470,7 +470,7 @@ VirtioScsiPassThru (
   // caller retry.
   //
   if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,
-        &Indices) != EFI_SUCCESS) {
+        &Indices, NULL) != EFI_SUCCESS) {
     Packet->InTransferLength  = 0;
     Packet->OutTransferLength = 0;
     Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
