Re: [PATCH net V3] vhost: log dirty page correctly

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

 




On 2019/1/15 上午2:04, Michael S. Tsirkin wrote:
On Fri, Jan 11, 2019 at 12:00:36PM +0800, Jason Wang wrote:
Vhost dirty page logging API is designed to sync through GPA. But we
try to log GIOVA when device IOTLB is enabled. This is wrong and may
lead to missing data after migration.

To solve this issue, when logging with device IOTLB enabled, we will:

1) reuse the device IOTLB translation result of GIOVA->HVA mapping to
    get HVA, for writable descriptor, get HVA through iovec. For used
    ring update, translate its GIOVA to HVA
2) traverse the GPA->HVA mapping to get the possible GPA and log
    through GPA. Pay attention this reverse mapping is not guaranteed
    to be unique, so we should log each possible GPA in this case.

This fix the failure of scp to guest during migration. In -next, we
will probably support passing GIOVA->GPA instead of GIOVA->HVA.

Fixes: 6b1e6cc7855b ("vhost: new device IOTLB API")
Reported-by: Jintack Lim<jintack@xxxxxxxxxxxxxxx>
Cc: Jintack Lim<jintack@xxxxxxxxxxxxxxx>
Signed-off-by: Jason Wang<jasowang@xxxxxxxxxx>
---
Changes from V2:
- check and log the case of range overlap
- remove unnecessary u64 cast
- use smp_wmb() for the case of device IOTLB as well
Changes from V1:
- return error instead of warn
---
  drivers/vhost/net.c   |  3 +-
  drivers/vhost/vhost.c | 88 ++++++++++++++++++++++++++++++++++++-------
  drivers/vhost/vhost.h |  3 +-
  3 files changed, 78 insertions(+), 16 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 36f3d0f49e60..bca86bf7189f 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -1236,7 +1236,8 @@ static void handle_rx(struct vhost_net *net)
  		if (nvq->done_idx > VHOST_NET_BATCH)
  			vhost_net_signal_used(nvq);
  		if (unlikely(vq_log))
-			vhost_log_write(vq, vq_log, log, vhost_len);
+			vhost_log_write(vq, vq_log, log, vhost_len,
+					vq->iov, in);
  		total_len += vhost_len;
  		if (unlikely(vhost_exceeds_weight(++recv_pkts, total_len))) {
  			vhost_poll_queue(&vq->poll);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 9f7942cbcbb2..55a2e8f9f8ca 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1733,13 +1733,78 @@ static int log_write(void __user *log_base,
  	return r;
  }
+static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len)
+{
+	struct vhost_umem *umem = vq->umem;
+	struct vhost_umem_node *u;
+	u64 start, end;
+	int r;
+	bool hit = false;
+
+	/* More than one GPAs can be mapped into a single HVA. So
+	 * iterate all possible umems here to be safe.
+	 */
+	list_for_each_entry(u, &umem->umem_list, link) {
+		if (u->userspace_addr > hva - 1 + len ||
+		    u->userspace_addr - 1 + u->size < hva)
+			continue;
+		start = max(u->userspace_addr, hva);
+		end = min(u->userspace_addr - 1 + u->size, hva - 1 + len);
+		r = log_write(vq->log_base,
+			      u->start + start - u->userspace_addr,
+			      end - start + 1);
+		if (r < 0)
+			return r;
+		hit = true;
+	}
+
+	if (!hit)
+		return -EFAULT;
+
+	return 0;
+}
+
I definitely like the simplicity.

But there's one point left here: if len crosses a region boundary,
but doesn't all fall within a region, we don't consistently report -EFAULT.

So I suspect we need to start by finding a region that contains hva.
If there are many of these - move right to the end of the
leftmost one and then repeat until we run out of len
or fail to find a region and exit with -EFAULT.


Ok, will do it in V4.

Thanks




_______________________________________________
Virtualization mailing list
Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linuxfoundation.org/mailman/listinfo/virtualization




[Index of Archives]     [KVM Development]     [Libvirt Development]     [Libvirt Users]     [CentOS Virtualization]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux