fs: vectored IO API for filesystem read/write

This improves API consistency with uv_read and uv_write and may
improve efficiency for some uses. Vectored IO is emulated when the
requisite system calls are unavailable.
This commit is contained in:
Benjamin Saunders 2014-02-09 12:45:49 -08:00 committed by Fedor Indutny
parent d4c12adff6
commit 7df24583e5
10 changed files with 305 additions and 69 deletions

View File

@ -295,14 +295,15 @@ typedef struct {
uv_file file; \
int flags; \
mode_t mode; \
void* buf; \
size_t len; \
unsigned int nbufs; \
uv_buf_t* bufs; \
off_t off; \
uv_uid_t uid; \
uv_gid_t gid; \
double atime; \
double mtime; \
struct uv__work work_req; \
uv_buf_t bufsml[4]; \
#define UV_WORK_PRIVATE_FIELDS \
struct uv__work work_req;

View File

@ -552,9 +552,10 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
WCHAR* new_pathw; \
int file_flags; \
int fd_out; \
void* buf; \
size_t length; \
unsigned int nbufs; \
uv_buf_t* bufs; \
int64_t offset; \
uv_buf_t bufsml[4]; \
}; \
struct { \
double atime; \

View File

@ -1729,13 +1729,13 @@ UV_EXTERN int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path,
int flags, int mode, uv_fs_cb cb);
UV_EXTERN int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file,
void* buf, size_t length, int64_t offset, uv_fs_cb cb);
const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb);
UV_EXTERN int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb);
UV_EXTERN int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file,
const void* buf, size_t length, int64_t offset, uv_fs_cb cb);
const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb);
UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path,
int mode, uv_fs_cb cb);

View File

