kfree(io->free_iovec);
 }
 
-static inline void io_rw_done(struct kiocb *kiocb, ssize_t ret)
-{
-       switch (ret) {
-       case -EIOCBQUEUED:
-               break;
-       case -ERESTARTSYS:
-       case -ERESTARTNOINTR:
-       case -ERESTARTNOHAND:
-       case -ERESTART_RESTARTBLOCK:
-               /*
-                * We can't just restart the syscall, since previously
-                * submitted sqes may already be in progress. Just fail this
-                * IO with EINTR.
-                */
-               ret = -EINTR;
-               fallthrough;
-       default:
-               kiocb->ki_complete(kiocb, ret);
-       }
-}
-
 static inline loff_t *io_kiocb_update_pos(struct io_kiocb *req)
 {
        struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
        smp_store_release(&req->iopoll_completed, 1);
 }
 
+static inline void io_rw_done(struct kiocb *kiocb, ssize_t ret)
+{
+       /* IO was queued async, completion will happen later */
+       if (ret == -EIOCBQUEUED)
+               return;
+
+       /* transform internal restart error codes */
+       if (unlikely(ret < 0)) {
+               switch (ret) {
+               case -ERESTARTSYS:
+               case -ERESTARTNOINTR:
+               case -ERESTARTNOHAND:
+               case -ERESTART_RESTARTBLOCK:
+                       /*
+                        * We can't just restart the syscall, since previously
+                        * submitted sqes may already be in progress. Just fail
+                        * this IO with EINTR.
+                        */
+                       ret = -EINTR;
+                       break;
+               }
+       }
+
+       INDIRECT_CALL_2(kiocb->ki_complete, io_complete_rw_iopoll,
+                       io_complete_rw, kiocb, ret);
+}
+
 static int kiocb_done(struct io_kiocb *req, ssize_t ret,
                       unsigned int issue_flags)
 {