diff mbox series

[3/4] um: chan_user: retry partial writes

Message ID 20231018123643.1255813-3-benjamin@sipsolutions.net
State Needs Review / ACK
Headers show
Series [1/4] um: irqs: process outstanding IRQs when unblocking signals | expand

Commit Message

Benjamin Berg Oct. 18, 2023, 12:36 p.m. UTC
From: Benjamin Berg <benjamin.berg@intel.com>

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>
---
 arch/um/drivers/chan_user.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 29c68820522a..339aae56b6f1 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -37,11 +37,23 @@  int generic_read(int fd, char *c_out, void *unused)
 
 int generic_write(int fd, const char *buf, int 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)