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
This commit is contained in:
Dmitry Chagin 2023-08-20 10:36:31 +03:00
parent 1f9d71ee32
commit 4231b825ac
2 changed files with 19 additions and 14 deletions

View File

@ -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;

View File

@ -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));
}