mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-29 05:38:21 +00:00
vmmcache: initial implementation
This commit is contained in:
+24
-1
@@ -6,6 +6,7 @@
|
||||
#include <errno.h>
|
||||
#include <kernel/alloc.h>
|
||||
#include <kernel/timekeeper.h>
|
||||
#include <kernel/pmm.h>
|
||||
|
||||
static devnode_t *devfsroot;
|
||||
|
||||
@@ -332,6 +333,26 @@ static int devfs_getdents(vnode_t *node, dent_t *buffer, size_t count, uintmax_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
size_t readc;
|
||||
int error = VOP_READ(node, MAKE_HHDM(pmm_getpageaddress(page)), PAGE_SIZE, offset, 0, &readc, NULL);
|
||||
if (readc == 0)
|
||||
return ENXIO;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
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);
|
||||
size_t writec;
|
||||
int error = VOP_WRITE(node, MAKE_HHDM(pmm_getpageaddress(page)), PAGE_SIZE, offset, 0, &writec, NULL);
|
||||
__assert(writec != 0);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int devfs_enodev() {
|
||||
return ENODEV;
|
||||
@@ -365,7 +386,9 @@ static vops_t vnops = {
|
||||
.ioctl = devfs_ioctl,
|
||||
.maxseek = devfs_maxseek,
|
||||
.resize = devfs_enodev,
|
||||
.rename = devfs_enodev
|
||||
.rename = devfs_enodev,
|
||||
.putpage = devfs_putpage,
|
||||
.getpage = devfs_getpage
|
||||
};
|
||||
|
||||
static void ctor(scache_t *cache, void *obj) {
|
||||
|
||||
+39
-4
@@ -9,6 +9,7 @@
|
||||
#include <mutex.h>
|
||||
#include <logging.h>
|
||||
#include <util.h>
|
||||
#include <kernel/vmmcache.h>
|
||||
|
||||
#define INODE_ROOT 2
|
||||
|
||||
@@ -1262,9 +1263,12 @@ int ext2_write(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset, int
|
||||
endoffset = -1ll;
|
||||
|
||||
if (endoffset > inodesize) {
|
||||
err = resizeinode(fs, node, endoffset);
|
||||
if (err)
|
||||
if (offset > inodesize) {
|
||||
*writec = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
size = min(endoffset, inodesize) - offset;
|
||||
}
|
||||
|
||||
err = rwbytes(fs, node, buffer, size, offset, true);
|
||||
@@ -1281,10 +1285,17 @@ int ext2_write(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset, int
|
||||
}
|
||||
|
||||
int ext2_resize(vnode_t *vnode, size_t newsize, cred_t *cred) {
|
||||
__assert(vnode->type == V_TYPE_REGULAR);
|
||||
ext2node_t *node = (ext2node_t *)vnode;
|
||||
ext2fs_t *fs = (ext2fs_t *)vnode->vfs;
|
||||
VOP_LOCK(vnode);
|
||||
int e = resizeinode(fs, node, newsize);
|
||||
size_t size = INODE_SIZE(&node->inode);
|
||||
int e = 0;
|
||||
if (size != newsize) {
|
||||
e = resizeinode(fs, node, newsize);
|
||||
if (size > newsize)
|
||||
vmmcache_truncate(vnode, newsize);
|
||||
}
|
||||
VOP_UNLOCK(vnode);
|
||||
return e;
|
||||
}
|
||||
@@ -1546,6 +1557,27 @@ static int ext2_unlink(vnode_t *vnode, char *name, cred_t *cred) {
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ext2_getpage(vnode_t *node, uintmax_t offset, struct page_t *page) {
|
||||
// only regular files get cached
|
||||
__assert(node->type == V_TYPE_REGULAR);
|
||||
size_t readc;
|
||||
int error = VOP_READ(node, MAKE_HHDM(pmm_getpageaddress(page)), PAGE_SIZE, offset, 0, &readc, NULL);
|
||||
if (readc == 0)
|
||||
return ENXIO;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
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);
|
||||
__assert(writec != 0);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int ext2_inactive(vnode_t *vnode) {
|
||||
ext2node_t *node = (ext2node_t *)vnode;
|
||||
ext2fs_t *fs = (ext2fs_t *)vnode->vfs;
|
||||
@@ -1564,6 +1596,7 @@ static int ext2_inactive(vnode_t *vnode) {
|
||||
__assert(hashtable_remove(&fs->inodetable, &node->id, sizeof(node->id)) == 0);
|
||||
MUTEX_RELEASE(&fs->inodetablelock);
|
||||
|
||||
vmmcache_truncate(vnode, 0);
|
||||
freeinode(fs, &node->inode, node->id);
|
||||
|
||||
slab_free(nodecache, node);
|
||||
@@ -1722,7 +1755,9 @@ static vops_t vnops = {
|
||||
.munmap = ext2_munmap,
|
||||
.unlink = ext2_unlink,
|
||||
.inactive = ext2_inactive,
|
||||
.rename = ext2_rename
|
||||
.rename = ext2_rename,
|
||||
.getpage = ext2_getpage,
|
||||
.putpage = ext2_putpage
|
||||
};
|
||||
|
||||
void ext2_init() {
|
||||
|
||||
@@ -258,7 +258,9 @@ static vops_t vnops = {
|
||||
.munmap = pipefs_enodev,
|
||||
.getdents = pipefs_enodev,
|
||||
.resize = pipefs_enodev,
|
||||
.rename = pipefs_enodev
|
||||
.rename = pipefs_enodev,
|
||||
.putpage = pipefs_enodev,
|
||||
.getpage = pipefs_enodev
|
||||
};
|
||||
|
||||
static void ctor(scache_t *cache, void *obj) {
|
||||
|
||||
@@ -184,7 +184,9 @@ static vops_t vnops = {
|
||||
.getdents = sockfs_enodev,
|
||||
.resize = sockfs_enodev,
|
||||
.rename = sockfs_enodev,
|
||||
.ioctl = sockfs_ioctl
|
||||
.ioctl = sockfs_ioctl,
|
||||
.putpage = sockfs_enodev,
|
||||
.getpage = sockfs_enodev
|
||||
};
|
||||
|
||||
static void ctor(scache_t *cache, void *obj) {
|
||||
|
||||
+46
-96
@@ -12,6 +12,7 @@
|
||||
#include <kernel/vmm.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <string.h>
|
||||
#include <kernel/vmmcache.h>
|
||||
|
||||
static scache_t *nodecache;
|
||||
static tmpfsnode_t *newnode(vfs_t *vfs, int type);
|
||||
@@ -31,60 +32,11 @@ static int tmpfs_mount(vfs_t **vfs, vnode_t *mountpoint, vnode_t *backing, void
|
||||
|
||||
#define DATAMMUFLAGS (ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_NOEXEC)
|
||||
|
||||
// expects to be called with node locked
|
||||
static int resize(tmpfsnode_t *node, size_t size) {
|
||||
if (size == node->attr.size || node->vnode.type != V_TYPE_REGULAR)
|
||||
return 0;
|
||||
|
||||
// if smaller, don't deallocate any pages
|
||||
if (size < node->attr.size) {
|
||||
node->attr.size = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// no mapping yet
|
||||
if (node->pagecount == 0) {
|
||||
size_t mapsize = ROUND_UP(size, PAGE_SIZE);
|
||||
node->data = vmm_map(NULL, mapsize, VMM_FLAGS_ALLOCATE, DATAMMUFLAGS, NULL);
|
||||
if (node->data == NULL)
|
||||
return ENOMEM;
|
||||
memset(node->data, 0, size);
|
||||
node->pagecount = mapsize / PAGE_SIZE;
|
||||
node->attr.size = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t diff = size - node->attr.size;
|
||||
// no need for new pages
|
||||
if (size < node->pagecount * PAGE_SIZE) {
|
||||
memset((void *)((uintptr_t)node->data + node->attr.size), 0, diff);
|
||||
node->attr.size = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// double the capacity or, if new size larger than double, resize to fit
|
||||
size_t newcount = size > node->pagecount * 2 * PAGE_SIZE ? ROUND_UP(size, PAGE_SIZE) / PAGE_SIZE : node->pagecount * 2;
|
||||
|
||||
void *newdata = vmm_map(NULL, newcount, VMM_FLAGS_PAGESIZE | VMM_FLAGS_ALLOCATE, DATAMMUFLAGS, NULL);
|
||||
if (newdata == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
memcpy(newdata, node->data, node->attr.size);
|
||||
memset(((void *)(uintptr_t)newdata + node->attr.size), 0, diff);
|
||||
vmm_unmap(node->data, node->pagecount, VMM_FLAGS_PAGESIZE);
|
||||
|
||||
node->pagecount = newcount;
|
||||
node->data = newdata;
|
||||
node->attr.size = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tmpfs_getattr(vnode_t *node, vattr_t *attr, cred_t *cred) {
|
||||
VOP_LOCK(node);
|
||||
tmpfsnode_t *tmpnode = (tmpfsnode_t *)node;
|
||||
*attr = tmpnode->attr;
|
||||
attr->blocksused = node->type == V_TYPE_DIR ? 1 : tmpnode->pagecount;
|
||||
attr->blocksused = ROUND_UP(attr->size, PAGE_SIZE) / PAGE_SIZE;
|
||||
VOP_UNLOCK(node);
|
||||
return 0;
|
||||
}
|
||||
@@ -233,50 +185,11 @@ static int tmpfs_root(vfs_t *vfs, vnode_t **vnode) {
|
||||
}
|
||||
|
||||
static int tmpfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) {
|
||||
tmpfsnode_t *tmpnode = (tmpfsnode_t *)node;
|
||||
if (node->type != V_TYPE_REGULAR)
|
||||
return EINVAL;
|
||||
|
||||
VOP_LOCK(node);
|
||||
// offset past end of file
|
||||
if (offset >= tmpnode->attr.size) {
|
||||
*readc = 0;
|
||||
VOP_UNLOCK(node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// top of read goes past end of file
|
||||
if (offset + size > tmpnode->attr.size)
|
||||
size = tmpnode->attr.size - offset;
|
||||
|
||||
*readc = size;
|
||||
memcpy(buffer, (void *)((uintptr_t)tmpnode->data + offset), size);
|
||||
|
||||
VOP_UNLOCK(node);
|
||||
return 0;
|
||||
__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) {
|
||||
tmpfsnode_t *tmpnode = (tmpfsnode_t *)node;
|
||||
if (node->type != V_TYPE_REGULAR)
|
||||
return EINVAL;
|
||||
|
||||
size_t top = offset + size;
|
||||
|
||||
VOP_LOCK(node);
|
||||
if (top > tmpnode->attr.size) {
|
||||
int err = resize(tmpnode, top);
|
||||
if (err) {
|
||||
VOP_UNLOCK(node);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
*writec = size;
|
||||
memcpy((void *)((uintptr_t)tmpnode->data + offset), buffer, size);
|
||||
|
||||
VOP_UNLOCK(node);
|
||||
return 0;
|
||||
__assert(!"tmpfs_read is handled by the page cache");
|
||||
}
|
||||
|
||||
static int tmpfs_access(vnode_t *node, mode_t mode, cred_t *cred) {
|
||||
@@ -530,6 +443,9 @@ static int tmpfs_getdents(vnode_t *node, dent_t *buffer, size_t count, uintmax_t
|
||||
}
|
||||
|
||||
static int tmpfs_inactive(vnode_t *node) {
|
||||
if (node->type == V_TYPE_REGULAR) {
|
||||
vmmcache_truncate(node, 0);
|
||||
}
|
||||
freenode((tmpfsnode_t *)node);
|
||||
return 0;
|
||||
}
|
||||
@@ -537,10 +453,44 @@ static int tmpfs_inactive(vnode_t *node) {
|
||||
static int tmpfs_resize(vnode_t *node, size_t size, cred_t *) {
|
||||
VOP_LOCK(node);
|
||||
|
||||
int err = resize((tmpfsnode_t *)node, size);
|
||||
tmpfsnode_t *tmpfsnode = (tmpfsnode_t *)node;
|
||||
if (size != tmpfsnode->attr.size && tmpfsnode->vnode.type == V_TYPE_REGULAR) {
|
||||
if (tmpfsnode->attr.size > size)
|
||||
vmmcache_truncate(node, size);
|
||||
|
||||
tmpfsnode->attr.size = size;
|
||||
}
|
||||
|
||||
VOP_UNLOCK(node);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tmpfs_getpage(vnode_t *node, uintmax_t offset, struct page_t *page) {
|
||||
int error = 0;
|
||||
|
||||
VOP_LOCK(node);
|
||||
tmpfsnode_t *tmpfsnode = (tmpfsnode_t *)node;
|
||||
if (offset >= tmpfsnode->attr.size)
|
||||
error = ENXIO;
|
||||
|
||||
VOP_UNLOCK(node);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
// since tmpfs files now store their data on the vmmcache,
|
||||
// all getpage will do will be set the page to 0 and pin it in memory
|
||||
void *phy = pmm_getpageaddress(page);
|
||||
void *phyhhdm = MAKE_HHDM(phy);
|
||||
|
||||
pmm_hold(phy);
|
||||
page->flags |= PAGE_FLAGS_PINNED;
|
||||
memset(phyhhdm, 0, PAGE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tmpfs_putpage(vnode_t *node, uintmax_t offset, struct page_t *page) {
|
||||
// putpage is a no-op on tmpfs
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vfsops_t vfsops = {
|
||||
@@ -568,7 +518,9 @@ static vops_t vnops = {
|
||||
.munmap = tmpfs_munmap,
|
||||
.getdents = tmpfs_getdents,
|
||||
.resize = tmpfs_resize,
|
||||
.rename = tmpfs_rename
|
||||
.rename = tmpfs_rename,
|
||||
.getpage = tmpfs_getpage,
|
||||
.putpage = tmpfs_putpage
|
||||
};
|
||||
|
||||
static tmpfsnode_t *newnode(vfs_t *vfs, int type) {
|
||||
@@ -613,8 +565,6 @@ static void freenode(tmpfsnode_t *node) {
|
||||
VOP_RELEASE(pnode);
|
||||
__assert(hashtable_destroy(&node->children) == 0);
|
||||
break;
|
||||
case V_TYPE_REGULAR:
|
||||
vmm_unmap(node->data, node->pagecount, VMM_FLAGS_PAGESIZE);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+170
-2
@@ -7,6 +7,8 @@
|
||||
#include <arch/cpu.h>
|
||||
#include <kernel/poll.h>
|
||||
#include <kernel/sock.h>
|
||||
#include <kernel/vmmcache.h>
|
||||
#include <kernel/block.h>
|
||||
|
||||
#define PATHNAME_MAX 512
|
||||
#define MAXLINKDEPTH 64
|
||||
@@ -144,13 +146,179 @@ int vfs_create(vnode_t *ref, char *path, vattr_t *attr, int type, vnode_t **node
|
||||
return err;
|
||||
}
|
||||
|
||||
static void bytestopages(uintmax_t offset, size_t size, uintmax_t *pageoffset, size_t *pagecount, uintmax_t *startoffset) {
|
||||
*pageoffset = offset / PAGE_SIZE;
|
||||
*startoffset = offset % PAGE_SIZE;
|
||||
size_t end = offset + size;
|
||||
size_t toppage = ROUND_UP(end, PAGE_SIZE) / PAGE_SIZE;
|
||||
*pagecount = toppage - *pageoffset;
|
||||
}
|
||||
|
||||
int vfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t *written, int flags) {
|
||||
int err = VOP_WRITE(node, buffer, size, offset, flags, written, getcred());
|
||||
int err;
|
||||
// TODO skip caching flag, cred check
|
||||
if (node->type == V_TYPE_REGULAR || node->type == V_TYPE_BLKDEV) {
|
||||
*written = 0;
|
||||
// can't write a size 0 buffer
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
// overflow
|
||||
if (size + offset < offset) {
|
||||
err = EINVAL;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
MUTEX_ACQUIRE(&node->sizelock, false);
|
||||
vattr_t attr;
|
||||
err = VOP_GETATTR(node, &attr, getcred());
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
size_t newsize = size + offset > attr.size ? size + offset : 0;
|
||||
|
||||
if (node->type == V_TYPE_REGULAR && newsize) {
|
||||
// do resize stuff if regular and applicable
|
||||
err = VOP_RESIZE(node, newsize, &_cpu()->thread->proc->cred);
|
||||
if (err)
|
||||
goto leave;
|
||||
} else if (node->type == V_TYPE_BLKDEV) {
|
||||
// else just get the disk size and limit the read size
|
||||
blockdesc_t blockdesc;
|
||||
int r;
|
||||
err = VOP_IOCTL(node, BLOCK_IOCTL_GETDESC, &blockdesc, &r);
|
||||
__assert(err == 0);
|
||||
|
||||
size_t bytesize = blockdesc.blockcapacity * blockdesc.blocksize;
|
||||
|
||||
if (offset >= bytesize)
|
||||
goto leave;
|
||||
|
||||
size = min(size + offset, bytesize) - offset;
|
||||
}
|
||||
|
||||
uintmax_t pageoffset, pagecount, startoffset;
|
||||
bytestopages(offset, size, &pageoffset, &pagecount, &startoffset);
|
||||
page_t *page = NULL;
|
||||
|
||||
if (startoffset) {
|
||||
// unaligned first page
|
||||
err = vmmcache_getpage(node, pageoffset * PAGE_SIZE, &page);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
size_t writesize = min(PAGE_SIZE - startoffset, size);
|
||||
void *address = MAKE_HHDM(pmm_getpageaddress(page));
|
||||
memcpy((void *)((uintptr_t)address + startoffset), buffer, writesize);
|
||||
vmmcache_makedirty(page);
|
||||
pmm_release(FROM_HHDM(address));
|
||||
*written += writesize;
|
||||
pageoffset += 1;
|
||||
pagecount -= 1;
|
||||
}
|
||||
|
||||
for (uintmax_t offset = 0; offset < pagecount * PAGE_SIZE; offset += PAGE_SIZE) {
|
||||
// the other pages
|
||||
err = vmmcache_getpage(node, pageoffset * PAGE_SIZE + offset, &page);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
size_t writesize = min(PAGE_SIZE, size - *written);
|
||||
void *address = MAKE_HHDM(pmm_getpageaddress(page));
|
||||
memcpy(address, (void *)((uintptr_t)buffer + *written), writesize);
|
||||
vmmcache_makedirty(page);
|
||||
pmm_release(FROM_HHDM(address));
|
||||
*written += writesize;
|
||||
}
|
||||
|
||||
leave:
|
||||
MUTEX_RELEASE(&node->sizelock);
|
||||
} else {
|
||||
// special file, just write as its not being cached
|
||||
err = VOP_WRITE(node, buffer, size, offset, flags, written, getcred());
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int vfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, size_t *bytesread, int flags) {
|
||||
int err = VOP_READ(node, buffer, size, offset, flags, bytesread, getcred());
|
||||
// TODO skip caching flag, cred check
|
||||
int err;
|
||||
if (node->type == V_TYPE_REGULAR || node->type == V_TYPE_BLKDEV) {
|
||||
*bytesread = 0;
|
||||
// can't read 0 bytes from the cache
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
// overflow
|
||||
if (size + offset < offset) {
|
||||
err = EINVAL;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
MUTEX_ACQUIRE(&node->sizelock, false);
|
||||
size_t nodesize = 0;
|
||||
|
||||
if (node->type == V_TYPE_REGULAR) {
|
||||
vattr_t attr;
|
||||
err = VOP_GETATTR(node, &attr, getcred());
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
nodesize = attr.size;
|
||||
} else {
|
||||
blockdesc_t blockdesc;
|
||||
int r;
|
||||
err = VOP_IOCTL(node, BLOCK_IOCTL_GETDESC, &blockdesc, &r);
|
||||
__assert(err == 0);
|
||||
|
||||
nodesize = blockdesc.blockcapacity * blockdesc.blocksize;
|
||||
}
|
||||
|
||||
// read past end of file?
|
||||
if (offset >= nodesize)
|
||||
goto leave;
|
||||
|
||||
size = min(size + offset, nodesize) - offset;
|
||||
|
||||
uintmax_t pageoffset, pagecount, startoffset;
|
||||
bytestopages(offset, size, &pageoffset, &pagecount, &startoffset);
|
||||
page_t *page = NULL;
|
||||
|
||||
if (startoffset) {
|
||||
// unaligned first page
|
||||
err = vmmcache_getpage(node, pageoffset * PAGE_SIZE, &page);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
size_t readsize = min(PAGE_SIZE - startoffset, size);
|
||||
void *address = MAKE_HHDM(pmm_getpageaddress(page));
|
||||
memcpy(buffer, (void *)((uintptr_t)address + startoffset), readsize);
|
||||
pmm_release(FROM_HHDM(address));
|
||||
*bytesread += readsize;
|
||||
pageoffset += 1;
|
||||
pagecount -= 1;
|
||||
}
|
||||
|
||||
for (uintmax_t offset = 0; offset < pagecount * PAGE_SIZE; offset += PAGE_SIZE) {
|
||||
// the other pages
|
||||
err = vmmcache_getpage(node, pageoffset * PAGE_SIZE + offset, &page);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
size_t readsize = min(PAGE_SIZE, size - *bytesread);
|
||||
void *address = MAKE_HHDM(pmm_getpageaddress(page));
|
||||
memcpy((void *)((uintptr_t)buffer + *bytesread), address, readsize);
|
||||
pmm_release(FROM_HHDM(address));
|
||||
*bytesread += readsize;
|
||||
}
|
||||
|
||||
leave:
|
||||
MUTEX_RELEASE(&node->sizelock);
|
||||
} else {
|
||||
// special file, just read as size doesn't matter
|
||||
err = VOP_READ(node, buffer, size, offset, flags, bytesread, getcred());
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user