kernel/fd: Merge vectored I/O implementations.
We now have just one rather than three (common_user_vector_io, _kern_readv, kern_writev.) No behavioral change intended, though there is some slight functional change (syscall flags are now set/unset much earlier.) Change-Id: I6c3c26cab1c19755ef15c8b3c9e38afe9b1d145c Reviewed-on: https://review.haiku-os.org/c/haiku/+/7822 Reviewed-by: waddlesplash <[email protected]> Reviewed-by: Adrien Destugues <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
ed33555f4c
commit
ff91caf6e5
+81
-162
@@ -696,10 +696,71 @@ fd_vnode(struct file_descriptor* descriptor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static ssize_t
|
||||||
common_close(int fd, bool kernel)
|
common_vector_io(int fd, off_t pos, const iovec* vecs, size_t count, bool write, bool kernel)
|
||||||
{
|
{
|
||||||
return close_fd_index(get_current_io_context(kernel), fd);
|
if (pos < -1)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
FileDescriptorPutter descriptor(get_fd(get_current_io_context(kernel), fd));
|
||||||
|
if (!descriptor.IsSet())
|
||||||
|
return B_FILE_ERROR;
|
||||||
|
|
||||||
|
if (write ? (descriptor->open_mode & O_RWMASK) == O_RDONLY
|
||||||
|
: (descriptor->open_mode & O_RWMASK) == O_WRONLY) {
|
||||||
|
return B_FILE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool movePosition = false;
|
||||||
|
if (pos == -1 && descriptor->pos != -1) {
|
||||||
|
pos = descriptor->pos;
|
||||||
|
movePosition = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write ? descriptor->ops->fd_write == NULL
|
||||||
|
: descriptor->ops->fd_read == NULL) {
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t status = B_OK;
|
||||||
|
ssize_t bytesTransferred = 0;
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
if (vecs[i].iov_base == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
size_t length = vecs[i].iov_len;
|
||||||
|
if (write) {
|
||||||
|
status = descriptor->ops->fd_write(descriptor.Get(), pos,
|
||||||
|
vecs[i].iov_base, &length);
|
||||||
|
} else {
|
||||||
|
status = descriptor->ops->fd_read(descriptor.Get(), pos, vecs[i].iov_base,
|
||||||
|
&length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != B_OK) {
|
||||||
|
if (bytesTransferred == 0)
|
||||||
|
return status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((uint64)bytesTransferred + length > SSIZE_MAX)
|
||||||
|
bytesTransferred = SSIZE_MAX;
|
||||||
|
else
|
||||||
|
bytesTransferred += (ssize_t)length;
|
||||||
|
|
||||||
|
if (pos != -1)
|
||||||
|
pos += length;
|
||||||
|
|
||||||
|
if (length < vecs[i].iov_len)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (movePosition) {
|
||||||
|
descriptor->pos = write && (descriptor->open_mode & O_APPEND) != 0
|
||||||
|
? descriptor->ops->fd_seek(descriptor.Get(), 0, SEEK_END) : pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytesTransferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -758,8 +819,6 @@ static ssize_t
|
|||||||
common_user_vector_io(int fd, off_t pos, const iovec* userVecs, size_t count,
|
common_user_vector_io(int fd, off_t pos, const iovec* userVecs, size_t count,
|
||||||
bool write)
|
bool write)
|
||||||
{
|
{
|
||||||
if (pos < -1)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
if (count > IOV_MAX)
|
if (count > IOV_MAX)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
@@ -771,67 +830,17 @@ common_user_vector_io(int fd, off_t pos, const iovec* userVecs, size_t count,
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
FileDescriptorPutter descriptor(get_fd(get_current_io_context(false), fd));
|
SyscallRestartWrapper<ssize_t> result = common_vector_io(fd, pos,
|
||||||
if (!descriptor.IsSet())
|
vecs, count, write, false);
|
||||||
return B_FILE_ERROR;
|
|
||||||
|
|
||||||
if (write ? (descriptor->open_mode & O_RWMASK) == O_RDONLY
|
return result;
|
||||||
: (descriptor->open_mode & O_RWMASK) == O_WRONLY) {
|
}
|
||||||
return B_FILE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool movePosition = false;
|
|
||||||
if (pos == -1 && descriptor->pos != -1) {
|
|
||||||
pos = descriptor->pos;
|
|
||||||
movePosition = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (write ? descriptor->ops->fd_write == NULL
|
static status_t
|
||||||
: descriptor->ops->fd_read == NULL) {
|
common_close(int fd, bool kernel)
|
||||||
return B_BAD_VALUE;
|
{
|
||||||
}
|
return close_fd_index(get_current_io_context(kernel), fd);
|
||||||
|
|
||||||
SyscallRestartWrapper<status_t> status;
|
|
||||||
|
|
||||||
ssize_t bytesTransferred = 0;
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
if (vecs[i].iov_base == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
size_t length = vecs[i].iov_len;
|
|
||||||
if (write) {
|
|
||||||
status = descriptor->ops->fd_write(descriptor.Get(), pos,
|
|
||||||
vecs[i].iov_base, &length);
|
|
||||||
} else {
|
|
||||||
status = descriptor->ops->fd_read(descriptor.Get(), pos, vecs[i].iov_base,
|
|
||||||
&length);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != B_OK) {
|
|
||||||
if (bytesTransferred == 0)
|
|
||||||
return status;
|
|
||||||
status = B_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((uint64)bytesTransferred + length > SSIZE_MAX)
|
|
||||||
bytesTransferred = SSIZE_MAX;
|
|
||||||
else
|
|
||||||
bytesTransferred += (ssize_t)length;
|
|
||||||
|
|
||||||
if (pos != -1)
|
|
||||||
pos += length;
|
|
||||||
|
|
||||||
if (length < vecs[i].iov_len)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (movePosition) {
|
|
||||||
descriptor->pos = write && (descriptor->open_mode & O_APPEND) != 0
|
|
||||||
? descriptor->ops->fd_seek(descriptor.Get(), 0, SEEK_END) : pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytesTransferred;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1053,59 +1062,6 @@ _kern_read(int fd, off_t pos, void* buffer, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
_kern_readv(int fd, off_t pos, const iovec* vecs, size_t count)
|
|
||||||
{
|
|
||||||
status_t status;
|
|
||||||
|
|
||||||
if (pos < -1)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
FileDescriptorPutter descriptor(get_fd(get_current_io_context(true), fd));
|
|
||||||
|
|
||||||
if (!descriptor.IsSet())
|
|
||||||
return B_FILE_ERROR;
|
|
||||||
if ((descriptor->open_mode & O_RWMASK) == O_WRONLY)
|
|
||||||
return B_FILE_ERROR;
|
|
||||||
|
|
||||||
bool movePosition = false;
|
|
||||||
if (pos == -1 && descriptor->pos != -1) {
|
|
||||||
pos = descriptor->pos;
|
|
||||||
movePosition = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor->ops->fd_read == NULL)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
SyscallFlagUnsetter _;
|
|
||||||
|
|
||||||
ssize_t bytesRead = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
size_t length = vecs[i].iov_len;
|
|
||||||
status = descriptor->ops->fd_read(descriptor.Get(), pos,
|
|
||||||
vecs[i].iov_base, &length);
|
|
||||||
if (status != B_OK) {
|
|
||||||
bytesRead = status;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((uint64)bytesRead + length > SSIZE_MAX)
|
|
||||||
bytesRead = SSIZE_MAX;
|
|
||||||
else
|
|
||||||
bytesRead += (ssize_t)length;
|
|
||||||
|
|
||||||
if (pos != -1)
|
|
||||||
pos += vecs[i].iov_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (movePosition)
|
|
||||||
descriptor->pos = pos;
|
|
||||||
|
|
||||||
return bytesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
_kern_write(int fd, off_t pos, const void* buffer, size_t length)
|
_kern_write(int fd, off_t pos, const void* buffer, size_t length)
|
||||||
{
|
{
|
||||||
@@ -1146,56 +1102,19 @@ _kern_write(int fd, off_t pos, const void* buffer, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
_kern_readv(int fd, off_t pos, const iovec* vecs, size_t count)
|
||||||
|
{
|
||||||
|
SyscallFlagUnsetter _;
|
||||||
|
return common_vector_io(fd, pos, vecs, count, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
_kern_writev(int fd, off_t pos, const iovec* vecs, size_t count)
|
_kern_writev(int fd, off_t pos, const iovec* vecs, size_t count)
|
||||||
{
|
{
|
||||||
status_t status;
|
|
||||||
|
|
||||||
if (pos < -1)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
FileDescriptorPutter descriptor(get_fd(get_current_io_context(true), fd));
|
|
||||||
|
|
||||||
if (!descriptor.IsSet())
|
|
||||||
return B_FILE_ERROR;
|
|
||||||
if ((descriptor->open_mode & O_RWMASK) == O_RDONLY)
|
|
||||||
return B_FILE_ERROR;
|
|
||||||
|
|
||||||
bool movePosition = false;
|
|
||||||
if (pos == -1 && descriptor->pos != -1) {
|
|
||||||
pos = descriptor->pos;
|
|
||||||
movePosition = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor->ops->fd_write == NULL)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
SyscallFlagUnsetter _;
|
SyscallFlagUnsetter _;
|
||||||
|
return common_vector_io(fd, pos, vecs, count, true, true);
|
||||||
ssize_t bytesWritten = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
size_t length = vecs[i].iov_len;
|
|
||||||
status = descriptor->ops->fd_write(descriptor.Get(), pos,
|
|
||||||
vecs[i].iov_base, &length);
|
|
||||||
if (status != B_OK) {
|
|
||||||
bytesWritten = status;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((uint64)bytesWritten + length > SSIZE_MAX)
|
|
||||||
bytesWritten = SSIZE_MAX;
|
|
||||||
else
|
|
||||||
bytesWritten += (ssize_t)length;
|
|
||||||
|
|
||||||
if (pos != -1)
|
|
||||||
pos += vecs[i].iov_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (movePosition)
|
|
||||||
descriptor->pos = pos;
|
|
||||||
|
|
||||||
return bytesWritten;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user