mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
vfs: use iovec_iterator for all file read and write, add vfs_read_iovec and vfs_write_iovec
This commit is contained in:
+22
-24
@@ -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;
|
||||
|
||||
+45
-23
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
+32
-4
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+32
-9
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user