--- /dev/null
+From 0b2febf38a33d7c40fb7bb4a58c113a1fa33c412 Mon Sep 17 00:00:00 2001
+From: Hannes Hering <hering2@de.ibm.com>
+Date: Mon, 4 May 2009 11:06:37 -0700
+Subject: ehea: fix invalid pointer access
+
+From: Hannes Hering <hering2@de.ibm.com>
+
+commit 0b2febf38a33d7c40fb7bb4a58c113a1fa33c412 upstream.
+
+This patch fixes an invalid pointer access in case the receive queue
+holds no pointer to the next skb when the queue is empty.
+
+Signed-off-by: Hannes Hering <hering2@de.ibm.com>
+Signed-off-by: Jan-Bernd Themann <themann@de.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/ehea/ehea_main.c | 31 ++++++++++++++++++-------------
+ 1 file changed, 18 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/ehea/ehea_main.c
++++ b/drivers/net/ehea/ehea_main.c
+@@ -529,14 +529,17 @@ static inline struct sk_buff *get_skb_by
+ x &= (arr_len - 1);
+
+ pref = skb_array[x];
+- prefetchw(pref);
+- prefetchw(pref + EHEA_CACHE_LINE);
++ if (pref) {
++ prefetchw(pref);
++ prefetchw(pref + EHEA_CACHE_LINE);
++
++ pref = (skb_array[x]->data);
++ prefetch(pref);
++ prefetch(pref + EHEA_CACHE_LINE);
++ prefetch(pref + EHEA_CACHE_LINE * 2);
++ prefetch(pref + EHEA_CACHE_LINE * 3);
++ }
+
+- pref = (skb_array[x]->data);
+- prefetch(pref);
+- prefetch(pref + EHEA_CACHE_LINE);
+- prefetch(pref + EHEA_CACHE_LINE * 2);
+- prefetch(pref + EHEA_CACHE_LINE * 3);
+ skb = skb_array[skb_index];
+ skb_array[skb_index] = NULL;
+ return skb;
+@@ -553,12 +556,14 @@ static inline struct sk_buff *get_skb_by
+ x &= (arr_len - 1);
+
+ pref = skb_array[x];
+- prefetchw(pref);
+- prefetchw(pref + EHEA_CACHE_LINE);
+-
+- pref = (skb_array[x]->data);
+- prefetchw(pref);
+- prefetchw(pref + EHEA_CACHE_LINE);
++ if (pref) {
++ prefetchw(pref);
++ prefetchw(pref + EHEA_CACHE_LINE);
++
++ pref = (skb_array[x]->data);
++ prefetchw(pref);
++ prefetchw(pref + EHEA_CACHE_LINE);
++ }
+
+ skb = skb_array[wqe_index];
+ skb_array[wqe_index] = NULL;
--- /dev/null
+From 328eaaba4e41a04c1dc4679d65bea3fee4349d86 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <miklos@szeredi.hu>
+Date: Tue, 14 Apr 2009 19:48:39 +0200
+Subject: ocfs2: fix i_mutex locking in ocfs2_splice_to_file()
+
+From: Miklos Szeredi <miklos@szeredi.hu>
+
+commit 328eaaba4e41a04c1dc4679d65bea3fee4349d86 upstream.
+
+Rearrange locking of i_mutex on destination and call to
+ocfs2_rw_lock() so locks are only held while buffers are copied with
+the pipe_to_file() actor, and not while waiting for more data on the
+pipe.
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ocfs2/file.c | 96 ++++++++++++++++++++++++++++++++++++++-----------
+ fs/splice.c | 5 +-
+ include/linux/splice.h | 2 +
+ 3 files changed, 80 insertions(+), 23 deletions(-)
+
+--- a/fs/ocfs2/file.c
++++ b/fs/ocfs2/file.c
+@@ -2075,6 +2075,22 @@ out_sems:
+ return written ? written : ret;
+ }
+
++static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
++ struct file *out,
++ struct splice_desc *sd)
++{
++ int ret;
++
++ ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, &sd->pos,
++ sd->total_len, 0, NULL);
++ if (ret < 0) {
++ mlog_errno(ret);
++ return ret;
++ }
++
++ return splice_from_pipe_feed(pipe, sd, pipe_to_file);
++}
++
+ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
+ struct file *out,
+ loff_t *ppos,
+@@ -2082,38 +2098,76 @@ static ssize_t ocfs2_file_splice_write(s
+ unsigned int flags)
+ {
+ int ret;
+- struct inode *inode = out->f_path.dentry->d_inode;
++ struct address_space *mapping = out->f_mapping;
++ struct inode *inode = mapping->host;
++ struct splice_desc sd = {
++ .total_len = len,
++ .flags = flags,
++ .pos = *ppos,
++ .u.file = out,
++ };
+
+ mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe,
+ (unsigned int)len,
+ out->f_path.dentry->d_name.len,
+ out->f_path.dentry->d_name.name);
+
+- mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
+-
+- ret = ocfs2_rw_lock(inode, 1);
+- if (ret < 0) {
+- mlog_errno(ret);
+- goto out;
+- }
++ if (pipe->inode)
++ mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT);
+
+- ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, ppos, len, 0,
+- NULL);
+- if (ret < 0) {
+- mlog_errno(ret);
+- goto out_unlock;
+- }
++ splice_from_pipe_begin(&sd);
++ do {
++ ret = splice_from_pipe_next(pipe, &sd);
++ if (ret <= 0)
++ break;
++
++ mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
++ ret = ocfs2_rw_lock(inode, 1);
++ if (ret < 0)
++ mlog_errno(ret);
++ else {
++ ret = ocfs2_splice_to_file(pipe, out, &sd);
++ ocfs2_rw_unlock(inode, 1);
++ }
++ mutex_unlock(&inode->i_mutex);
++ } while (ret > 0);
++ splice_from_pipe_end(pipe, &sd);
+
+ if (pipe->inode)
+- mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD);
+- ret = generic_file_splice_write_nolock(pipe, out, ppos, len, flags);
+- if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
+
+-out_unlock:
+- ocfs2_rw_unlock(inode, 1);
+-out:
+- mutex_unlock(&inode->i_mutex);
++ if (sd.num_spliced)
++ ret = sd.num_spliced;
++
++ if (ret > 0) {
++ unsigned long nr_pages;
++
++ *ppos += ret;
++ nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
++
++ /*
++ * If file or inode is SYNC and we actually wrote some data,
++ * sync it.
++ */
++ if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
++ int err;
++
++ mutex_lock(&inode->i_mutex);
++ err = ocfs2_rw_lock(inode, 1);
++ if (err < 0) {
++ mlog_errno(err);
++ } else {
++ err = generic_osync_inode(inode, mapping,
++ OSYNC_METADATA|OSYNC_DATA);
++ ocfs2_rw_unlock(inode, 1);
++ }
++ mutex_unlock(&inode->i_mutex);
++
++ if (err)
++ ret = err;
++ }
++ balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
++ }
+
+ mlog_exit(ret);
+ return ret;
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -553,8 +553,8 @@ static int pipe_to_sendpage(struct pipe_
+ * SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create
+ * a new page in the output file page cache and fill/dirty that.
+ */
+-static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+- struct splice_desc *sd)
++int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
++ struct splice_desc *sd)
+ {
+ struct file *file = sd->u.file;
+ struct address_space *mapping = file->f_mapping;
+@@ -598,6 +598,7 @@ static int pipe_to_file(struct pipe_inod
+ out:
+ return ret;
+ }
++EXPORT_SYMBOL(pipe_to_file);
+
+ static void wakeup_pipe_writers(struct pipe_inode_info *pipe)
+ {
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -75,6 +75,8 @@ extern int splice_from_pipe_next(struct
+ extern void splice_from_pipe_begin(struct splice_desc *);
+ extern void splice_from_pipe_end(struct pipe_inode_info *,
+ struct splice_desc *);
++extern int pipe_to_file(struct pipe_inode_info *, struct pipe_buffer *,
++ struct splice_desc *);
+
+ extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+ struct splice_pipe_desc *);
--- /dev/null
+From d9f0c5f9bc74f16d0ea0f6c518b209e48783a796 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Wed, 4 Feb 2009 11:23:56 -0700
+Subject: powerpc/5200: Don't specify IRQF_SHARED in PSC UART driver
+
+From: Grant Likely <grant.likely@secretlab.ca>
+
+commit d9f0c5f9bc74f16d0ea0f6c518b209e48783a796 upstream.
+
+The MPC5200 PSC device is wired up to a dedicated interrupt line
+which is never shared. This patch removes the IRQF_SHARED flag
+from the request_irq() call which eliminates the "IRQF_DISABLED
+is not guaranteed on shared IRQs" warning message from the console
+output.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/mpc52xx_uart.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/serial/mpc52xx_uart.c
++++ b/drivers/serial/mpc52xx_uart.c
+@@ -515,7 +515,7 @@ mpc52xx_uart_startup(struct uart_port *p
+
+ /* Request IRQ */
+ ret = request_irq(port->irq, mpc52xx_uart_int,
+- IRQF_DISABLED | IRQF_SAMPLE_RANDOM | IRQF_SHARED,
++ IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+ "mpc52xx_psc_uart", port);
+ if (ret)
+ return ret;
epoll-fix-size-check-in-epoll_create.patch
nfsd4-check-for-negative-dentry-before-use-in-nfsv4-readdir.patch
nfs-fix-the-notifications-when-renaming-onto-an-existing-file.patch
+ehea-fix-invalid-pointer-access.patch
+powerpc-5200-don-t-specify-irqf_shared-in-psc-uart-driver.patch
+splice-split-up-__splice_from_pipe.patch
+splice-remove-i_mutex-locking-in-splice_from_pipe.patch
+splice-fix-i_mutex-locking-in-generic_splice_write.patch
+ocfs2-fix-i_mutex-locking-in-ocfs2_splice_to_file.patch
--- /dev/null
+From eb443e5a25d43996deb62b9bcee1a4ce5dea2ead Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <miklos@szeredi.hu>
+Date: Tue, 14 Apr 2009 19:48:38 +0200
+Subject: splice: fix i_mutex locking in generic_splice_write()
+
+From: Miklos Szeredi <miklos@szeredi.hu>
+
+commit eb443e5a25d43996deb62b9bcee1a4ce5dea2ead upstream.
+
+Rearrange locking of i_mutex on destination so it's only held while
+buffers are copied with the pipe_to_file() actor, and not while
+waiting for more data on the pipe.
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/splice.c | 34 +++++++++++++++++++++++-----------
+ 1 file changed, 23 insertions(+), 11 deletions(-)
+
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -893,17 +893,29 @@ generic_file_splice_write(struct pipe_in
+ };
+ ssize_t ret;
+
+- WARN_ON(S_ISFIFO(inode->i_mode));
+- mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
+- ret = file_remove_suid(out);
+- if (likely(!ret)) {
+- if (pipe->inode)
+- mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD);
+- ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
+- if (pipe->inode)
+- mutex_unlock(&pipe->inode->i_mutex);
+- }
+- mutex_unlock(&inode->i_mutex);
++ if (pipe->inode)
++ mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT);
++
++ splice_from_pipe_begin(&sd);
++ do {
++ ret = splice_from_pipe_next(pipe, &sd);
++ if (ret <= 0)
++ break;
++
++ mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
++ ret = file_remove_suid(out);
++ if (!ret)
++ ret = splice_from_pipe_feed(pipe, &sd, pipe_to_file);
++ mutex_unlock(&inode->i_mutex);
++ } while (ret > 0);
++ splice_from_pipe_end(pipe, &sd);
++
++ if (pipe->inode)
++ mutex_unlock(&pipe->inode->i_mutex);
++
++ if (sd.num_spliced)
++ ret = sd.num_spliced;
++
+ if (ret > 0) {
+ unsigned long nr_pages;
+
--- /dev/null
+From 2933970b960223076d6affcf7a77e2bc546b8102 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <miklos@szeredi.hu>
+Date: Tue, 14 Apr 2009 19:48:37 +0200
+Subject: splice: remove i_mutex locking in splice_from_pipe()
+
+From: Miklos Szeredi <miklos@szeredi.hu>
+
+commit 2933970b960223076d6affcf7a77e2bc546b8102 upstream.
+
+splice_from_pipe() is only called from two places:
+
+ - generic_splice_sendpage()
+ - splice_write_null()
+
+Neither of these require i_mutex to be taken on the destination inode.
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/splice.c | 18 ++----------------
+ 1 file changed, 2 insertions(+), 16 deletions(-)
+
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -782,7 +782,7 @@ EXPORT_SYMBOL(__splice_from_pipe);
+ * @actor: handler that splices the data
+ *
+ * Description:
+- * See __splice_from_pipe. This function locks the input and output inodes,
++ * See __splice_from_pipe. This function locks the pipe inode,
+ * otherwise it's identical to __splice_from_pipe().
+ *
+ */
+@@ -791,7 +791,6 @@ ssize_t splice_from_pipe(struct pipe_ino
+ splice_actor *actor)
+ {
+ ssize_t ret;
+- struct inode *inode = out->f_mapping->host;
+ struct splice_desc sd = {
+ .total_len = len,
+ .flags = flags,
+@@ -799,24 +798,11 @@ ssize_t splice_from_pipe(struct pipe_ino
+ .u.file = out,
+ };
+
+- /*
+- * The actor worker might be calling ->prepare_write and
+- * ->commit_write. Most of the time, these expect i_mutex to
+- * be held. Since this may result in an ABBA deadlock with
+- * pipe->inode, we have to order lock acquiry here.
+- *
+- * Outer lock must be inode->i_mutex, as pipe_wait() will
+- * release and reacquire pipe->inode->i_mutex, AND inode must
+- * never be a pipe.
+- */
+- WARN_ON(S_ISFIFO(inode->i_mode));
+- mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
+ if (pipe->inode)
+- mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD);
++ mutex_lock(&pipe->inode->i_mutex);
+ ret = __splice_from_pipe(pipe, &sd, actor);
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
+- mutex_unlock(&inode->i_mutex);
+
+ return ret;
+ }
--- /dev/null
+From b3c2d2ddd63944ef2a1e4a43077b602288107e01 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <miklos@szeredi.hu>
+Date: Tue, 14 Apr 2009 19:48:36 +0200
+Subject: splice: split up __splice_from_pipe()
+
+From: Miklos Szeredi <miklos@szeredi.hu>
+
+commit b3c2d2ddd63944ef2a1e4a43077b602288107e01 upstream.
+
+Split up __splice_from_pipe() into four helper functions:
+
+ splice_from_pipe_begin()
+ splice_from_pipe_next()
+ splice_from_pipe_feed()
+ splice_from_pipe_end()
+
+splice_from_pipe_next() will wait (if necessary) for more buffers to
+be added to the pipe. splice_from_pipe_feed() will feed the buffers
+to the supplied actor and return when there's no more data available
+(or if all of the requested data has been copied).
+
+This is necessary so that implementations can do locking around the
+non-waiting splice_from_pipe_feed().
+
+This patch should not cause any change in behavior.
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/splice.c | 223 ++++++++++++++++++++++++++++++++-----------------
+ include/linux/splice.h | 10 ++
+ 2 files changed, 156 insertions(+), 77 deletions(-)
+
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -599,107 +599,176 @@ out:
+ return ret;
+ }
+
++static void wakeup_pipe_writers(struct pipe_inode_info *pipe)
++{
++ smp_mb();
++ if (waitqueue_active(&pipe->wait))
++ wake_up_interruptible(&pipe->wait);
++ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
++}
++
+ /**
+- * __splice_from_pipe - splice data from a pipe to given actor
++ * splice_from_pipe_feed - feed available data from a pipe to a file
+ * @pipe: pipe to splice from
+ * @sd: information to @actor
+ * @actor: handler that splices the data
+ *
+ * Description:
+- * This function does little more than loop over the pipe and call
+- * @actor to do the actual moving of a single struct pipe_buffer to
+- * the desired destination. See pipe_to_file, pipe_to_sendpage, or
+- * pipe_to_user.
++
++ * This function loops over the pipe and calls @actor to do the
++ * actual moving of a single struct pipe_buffer to the desired
++ * destination. It returns when there's no more buffers left in
++ * the pipe or if the requested number of bytes (@sd->total_len)
++ * have been copied. It returns a positive number (one) if the
++ * pipe needs to be filled with more data, zero if the required
++ * number of bytes have been copied and -errno on error.
+ *
++ * This, together with splice_from_pipe_{begin,end,next}, may be
++ * used to implement the functionality of __splice_from_pipe() when
++ * locking is required around copying the pipe buffers to the
++ * destination.
+ */
+-ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
+- splice_actor *actor)
++int splice_from_pipe_feed(struct pipe_inode_info *pipe, struct splice_desc *sd,
++ splice_actor *actor)
+ {
+- int ret, do_wakeup, err;
+-
+- ret = 0;
+- do_wakeup = 0;
++ int ret;
+
+- for (;;) {
+- if (pipe->nrbufs) {
+- struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
+- const struct pipe_buf_operations *ops = buf->ops;
+-
+- sd->len = buf->len;
+- if (sd->len > sd->total_len)
+- sd->len = sd->total_len;
+-
+- err = actor(pipe, buf, sd);
+- if (err <= 0) {
+- if (!ret && err != -ENODATA)
+- ret = err;
++ while (pipe->nrbufs) {
++ struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
++ const struct pipe_buf_operations *ops = buf->ops;
++
++ sd->len = buf->len;
++ if (sd->len > sd->total_len)
++ sd->len = sd->total_len;
++
++ ret = actor(pipe, buf, sd);
++ if (ret <= 0) {
++ if (ret == -ENODATA)
++ ret = 0;
++ return ret;
++ }
++ buf->offset += ret;
++ buf->len -= ret;
++
++ sd->num_spliced += ret;
++ sd->len -= ret;
++ sd->pos += ret;
++ sd->total_len -= ret;
+
+- break;
+- }
++ if (!buf->len) {
++ buf->ops = NULL;
++ ops->release(pipe, buf);
++ pipe->curbuf = (pipe->curbuf + 1) & (PIPE_BUFFERS - 1);
++ pipe->nrbufs--;
++ if (pipe->inode)
++ sd->need_wakeup = true;
++ }
+
+- ret += err;
+- buf->offset += err;
+- buf->len -= err;
+-
+- sd->len -= err;
+- sd->pos += err;
+- sd->total_len -= err;
+- if (sd->len)
+- continue;
+-
+- if (!buf->len) {
+- buf->ops = NULL;
+- ops->release(pipe, buf);
+- pipe->curbuf = (pipe->curbuf + 1) & (PIPE_BUFFERS - 1);
+- pipe->nrbufs--;
+- if (pipe->inode)
+- do_wakeup = 1;
+- }
++ if (!sd->total_len)
++ return 0;
++ }
+
+- if (!sd->total_len)
+- break;
+- }
++ return 1;
++}
++EXPORT_SYMBOL(splice_from_pipe_feed);
+
+- if (pipe->nrbufs)
+- continue;
++/**
++ * splice_from_pipe_next - wait for some data to splice from
++ * @pipe: pipe to splice from
++ * @sd: information about the splice operation
++ *
++ * Description:
++ * This function will wait for some data and return a positive
++ * value (one) if pipe buffers are available. It will return zero
++ * or -errno if no more data needs to be spliced.
++ */
++int splice_from_pipe_next(struct pipe_inode_info *pipe, struct splice_desc *sd)
++{
++ while (!pipe->nrbufs) {
+ if (!pipe->writers)
+- break;
+- if (!pipe->waiting_writers) {
+- if (ret)
+- break;
+- }
++ return 0;
+
+- if (sd->flags & SPLICE_F_NONBLOCK) {
+- if (!ret)
+- ret = -EAGAIN;
+- break;
+- }
++ if (!pipe->waiting_writers && sd->num_spliced)
++ return 0;
+
+- if (signal_pending(current)) {
+- if (!ret)
+- ret = -ERESTARTSYS;
+- break;
+- }
++ if (sd->flags & SPLICE_F_NONBLOCK)
++ return -EAGAIN;
+
+- if (do_wakeup) {
+- smp_mb();
+- if (waitqueue_active(&pipe->wait))
+- wake_up_interruptible_sync(&pipe->wait);
+- kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
+- do_wakeup = 0;
++ if (signal_pending(current))
++ return -ERESTARTSYS;
++
++ if (sd->need_wakeup) {
++ wakeup_pipe_writers(pipe);
++ sd->need_wakeup = false;
+ }
+
+ pipe_wait(pipe);
+ }
+
+- if (do_wakeup) {
+- smp_mb();
+- if (waitqueue_active(&pipe->wait))
+- wake_up_interruptible(&pipe->wait);
+- kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
+- }
++ return 1;
++}
++EXPORT_SYMBOL(splice_from_pipe_next);
+
+- return ret;
++/**
++ * splice_from_pipe_begin - start splicing from pipe
++ * @pipe: pipe to splice from
++ *
++ * Description:
++ * This function should be called before a loop containing
++ * splice_from_pipe_next() and splice_from_pipe_feed() to
++ * initialize the necessary fields of @sd.
++ */
++void splice_from_pipe_begin(struct splice_desc *sd)
++{
++ sd->num_spliced = 0;
++ sd->need_wakeup = false;
++}
++EXPORT_SYMBOL(splice_from_pipe_begin);
++
++/**
++ * splice_from_pipe_end - finish splicing from pipe
++ * @pipe: pipe to splice from
++ * @sd: information about the splice operation
++ *
++ * Description:
++ * This function will wake up pipe writers if necessary. It should
++ * be called after a loop containing splice_from_pipe_next() and
++ * splice_from_pipe_feed().
++ */
++void splice_from_pipe_end(struct pipe_inode_info *pipe, struct splice_desc *sd)
++{
++ if (sd->need_wakeup)
++ wakeup_pipe_writers(pipe);
++}
++EXPORT_SYMBOL(splice_from_pipe_end);
++
++/**
++ * __splice_from_pipe - splice data from a pipe to given actor
++ * @pipe: pipe to splice from
++ * @sd: information to @actor
++ * @actor: handler that splices the data
++ *
++ * Description:
++ * This function does little more than loop over the pipe and call
++ * @actor to do the actual moving of a single struct pipe_buffer to
++ * the desired destination. See pipe_to_file, pipe_to_sendpage, or
++ * pipe_to_user.
++ *
++ */
++ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
++ splice_actor *actor)
++{
++ int ret;
++
++ splice_from_pipe_begin(sd);
++ do {
++ ret = splice_from_pipe_next(pipe, sd);
++ if (ret > 0)
++ ret = splice_from_pipe_feed(pipe, sd, actor);
++ } while (ret > 0);
++ splice_from_pipe_end(pipe, sd);
++
++ return sd->num_spliced ? sd->num_spliced : ret;
+ }
+ EXPORT_SYMBOL(__splice_from_pipe);
+
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -36,6 +36,8 @@ struct splice_desc {
+ void *data; /* cookie */
+ } u;
+ loff_t pos; /* file position */
++ size_t num_spliced; /* number of bytes already spliced */
++ bool need_wakeup; /* need to wake up writer */
+ };
+
+ struct partial_page {
+@@ -66,6 +68,14 @@ extern ssize_t splice_from_pipe(struct p
+ splice_actor *);
+ extern ssize_t __splice_from_pipe(struct pipe_inode_info *,
+ struct splice_desc *, splice_actor *);
++extern int splice_from_pipe_feed(struct pipe_inode_info *, struct splice_desc *,
++ splice_actor *);
++extern int splice_from_pipe_next(struct pipe_inode_info *,
++ struct splice_desc *);
++extern void splice_from_pipe_begin(struct splice_desc *);
++extern void splice_from_pipe_end(struct pipe_inode_info *,
++ struct splice_desc *);
++
+ extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+ struct splice_pipe_desc *);
+ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,