splice: only return -EAGAIN if there's hope of more data
authorJens Axboe <jens.axboe@oracle.com>
Wed, 20 Feb 2008 09:34:51 +0000 (10:34 +0100)
committerJens Axboe <axboe@carl.home.kernel.dk>
Tue, 4 Mar 2008 10:14:39 +0000 (11:14 +0100)
sys_tee() currently is a bit eager in returning -EAGAIN, it may do so
even if we don't have a chance of anymore data becoming available. So
improve the logic and only return -EAGAIN if we have an attached writer
to the input pipe.

Reported by Johann Felix Soden <johfel@gmx.de> and
Patrick McManus <mcmanus@ducksong.com>.

Tested-by: Johann Felix Soden <johfel@users.sourceforge.net>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
fs/splice.c

index 9b559ee711a8e59f8e12fb0029b4d5a0356b7df4..0670c915cd35c5e8b653494d4d5b1efe76867e2e 100644 (file)
@@ -1669,6 +1669,13 @@ static int link_pipe(struct pipe_inode_info *ipipe,
                i++;
        } while (len);
 
+       /*
+        * return EAGAIN if we have the potential of some data in the
+        * future, otherwise just return 0
+        */
+       if (!ret && ipipe->waiting_writers && (flags & SPLICE_F_NONBLOCK))
+               ret = -EAGAIN;
+
        inode_double_unlock(ipipe->inode, opipe->inode);
 
        /*
@@ -1709,11 +1716,8 @@ static long do_tee(struct file *in, struct file *out, size_t len,
                ret = link_ipipe_prep(ipipe, flags);
                if (!ret) {
                        ret = link_opipe_prep(opipe, flags);
-                       if (!ret) {
+                       if (!ret)
                                ret = link_pipe(ipipe, opipe, len, flags);
-                               if (!ret && (flags & SPLICE_F_NONBLOCK))
-                                       ret = -EAGAIN;
-                       }
                }
        }