kernel/fs: Use the new fd_readv/fd_writev hooks in common_vector_io.
And move the file_readv/file_writev implementation to the VFS.
This commit is contained in:
+17
-26
@@ -29,7 +29,6 @@
|
|||||||
#include <vfs.h>
|
#include <vfs.h>
|
||||||
#include <wait_for_objects.h>
|
#include <wait_for_objects.h>
|
||||||
|
|
||||||
#include "Vnode.h"
|
|
||||||
#include "vfs_tracing.h"
|
#include "vfs_tracing.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -709,30 +708,22 @@ common_vector_io(int fd, off_t pos, const iovec* vecs, size_t count, bool write,
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we can bypass the loop and perform I/O directly. We can only do this
|
if (!movePosition && count > 1 && (write ? descriptor->ops->fd_writev != NULL
|
||||||
// for vnodes that have no cache, as the I/O hook bypasses the cache entirely.
|
: descriptor->ops->fd_readv != NULL)) {
|
||||||
struct vnode* vnode = descriptor->u.vnode;
|
ssize_t result;
|
||||||
|
if (write) {
|
||||||
|
result = descriptor->ops->fd_writev(descriptor.Get(), pos,
|
||||||
|
vecs, count);
|
||||||
|
} else {
|
||||||
|
result = descriptor->ops->fd_readv(descriptor.Get(), pos,
|
||||||
|
vecs, count);
|
||||||
|
}
|
||||||
|
if (result != B_UNSUPPORTED)
|
||||||
|
return result;
|
||||||
|
// If not supported, just fall back to the loop.
|
||||||
|
}
|
||||||
|
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
if (!movePosition && pos != -1 && count > 1 && fd_is_file(descriptor.Get())
|
|
||||||
&& vnode != NULL && vnode->cache == NULL && vnode->ops->io != NULL) {
|
|
||||||
BStackOrHeapArray<generic_io_vec, 8> iovecs(count);
|
|
||||||
if (!iovecs.IsValid())
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
generic_size_t length = 0;
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
iovecs[i].base = (generic_addr_t)vecs[i].iov_base;
|
|
||||||
iovecs[i].length = vecs[i].iov_len;
|
|
||||||
length += vecs[i].iov_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = (write ? vfs_write_pages : vfs_read_pages)(vnode,
|
|
||||||
descriptor->cookie, pos, iovecs, count, 0, &length);
|
|
||||||
if (length > 0)
|
|
||||||
return length;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t bytesTransferred = 0;
|
ssize_t bytesTransferred = 0;
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
if (vecs[i].iov_base == NULL)
|
if (vecs[i].iov_base == NULL)
|
||||||
@@ -743,8 +734,8 @@ common_vector_io(int fd, off_t pos, const iovec* vecs, size_t count, bool write,
|
|||||||
status = descriptor->ops->fd_write(descriptor.Get(), pos,
|
status = descriptor->ops->fd_write(descriptor.Get(), pos,
|
||||||
vecs[i].iov_base, &length);
|
vecs[i].iov_base, &length);
|
||||||
} else {
|
} else {
|
||||||
status = descriptor->ops->fd_read(descriptor.Get(), pos, vecs[i].iov_base,
|
status = descriptor->ops->fd_read(descriptor.Get(), pos,
|
||||||
&length);
|
vecs[i].iov_base, &length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
|
|||||||
@@ -358,6 +358,10 @@ static status_t file_read(struct file_descriptor* descriptor, off_t pos,
|
|||||||
void* buffer, size_t* _bytes);
|
void* buffer, size_t* _bytes);
|
||||||
static status_t file_write(struct file_descriptor* descriptor, off_t pos,
|
static status_t file_write(struct file_descriptor* descriptor, off_t pos,
|
||||||
const void* buffer, size_t* _bytes);
|
const void* buffer, size_t* _bytes);
|
||||||
|
static ssize_t file_readv(struct file_descriptor* descriptor, off_t pos,
|
||||||
|
const struct iovec *vecs, int count);
|
||||||
|
static ssize_t file_writev(struct file_descriptor* descriptor, off_t pos,
|
||||||
|
const struct iovec *vecs, int count);
|
||||||
static off_t file_seek(struct file_descriptor* descriptor, off_t pos,
|
static off_t file_seek(struct file_descriptor* descriptor, off_t pos,
|
||||||
int seekType);
|
int seekType);
|
||||||
static void file_free_fd(struct file_descriptor* descriptor);
|
static void file_free_fd(struct file_descriptor* descriptor);
|
||||||
@@ -435,8 +439,8 @@ static struct fd_ops sFileOps = {
|
|||||||
file_free_fd,
|
file_free_fd,
|
||||||
file_read,
|
file_read,
|
||||||
file_write,
|
file_write,
|
||||||
NULL, // readv()
|
file_readv,
|
||||||
NULL, // writev()
|
file_writev,
|
||||||
file_seek,
|
file_seek,
|
||||||
common_ioctl,
|
common_ioctl,
|
||||||
NULL, // set_flags()
|
NULL, // set_flags()
|
||||||
@@ -5725,6 +5729,63 @@ file_write(struct file_descriptor* descriptor, off_t pos, const void* buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
file_vector_io(struct file_descriptor* descriptor, off_t pos,
|
||||||
|
const struct iovec *vecs, int count, bool write)
|
||||||
|
{
|
||||||
|
struct vnode* vnode = descriptor->u.vnode;
|
||||||
|
if (pos != -1 && descriptor->pos == -1)
|
||||||
|
return ESPIPE;
|
||||||
|
if (S_ISDIR(vnode->Type()))
|
||||||
|
return B_IS_A_DIRECTORY;
|
||||||
|
|
||||||
|
if (pos == -1)
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
if (!HAS_FS_CALL(vnode, io))
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
// We can only perform real vectored I/O for vnodes that have no cache,
|
||||||
|
// because the I/O hook bypasses the cache entirely.
|
||||||
|
if (vnode->cache != NULL)
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
BStackOrHeapArray<generic_io_vec, 8> iovecs(count);
|
||||||
|
if (!iovecs.IsValid())
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
generic_size_t length = 0;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
iovecs[i].base = (generic_addr_t)vecs[i].iov_base;
|
||||||
|
iovecs[i].length = vecs[i].iov_len;
|
||||||
|
length += vecs[i].iov_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t status = (write ? vfs_write_pages : vfs_read_pages)(vnode,
|
||||||
|
descriptor->cookie, pos, iovecs, count, 0, &length);
|
||||||
|
if (length > 0)
|
||||||
|
return length;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
file_readv(struct file_descriptor* descriptor, off_t pos,
|
||||||
|
const struct iovec *vecs, int count)
|
||||||
|
{
|
||||||
|
FUNCTION(("file_readv: pos %" B_PRIdOFF "\n", pos));
|
||||||
|
return file_vector_io(descriptor, pos, vecs, count, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
file_writev(struct file_descriptor* descriptor, off_t pos,
|
||||||
|
const struct iovec *vecs, int count)
|
||||||
|
{
|
||||||
|
FUNCTION(("file_writev: pos %" B_PRIdOFF "\n", pos));
|
||||||
|
return file_vector_io(descriptor, pos, vecs, count, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static off_t
|
static off_t
|
||||||
file_seek(struct file_descriptor* descriptor, off_t pos, int seekType)
|
file_seek(struct file_descriptor* descriptor, off_t pos, int seekType)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user