--- /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 fd9db7297749c05fcf5721ce5393a5a8b8772f2a Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@suse.cz>
+Date: Tue, 28 Apr 2009 16:56:35 +0200
+Subject: fuse: destroy bdi on error
+
+From: Miklos Szeredi <mszeredi@suse.cz>
+
+commit fd9db7297749c05fcf5721ce5393a5a8b8772f2a upstream.
+
+Destroy bdi on error in fuse_fill_super().
+
+This was an omission from commit 26c3679101dbccc054dcf370143941844ba70531
+"fuse: destroy bdi on umount", which moved the bdi_destroy() call from
+fuse_conn_put() to fuse_put_super().
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/fuse/inode.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -908,6 +908,7 @@ static int fuse_fill_super(struct super_
+ err_put_root:
+ dput(root_dentry);
+ err_put_conn:
++ bdi_destroy(&fc->bdi);
+ fuse_conn_put(fc);
+ err_fput:
+ fput(file);
--- /dev/null
+From e286e86e6d2042d67d09244aa0e05ffef75c9d54 Mon Sep 17 00:00:00 2001
+From: Avi Kivity <avi@redhat.com>
+Date: Sun, 3 May 2009 18:50:55 +0300
+Subject: KVM: Make EFER reads safe when EFER does not exist
+
+From: Avi Kivity <avi@redhat.com>
+
+commit e286e86e6d2042d67d09244aa0e05ffef75c9d54 upstream.
+
+Some processors don't have EFER; don't oops if userspace wants us to
+read EFER when we check NX.
+
+Signed-off-by: Avi Kivity <avi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/kvm/x86.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -1075,9 +1075,9 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *
+
+ static int is_efer_nx(void)
+ {
+- u64 efer;
++ unsigned long long efer = 0;
+
+- rdmsrl(MSR_EFER, efer);
++ rdmsrl_safe(MSR_EFER, &efer);
+ return efer & EFER_NX;
+ }
+
--- /dev/null
+From 99f85a28a78e96d28907fe036e1671a218fee597 Mon Sep 17 00:00:00 2001
+From: Avi Kivity <avi@redhat.com>
+Date: Mon, 11 May 2009 14:21:10 +0300
+Subject: KVM: SVM: Remove port 80 passthrough
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+From: Avi Kivity <avi@redhat.com>
+
+commit 99f85a28a78e96d28907fe036e1671a218fee597 upstream.
+
+KVM optimizes guest port 80 accesses by passthing them through to the host.
+Some AMD machines die on port 80 writes, allowing the guest to hard-lock the
+host.
+
+Remove the port passthrough to avoid the problem.
+
+Reported-by: Piotr Jaroszyński <p.jaroszynski@gmail.com>
+Tested-by: Piotr Jaroszyński <p.jaroszynski@gmail.com>
+Signed-off-by: Avi Kivity <avi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/kvm/svm.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/arch/x86/kvm/svm.c
++++ b/arch/x86/kvm/svm.c
+@@ -411,7 +411,6 @@ static __init int svm_hardware_setup(voi
+
+ iopm_va = page_address(iopm_pages);
+ memset(iopm_va, 0xff, PAGE_SIZE * (1 << IOPM_ALLOC_ORDER));
+- clear_bit(0x80, iopm_va); /* allow direct access to PC debug port */
+ iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT;
+
+ if (boot_cpu_has(X86_FEATURE_NX))
+++ /dev/null
-From 8e532175277d9a5eae49768ed086555081f741a7 Mon Sep 17 00:00:00 2001
-From: Jiri Slaby <jirislaby@gmail.com>
-Date: Mon, 4 May 2009 18:04:55 +0200
-Subject: mac80211: minstrel, fix memory corruption
-
-From: Jiri Slaby <jirislaby@gmail.com>
-
-commit 8e532175277d9a5eae49768ed086555081f741a7 upstream.
-
-minstrel doesn't count max rate count in fact, since it doesn't use
-a loop variable `i' and hence allocs space only for bitrates found in
-the first band.
-
-Fix it by involving the `i' as an index so that it traverses all the
-bands now and finds the real max bitrate count.
-
-Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
-Cc: Felix Fietkau <nbd@openwrt.org>
-Signed-off-by: John W. Linville <linville@tuxdriver.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-
----
- net/mac80211/rc80211_minstrel.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/net/mac80211/rc80211_minstrel.c
-+++ b/net/mac80211/rc80211_minstrel.c
-@@ -476,7 +476,7 @@ minstrel_alloc_sta(void *priv, struct ie
- return NULL;
-
- for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
-- sband = hw->wiphy->bands[hw->conf.channel->band];
-+ sband = hw->wiphy->bands[i];
- if (sband->n_bitrates > max_rates)
- max_rates = sband->n_bitrates;
- }
--- /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
+@@ -1912,6 +1912,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,
+@@ -1919,38 +1935,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
+@@ -554,8 +554,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;
+@@ -599,6 +599,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
+@@ -522,7 +522,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;
cifs-fix-buffer-size-in-cifs_convertucspath.patch
cifs-fix-unicode-string-area-word-alignment-in-session-setup.patch
mac80211-pid-fix-memory-corruption.patch
-mac80211-minstrel-fix-memory-corruption.patch
mm-page_mkwrite-change-prototype-to-match-fault.patch
fs-fix-page_mkwrite-error-cases-in-core-code-and-btrfs.patch
mm-close-page_mkwrite-races.patch
lockd-fix-list-corruption-on-lockd-restart.patch
dmatest-fix-max-channels-handling.patch
hid-add-noget-quirk-for-devices-from-ch-products.patch
+kvm-svm-remove-port-80-passthrough.patch
+kvm-make-efer-reads-safe-when-efer-does-not-exist.patch
+fuse-destroy-bdi-on-error.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
+ehea-fix-invalid-pointer-access.patch
+powerpc-5200-don-t-specify-irqf_shared-in-psc-uart-driver.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
+@@ -894,17 +894,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
+@@ -783,7 +783,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().
+ *
+ */
+@@ -792,7 +792,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,
+@@ -800,24 +799,11 @@ ssize_t splice_from_pipe(struct pipe_ino
+ .u.file = out,
+ };
+
+- /*
+- * The actor worker might be calling ->write_begin and
+- * ->write_end. 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
+@@ -600,107 +600,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 *,