mirror of
https://github.com/drasko/codezero.git
synced 2026-01-15 12:23:15 +01:00
218 lines
4.5 KiB
C
218 lines
4.5 KiB
C
/*
|
|
* vm object utility functions.
|
|
*
|
|
* Copyright (C) 2008 Bahadir Balban
|
|
*/
|
|
#include <file.h>
|
|
#include <vm_area.h>
|
|
#include <l4/macros.h>
|
|
#include <l4/api/errno.h>
|
|
#include <kmalloc/kmalloc.h>
|
|
#include <globals.h>
|
|
|
|
/* Global list of all in-memory files on the system */
|
|
struct global_list global_vm_files = {
|
|
.list = { &global_vm_files.list, &global_vm_files.list },
|
|
.total = 0,
|
|
};
|
|
|
|
/* Global list of in-memory vm objects in the system */
|
|
struct global_list global_vm_objects = {
|
|
.list = { &global_vm_objects.list, &global_vm_objects.list },
|
|
.total = 0,
|
|
};
|
|
|
|
|
|
void global_add_vm_object(struct vm_object *obj)
|
|
{
|
|
BUG_ON(!list_empty(&obj->list));
|
|
list_add(&obj->list, &global_vm_objects.list);
|
|
global_vm_objects.total++;
|
|
}
|
|
|
|
void global_remove_vm_object(struct vm_object *obj)
|
|
{
|
|
BUG_ON(list_empty(&obj->list));
|
|
list_del_init(&obj->list);
|
|
BUG_ON(--global_vm_objects.total < 0);
|
|
}
|
|
|
|
void global_add_vm_file(struct vm_file *f)
|
|
{
|
|
BUG_ON(!list_empty(&f->list));
|
|
list_add(&f->list, &global_vm_files.list);
|
|
global_vm_files.total++;
|
|
|
|
global_add_vm_object(&f->vm_obj);
|
|
}
|
|
|
|
void global_remove_vm_file(struct vm_file *f)
|
|
{
|
|
BUG_ON(list_empty(&f->list));
|
|
list_del_init(&f->list);
|
|
BUG_ON(--global_vm_files.total < 0);
|
|
|
|
global_remove_vm_object(&f->vm_obj);
|
|
}
|
|
|
|
void print_cache_pages(struct vm_object *vmo)
|
|
{
|
|
struct page *p;
|
|
|
|
if (!list_empty(&vmo->page_cache))
|
|
printf("Pages:\n======\n");
|
|
|
|
list_for_each_entry(p, &vmo->page_cache, list) {
|
|
dprintf("Page offset: 0x%x, virtual: 0x%x, refcnt: %d\n", p->offset,
|
|
p->virtual, p->refcnt);
|
|
}
|
|
}
|
|
|
|
void vm_object_print(struct vm_object *vmo)
|
|
{
|
|
struct vm_file *f;
|
|
|
|
printf("Object type: %s %s. links: %d, shadows: %d, Pages in cache: %d.\n",
|
|
vmo->flags & VM_WRITE ? "writeable" : "read-only",
|
|
vmo->flags & VM_OBJ_FILE ? "file" : "shadow", vmo->nlinks, vmo->shadows,
|
|
vmo->npages);
|
|
if (vmo->flags & VM_OBJ_FILE) {
|
|
f = vm_object_to_file(vmo);
|
|
char *ftype;
|
|
|
|
if (f->type == VM_FILE_DEVZERO)
|
|
ftype = "devzero";
|
|
else if (f->type == VM_FILE_BOOTFILE)
|
|
ftype = "bootfile";
|
|
else if (f->type == VM_FILE_SHM)
|
|
ftype = "shm file";
|
|
else if (f->type == VM_FILE_VFS)
|
|
ftype = "regular";
|
|
else
|
|
BUG();
|
|
|
|
printf("File type: %s\n", ftype);
|
|
}
|
|
// print_cache_pages(vmo);
|
|
// printf("\n");
|
|
}
|
|
|
|
void vm_print_files(struct list_head *files)
|
|
{
|
|
struct vm_file *f;
|
|
|
|
list_for_each_entry(f, files, list)
|
|
vm_object_print(&f->vm_obj);
|
|
}
|
|
|
|
void vm_print_objects(struct list_head *objects)
|
|
{
|
|
struct vm_object *vmo;
|
|
|
|
list_for_each_entry(vmo, objects, list)
|
|
vm_object_print(vmo);
|
|
}
|
|
|
|
struct vm_object *vm_object_init(struct vm_object *obj)
|
|
{
|
|
INIT_LIST_HEAD(&obj->list);
|
|
INIT_LIST_HEAD(&obj->shref);
|
|
INIT_LIST_HEAD(&obj->shdw_list);
|
|
INIT_LIST_HEAD(&obj->page_cache);
|
|
INIT_LIST_HEAD(&obj->link_list);
|
|
|
|
return obj;
|
|
}
|
|
|
|
/* Allocate and initialise a vmfile, and return it */
|
|
struct vm_object *vm_object_create(void)
|
|
{
|
|
struct vm_object *obj;
|
|
|
|
if (!(obj = kzalloc(sizeof(*obj))))
|
|
return 0;
|
|
|
|
return vm_object_init(obj);
|
|
}
|
|
|
|
struct vm_file *vm_file_create(void)
|
|
{
|
|
struct vm_file *f;
|
|
|
|
if (!(f = kzalloc(sizeof(*f))))
|
|
return PTR_ERR(-ENOMEM);
|
|
|
|
INIT_LIST_HEAD(&f->list);
|
|
vm_object_init(&f->vm_obj);
|
|
f->vm_obj.flags = VM_OBJ_FILE;
|
|
|
|
return f;
|
|
}
|
|
|
|
/*
|
|
* Populates the priv_data with vfs-file-specific
|
|
* information.
|
|
*/
|
|
struct vm_file *vfs_file_create(void)
|
|
{
|
|
struct vm_file *f = vm_file_create();
|
|
|
|
if (IS_ERR(f))
|
|
return f;
|
|
|
|
f->priv_data = kzalloc(sizeof(struct vfs_file_data));
|
|
f->type = VM_FILE_VFS;
|
|
|
|
return f;
|
|
}
|
|
|
|
/* Deletes the object via its base, along with all its pages */
|
|
int vm_object_delete(struct vm_object *vmo)
|
|
{
|
|
struct vm_file *f;
|
|
|
|
// vm_object_print(vmo);
|
|
|
|
/* Release all pages */
|
|
vmo->pager->ops.release_pages(vmo);
|
|
|
|
/* Remove from global list */
|
|
if (vmo->flags & VM_OBJ_FILE)
|
|
global_remove_vm_file(vm_object_to_file(vmo));
|
|
else if (vmo->flags & VM_OBJ_SHADOW)
|
|
global_remove_vm_object(vmo);
|
|
else BUG();
|
|
|
|
/* Check any references */
|
|
BUG_ON(vmo->nlinks);
|
|
BUG_ON(vmo->shadows);
|
|
BUG_ON(!list_empty(&vmo->shdw_list));
|
|
BUG_ON(!list_empty(&vmo->link_list));
|
|
BUG_ON(!list_empty(&vmo->page_cache));
|
|
BUG_ON(!list_empty(&vmo->shref));
|
|
|
|
/* Obtain and free via the base object */
|
|
if (vmo->flags & VM_OBJ_FILE) {
|
|
f = vm_object_to_file(vmo);
|
|
BUG_ON(!list_empty(&f->list));
|
|
if (f->priv_data) {
|
|
if (f->destroy_priv_data)
|
|
f->destroy_priv_data(f);
|
|
else
|
|
kfree(f->priv_data);
|
|
}
|
|
kfree(f);
|
|
} else if (vmo->flags & VM_OBJ_SHADOW)
|
|
kfree(vmo);
|
|
else BUG();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int vm_file_delete(struct vm_file *f)
|
|
{
|
|
/* Delete file via base object */
|
|
return vm_object_delete(&f->vm_obj);
|
|
}
|
|
|