@ -44,10 +44,22 @@
#include <utime.h>
#include <poll.h>
#if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
# define HAVE_PREADV 1
#else
# define HAVE_PREADV 0
#endif
#if defined(__linux__) || defined(__sun)
# include <sys/sendfile.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
# include <sys/socket.h>
#endif
#if HAVE_PREADV || defined(__APPLE__)
# include <sys/uio.h>
#endif
@ -191,10 +203,59 @@ skip:
static ssize_t uv__fs_read(uv_fs_t* req) {
ssize_t result;
if (req->off < 0)
return read(req->file, req->buf, req->len);
else
return pread(req->file, req->buf, req->len, req->off);
result = readv(req->file, (struct iovec*) req->bufs, req->nbufs);
else {
#if HAVE_PREADV
result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
#else
# if defined(__linux__)
static int no_preadv;
if (no_preadv)
# endif
{
off_t nread;
size_t index;
# if defined(__linux__)
retry:
# endif
nread = 0;
index = 0;
result = 1;
do {
if (req->bufs[index].len > 0) {
result = pread(req->file,
req->bufs[index].base,
req->bufs[index].len,
req->off + nread);
if (result > 0)
nread += result;
}
index++;
} while (index < req->nbufs && result > 0);
if (nread > 0)
result = nread;
}
# if defined(__linux__)
else {
result = uv__preadv(req->file,
(struct iovec*)req->bufs,
req->nbufs,
req->off);
if (result == -1 && errno == ENOSYS) {
no_preadv = 1;
goto retry;
}
}
# endif
#endif
}
if (req->bufs != req->bufsml)
free(req->bufs);
return result;
}
@ -306,7 +367,7 @@ static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
int out_fd;
char buf[8192];
len = req->len;
len = req->bufsml[0].len;
in_fd = req->flags;
out_fd = req->file;
offset = req->off;
@ -419,7 +480,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
ssize_t r;
off = req->off;
r = sendfile(out_fd, in_fd, &off, req->len);
r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len);
/* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
* it still writes out data. Fortunately, we can detect it by checking if
@ -453,11 +514,11 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
#if defined(__FreeBSD__)
len = 0;
r = sendfile(in_fd, out_fd, req->off, req->len, NULL, &len, 0);
r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
#else
/* The darwin sendfile takes len as an input for the length to send,
* so make sure to initialize it with the caller's value. */
len = req->len;
len = req->bufsml[0].len;
r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0);
#endif
@ -507,14 +568,61 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
#endif
if (req->off < 0)
r = write(req->file, req->buf, req->len);
else
r = pwrite(req->file, req->buf, req->len, req->off);
r = writev(req->file, (struct iovec*) req->bufs, req->nbufs);
else {
#if HAVE_PREADV
r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
#else
# if defined(__linux__)
static int no_pwritev;
if (no_pwritev)
# endif
{
off_t written;
size_t index;
# if defined(__linux__)
retry:
# endif
written = 0;
index = 0;
r = 1;
do {
if (req->bufs[index].len > 0) {
r = pwrite(req->file,
req->bufs[index].base,
req->bufs[index].len,
req->off + written);
if (r > 0)
written += r;
}
index++;
} while (index < req->nbufs && r > 0);
if (written > 0)
r = written;
}
# if defined(__linux__)
else {
r = uv__pwritev(req->file,
(struct iovec*) req->bufs,
req->nbufs,
req->off);
if (r == -1 && errno == ENOSYS) {
no_pwritev = 1;
goto retry;
}
}
# endif
#endif
}
#if defined(__APPLE__)
pthread_mutex_unlock(&lock);
#endif
if (req->bufs != req->bufsml)
free(req->bufs);
return r;
}
@ -865,14 +973,23 @@ int uv_fs_open(uv_loop_t* loop,
int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
uv_file file,
void* buf,
size_t len,
const uv_buf_t bufs[],
unsigned int nbufs,
int64_t off,
uv_fs_cb cb) {
INIT(READ);
req->file = file;
req->buf = buf;
req->len = len;
req->nbufs = nbufs;
req->bufs = req->bufsml;
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = malloc(nbufs * sizeof(*bufs));
if (req->bufs == NULL)
return -ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
req->off = off;
POST;
}
@ -929,7 +1046,7 @@ int uv_fs_sendfile(uv_loop_t* loop,
req->flags = in_fd; /* hack */
req->file = out_fd;
req->off = off;
req->len = len;
req->bufsml[0].len = len;
POST;
}
@ -978,14 +1095,23 @@ int uv_fs_utime(uv_loop_t* loop,
int uv_fs_write(uv_loop_t* loop,
uv_fs_t* req,
uv_file file,
const void* buf,
size_t len,
const uv_buf_t bufs[],
unsigned int nbufs,
int64_t off,
uv_fs_cb cb) {
INIT(WRITE);
req->file = file;
req->buf = (void*) buf;
req->len = len;
req->nbufs = nbufs;
req->bufs = req->bufsml;
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = malloc(nbufs * sizeof(*bufs));
if (req->bufs == NULL)
return -ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
req->off = off;
POST;
}

View File

@ -199,6 +199,26 @@
# endif
#endif /* __NR_utimensat */
#ifndef __NR_preadv
# if defined(__x86_64__)
# define __NR_preadv 295
# elif defined(__i386__)
# define __NR_preadv 333
# elif defined(__arm__)
# define __NR_preadv (UV_SYSCALL_BASE + 361)
# endif
#endif /* __NR_preadv */
#ifndef __NR_pwritev
# if defined(__x86_64__)
# define __NR_pwritev 296
# elif defined(__i386__)
# define __NR_pwritev 334
# elif defined(__arm__)
# define __NR_pwritev (UV_SYSCALL_BASE + 362)
# endif
#endif /* __NR_pwritev */
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
#if defined(__i386__)
@ -386,3 +406,19 @@ int uv__utimesat(int dirfd,
return errno = ENOSYS, -1;
#endif
}
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) {
#if defined(__NR_preadv)
return syscall(__NR_preadv, fd, iov, iovcnt, offset);
#else
return errno = ENOSYS, -1;
#endif
}
ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) {
#if defined(__NR_pwritev)
return syscall(__NR_pwritev, fd, iov, iovcnt, offset);
#else
return errno = ENOSYS, -1;
#endif
}

View File

@ -147,5 +147,7 @@ int uv__utimesat(int dirfd,
const char* path,
const struct timespec times[2],
int flags);
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
#endif /* UV_LINUX_SYSCALL_H_ */

View File

