aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Chagin <dchagin@FreeBSD.org>2023-08-20 07:36:31 +0000
committerDmitry Chagin <dchagin@FreeBSD.org>2023-08-20 07:36:31 +0000
commit4231b825ac19112b84b4001625e0ef7a80e82f80 (patch)
treed20a0e8a3a141b2cea49d4216867bd0e697e0a3d
parent1f9d71ee32cf74ece18f36b31c7e9ea1613be730 (diff)
downloadsrc-4231b825ac19112b84b4001625e0ef7a80e82f80.tar.gz
src-4231b825ac19112b84b4001625e0ef7a80e82f80.zip
linux(4): Add a dedicated writev syscall wrapper
Adding a writev syscall wrapper is needed due to Linux family of write syscalls doesn't distinguish between in kernel blocking operations and always returns EAGAIN while FreeBSD can return ENOBUFS. MFC after: 1 month
-rw-r--r--sys/amd64/linux32/linux32_machdep.c14
-rw-r--r--sys/compat/linux/linux_file.c19
2 files changed, 19 insertions, 14 deletions
diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c
index 2598384aada5..ac8234503bdd 100644
--- a/sys/amd64/linux32/linux32_machdep.c
+++ b/sys/amd64/linux32/linux32_machdep.c
@@ -196,20 +196,6 @@ linux_readv(struct thread *td, struct linux_readv_args *uap)
return (error);
}
-int
-linux_writev(struct thread *td, struct linux_writev_args *uap)
-{
- struct uio *auio;
- int error;
-
- error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio);
- if (error)
- return (error);
- error = kern_writev(td, uap->fd, auio);
- free(auio, M_IOV);
- return (error);
-}
-
struct l_ipc_kludge {
l_uintptr_t msgp;
l_long msgtyp;
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 6a1f61984b08..27b6e1a5f77d 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -47,6 +47,7 @@
#ifdef COMPAT_LINUX32
#include <compat/freebsd32/freebsd32_misc.h>
+#include <compat/freebsd32/freebsd32_util.h>
#include <machine/../linux32/linux.h>
#include <machine/../linux32/linux32_proto.h>
#else
@@ -1855,3 +1856,21 @@ linux_write(struct thread *td, struct linux_write_args *args)
return (linux_enobufs2eagain(td, args->fd, sys_write(td, &bargs)));
}
+
+int
+linux_writev(struct thread *td, struct linux_writev_args *args)
+{
+ struct uio *auio;
+ int error;
+
+#ifdef COMPAT_LINUX32
+ error = freebsd32_copyinuio(PTRIN(args->iovp), args->iovcnt, &auio);
+#else
+ error = copyinuio(args->iovp, args->iovcnt, &auio);
+#endif
+ if (error != 0)
+ return (error);
+ error = kern_writev(td, args->fd, auio);
+ free(auio, M_IOV);
+ return (linux_enobufs2eagain(td, args->fd, error));
+}