splice, net: Add a splice_eof op to file-ops and socket-ops
[platform/kernel/linux-starfive.git] / fs / splice.c
index e337630..67dbd85 100644 (file)
@@ -970,6 +970,17 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
 }
 
 /*
+ * Indicate to the caller that there was a premature EOF when reading from the
+ * source and the caller didn't indicate they would be sending more data after
+ * this.
+ */
+static void do_splice_eof(struct splice_desc *sd)
+{
+       if (sd->splice_eof)
+               sd->splice_eof(sd);
+}
+
+/*
  * Attempt to initiate a splice from a file to a pipe.
  */
 static long do_splice_to(struct file *in, loff_t *ppos,
@@ -1068,7 +1079,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
 
                ret = do_splice_to(in, &pos, pipe, len, flags);
                if (unlikely(ret <= 0))
-                       goto out_release;
+                       goto read_failure;
 
                read_len = ret;
                sd->total_len = read_len;
@@ -1108,6 +1119,15 @@ done:
        file_accessed(in);
        return bytes;
 
+read_failure:
+       /*
+        * If the user did *not* set SPLICE_F_MORE *and* we didn't hit that
+        * "use all of len" case that cleared SPLICE_F_MORE, *and* we did a
+        * "->splice_in()" that returned EOF (ie zero) *and* we have sent at
+        * least 1 byte *then* we will also do the ->splice_eof() call.
+        */
+       if (ret == 0 && !more && len > 0 && bytes)
+               do_splice_eof(sd);
 out_release:
        /*
         * If we did an incomplete transfer we must release
@@ -1136,6 +1156,14 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
                              sd->flags);
 }
 
+static void direct_file_splice_eof(struct splice_desc *sd)
+{
+       struct file *file = sd->u.file;
+
+       if (file->f_op->splice_eof)
+               file->f_op->splice_eof(file);
+}
+
 /**
  * do_splice_direct - splices data directly between two files
  * @in:                file to splice from
@@ -1161,6 +1189,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
                .flags          = flags,
                .pos            = *ppos,
                .u.file         = out,
+               .splice_eof     = direct_file_splice_eof,
                .opos           = opos,
        };
        long ret;