From 81ebffdc878cfbd835a316954b1ae4eeb77c5c5f Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Wed, 9 Apr 2008 16:55:54 +0100 Subject: [PATCH] VFS updates, readme updates. Separated vfs file as a specific file. vm file is not always a vfs file. Updated the README sys_open was not returning back to client, added that. Added comments for future vfs additions. --- README | 20 +++++++------- libs/c/src/perror.c | 2 +- tasks/fs0/src/syscalls.c | 52 +++++++++++++++++++++++++++++-------- tasks/fs0/src/task.c | 10 +++---- tasks/mm0/include/file.h | 12 ++++++++- tasks/mm0/include/vm_area.h | 2 +- tasks/mm0/src/file.c | 6 +++-- tasks/mm0/src/vm_object.c | 20 +++++++++++++- tasks/test0/src/dirtest.c | 7 ++--- 9 files changed, 96 insertions(+), 35 deletions(-) diff --git a/README b/README index d811140..3ee8661 100644 --- a/README +++ b/README @@ -130,15 +130,15 @@ opportunity to incorporate the latest ideas in OS technology. Can you summarise all this? Why should I use Codezero, again? Codezero is an operating system that targets embedded systems. It supports the -most fundamental posix calls and modern features such as demand-paging and has a -virtual filesystem layer. Different from other posix-like systems, it is based -on a microkernel design. It has a cleanly separated set of services, it is small -and well-focused. It's design is carefully thought out, so it's not just a -mock-up implementation of an operating system API. It's source code is also -freely available. For these reasons it is a good candidate as systems software -to be used on embedded platforms. Currently it has little or no users, therefore -compared to systems with a saturated user base it is possible to tailor it -rapidly towards the needs of any users who want to be the first to incorporate -it for their needs. +most fundamental posix calls and it implements modern features such as +demand-paging and virtual filesystem layer. Different from other posix-like +systems, it is based on a microkernel design. It has a cleanly separated set of +services, it is small and well-focused. It's design is carefully thought out, so +it's not just a mock-up implementation of an operating system API. It's source +code is also freely available (See LICENSE heading). For these reasons it is a +good candidate as systems software to be used on embedded platforms. Currently +it has little or no users, therefore compared to systems with a saturated user +base it is possible to tailor it rapidly towards the needs of any users who want +to be the first to incorporate it for their needs. diff --git a/libs/c/src/perror.c b/libs/c/src/perror.c index ca06e4c..518655c 100644 --- a/libs/c/src/perror.c +++ b/libs/c/src/perror.c @@ -11,5 +11,5 @@ extern int errno; void perror(const char *str) { - printf("%s: %d\n", errno); + printf("%s: %d\n", str, errno); } diff --git a/tasks/fs0/src/syscalls.c b/tasks/fs0/src/syscalls.c index 70a00c5..ca1cb79 100644 --- a/tasks/fs0/src/syscalls.c +++ b/tasks/fs0/src/syscalls.c @@ -92,10 +92,13 @@ int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode) /* Get the vnode */ if (IS_ERR(v = vfs_lookup_bypath(task, pathbuf))) { if (!(flags & O_CREAT)) { - return (int)v; + l4_ipc_return((int)v); + return 0; } else { - if ((err = vfs_create(task, pathname, mode)) < 0) - return err; + if ((err = vfs_create(task, pathname, mode)) < 0) { + l4_ipc_return(err); + return 0; + } } } @@ -108,6 +111,7 @@ int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode) /* Tell the pager about opened vnode information */ BUG_ON(pager_sys_open(sender, fd, v->vnum, v->size) < 0); + l4_ipc_return(0); return 0; } @@ -202,6 +206,26 @@ int pager_sys_write(l4id_t sender, unsigned long vnum, unsigned long f_offset, return 0; } +/* + * FIXME: Here's how this should have been: + * v->ops.readdir() -> Reads fs-specific directory contents. i.e. reads + * the directory buffer, doesn't care however contained vnode details are + * stored. + * + * After reading, it converts the fs-spceific contents into generic vfs + * dentries and populates the dentries of those vnodes. + * + * If vfs_readdir() is issued, those generic dentries are converted into + * the posix-defined directory record structure. During this on-the-fly + * generation, pseudo-entries such as . and .. are also added. + * + * If this layering is not done, i.e. the low-level dentry buffer already + * keeps this record structure and we try to return that, then we wont + * have a chance to add the pseudo-entries . and .. These record entries + * are essentially created from parent vnode and current vnode but using + * the names . and .. + */ + /* * Reads @count bytes of posix struct dirents into @buf. This implements * the raw dirent read syscall upon which readdir() etc. posix calls @@ -219,19 +243,25 @@ int sys_readdir(l4id_t sender, int fd, void *buf, int count) BUG_ON(!(t = find_task(sender))); /* Convert fd to vnum. */ - BUG_ON(!(vnum = t->fd[fd])); + BUG_ON((vnum = t->fd[fd]) < 0); /* Lookup vnode */ - if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) - return -EINVAL; /* No such vnode */ + if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) { + l4_ipc_return(-EINVAL); + return 0; /* No such vnode */ + } /* Ensure vnode is a directory */ - if (!vfs_isdir(v)) - return -ENOTDIR; + if (!vfs_isdir(v)) { + l4_ipc_return(-ENOTDIR); + return 0; + } /* Read the whole content from fs, if haven't done so yet */ - if ((err = v->ops.readdir(v)) < 0) - return err; + if ((err = v->ops.readdir(v)) < 0) { + l4_ipc_return(err); + return 0; + } /* Bytes to read, minimum of vnode size and count requested */ nbytes = (v->size <= count) ? v->size : count; @@ -239,7 +269,7 @@ int sys_readdir(l4id_t sender, int fd, void *buf, int count) /* Do we have those bytes at hand? */ if (v->dirbuf.buffer && (v->dirbuf.npages * PAGE_SIZE) >= nbytes) { memcpy(buf, v->dirbuf.buffer, nbytes); - return nbytes; + l4_ipc_return(nbytes); } return 0; diff --git a/tasks/fs0/src/task.c b/tasks/fs0/src/task.c index 7b3adac..12746be 100644 --- a/tasks/fs0/src/task.c +++ b/tasks/fs0/src/task.c @@ -141,8 +141,8 @@ int task_utcb_attach(struct tcb *t) if ((unsigned long)shmaddr != t->utcb_address) return -EINVAL; - printf("%s: Mapped utcb of task %d @ 0x%x\n", - __TASKNAME__, t->tid, shmaddr); + //printf("%s: Mapped utcb of task %d @ 0x%x\n", + // __TASKNAME__, t->tid, shmaddr); return 0; @@ -170,9 +170,9 @@ int init_task_structs(struct task_data_head *tdata_head) t->curdir = vfs_root.pivot; /* Print task information */ - printf("%s: Task info received from mm0:\n", __TASKNAME__); - printf("%s: task id: %d, utcb address: 0x%x\n", - __TASKNAME__, t->tid, t->utcb_address); + //printf("%s: Task info received from mm0:\n", __TASKNAME__); + //printf("%s: task id: %d, utcb address: 0x%x\n", + // __TASKNAME__, t->tid, t->utcb_address); /* shm attach to the utcbs for all these tasks except own */ if (t->tid != self_tid()) diff --git a/tasks/mm0/include/file.h b/tasks/mm0/include/file.h index f6d694a..4545024 100644 --- a/tasks/mm0/include/file.h +++ b/tasks/mm0/include/file.h @@ -2,6 +2,7 @@ #define __MM0_FILE_H__ #include +#include #include void vmfile_init(void); @@ -17,6 +18,15 @@ int sys_read(l4id_t sender, int fd, void *buf, int count); int sys_write(l4id_t sender, int fd, void *buf, int count); int sys_lseek(l4id_t sender, int fd, off_t offset, int whence); -#define vm_file_to_vnum(f) (*(unsigned long *)((f)->priv_data)) +struct vfs_file_data { + unsigned long vnum; +}; + +#define vm_file_to_vnum(f) \ + (((struct vfs_file_data *)((f)->priv_data))->vnum) +struct vm_file *vfs_file_create(void); + + extern struct list_head vm_file_list; + #endif /* __MM0_FILE_H__ */ diff --git a/tasks/mm0/include/vm_area.h b/tasks/mm0/include/vm_area.h index 54ef3ad..5294f04 100644 --- a/tasks/mm0/include/vm_area.h +++ b/tasks/mm0/include/vm_area.h @@ -40,7 +40,7 @@ /* Defines the type of file. A device file? Regular file? One used at boot? */ enum VM_FILE_TYPE { VM_FILE_DEVZERO = 1, - VM_FILE_REGULAR, + VM_FILE_VFS, VM_FILE_BOOTFILE, VM_FILE_SHM, }; diff --git a/tasks/mm0/src/file.c b/tasks/mm0/src/file.c index e2a486f..ed29d49 100644 --- a/tasks/mm0/src/file.c +++ b/tasks/mm0/src/file.c @@ -93,7 +93,9 @@ int vfs_receive_sys_open(l4id_t sender, l4id_t opener, int fd, /* Check if that vm_file is already in the list */ list_for_each_entry(vmfile, &vm_file_list, list) { - if (vm_file_to_vnum(vmfile) == vnum) { + /* Check it is a vfs file and if so vnums match. */ + if ((vmfile->type & VM_FILE_VFS) && + vm_file_to_vnum(vmfile) == vnum) { /* Add a reference to it from the task */ t->fd[fd].vmfile = vmfile; vmfile->vm_obj.refcnt++; @@ -102,7 +104,7 @@ int vfs_receive_sys_open(l4id_t sender, l4id_t opener, int fd, } /* Otherwise allocate a new one for this vnode */ - if (IS_ERR(vmfile = vm_file_create())) + if (IS_ERR(vmfile = vfs_file_create())) return (int)vmfile; /* Initialise and add it to global list */ diff --git a/tasks/mm0/src/vm_object.c b/tasks/mm0/src/vm_object.c index d80eb8d..6284e64 100644 --- a/tasks/mm0/src/vm_object.c +++ b/tasks/mm0/src/vm_object.c @@ -3,6 +3,7 @@ * * Copyright (C) 2008 Bahadir Balban */ +#include #include #include #include @@ -40,7 +41,7 @@ void vm_object_print(struct vm_object *vmo) ftype = "bootfile"; else if (f->type == VM_FILE_SHM) ftype = "shm file"; - else if (f->type == VM_FILE_REGULAR) + else if (f->type == VM_FILE_VFS) ftype = "regular"; else BUG(); @@ -91,6 +92,23 @@ struct vm_file *vm_file_create(void) 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) { diff --git a/tasks/test0/src/dirtest.c b/tasks/test0/src/dirtest.c index b433226..af2dce7 100644 --- a/tasks/test0/src/dirtest.c +++ b/tasks/test0/src/dirtest.c @@ -113,14 +113,15 @@ int lsdir(char *path) perror("OPEN"); return 0; } else - // printf("OPEN OK.\n"); + printf("OPEN OK.\n"); if ((bytes = os_readdir(fd, dents, sizeof(struct dirent) * DENTS_TOTAL)) < 0) { perror("GETDENTS"); return 0; - } - //printf("GETDENTS OK.\n"); + } else { + printf("GETDENTS OK.\n"); print_dirents(path, dents, bytes); + } return 0; }