Index: pipe.c
===================================================================
--- pipe.c	(revision 3555)
+++ pipe.c	(revision 3577)
@@ -729,8 +729,8 @@
 	return 0;
 }
 
-static ssize_t xnpipe_read(struct file *file,
-			   char *buf, size_t count, loff_t *ppos)
+static ssize_t xnpipe_readv(struct file *file, const struct iovec *iovec,
+			    unsigned long nr_segs, loff_t *ppos)
 {
 	struct xnpipe_state *state = file->private_data;
 	int sigpending, err = 0;
@@ -739,9 +739,8 @@
 	struct xnholder *h;
 	ssize_t ret;
 	spl_t s;
-
-	if (!access_ok(VERIFY_WRITE, buf, count))
-		return -EFAULT;
+	char *buf;
+	size_t count = 0;
 
 	xnlock_get_irqsave(&nklock, s);
 
@@ -782,8 +781,21 @@
 	 */
 
 	inbytes = 0;
+	ret = 0;
 
 	for (;;) {
+		if (inbytes == count && nr_segs) {
+			buf = iovec->iov_base, count = iovec++->iov_len;
+			--nr_segs;
+			inbytes = 0;
+			if (!access_ok(VERIFY_WRITE, buf, count)) {
+				err = -EFAULT;
+				break;
+			}
+
+			continue;
+		}
+
 		nbytes = xnpipe_m_size(mh) - xnpipe_m_rdoff(mh);
 
 		if (nbytes + inbytes > count)
@@ -807,10 +819,10 @@
 
 		inbytes += nbytes;
 		xnpipe_m_rdoff(mh) += nbytes;
+		ret += nbytes;
 	}
 
-	state->ionrd -= inbytes;
-	ret = inbytes;
+	state->ionrd -= ret;
 
 	if (xnpipe_m_size(mh) > xnpipe_m_rdoff(mh))
 		prependq(&state->outq, &mh->link);
@@ -837,6 +849,13 @@
 	return err ? : ret;
 }
 
+static ssize_t xnpipe_read(struct file *file,
+			   char *buf, size_t count, loff_t *ppos)
+{
+	struct iovec iov = { .iov_base = buf, .iov_len = count };
+	return xnpipe_readv(file, &iov, 1, ppos);
+}
+
 static ssize_t xnpipe_write(struct file *file,
 			    const char *buf, size_t count, loff_t *ppos)
 {
@@ -1060,6 +1079,7 @@
 static struct file_operations xnpipe_fops = {
 	.owner = THIS_MODULE,
 	.read = xnpipe_read,
+	.readv = xnpipe_readv,
 	.write = xnpipe_write,
 	.poll = xnpipe_poll,
 	.ioctl = xnpipe_ioctl,
