diff --git a/src/system/kernel/fs/fd.cpp b/src/system/kernel/fs/fd.cpp index d19ab6f951..d85450c99e 100644 --- a/src/system/kernel/fs/fd.cpp +++ b/src/system/kernel/fs/fd.cpp @@ -29,6 +29,7 @@ #include #include +#include "Vnode.h" #include "vfs_tracing.h" @@ -722,7 +723,30 @@ common_vector_io(int fd, off_t pos, const iovec* vecs, size_t count, bool write, return B_BAD_VALUE; } + // See if we can bypass the loop and perform I/O directly. We can only do this + // for vnodes that have no cache, as the I/O hook bypasses the cache entirely. + struct vnode* vnode = descriptor->u.vnode; status_t status = B_OK; + if (!movePosition && pos != -1 && count > 1 && descriptor->type == FDTYPE_FILE + && vnode != NULL && vnode->cache == NULL && vnode->ops->io != NULL) { + BStackOrHeapArray 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; for (size_t i = 0; i < count; i++) { if (vecs[i].iov_base == NULL)