]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
um: chan_user: retry partial writes
authorBenjamin Berg <benjamin.berg@intel.com>
Wed, 18 Oct 2023 12:36:42 +0000 (14:36 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 3 Jul 2024 10:18:02 +0000 (12:18 +0200)
In the next commit, we are going to set the output FD to be blocking.
Once that is done, the write() may be short if an interrupt happens
while it is writing out data. As such, to properly catch an EINTR error,
we need to retry the write.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Link: https://patch.msgid.link/20231018123643.1255813-3-benjamin@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
arch/um/drivers/chan_user.c

index 60fcb181835dd2bc81b9cb36c52c89ec974c083e..a66e556012c4840fb629aa26dd82641d15dd185f 100644 (file)
@@ -37,11 +37,23 @@ int generic_read(int fd, __u8 *c_out, void *unused)
 
 int generic_write(int fd, const __u8 *buf, size_t n, void *unused)
 {
+       int written = 0;
        int err;
 
-       CATCH_EINTR(err = write(fd, buf, n));
-       if (err > 0)
-               return err;
+       /* The FD may be in blocking mode, as such, need to retry short writes,
+        * they may have been interrupted by a signal.
+        */
+       do {
+               errno = 0;
+               err = write(fd, buf + written, n - written);
+               if (err > 0) {
+                       written += err;
+                       continue;
+               }
+       } while (err < 0 && errno == EINTR);
+
+       if (written > 0)
+               return written;
        else if (errno == EAGAIN)
                return 0;
        else if (err == 0)