@ -546,6 +546,8 @@ void fs__read(uv_fs_t* req) {
LARGE_INTEGER offset_;
DWORD bytes;
DWORD error;
int result;
unsigned int index;
VERIFY_FD(fd, req);
@ -573,7 +575,20 @@ void fs__read(uv_fs_t* req) {
overlapped_ptr = NULL;
}
if (ReadFile(handle, req->buf, req->length, &bytes, overlapped_ptr)) {
index = 0;
bytes = 0;
do {
DWORD incremental_bytes;
result = ReadFile(handle,
req->bufs[index].base,
req->bufs[index].len,
&incremental_bytes,
overlapped_ptr);
bytes += incremental_bytes;
++index;
} while (result && index < req->nbufs);
if (result || bytes > 0) {
SET_REQ_RESULT(req, bytes);
} else {
error = GetLastError();
@ -594,6 +609,8 @@ void fs__write(uv_fs_t* req) {
OVERLAPPED overlapped, *overlapped_ptr;
LARGE_INTEGER offset_;
DWORD bytes;
int result;
unsigned int index;
VERIFY_FD(fd, req);
@ -620,7 +637,20 @@ void fs__write(uv_fs_t* req) {
overlapped_ptr = NULL;
}
if (WriteFile(handle, req->buf, length, &bytes, overlapped_ptr)) {
index = 0;
bytes = 0;
do {
DWORD incremental_bytes;
result = WriteFile(handle,
req->bufs[index].base,
req->bufs[index].len,
&incremental_bytes,
overlapped_ptr);
bytes += incremental_bytes;
++index;
} while (result && index < req->nbufs);
if (result || bytes > 0) {
SET_REQ_RESULT(req, bytes);
} else {
SET_REQ_WIN32_ERROR(req, GetLastError());
@ -1569,13 +1599,27 @@ int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
}
int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file fd, void* buf,
size_t length, int64_t offset, uv_fs_cb cb) {
int uv_fs_read(uv_loop_t* loop,
uv_fs_t* req,
uv_file fd,
const uv_buf_t bufs[],
unsigned int nbufs,
int64_t offset,
uv_fs_cb cb) {
uv_fs_req_init(loop, req, UV_FS_READ, cb);
req->fd = fd;
req->buf = buf;
req->length = length;
req->nbufs = nbufs;
req->bufs = req->bufsml;
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = malloc(nbufs * sizeof(*bufs));
if (req->bufs == NULL)
return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
req->offset = offset;
if (cb) {
@ -1593,8 +1637,17 @@ int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file fd, const void* buf,
uv_fs_req_init(loop, req, UV_FS_WRITE, cb);
req->fd = fd;
req->buf = (void*) buf;
req->length = length;
req->nbufs = nbufs;
req->bufs = req->bufsml;
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = malloc(nbufs * sizeof(*bufs));
if (req->bufs == NULL)
return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
req->offset = offset;
if (cb) {

View File

@ -79,13 +79,15 @@ static void touch_file(uv_loop_t* loop, const char* name) {
int r;
uv_file file;
uv_fs_t req;
uv_buf_t buf;
r = uv_fs_open(loop, &req, name, O_RDWR, 0, NULL);
ASSERT(r >= 0);
file = r;
uv_fs_req_cleanup(&req);
r = uv_fs_write(loop, &req, file, "foo", 4, -1, NULL);
buf = uv_buf_init("foo", 4);
r = uv_fs_write(loop, &req, file, &buf, 1, -1, NULL);
ASSERT(r >= 0);
uv_fs_req_cleanup(&req);

View File

@ -102,7 +102,7 @@ static uv_fs_t futime_req;
static char buf[32];
static char test_buf[] = "test-buffer\n";
static uv_buf_t iov;
static void check_permission(const char* filename, unsigned int mode) {
int r;
@ -284,7 +284,8 @@ static void open_cb(uv_fs_t* req) {
ASSERT(memcmp(req->path, "test_file2\0", 11) == 0);
uv_fs_req_cleanup(req);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1,
read_cb);
ASSERT(r == 0);
}
@ -345,8 +346,8 @@ static void create_cb(uv_fs_t* req) {
ASSERT(req->result >= 0);
create_cb_count++;
uv_fs_req_cleanup(req);
r = uv_fs_write(loop, &write_req, req->result, test_buf, sizeof(test_buf),
-1, write_cb);
iov = uv_buf_init(test_buf, sizeof(test_buf));
r = uv_fs_write(loop, &write_req, req->result, &iov, 1, -1, write_cb);
ASSERT(r == 0);
}
@ -663,8 +664,8 @@ TEST_IMPL(fs_file_sync) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
sizeof(test_buf), -1, NULL);
iov = uv_buf_init(test_buf, sizeof(test_buf));
r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
@ -679,8 +680,8 @@ TEST_IMPL(fs_file_sync) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
NULL);
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(read_req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
@ -707,7 +708,8 @@ TEST_IMPL(fs_file_sync) {
uv_fs_req_cleanup(&open_req1);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1,
NULL);
ASSERT(r >= 0);
ASSERT(read_req.result >= 0);
@ -910,7 +912,8 @@ TEST_IMPL(fs_fstat) {
file = req.result;
uv_fs_req_cleanup(&req);
r = uv_fs_write(loop, &req, file, test_buf, sizeof(test_buf), -1, NULL);
iov = uv_buf_init(test_buf, sizeof(test_buf));
r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL);
ASSERT(r == sizeof(test_buf));
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
@ -1020,7 +1023,8 @@ TEST_IMPL(fs_chmod) {
file = req.result;
uv_fs_req_cleanup(&req);
r = uv_fs_write(loop, &req, file, test_buf, sizeof(test_buf), -1, NULL);
iov = uv_buf_init(test_buf, sizeof(test_buf));
r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL);
ASSERT(r == sizeof(test_buf));
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
@ -1183,7 +1187,8 @@ TEST_IMPL(fs_link) {
file = req.result;
uv_fs_req_cleanup(&req);
r = uv_fs_write(loop, &req, file, test_buf, sizeof(test_buf), -1, NULL);
iov = uv_buf_init(test_buf, sizeof(test_buf));
r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL);
ASSERT(r == sizeof(test_buf));
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
@ -1203,7 +1208,8 @@ TEST_IMPL(fs_link) {
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL);
ASSERT(r >= 0);
ASSERT(req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
@ -1223,7 +1229,8 @@ TEST_IMPL(fs_link) {
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL);
ASSERT(r >= 0);
ASSERT(req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
@ -1289,7 +1296,8 @@ TEST_IMPL(fs_symlink) {
file = req.result;
uv_fs_req_cleanup(&req);
r = uv_fs_write(loop, &req, file, test_buf, sizeof(test_buf), -1, NULL);
iov = uv_buf_init(test_buf, sizeof(test_buf));
r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL);
ASSERT(r == sizeof(test_buf));
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
@ -1326,7 +1334,8 @@ TEST_IMPL(fs_symlink) {
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL);
ASSERT(r >= 0);
ASSERT(req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
@ -1365,7 +1374,8 @@ TEST_IMPL(fs_symlink) {
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL);
ASSERT(r >= 0);
ASSERT(req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
@ -1774,8 +1784,8 @@ TEST_IMPL(fs_file_open_append) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
sizeof(test_buf), -1, NULL);
iov = uv_buf_init(test_buf, sizeof(test_buf));
r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
@ -1790,8 +1800,8 @@ TEST_IMPL(fs_file_open_append) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
sizeof(test_buf), -1, NULL);
iov = uv_buf_init(test_buf, sizeof(test_buf));
r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
@ -1806,7 +1816,8 @@ TEST_IMPL(fs_file_open_append) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1,
NULL);
printf("read = %d\n", r);
ASSERT(r == 26);
@ -1844,8 +1855,8 @@ TEST_IMPL(fs_rename_to_existing_file) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
sizeof(test_buf), -1, NULL);
iov = uv_buf_init(test_buf, sizeof(test_buf));
r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
@ -1877,7 +1888,8 @@ TEST_IMPL(fs_rename_to_existing_file) {
uv_fs_req_cleanup(&open_req1);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1,
NULL);
ASSERT(r >= 0);
ASSERT(read_req.result >= 0);
@ -1912,8 +1924,8 @@ TEST_IMPL(fs_read_file_eof) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
sizeof(test_buf), -1, NULL);
iov = uv_buf_init(test_buf, sizeof(test_buf));
r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
@ -1929,15 +1941,16 @@ TEST_IMPL(fs_read_file_eof) {
uv_fs_req_cleanup(&open_req1);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
NULL);
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(read_req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
uv_fs_req_cleanup(&read_req);
r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf),
read_req.result, NULL);
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1,
read_req.result, NULL);
ASSERT(r == 0);
ASSERT(read_req.result == 0);
uv_fs_req_cleanup(&read_req);

View File

@ -218,6 +218,7 @@ TEST_IMPL(spawn_stdout_to_file) {
uv_file file;
uv_fs_t fs_req;
uv_stdio_container_t stdio[2];
uv_buf_t buf;
/* Setup. */
unlink("stdout_file");
@ -246,8 +247,8 @@ TEST_IMPL(spawn_stdout_to_file) {
ASSERT(exit_cb_called == 1);
ASSERT(close_cb_called == 1);
r = uv_fs_read(uv_default_loop(), &fs_req, file, output, sizeof(output),
0, NULL);
buf = uv_buf_init(output, sizeof(output));
r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL);
ASSERT(r == 12);
uv_fs_req_cleanup(&fs_req);
@ -271,6 +272,7 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file) {
uv_file file;
uv_fs_t fs_req;
uv_stdio_container_t stdio[3];
uv_buf_t buf;
/* Setup. */
unlink("stdout_file");
@ -301,8 +303,8 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file) {
ASSERT(exit_cb_called == 1);
ASSERT(close_cb_called == 1);
r = uv_fs_read(uv_default_loop(), &fs_req, file, output, sizeof(output),
0, NULL);
buf = uv_buf_init(output, sizeof(output));
r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL);
ASSERT(r == 27);
uv_fs_req_cleanup(&fs_req);