mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
tmpfs: propery O_DIRECT semantics
This commit is contained in:
+5
-47
@@ -165,6 +165,9 @@ static int tmpfs_open(vnode_t **nodep, int flags, cred_t *cred) {
|
||||
if (node->type == V_TYPE_SOCKET)
|
||||
return ENXIO;
|
||||
|
||||
if (node->type == V_TYPE_REGULAR && (flags & V_FFLAGS_NOCACHE))
|
||||
return EINVAL;
|
||||
|
||||
if (node->type == V_TYPE_CHDEV || node->type == V_TYPE_BLKDEV) {
|
||||
vnode_t *devnode;
|
||||
error = devfs_getnode(node, tmpnode->attr.rdevmajor, tmpnode->attr.rdevminor, &devnode);
|
||||
@@ -224,63 +227,18 @@ static int tmpfs_root(vfs_t *vfs, vnode_t **vnode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tmpfs_rw(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, size_t *done, bool write) {
|
||||
*done = 0;
|
||||
while (*done < size) {
|
||||
uintmax_t current_offset = offset + *done;
|
||||
uintmax_t page_offset = current_offset / PAGE_SIZE * PAGE_SIZE;
|
||||
size_t page_start = current_offset % PAGE_SIZE;
|
||||
size_t copy_size = min(PAGE_SIZE - page_start, size - *done);
|
||||
|
||||
page_t *page;
|
||||
int error = mm_cache_get_page(node, page_offset, 0, &page);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
void *address = MAKE_HHDM(mm_get_page_address(page));
|
||||
if (write)
|
||||
error = iovec_iterator_copy_to_buffer(iovec_iterator, (void *)((uintptr_t)address + page_start), copy_size);
|
||||
else
|
||||
error = iovec_iterator_copy_from_buffer(iovec_iterator, (void *)((uintptr_t)address + page_start), copy_size);
|
||||
mm_release_page(FROM_HHDM(address));
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
*done += copy_size;
|
||||
}
|
||||
|
||||
if (write && *done)
|
||||
((tmpfsnode_t *)node)->attr.mtime = timekeeper_time();
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (node->type != V_TYPE_REGULAR)
|
||||
return EINVAL;
|
||||
|
||||
tmpfsnode_t *tmpfsnode = (tmpfsnode_t *)node;
|
||||
if (offset >= tmpfsnode->attr.size) {
|
||||
*readc = 0;
|
||||
return 0;
|
||||
}
|
||||
size = min(size, tmpfsnode->attr.size - offset);
|
||||
return tmpfs_rw(node, iovec_iterator, size, offset, readc, false);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (node->type != V_TYPE_REGULAR)
|
||||
return EINVAL;
|
||||
|
||||
if (size + offset < offset)
|
||||
return EOVERFLOW;
|
||||
__assert(size + offset <= ((tmpfsnode_t *)node)->attr.size);
|
||||
return tmpfs_rw(node, iovec_iterator, size, offset, writec, true);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
static int tmpfs_access(vnode_t *vnode, mode_t mode, cred_t *cred) {
|
||||
|
||||
Reference in New Issue
Block a user