All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: David Miller <davem@davemloft.net>,
	cornelia.huck@de.ibm.com, rusty@au1.ibm.com, nab@linux-iscsi.org,
	pbonzini@redhat.com, thuth@linux.vnet.ibm.com,
	dahi@linux.vnet.ibm.com, kvm@vger.kernel.org,
	virtualization@lists.linux-foundation.org,
	netdev@vger.kernel.org
Subject: [PATCH v5 30/45] vhost: virtio 1.0 endian-ness support
Date: Thu, 27 Nov 2014 14:32:34 +0200	[thread overview]
Message-ID: <1417091078-24611-31-git-send-email-mst@redhat.com> (raw)
In-Reply-To: <1417091078-24611-1-git-send-email-mst@redhat.com>

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 drivers/vhost/vhost.c | 93 +++++++++++++++++++++++++++++++--------------------
 1 file changed, 56 insertions(+), 37 deletions(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index c90f437..4d379ed 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -33,8 +33,8 @@ enum {
 	VHOST_MEMORY_F_LOG = 0x1,
 };
 
-#define vhost_used_event(vq) ((u16 __user *)&vq->avail->ring[vq->num])
-#define vhost_avail_event(vq) ((u16 __user *)&vq->used->ring[vq->num])
+#define vhost_used_event(vq) ((__virtio16 __user *)&vq->avail->ring[vq->num])
+#define vhost_avail_event(vq) ((__virtio16 __user *)&vq->used->ring[vq->num])
 
 static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh,
 			    poll_table *pt)
