diff --git a/kernel-src/fs/devfs.c b/kernel-src/fs/devfs.c index f63f0a4e..5716feeb 100644 --- a/kernel-src/fs/devfs.c +++ b/kernel-src/fs/devfs.c @@ -71,7 +71,7 @@ int devfs_close(vnode_t *node, int flags, cred_t *cred) { return devnode->devops->close(devnode->attr.rdevminor, flags); } -int devfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) { +int devfs_read(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) { if (node->type == V_TYPE_DIR) return EISDIR; @@ -85,19 +85,10 @@ int devfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int f if (devnode->devops->read == NULL) return ENODEV; - // TODO remove this once the whole fs uses iovec - iovec_iterator_t iovec_iterator; - iovec_t iovec = { - .addr = buffer, - .len = size - }; - - iovec_iterator_init(&iovec_iterator, &iovec, 1); - - return devnode->devops->read(devnode->attr.rdevminor, &iovec_iterator, size, offset, flags, readc); + return devnode->devops->read(devnode->attr.rdevminor, iovec_iterator, size, offset, flags, readc); } -int devfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) { +int devfs_write(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) { if (node->type == V_TYPE_DIR) return EISDIR; @@ -111,16 +102,7 @@ int devfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int if (devnode->devops->write == NULL) return ENODEV; - // TODO remove this once the whole fs uses iovec - iovec_iterator_t iovec_iterator; - iovec_t iovec = { - .addr = buffer, - .len = size - }; - - iovec_iterator_init(&iovec_iterator, &iovec, 1); - - return devnode->devops->write(devnode->attr.rdevminor, &iovec_iterator, size, offset, flags, writec); + return devnode->devops->write(devnode->attr.rdevminor, iovec_iterator, size, offset, flags, writec); } int devfs_lookup(vnode_t *node, char *name, vnode_t **result, cred_t *cred) { @@ -400,8 +382,16 @@ static int devfs_getdents(vnode_t *node, dent_t *buffer, size_t count, uintmax_t static int devfs_getpage(vnode_t *node, uintmax_t offset, struct page_t *page) { // only block devices will have this called __assert(node->type == V_TYPE_BLKDEV); + iovec_t iovec = { + .addr = MAKE_HHDM(pmm_getpageaddress(page)), + .len = PAGE_SIZE + }; + + iovec_iterator_t iovec_iterator; + iovec_iterator_init(&iovec_iterator, &iovec, 1); + size_t readc; - int error = VOP_READ(node, MAKE_HHDM(pmm_getpageaddress(page)), PAGE_SIZE, offset, 0, &readc, NULL); + int error = VOP_READ(node, &iovec_iterator, PAGE_SIZE, offset, 0, &readc, NULL); if (readc == 0) return ENXIO; @@ -411,8 +401,16 @@ static int devfs_getpage(vnode_t *node, uintmax_t offset, struct page_t *page) { static int devfs_putpage(vnode_t *node, uintmax_t offset, struct page_t *page) { // only block devices will have this called __assert(node->type == V_TYPE_BLKDEV); + iovec_t iovec = { + .addr = MAKE_HHDM(pmm_getpageaddress(page)), + .len = PAGE_SIZE + }; + + iovec_iterator_t iovec_iterator; + iovec_iterator_init(&iovec_iterator, &iovec, 1); + size_t writec; - int error = VOP_WRITE(node, MAKE_HHDM(pmm_getpageaddress(page)), PAGE_SIZE, offset, 0, &writec, NULL); + int error = VOP_WRITE(node, &iovec_iterator, PAGE_SIZE, offset, 0, &writec, NULL); __assert(writec != 0); return error; diff --git a/kernel-src/fs/ext2.c b/kernel-src/fs/ext2.c index 240e66e1..8feef5db 100644 --- a/kernel-src/fs/ext2.c +++ b/kernel-src/fs/ext2.c @@ -749,12 +749,11 @@ static int resizeinode(ext2fs_t *fs, ext2node_t *node, size_t newsize) { return 0; } -static int rwblocks(ext2fs_t *fs, ext2node_t *node, void *buffer, size_t count, uintmax_t index, bool write, bool cache) { +static int rwblocks_iovec(ext2fs_t *fs, ext2node_t *node, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t index, bool write, bool cache) { for (uintmax_t i = 0; i < count; ++i) { size_t inodesize = INODE_SIZE(&node->inode); __assert(index + i < ROUND_UP(inodesize, fs->blocksize) / fs->blocksize); - void *bufferp = (void *)((uintptr_t)buffer + i * fs->blocksize); blockptr_t block; int e = getinodeblock(fs, node, index + i, &block); if (e) @@ -775,14 +774,14 @@ static int rwblocks(ext2fs_t *fs, ext2node_t *node, void *buffer, size_t count, block = newblock; } else if (block == 0 && write == false) { - memset(bufferp, 0, fs->blocksize); + iovec_iterator_memset(iovec_iterator, 0, fs->blocksize); continue; } size_t donecount; e = write ? - vfs_write(fs->backing, bufferp, fs->blocksize, BLOCK_GETDISKOFFSET(fs, block), &donecount, cache ? 0 : V_FFLAGS_NOCACHE) : - vfs_read(fs->backing, bufferp, fs->blocksize, BLOCK_GETDISKOFFSET(fs, block), &donecount, cache ? 0 : V_FFLAGS_NOCACHE); + vfs_write_iovec(fs->backing, iovec_iterator, fs->blocksize, BLOCK_GETDISKOFFSET(fs, block), &donecount, cache ? 0 : V_FFLAGS_NOCACHE) : + vfs_read_iovec(fs->backing, iovec_iterator, fs->blocksize, BLOCK_GETDISKOFFSET(fs, block), &donecount, cache ? 0 : V_FFLAGS_NOCACHE); if (e) return e; @@ -792,7 +791,7 @@ static int rwblocks(ext2fs_t *fs, ext2node_t *node, void *buffer, size_t count, return 0; } -static int rwblock(ext2fs_t *fs, ext2node_t *node, void *buffer, size_t count, uintmax_t offset, uintmax_t index, bool write, bool cache) { +static int rwblock_iovec(ext2fs_t *fs, ext2node_t *node, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, uintmax_t index, bool write, bool cache) { __assert(offset + count <= fs->blocksize); size_t inodesize = INODE_SIZE(&node->inode); __assert(index < ROUND_UP(inodesize, fs->blocksize) / fs->blocksize); @@ -818,14 +817,14 @@ static int rwblock(ext2fs_t *fs, ext2node_t *node, void *buffer, size_t count, u block = newblock; } else if (block == 0 && write == false) { - memset(buffer, 0, count); + iovec_iterator_memset(iovec_iterator, 0, count); return 0; } size_t donecount; e = write ? - vfs_write(fs->backing, buffer, count, BLOCK_GETDISKOFFSET(fs, block) + offset, &donecount, cache ? 0 : V_FFLAGS_NOCACHE) : - vfs_read(fs->backing, buffer, count, BLOCK_GETDISKOFFSET(fs, block) + offset, &donecount, cache ? 0 : V_FFLAGS_NOCACHE); + vfs_write_iovec(fs->backing, iovec_iterator, count, BLOCK_GETDISKOFFSET(fs, block) + offset, &donecount, cache ? 0 : V_FFLAGS_NOCACHE) : + vfs_read_iovec(fs->backing, iovec_iterator, count, BLOCK_GETDISKOFFSET(fs, block) + offset, &donecount, cache ? 0 : V_FFLAGS_NOCACHE); if (e) return e; @@ -834,7 +833,7 @@ static int rwblock(ext2fs_t *fs, ext2node_t *node, void *buffer, size_t count, u return e; } -static int rwbytes(ext2fs_t *fs, ext2node_t *node, void *buffer, size_t count, uintmax_t offset, bool write, bool cache) { +static int rwbytes_iovec(ext2fs_t *fs, ext2node_t *node, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, bool write, bool cache) { uintmax_t index = offset / fs->blocksize; uintmax_t startoffset = offset % fs->blocksize; @@ -842,11 +841,10 @@ static int rwbytes(ext2fs_t *fs, ext2node_t *node, void *buffer, size_t count, u if (startoffset) { size_t blockremaining = fs->blocksize - startoffset; size_t docount = min(blockremaining, count); - int e = rwblock(fs, node, buffer, docount, startoffset, index, write, cache); + int e = rwblock_iovec(fs, node, iovec_iterator, docount, startoffset, index, write, cache); if (e) return e; - buffer = (void *)((uintptr_t)buffer + docount); count -= docount; index += 1; } @@ -854,17 +852,28 @@ static int rwbytes(ext2fs_t *fs, ext2node_t *node, void *buffer, size_t count, u // r/w all middle blocks size_t blocks = count / fs->blocksize; if (blocks) { - int e = rwblocks(fs, node, buffer, blocks, index, write, cache); + int e = rwblocks_iovec(fs, node, iovec_iterator, blocks, index, write, cache); if (e) return e; count -= blocks * fs->blocksize; - buffer = (void *)((uintptr_t)buffer + blocks * fs->blocksize); index += blocks; } // r/w remaining block if there's any data left and return - return count ? rwblock(fs, node, buffer, count, 0, index, write, cache) : 0; + return count ? rwblock_iovec(fs, node, iovec_iterator, count, 0, index, write, cache) : 0; +} + +static int rwbytes(ext2fs_t *fs, ext2node_t *node, void *buffer, size_t count, uintmax_t offset, bool write, bool cache) { + iovec_t iovec = { + .addr = buffer, + .len = count + }; + + iovec_iterator_t iovec_iterator; + iovec_iterator_init(&iovec_iterator, &iovec, 1); + + return rwbytes_iovec(fs, node, &iovec_iterator, count, offset, write, cache); } #define BUFFER_MAP_FLAGS (ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC) @@ -1317,9 +1326,7 @@ static int ext2_readlink(vnode_t *vnode, char **link, cred_t *cred) { return err; } -// this *should*, by the rules of the vnode ops, accept a user buffer. however, this will never be the case. all I/O will -// go through the page cache -static int ext2_read(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) { +static int ext2_read(vnode_t *vnode, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) { if (vnode->type == V_TYPE_DIR) return EISDIR; @@ -1350,7 +1357,7 @@ static int ext2_read(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset if (size == 0) goto cleanup; - err = rwbytes(fs, node, buffer, size, offset, false, false); + err = rwbytes_iovec(fs, node, iovec_iterator, size, offset, false, false); *readc = err ? -1 : size; @@ -1360,7 +1367,7 @@ static int ext2_read(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset // this *should*, by the rules of the vnode ops, accept a user buffer. however, this will never be the case. all I/O will // go through the page cache -int ext2_write(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) { +int ext2_write(vnode_t *vnode, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) { if (vnode->type == V_TYPE_DIR) return EISDIR; @@ -1386,7 +1393,7 @@ int ext2_write(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset, int size = min(endoffset, inodesize) - offset; } - err = rwbytes(fs, node, buffer, size, offset, true, false); + err = rwbytes(fs, node, iovec_iterator, size, offset, true, false); *writec = err ? -1 : size; if (err) goto cleanup; @@ -1695,7 +1702,15 @@ static int ext2_getpage(vnode_t *node, uintmax_t offset, struct page_t *page) { __assert(node->type == V_TYPE_REGULAR); size_t readc = PAGE_SIZE; void *addr = MAKE_HHDM(pmm_getpageaddress(page)); - int error = VOP_READ(node, addr, PAGE_SIZE, offset, 0, &readc, NULL); + + iovec_t iovec = { + .addr = addr, + .len = PAGE_SIZE + }; + + iovec_iterator_t iovec_iterator; + iovec_iterator_init(&iovec_iterator, &iovec, 1); + int error = VOP_READ(node, &iovec_iterator, PAGE_SIZE, offset, 0, &readc, NULL); if (readc == 0) return ENXIO; else if (readc != PAGE_SIZE) @@ -1708,7 +1723,14 @@ static int ext2_putpage(vnode_t *node, uintmax_t offset, struct page_t *page) { // only regular files get cached __assert(node->type == V_TYPE_REGULAR); size_t writec; - int error = VOP_WRITE(node, MAKE_HHDM(pmm_getpageaddress(page)), PAGE_SIZE, offset, 0, &writec, NULL); + iovec_t iovec = { + .addr = MAKE_HHDM(pmm_getpageaddress(page)), + .len = PAGE_SIZE + }; + + iovec_iterator_t iovec_iterator; + iovec_iterator_init(&iovec_iterator, &iovec, 1); + int error = VOP_WRITE(node, &iovec_iterator, PAGE_SIZE, offset, 0, &writec, NULL); // its possible that writec is zero here. the condition where this is possible is when // the file is truncated after the check in the page sync function but before it actually is diff --git a/kernel-src/fs/pipefs.c b/kernel-src/fs/pipefs.c index 9b8bf319..7d204b91 100644 --- a/kernel-src/fs/pipefs.c +++ b/kernel-src/fs/pipefs.c @@ -130,8 +130,7 @@ static int internalpoll(vnode_t *node, polldata_t *data, int events) { return revents; } -// buffer can possibly be a user address -int pipefs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) { +int pipefs_read(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) { pipenode_t *pipenode = (pipenode_t *)node; INTERNAL_LOCK(node); @@ -171,7 +170,7 @@ int pipefs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int INTERNAL_LOCK(node); } - *readc = ringbuffer_read(&pipenode->data, buffer, size); + *readc = iovec_iterator_read_from_ringbuffer(iovec_iterator, &pipenode->data, size); if (*readc == RINGBUFFER_USER_COPY_FAILED) error = EFAULT; @@ -184,7 +183,7 @@ int pipefs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int return error; } -static int writetopipe(pipenode_t *pipenode, void *buffer, size_t size, size_t *writec) { +static int writetopipe(pipenode_t *pipenode, iovec_iterator_t *iovec_iterator, size_t size, size_t *writec) { if (pipenode->readers == 0) { if (current_thread()->proc) signal_signalproc(current_thread()->proc, SIGPIPE); @@ -192,7 +191,7 @@ static int writetopipe(pipenode_t *pipenode, void *buffer, size_t size, size_t * return EPIPE; } - *writec = ringbuffer_write(&pipenode->data, buffer, size); + *writec = iovec_iterator_write_to_ringbuffer(iovec_iterator, &pipenode->data, size); if (*writec == RINGBUFFER_USER_COPY_FAILED) return EFAULT; @@ -201,7 +200,7 @@ static int writetopipe(pipenode_t *pipenode, void *buffer, size_t size, size_t * return 0; } -int pipefs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) { +int pipefs_write(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) { pipenode_t *pipenode = (pipenode_t *)node; INTERNAL_LOCK(node); @@ -247,7 +246,7 @@ int pipefs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int if (nonblock == false && atomic == false && freebytes) { size_t tmp; size_t writecount = min(freebytes, size - case3written); - error = writetopipe(pipenode, (void *)((uintptr_t)buffer + case3written), writecount, &tmp); + error = writetopipe(pipenode, iovec_iterator, writecount, &tmp); if (error) goto leave; @@ -290,7 +289,7 @@ int pipefs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int INTERNAL_LOCK(node); } - error = writetopipe(pipenode, buffer, size, writec); + error = writetopipe(pipenode, iovec_iterator, size, writec); leave: INTERNAL_UNLOCK(node); diff --git a/kernel-src/fs/sockfs.c b/kernel-src/fs/sockfs.c index 212c6f52..58e7eb9a 100644 --- a/kernel-src/fs/sockfs.c +++ b/kernel-src/fs/sockfs.c @@ -24,14 +24,42 @@ int sockfs_close(vnode_t *node, int flags, cred_t *cred) { return ENOSYS; // not needed } -int sockfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) { +int sockfs_read(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *bytes_read, cred_t *cred) { socket_t *socket = SOCKFS_SOCKET_FROM_NODE(node); - return socket_read(socket, buffer, size, flags, readc); + sockdesc_t desc = { + .addr = NULL, + .iovec_iterator = iovec_iterator, + .count = size, + .flags = flags, + .donecount = 0, + .ctrl = NULL, + .ctrllen = 0 + }; + + int e = socket->ops->recv(socket, &desc); + + *bytes_read = desc.donecount; + + return e; } -int sockfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) { +int sockfs_write(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *bytes_written, cred_t *cred) { socket_t *socket = SOCKFS_SOCKET_FROM_NODE(node); - return socket_write(socket, buffer, size, flags, writec); + sockdesc_t desc = { + .addr = NULL, + .iovec_iterator = iovec_iterator, + .count = size, + .flags = flags, + .donecount = 0, + .ctrl = NULL, + .ctrllen = 0 + }; + + int e = socket->ops->send(socket, &desc); + + *bytes_written = desc.donecount; + + return e; } int sockfs_poll(vnode_t *node, polldata_t *data, int events) { diff --git a/kernel-src/fs/tmpfs.c b/kernel-src/fs/tmpfs.c index 3099ec12..2ec25cfe 100644 --- a/kernel-src/fs/tmpfs.c +++ b/kernel-src/fs/tmpfs.c @@ -220,7 +220,7 @@ static int tmpfs_root(vfs_t *vfs, vnode_t **vnode) { return 0; } -static int tmpfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) { +static int tmpfs_read(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) { if (node->type == V_TYPE_DIR) return EISDIR; @@ -230,7 +230,7 @@ static int tmpfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset __assert(!"tmpfs_read is handled by the page cache"); } -static int tmpfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) { +static int tmpfs_write(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) { if (node->type == V_TYPE_DIR) return EISDIR; diff --git a/kernel-src/fs/vfs.c b/kernel-src/fs/vfs.c index 5329d1b5..61cd6ff5 100644 --- a/kernel-src/fs/vfs.c +++ b/kernel-src/fs/vfs.c @@ -229,8 +229,7 @@ static int writenocache(vnode_t *node, page_t *page, uintmax_t pageoffset) { return e; } -// buffer can be a user address -int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t *written, int flags) { +int vfs_write_iovec(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, size_t *written, int flags) { int err = 0; if (vfs_iscacheable(node)) { *written = 0; @@ -292,7 +291,7 @@ int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t size_t writesize = min(PAGE_SIZE - startoffset, size); void *address = MAKE_HHDM(pmm_getpageaddress(page)); - err = USERCOPY_POSSIBLY_FROM_USER((void *)((uintptr_t)address + startoffset), buffer, writesize); + err = iovec_iterator_copy_to_buffer(iovec_iterator, (void *)((uintptr_t)address + startoffset), writesize); if (err) { pmm_release(FROM_HHDM(address)); goto leave; @@ -320,7 +319,7 @@ int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t size_t writesize = min(PAGE_SIZE, size - *written); void *address = MAKE_HHDM(pmm_getpageaddress(page)); - err = USERCOPY_POSSIBLY_FROM_USER(address, (void *)((uintptr_t)buffer + *written), writesize); + err = iovec_iterator_copy_to_buffer(iovec_iterator, address, writesize); if (err) { pmm_release(FROM_HHDM(address)); goto leave; @@ -343,14 +342,14 @@ int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t } else { // special file, just write as its not being cached VOP_LOCK(node); - err = VOP_WRITE(node, buffer, size, offset, flags, written, getcred()); + err = VOP_WRITE(node, iovec_iterator, size, offset, flags, written, getcred()); VOP_UNLOCK(node); } return err; } -int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t *bytesread, int flags) { +int vfs_read_iovec(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, size_t *bytesread, int flags) { int err = 0; if (vfs_iscacheable(node)) { *bytesread = 0; @@ -406,7 +405,7 @@ int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t size_t readsize = min(PAGE_SIZE - startoffset, size); void *address = MAKE_HHDM(pmm_getpageaddress(page)); - err = USERCOPY_POSSIBLY_TO_USER(buffer, (void *)((uintptr_t)address + startoffset), readsize); + err = iovec_iterator_copy_from_buffer(iovec_iterator, (void *)((uintptr_t)address + startoffset), readsize); if (err) { pmm_release(FROM_HHDM(address)); goto leave; @@ -433,7 +432,7 @@ int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t size_t readsize = min(PAGE_SIZE, size - *bytesread); void *address = MAKE_HHDM(pmm_getpageaddress(page)); - err = USERCOPY_POSSIBLY_TO_USER((void *)((uintptr_t)buffer + *bytesread), address, readsize); + err = iovec_iterator_copy_from_buffer(iovec_iterator, address, readsize); if (err) { pmm_release(FROM_HHDM(address)); goto leave; @@ -451,12 +450,36 @@ int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t } else { // special file, just read as size doesn't matter VOP_LOCK(node); - err = VOP_READ(node, buffer, size, offset, flags, bytesread, getcred()); + err = VOP_READ(node, iovec_iterator, size, offset, flags, bytesread, getcred()); VOP_UNLOCK(node); } return err; } +int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t *written, int flags) { + iovec_t iovec = { + .addr = buffer, + .len = size + }; + + iovec_iterator_t iovec_iterator; + iovec_iterator_init(&iovec_iterator, &iovec, 1); + + return vfs_write_iovec(node, &iovec_iterator, size, offset, written, flags); +} + +int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t *bytes_read, int flags) { + iovec_t iovec = { + .addr = buffer, + .len = size + }; + + iovec_iterator_t iovec_iterator; + iovec_iterator_init(&iovec_iterator, &iovec, 1); + + return vfs_read_iovec(node, &iovec_iterator, size, offset, bytes_read, flags); +} + // if type is V_TYPE_LINK, a symlink is made // in that case, destref is ignored, destpath is the link value and attr points to the attributes of the symlink // if type is V_TYPE_REGULAR, a hardlink is made. diff --git a/kernel-src/include/kernel/sock.h b/kernel-src/include/kernel/sock.h index 093009ef..147394e0 100644 --- a/kernel-src/include/kernel/sock.h +++ b/kernel-src/include/kernel/sock.h @@ -39,7 +39,7 @@ typedef struct { typedef struct { sockaddr_t *addr; - iovec_iterator_t iovec_iterator; + iovec_iterator_t *iovec_iterator; size_t count; uintmax_t flags; size_t donecount; @@ -80,8 +80,11 @@ typedef struct { #define SOCKFS_SOCKET_FROM_NODE(nodep) (((socketnode_t *)(nodep))->socket) static inline int socket_read(socket_t *socket, void *buffer, size_t size, uintmax_t flags, size_t *bytes_read) { + iovec_iterator_t iovec_iterator; + sockdesc_t desc = { .addr = NULL, + .iovec_iterator = &iovec_iterator, .count = size, .flags = flags, .donecount = 0, @@ -94,7 +97,7 @@ static inline int socket_read(socket_t *socket, void *buffer, size_t size, uintm .len = size }; - iovec_iterator_init(&desc.iovec_iterator, &iovec, 1); + iovec_iterator_init(desc.iovec_iterator, &iovec, 1); int e = socket->ops->recv(socket, &desc); @@ -104,8 +107,11 @@ static inline int socket_read(socket_t *socket, void *buffer, size_t size, uintm } static inline int socket_write(socket_t *socket, void *buffer, size_t size, uintmax_t flags, size_t *bytes_written) { + iovec_iterator_t iovec_iterator; + sockdesc_t desc = { .addr = NULL, + .iovec_iterator = &iovec_iterator, .count = size, .flags = flags, .donecount = 0, @@ -118,7 +124,7 @@ static inline int socket_write(socket_t *socket, void *buffer, size_t size, uint .len = size }; - iovec_iterator_init(&desc.iovec_iterator, &iovec, 1); + iovec_iterator_init(desc.iovec_iterator, &iovec, 1); int e = socket->ops->send(socket, &desc); diff --git a/kernel-src/include/kernel/vfs.h b/kernel-src/include/kernel/vfs.h index baf46566..11f804a0 100644 --- a/kernel-src/include/kernel/vfs.h +++ b/kernel-src/include/kernel/vfs.h @@ -118,8 +118,8 @@ struct polldata; typedef struct vops_t { int (*open)(vnode_t **node, int flags, cred_t *cred); int (*close)(vnode_t *node, int flags, cred_t *cred); - int (*read)(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred); - int (*write)(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred); + int (*read)(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred); + int (*write)(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred); int (*lookup)(vnode_t *node, char *name, vnode_t **result, cred_t *cred); int (*create)(vnode_t *parent, char *name, vattr_t *attr, int type, vnode_t **result, cred_t *cred); int (*getattr)(vnode_t *node, vattr_t *attr, cred_t *cred); @@ -214,6 +214,8 @@ int vfs_register(vfsops_t *vfsops, char *name); int vfs_open(vnode_t *ref, char *path, int flags, vnode_t **result); int vfs_close(vnode_t *node, int flags); +int vfs_write_iovec(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, size_t *written, int flags); +int vfs_read_iovec(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, size_t *bytesread, int flags); int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t *written, int flags); int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t *bytesread, int flags); int vfs_create(vnode_t *ref, char *path, vattr_t *attr, int type, vnode_t **node); diff --git a/kernel-src/io/net/localsocket.c b/kernel-src/io/net/localsocket.c index 7157eaea..ac39229e 100644 --- a/kernel-src/io/net/localsocket.c +++ b/kernel-src/io/net/localsocket.c @@ -363,7 +363,7 @@ static int localsock_send(socket_t *socket, sockdesc_t *sockdesc) { goto leave; } - sockdesc->donecount = iovec_iterator_write_to_ringbuffer(&sockdesc->iovec_iterator, &peer->ringbuffer, sockdesc->count); + sockdesc->donecount = iovec_iterator_write_to_ringbuffer(sockdesc->iovec_iterator, &peer->ringbuffer, sockdesc->count); if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) { error = EFAULT; goto leave; @@ -467,13 +467,13 @@ static int localsock_recv(socket_t *socket, sockdesc_t *sockdesc) { } if (flags & SOCKET_RECV_FLAGS_PEEK) { - sockdesc->donecount = iovec_iterator_peek_from_ringbuffer(&sockdesc->iovec_iterator, &localsocket->ringbuffer, 0, recvcount); + sockdesc->donecount = iovec_iterator_peek_from_ringbuffer(sockdesc->iovec_iterator, &localsocket->ringbuffer, 0, recvcount); if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) { error = EFAULT; goto leave; } } else { - sockdesc->donecount = iovec_iterator_read_from_ringbuffer(&sockdesc->iovec_iterator, &localsocket->ringbuffer, recvcount); + sockdesc->donecount = iovec_iterator_read_from_ringbuffer(sockdesc->iovec_iterator, &localsocket->ringbuffer, recvcount); if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) { error = EPIPE; goto leave; diff --git a/kernel-src/io/net/tcp.c b/kernel-src/io/net/tcp.c index 72131e6c..190c7f05 100644 --- a/kernel-src/io/net/tcp.c +++ b/kernel-src/io/net/tcp.c @@ -1305,7 +1305,7 @@ static int tcp_send(socket_t *socket, sockdesc_t *sockdesc) { size_t writesize = min(TCB_RINGBUFFER_SIZE - RINGBUFFER_DATACOUNT(&tcb->transmitbuffer), sockdesc->count); __assert(writesize); - sockdesc->donecount = iovec_iterator_write_to_ringbuffer(&sockdesc->iovec_iterator, &tcb->transmitbuffer, writesize); + sockdesc->donecount = iovec_iterator_write_to_ringbuffer(sockdesc->iovec_iterator, &tcb->transmitbuffer, writesize); if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) { error = EFAULT; goto leave; @@ -1386,13 +1386,13 @@ static int tcp_recv(socket_t *socket, sockdesc_t *sockdesc) { size_t copycount = min(RINGBUFFER_DATACOUNT(&tcb->receivebuffer), sockdesc->count); if (flags & SOCKET_RECV_FLAGS_PEEK) { - sockdesc->donecount = iovec_iterator_peek_from_ringbuffer(&sockdesc->iovec_iterator, &tcb->receivebuffer, 0, copycount); + sockdesc->donecount = iovec_iterator_peek_from_ringbuffer(sockdesc->iovec_iterator, &tcb->receivebuffer, 0, copycount); if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) { error = EFAULT; goto cleanup; } } else { - sockdesc->donecount = iovec_iterator_read_from_ringbuffer(&sockdesc->iovec_iterator, &tcb->receivebuffer, copycount); + sockdesc->donecount = iovec_iterator_read_from_ringbuffer(sockdesc->iovec_iterator, &tcb->receivebuffer, copycount); if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) { error = EFAULT; goto cleanup; diff --git a/kernel-src/io/net/udp.c b/kernel-src/io/net/udp.c index f2bab61a..e5c033a6 100644 --- a/kernel-src/io/net/udp.c +++ b/kernel-src/io/net/udp.c @@ -203,7 +203,7 @@ static int udp_send(socket_t *socket, sockdesc_t *sockdesc) { socket->state = SOCKET_STATE_BOUND; } - e = udp_sendpacket(&sockdesc->iovec_iterator, sockdesc->count, sockdesc->addr ? sockdesc->addr->ipv4addr.addr : udpsocket->peeraddress, + e = udp_sendpacket(sockdesc->iovec_iterator, sockdesc->count, sockdesc->addr ? sockdesc->addr->ipv4addr.addr : udpsocket->peeraddress, udpsocket->port, sockdesc->addr ? sockdesc->addr->ipv4addr.port : udpsocket->peerport, udpsocket->socket.netdev); sockdesc->donecount = sockdesc->count; @@ -274,7 +274,7 @@ static int udp_recv(socket_t *socket, sockdesc_t *sockdesc) { copycount = min(header.length, sockdesc->count); - sockdesc->donecount = iovec_iterator_peek_from_ringbuffer(&sockdesc->iovec_iterator, &udpsocket->ringbuffer, sizeof(header), copycount); + sockdesc->donecount = iovec_iterator_peek_from_ringbuffer(sockdesc->iovec_iterator, &udpsocket->ringbuffer, sizeof(header), copycount); if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) { e = EFAULT; goto cleanup; diff --git a/kernel-src/sys/syscalls/recvmsg.c b/kernel-src/sys/syscalls/recvmsg.c index 24848fc4..9d53787a 100644 --- a/kernel-src/sys/syscalls/recvmsg.c +++ b/kernel-src/sys/syscalls/recvmsg.c @@ -55,8 +55,10 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) if (flags & MSG_WAITALL) recvflags |= SOCKET_RECV_FLAGS_WAITALL; + iovec_iterator_t iovec_iterator; sockdesc_t desc = { .addr = &sockaddr, + .iovec_iterator = &iovec_iterator, .count = buffersize, .flags = fileflagstovnodeflags(file->flags) | recvflags, .donecount = 0, @@ -65,7 +67,7 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) .ctrldone = 0 }; - iovec_iterator_init(&desc.iovec_iterator, msghdr.iov, msghdr.iovcount); + iovec_iterator_init(desc.iovec_iterator, msghdr.iov, msghdr.iovcount); ret.errno = socket->ops->recv(socket, &desc); if (ret.errno) diff --git a/kernel-src/sys/syscalls/sendmsg.c b/kernel-src/sys/syscalls/sendmsg.c index 3279ea67..b32de3c8 100644 --- a/kernel-src/sys/syscalls/sendmsg.c +++ b/kernel-src/sys/syscalls/sendmsg.c @@ -49,8 +49,10 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); + iovec_iterator_t iovec_iterator; sockdesc_t desc = { .addr = msghdr.addr ? &sockaddr : NULL, + .iovec_iterator = &iovec_iterator, .count = buffersize, .flags = fileflagstovnodeflags(file->flags) | ((flags & MSG_NOSIGNAL) ? SOCKET_SEND_FLAGS_NOSIGNAL : 0), .donecount = 0, @@ -59,7 +61,7 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) .ctrldone = 0 }; - iovec_iterator_init(&desc.iovec_iterator, msghdr.iov, msghdr.iovcount); + iovec_iterator_init(desc.iovec_iterator, msghdr.iov, msghdr.iovcount); ret.errno = socket->ops->send(socket, &desc); ret.ret = ret.errno ? -1 : desc.donecount;