[GFS2] Only do lo_incore_commit once
[safe/jmp/linux-2.6] / fs / splice.c
index 0a0b79b..0670c91 100644 (file)
@@ -1031,7 +1031,9 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
                        goto out_release;
        }
 
+done:
        pipe->nrbufs = pipe->curbuf = 0;
+       file_accessed(in);
        return bytes;
 
 out_release:
@@ -1047,16 +1049,11 @@ out_release:
                        buf->ops = NULL;
                }
        }
-       pipe->nrbufs = pipe->curbuf = 0;
-
-       /*
-        * If we transferred some data, return the number of bytes:
-        */
-       if (bytes > 0)
-               return bytes;
 
-       return ret;
+       if (!bytes)
+               bytes = ret;
 
+       goto done;
 }
 EXPORT_SYMBOL(splice_direct_to_actor);
 
@@ -1182,6 +1179,9 @@ static int copy_from_user_mmap_sem(void *dst, const void __user *src, size_t n)
 {
        int partial;
 
+       if (!access_ok(VERIFY_READ, src, n))
+               return -EFAULT;
+
        pagefault_disable();
        partial = __copy_from_user_inatomic(dst, src, n);
        pagefault_enable();
@@ -1234,7 +1234,7 @@ static int get_iovec_page_array(const struct iovec __user *iov,
                if (unlikely(!len))
                        break;
                error = -EFAULT;
-               if (unlikely(!base))
+               if (!access_ok(VERIFY_READ, base, len))
                        break;
 
                /*
@@ -1390,6 +1390,11 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
                        break;
                }
 
+               if (unlikely(!access_ok(VERIFY_WRITE, base, len))) {
+                       error = -EFAULT;
+                       break;
+               }
+
                sd.len = 0;
                sd.total_len = len;
                sd.flags = flags;
@@ -1664,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);
 
        /*
@@ -1704,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;
-                       }
                }
        }