@@ -1001,7 +1001,7 @@ EXPORT_SYMBOL_GPL(vhost_log_write);
 static int vhost_update_used_flags(struct vhost_virtqueue *vq)
 {
 	void __user *used;
-	if (__put_user(vq->used_flags, &vq->used->flags) < 0)
+	if (__put_user(cpu_to_vhost16(vq, vq->used_flags), &vq->used->flags) < 0)
 		return -EFAULT;
 	if (unlikely(vq->log_used)) {
 		/* Make sure the flag is seen before log. */
@@ -1019,7 +1019,7 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)
 
 static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
 {
-	if (__put_user(vq->avail_idx, vhost_avail_event(vq)))
+	if (__put_user(cpu_to_vhost16(vq, vq->avail_idx), vhost_avail_event(vq)))
 		return -EFAULT;
 	if (unlikely(vq->log_used)) {
 		void __user *used;
@@ -1038,6 +1038,7 @@ static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
 
 int vhost_init_used(struct vhost_virtqueue *vq)
 {
+	__virtio16 last_used_idx;
 	int r;
 	if (!vq->private_data)
 		return 0;
@@ -1046,7 +1047,13 @@ int vhost_init_used(struct vhost_virtqueue *vq)
 	if (r)
 		return r;
 	vq->signalled_used_valid = false;
-	return get_user(vq->last_used_idx, &vq->used->idx);
+	if (!access_ok(VERIFY_READ, &vq->used->idx, sizeof vq->used->idx))
+		return -EFAULT;
+	r = __get_user(last_used_idx, &vq->used->idx);
+	if (r)
+		return r;
+	vq->last_used_idx = vhost16_to_cpu(vq, last_used_idx);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(vhost_init_used);
 
@@ -1087,16 +1094,16 @@ static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len,
 /* Each buffer in the virtqueues is actually a chain of descriptors.  This
  * function returns the next descriptor in the chain,
  * or -1U if we're at the end. */
-static unsigned next_desc(struct vring_desc *desc)
+static unsigned next_desc(struct vhost_virtqueue *vq, struct vring_desc *desc)
 {
 	unsigned int next;
 
 	/* If this descriptor says it doesn't chain, we're done. */
-	if (!(desc->flags & VRING_DESC_F_NEXT))
+	if (!(desc->flags & cpu_to_vhost16(vq, VRING_DESC_F_NEXT)))
 		return -1U;
 
 	/* Check they're not leading us off end of descriptors. */
-	next = desc->next;
+	next = vhost16_to_cpu(vq, desc->next);
 	/* Make sure compiler knows to grab that: we don't want it changing! */
 	/* We will use the result as an index in an array, so most
 	 * architectures only need a compiler barrier here. */
@@ -1113,18 +1120,19 @@ static int get_indirect(struct vhost_virtqueue *vq,
 {
 	struct vring_desc desc;
 	unsigned int i = 0, count, found = 0;
+	u32 len = vhost32_to_cpu(vq, indirect->len);
 	int ret;
 
 	/* Sanity check */
-	if (unlikely(indirect->len % sizeof desc)) {
+	if (unlikely(len % sizeof desc)) {
 		vq_err(vq, "Invalid length in indirect descriptor: "
 		       "len 0x%llx not multiple of 0x%zx\n",
-		       (unsigned long long)indirect->len,
+		       (unsigned long long)vhost32_to_cpu(vq, indirect->len),
 		       sizeof desc);
 		return -EINVAL;
 	}
 
-	ret = translate_desc(vq, indirect->addr, indirect->len, vq->indirect,
+	ret = translate_desc(vq, vhost64_to_cpu(vq, indirect->addr), len, vq->indirect,
 			     UIO_MAXIOV);
 	if (unlikely(ret < 0)) {
 		vq_err(vq, "Translation failure %d in indirect.\n", ret);
@@ -1135,7 +1143,7 @@ static int get_indirect(struct vhost_virtqueue *vq,
 	 * architectures only need a compiler barrier here. */
 	read_barrier_depends();
 
-	count = indirect->len / sizeof desc;
+	count = len / sizeof desc;
 	/* Buffers are chained via a 16 bit next field, so
 	 * we can have at most 2^16 of these. */
 	if (unlikely(count > USHRT_MAX + 1)) {
@@ -1155,16 +1163,17 @@ static int get_indirect(struct vhost_virtqueue *vq,
 		if (unlikely(memcpy_fromiovec((unsigned char *)&desc,
 					      vq->indirect, sizeof desc))) {
 			vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n",
-			       i, (size_t)indirect->addr + i * sizeof desc);
+			       i, (size_t)vhost64_to_cpu(vq, indirect->addr) + i * sizeof desc);
 			return -EINVAL;
 		}
-		if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) {
+		if (unlikely(desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_INDIRECT))) {
 			vq_err(vq, "Nested indirect descriptor: idx %d, %zx\n",
-			       i, (size_t)indirect->addr + i * sizeof desc);
+			       i, (size_t)vhost64_to_cpu(vq, indirect->addr) + i * sizeof desc);
 			return -EINVAL;
 		}
 
-		ret = translate_desc(vq, desc.addr, desc.len, iov + iov_count,
+		ret = translate_desc(vq, vhost64_to_cpu(vq, desc.addr),
+				     vhost32_to_cpu(vq, desc.len), iov + iov_count,
 				     iov_size - iov_count);
 		if (unlikely(ret < 0)) {
 			vq_err(vq, "Translation failure %d indirect idx %d\n",
@@ -1172,11 +1181,11 @@ static int get_indirect(struct vhost_virtqueue *vq,
 			return ret;
 		}
 		/* If this is an input descriptor, increment that count. */
-		if (desc.flags & VRING_DESC_F_WRITE) {
+		if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_WRITE)) {
 			*in_num += ret;
 			if (unlikely(log)) {
-				log[*log_num].addr = desc.addr;
-				log[*log_num].len = desc.len;
+				log[*log_num].addr = vhost64_to_cpu(vq, desc.addr);
+				log[*log_num].len = vhost32_to_cpu(vq, desc.len);
 				++*log_num;
 			}
 		} else {
@@ -1189,7 +1198,7 @@ static int get_indirect(struct vhost_virtqueue *vq,
 			}
 			*out_num += ret;
 		}
-	} while ((i = next_desc(&desc)) != -1);
+	} while ((i = next_desc(vq, &desc)) != -1);
 	return 0;
 }
 
@@ -1209,15 +1218,18 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
 	struct vring_desc desc;
 	unsigned int i, head, found = 0;
 	u16 last_avail_idx;
+	__virtio16 avail_idx;
+	__virtio16 ring_head;
 	int ret;
 
 	/* Check it isn't doing very strange things with descriptor numbers. */
 	last_avail_idx = vq->last_avail_idx;
-	if (unlikely(__get_user(vq->avail_idx, &vq->avail->idx))) {
+	if (unlikely(__get_user(avail_idx, &vq->avail->idx))) {
 		vq_err(vq, "Failed to access avail idx at %p\n",
 		       &vq->avail->idx);
 		return -EFAULT;
 	}
+	vq->avail_idx = vhost16_to_cpu(vq, avail_idx);
 
 	if (unlikely((u16)(vq->avail_idx - last_avail_idx) > vq->num)) {
 		vq_err(vq, "Guest moved used index from %u to %u",
@@ -1234,7 +1246,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
 
 	/* Grab the next descriptor number they're advertising, and increment
 	 * the index we've seen. */
-	if (unlikely(__get_user(head,
+	if (unlikely(__get_user(ring_head,
 				&vq->avail->ring[last_avail_idx % vq->num]))) {
 		vq_err(vq, "Failed to read head: idx %d address %p\n",
 		       last_avail_idx,
@@ -1242,6 +1254,8 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
 		return -EFAULT;
 	}
 
+	head = vhost16_to_cpu(vq, ring_head);
+
 	/* If their number is silly, that's an error. */
 	if (unlikely(head >= vq->num)) {
 		vq_err(vq, "Guest says index %u > %u is available",
@@ -1274,7 +1288,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
 			       i, vq->desc + i);
 			return -EFAULT;
 		}
-		if (desc.flags & VRING_DESC_F_INDIRECT) {
+		if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_INDIRECT)) {
 			ret = get_indirect(vq, iov, iov_size,
 					   out_num, in_num,
 					   log, log_num, &desc);
@@ -1286,20 +1300,21 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
 			continue;
 		}
 
-		ret = translate_desc(vq, desc.addr, desc.len, iov + iov_count,
+		ret = translate_desc(vq, vhost64_to_cpu(vq, desc.addr),
+				     vhost32_to_cpu(vq, desc.len), iov + iov_count,
 				     iov_size - iov_count);
 		if (unlikely(ret < 0)) {
 			vq_err(vq, "Translation failure %d descriptor idx %d\n",
 			       ret, i);
 			return ret;
 		}
-		if (desc.flags & VRING_DESC_F_WRITE) {
+		if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_WRITE)) {
 			/* If this is an input descriptor,
 			 * increment that count. */
 			*in_num += ret;
 			if (unlikely(log)) {
-				log[*log_num].addr = desc.addr;
-				log[*log_num].len = desc.len;
+				log[*log_num].addr = vhost64_to_cpu(vq, desc.addr);
+				log[*log_num].len = vhost32_to_cpu(vq, desc.len);
 				++*log_num;
 			}
 		} else {
@@ -1312,7 +1327,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
 			}
 			*out_num += ret;
 		}
-	} while ((i = next_desc(&desc)) != -1);
+	} while ((i = next_desc(vq, &desc)) != -1);
 
 	/* On success, increment avail index. */
 	vq->last_avail_idx++;
@@ -1335,7 +1350,10 @@ EXPORT_SYMBOL_GPL(vhost_discard_vq_desc);
  * want to notify the guest, using eventfd. */
 int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len)
 {
-	struct vring_used_elem heads = { head, len };
+	struct vring_used_elem heads = {
+		cpu_to_vhost32(vq, head),
+		cpu_to_vhost32(vq, len)
+	};
 
 	return vhost_add_used_n(vq, &heads, 1);
 }
@@ -1404,7 +1422,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
 
 	/* Make sure buffer is written before we update index. */
 	smp_wmb();
-	if (put_user(vq->last_used_idx, &vq->used->idx)) {
+	if (__put_user(cpu_to_vhost16(vq, vq->last_used_idx), &vq->used->idx)) {
 		vq_err(vq, "Failed to increment used idx");
 		return -EFAULT;
 	}
@@ -1422,7 +1440,8 @@ EXPORT_SYMBOL_GPL(vhost_add_used_n);
 
 static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
 {
-	__u16 old, new, event;
+	__u16 old, new;
+	__virtio16 event;
 	bool v;
 	/* Flush out used index updates. This is paired
 	 * with the barrier that the Guest executes when enabling
@@ -1434,12 +1453,12 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
 		return true;
 
 	if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) {
-		__u16 flags;
+		__virtio16 flags;
 		if (__get_user(flags, &vq->avail->flags)) {
 			vq_err(vq, "Failed to get flags");
 			return true;
 		}
-		return !(flags & VRING_AVAIL_F_NO_INTERRUPT);
+		return !(flags & cpu_to_vhost16(vq, VRING_AVAIL_F_NO_INTERRUPT));
 	}
 	old = vq->signalled_used;
 	v = vq->signalled_used_valid;
@@ -1449,11 +1468,11 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
 	if (unlikely(!v))
 		return true;
 
-	if (get_user(event, vhost_used_event(vq))) {
+	if (__get_user(event, vhost_used_event(vq))) {
 		vq_err(vq, "Failed to get used event idx");
 		return true;
 	}
-	return vring_need_event(event, new, old);
+	return vring_need_event(vhost16_to_cpu(vq, event), new, old);
 }
 
 /* This actually signals the guest, using eventfd. */
@@ -1488,7 +1507,7 @@ EXPORT_SYMBOL_GPL(vhost_add_used_and_signal_n);
 /* OK, now we need to know about added descriptors. */
 bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
 {
-	u16 avail_idx;
+	__virtio16 avail_idx;
 	int r;
 
 	if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY))
@@ -1519,7 +1538,7 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
 		return false;
 	}
 
-	return avail_idx != vq->avail_idx;
+	return vhost16_to_cpu(vq, avail_idx) != vq->avail_idx;
 }
 EXPORT_SYMBOL_GPL(vhost_enable_notify);
 
-- 
MST

  parent reply	other threads:[~2014-11-27 12:32 UTC|newest]

Thread overview: 85+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-27 12:29 [PATCH v5 00/45] linux: towards virtio-1 guest support Michael S. Tsirkin
2014-11-27 12:29 ` [PATCH v5 01/45] virtio: use u32, not bitmap for struct virtio_device's features Michael S. Tsirkin
2014-11-27 12:29   ` Michael S. Tsirkin
2014-11-27 16:15   ` David Hildenbrand
2014-11-27 16:15     ` David Hildenbrand
2014-11-27 16:28     ` Michael S. Tsirkin
2014-11-27 16:28       ` Michael S. Tsirkin
2014-11-27 16:34       ` David Hildenbrand
2014-11-27 16:34         ` David Hildenbrand
2014-11-27 12:30 ` [PATCH v5 02/45] mic_virtio: robust feature array size calculation Michael S. Tsirkin
2014-11-27 12:30 ` [PATCH v5 03/45] virtio: add support for 64 bit features Michael S. Tsirkin
2014-11-27 12:30   ` Michael S. Tsirkin
2014-11-27 12:30 ` [PATCH v5 04/45] virtio: assert 32 bit features in transports Michael S. Tsirkin
2014-11-27 12:30   ` Michael S. Tsirkin
2014-11-27 12:30 ` [PATCH v5 05/45] virtio_ccw: add support for 64 bit features Michael S. Tsirkin
2014-11-27 12:30 ` [PATCH v5 06/45] virtio: add virtio 1.0 feature bit Michael S. Tsirkin
2014-11-27 12:30   ` Michael S. Tsirkin
2014-11-27 12:30 ` [PATCH v5 07/45] virtio: memory access APIs Michael S. Tsirkin
2014-11-27 12:30 ` Michael S. Tsirkin
2014-11-27 12:30 ` [PATCH v5 08/45] virtio_ring: switch to new " Michael S. Tsirkin
2014-11-27 12:30   ` Michael S. Tsirkin
2014-11-27 12:30 ` [PATCH v5 09/45] virtio_config: endian conversion for v1.0 Michael S. Tsirkin
2014-11-27 12:30 ` Michael S. Tsirkin
2014-11-27 12:30 ` [PATCH v5 10/45] virtio: allow transports to get avail/used addresses Michael S. Tsirkin
2014-11-27 12:30   ` Michael S. Tsirkin
2014-11-27 12:31 ` [PATCH v5 11/45] virtio: set FEATURES_OK Michael S. Tsirkin
2014-11-27 12:31   ` Michael S. Tsirkin
2014-11-27 12:31 ` [PATCH v5 12/45] virtio: simplify feature bit handling Michael S. Tsirkin
2014-11-27 12:31 ` Michael S. Tsirkin
2014-11-27 12:31 ` [PATCH v5 13/45] virtio: add legacy feature table support Michael S. Tsirkin
2014-11-27 12:31 ` Michael S. Tsirkin
2014-11-27 12:31 ` [PATCH v5 14/45] virtio_net: v1.0 endianness Michael S. Tsirkin
2014-11-27 12:31   ` Michael S. Tsirkin
2014-11-27 12:31 ` [PATCH v5 15/45] virtio_blk: v1.0 support Michael S. Tsirkin
2014-11-27 12:31 ` Michael S. Tsirkin
2014-11-27 12:31 ` [PATCH v5 16/45] KVM: s390: Set virtio-ccw transport revision Michael S. Tsirkin
2014-11-27 16:01   ` David Hildenbrand
2014-11-27 12:31 ` [PATCH v5 17/45] KVM: s390: virtio-ccw revision 1 SET_VQ Michael S. Tsirkin
2014-11-27 12:31 ` [PATCH v5 18/45] KVM: s390 allow virtio_ccw status writes to fail Michael S. Tsirkin
2014-11-27 12:31 ` [PATCH v5 19/45] KVM: s390: enable virtio-ccw revision 1 Michael S. Tsirkin
2014-11-27 12:31 ` [PATCH v5 20/45] virtio_blk: make serial attribute static Michael S. Tsirkin
2014-11-27 12:31 ` Michael S. Tsirkin
2014-11-27 12:31 ` [PATCH v5 21/45] virtio_blk: fix race at module removal Michael S. Tsirkin
2014-11-27 12:31 ` Michael S. Tsirkin
2014-11-27 12:31 ` [PATCH v5 22/45] virtio_net: pass vi around Michael S. Tsirkin
2014-11-27 12:31 ` Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 23/45] virtio_net: get rid of virtio_net_hdr/skb_vnet_hdr Michael S. Tsirkin
2014-11-27 12:32 ` Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 24/45] virtio_net: stricter short buffer length checks Michael S. Tsirkin
2014-11-27 12:32   ` Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 25/45] virtio_net: bigger header when VERSION_1 is set Michael S. Tsirkin
2014-11-27 12:32 ` Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 26/45] virtio_net: enable v1.0 support Michael S. Tsirkin
2014-11-27 12:32   ` Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 27/45] vhost: make features 64 bit Michael S. Tsirkin
2014-11-27 12:32   ` Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 28/45] vhost: add memory access wrappers Michael S. Tsirkin
2014-11-27 12:32 ` Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 29/45] vhost/net: force len for TX to host endian Michael S. Tsirkin
2014-11-27 12:32   ` Michael S. Tsirkin
2014-11-27 12:32 ` Michael S. Tsirkin [this message]
2014-11-27 12:32 ` [PATCH v5 30/45] vhost: virtio 1.0 endian-ness support Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 31/45] vhost/net: virtio 1.0 byte swap Michael S. Tsirkin
2014-11-27 12:32 ` Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 32/45] vhost/net: larger header for virtio 1.0 Michael S. Tsirkin
2014-11-27 12:32 ` Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 33/45] virtio_net: disable mac write " Michael S. Tsirkin
2014-11-27 12:32 ` Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 34/45] vhost/net: enable " Michael S. Tsirkin
2014-11-27 12:32   ` Michael S. Tsirkin
2014-11-27 12:32 ` [PATCH v5 35/45] vhost/net: suppress compiler warning Michael S. Tsirkin
2014-11-27 12:32 ` Michael S. Tsirkin
2014-11-27 12:33 ` [PATCH v5 36/45] tun: move internal flag defines out of uapi Michael S. Tsirkin
2014-11-27 12:33 ` [PATCH v5 37/45] tun: drop most type defines Michael S. Tsirkin
2014-11-27 12:33 ` [PATCH v5 38/45] tun: add VNET_LE flag Michael S. Tsirkin
2014-11-27 12:33 ` [PATCH v5 39/45] tun: TUN_VNET_LE support, fix sparse warnings for virtio headers Michael S. Tsirkin
2014-11-27 12:33 ` [PATCH v5 40/45] macvtap: TUN_VNET_HDR support Michael S. Tsirkin
2014-11-27 12:33 ` [PATCH v5 41/45] virtio_scsi: v1.0 support Michael S. Tsirkin
2014-11-27 12:33 ` Michael S. Tsirkin
2014-11-27 12:33 ` [PATCH v5 42/45] virtio_scsi: move to uapi Michael S. Tsirkin
2014-11-27 12:33 ` [PATCH v5 43/45] virtio_scsi: export to userspace Michael S. Tsirkin
2014-11-27 12:33 ` Michael S. Tsirkin
2014-11-27 12:33 ` [PATCH v5 44/45] vhost/scsi: partial virtio 1.0 support Michael S. Tsirkin
2014-11-27 12:33 ` Michael S. Tsirkin
2014-11-27 12:33 ` [PATCH v5 45/45] af_packet: virtio 1.0 stubs Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1417091078-24611-31-git-send-email-mst@redhat.com \
    --to=mst@redhat.com \
    --cc=cornelia.huck@de.ibm.com \
    --cc=dahi@linux.vnet.ibm.com \
    --cc=davem@davemloft.net \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nab@linux-iscsi.org \
    --cc=netdev@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=rusty@au1.ibm.com \
    --cc=thuth@linux.vnet.ibm.com \
    --cc=virtualization@lists.linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.