LCOV - code coverage report
Current view: top level - io_uring - splice.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 50 0.0 %
Date: 2023-08-24 13:40:31 Functions: 0 4 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : #include <linux/kernel.h>
       3             : #include <linux/errno.h>
       4             : #include <linux/fs.h>
       5             : #include <linux/file.h>
       6             : #include <linux/mm.h>
       7             : #include <linux/slab.h>
       8             : #include <linux/namei.h>
       9             : #include <linux/io_uring.h>
      10             : #include <linux/splice.h>
      11             : 
      12             : #include <uapi/linux/io_uring.h>
      13             : 
      14             : #include "io_uring.h"
      15             : #include "splice.h"
      16             : 
      17             : struct io_splice {
      18             :         struct file                     *file_out;
      19             :         loff_t                          off_out;
      20             :         loff_t                          off_in;
      21             :         u64                             len;
      22             :         int                             splice_fd_in;
      23             :         unsigned int                    flags;
      24             : };
      25             : 
      26             : static int __io_splice_prep(struct io_kiocb *req,
      27             :                             const struct io_uring_sqe *sqe)
      28             : {
      29           0 :         struct io_splice *sp = io_kiocb_to_cmd(req, struct io_splice);
      30           0 :         unsigned int valid_flags = SPLICE_F_FD_IN_FIXED | SPLICE_F_ALL;
      31             : 
      32           0 :         sp->len = READ_ONCE(sqe->len);
      33           0 :         sp->flags = READ_ONCE(sqe->splice_flags);
      34           0 :         if (unlikely(sp->flags & ~valid_flags))
      35             :                 return -EINVAL;
      36           0 :         sp->splice_fd_in = READ_ONCE(sqe->splice_fd_in);
      37           0 :         req->flags |= REQ_F_FORCE_ASYNC;
      38             :         return 0;
      39             : }
      40             : 
      41           0 : int io_tee_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
      42             : {
      43           0 :         if (READ_ONCE(sqe->splice_off_in) || READ_ONCE(sqe->off))
      44             :                 return -EINVAL;
      45             :         return __io_splice_prep(req, sqe);
      46             : }
      47             : 
      48           0 : int io_tee(struct io_kiocb *req, unsigned int issue_flags)
      49             : {
      50           0 :         struct io_splice *sp = io_kiocb_to_cmd(req, struct io_splice);
      51           0 :         struct file *out = sp->file_out;
      52           0 :         unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
      53             :         struct file *in;
      54           0 :         long ret = 0;
      55             : 
      56           0 :         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
      57             : 
      58           0 :         if (sp->flags & SPLICE_F_FD_IN_FIXED)
      59           0 :                 in = io_file_get_fixed(req, sp->splice_fd_in, issue_flags);
      60             :         else
      61           0 :                 in = io_file_get_normal(req, sp->splice_fd_in);
      62           0 :         if (!in) {
      63             :                 ret = -EBADF;
      64             :                 goto done;
      65             :         }
      66             : 
      67           0 :         if (sp->len)
      68           0 :                 ret = do_tee(in, out, sp->len, flags);
      69             : 
      70           0 :         if (!(sp->flags & SPLICE_F_FD_IN_FIXED))
      71             :                 io_put_file(in);
      72             : done:
      73           0 :         if (ret != sp->len)
      74           0 :                 req_set_fail(req);
      75           0 :         io_req_set_res(req, ret, 0);
      76           0 :         return IOU_OK;
      77             : }
      78             : 
      79           0 : int io_splice_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
      80             : {
      81           0 :         struct io_splice *sp = io_kiocb_to_cmd(req, struct io_splice);
      82             : 
      83           0 :         sp->off_in = READ_ONCE(sqe->splice_off_in);
      84           0 :         sp->off_out = READ_ONCE(sqe->off);
      85           0 :         return __io_splice_prep(req, sqe);
      86             : }
      87             : 
      88           0 : int io_splice(struct io_kiocb *req, unsigned int issue_flags)
      89             : {
      90           0 :         struct io_splice *sp = io_kiocb_to_cmd(req, struct io_splice);
      91           0 :         struct file *out = sp->file_out;
      92           0 :         unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
      93             :         loff_t *poff_in, *poff_out;
      94             :         struct file *in;
      95           0 :         long ret = 0;
      96             : 
      97           0 :         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
      98             : 
      99           0 :         if (sp->flags & SPLICE_F_FD_IN_FIXED)
     100           0 :                 in = io_file_get_fixed(req, sp->splice_fd_in, issue_flags);
     101             :         else
     102           0 :                 in = io_file_get_normal(req, sp->splice_fd_in);
     103           0 :         if (!in) {
     104             :                 ret = -EBADF;
     105             :                 goto done;
     106             :         }
     107             : 
     108           0 :         poff_in = (sp->off_in == -1) ? NULL : &sp->off_in;
     109           0 :         poff_out = (sp->off_out == -1) ? NULL : &sp->off_out;
     110             : 
     111           0 :         if (sp->len)
     112           0 :                 ret = do_splice(in, poff_in, out, poff_out, sp->len, flags);
     113             : 
     114           0 :         if (!(sp->flags & SPLICE_F_FD_IN_FIXED))
     115             :                 io_put_file(in);
     116             : done:
     117           0 :         if (ret != sp->len)
     118           0 :                 req_set_fail(req);
     119           0 :         io_req_set_res(req, ret, 0);
     120           0 :         return IOU_OK;
     121             : }

Generated by: LCOV version 1.14