Reorganised sys_open.

vfs_create and mknod now returns the newly created vnode.
(which might be used by upper layers).
This commit is contained in:
Bahadir Balban
2008-04-19 00:40:48 +01:00
parent f7163b7e93
commit 8c4c436925
5 changed files with 77 additions and 33 deletions
+2 -1
View File
@@ -53,7 +53,8 @@ struct vnode_ops {
vnode_op_t link; vnode_op_t link;
vnode_op_t unlink; vnode_op_t unlink;
int (*mkdir)(struct vnode *parent, const char *name); int (*mkdir)(struct vnode *parent, const char *name);
int (*mknod)(struct vnode *parent, const char *name, unsigned int mode); struct vnode *(*mknod)(struct vnode *parent, const char *name,
unsigned int mode);
vnode_op_t rmdir; vnode_op_t rmdir;
vnode_op_t rename; vnode_op_t rename;
vnode_op_t getattr; vnode_op_t getattr;
+9 -8
View File
@@ -208,9 +208,10 @@ int memfs_write_vnode(struct superblock *sb, struct vnode *v)
/* /*
* Creates ordinary files and directories at the moment. In the future, * Creates ordinary files and directories at the moment. In the future,
* other file types will be added. * other file types will be added. Returns the created node.
*/ */
int memfs_vnode_mknod(struct vnode *v, const char *dirname, unsigned int mode) struct vnode *memfs_vnode_mknod(struct vnode *v, const char *dirname,
unsigned int mode)
{ {
struct dentry *d, *parent = list_entry(v->dentries.next, struct dentry *d, *parent = list_entry(v->dentries.next,
struct dentry, vref); struct dentry, vref);
@@ -230,25 +231,25 @@ int memfs_vnode_mknod(struct vnode *v, const char *dirname, unsigned int mode)
/* Populate the children */ /* Populate the children */
if ((err = v->ops.readdir(v)) < 0) if ((err = v->ops.readdir(v)) < 0)
return err; return PTR_ERR(err);
/* Check there's no existing child with same name */ /* Check there's no existing child with same name */
list_for_each_entry(d, &parent->children, child) { list_for_each_entry(d, &parent->children, child) {
/* Does the name exist as a child? */ /* Does the name exist as a child? */
if(d->ops.compare(d, dirname)) if(d->ops.compare(d, dirname))
return -EEXIST; return PTR_ERR(-EEXIST);
} }
/* Allocate a new vnode for the new directory */ /* Allocate a new vnode for the new directory */
if (IS_ERR(newv = v->sb->ops->alloc_vnode(v->sb))) if (IS_ERR(newv = v->sb->ops->alloc_vnode(v->sb)))
return (int)newv; return newv;
/* Initialise the vnode */ /* Initialise the vnode */
vfs_set_type(newv, S_IFDIR); vfs_set_type(newv, S_IFDIR);
/* Get the next directory entry available on the parent vnode */ /* Get the next directory entry available on the parent vnode */
if (v->dirbuf.npages * PAGE_SIZE <= v->size) if (v->dirbuf.npages * PAGE_SIZE <= v->size)
return -ENOSPC; return PTR_ERR(-ENOSPC);
/* Fill in the new entry to parent directory entry */ /* Fill in the new entry to parent directory entry */
memfsd = (struct memfs_dentry *)&v->dirbuf.buffer[v->size]; memfsd = (struct memfs_dentry *)&v->dirbuf.buffer[v->size];
@@ -267,7 +268,7 @@ int memfs_vnode_mknod(struct vnode *v, const char *dirname, unsigned int mode)
/* Allocate a new vfs dentry */ /* Allocate a new vfs dentry */
if (!(newd = vfs_alloc_dentry())) if (!(newd = vfs_alloc_dentry()))
return -ENOMEM; return PTR_ERR(-ENOMEM);
/* Initialise it */ /* Initialise it */
newd->ops = generic_dentry_operations; newd->ops = generic_dentry_operations;
@@ -285,7 +286,7 @@ int memfs_vnode_mknod(struct vnode *v, const char *dirname, unsigned int mode)
list_add(&newd->cache_list, &dentry_cache); list_add(&newd->cache_list, &dentry_cache);
list_add(&newv->cache_list, &vnode_cache); list_add(&newv->cache_list, &vnode_cache);
return 0; return newv;
} }
/* /*
+32 -20
View File
@@ -58,35 +58,41 @@ void print_vnode(struct vnode *v)
} }
/* Creates a node under a directory, e.g. a file, directory. */ /* Creates a node under a directory, e.g. a file, directory. */
int vfs_create(struct tcb *task, struct pathdata *pdata, unsigned int mode) struct vnode *vfs_create(struct tcb *task, struct pathdata *pdata,
unsigned int mode)
{ {
struct vnode *vparent; struct vnode *vparent, *newnode;
const char *nodename; const char *nodename;
int err;
/* The last component is to be created */ /* The last component is to be created */
nodename = pathdata_last_component(pdata); nodename = pathdata_last_component(pdata);
/* Check that the parent directory exists. */ /* Check that the parent directory exists. */
if (IS_ERR(vparent = vfs_lookup_bypath(pdata))) if (IS_ERR(vparent = vfs_lookup_bypath(pdata)))
return (int)vparent; return vparent;
/* The parent vnode must be a directory. */ /* The parent vnode must be a directory. */
if (!vfs_isdir(vparent)) if (!vfs_isdir(vparent))
return -ENOENT; return PTR_ERR(-ENOENT);
/* Create new directory under the parent */ /* Create new directory under the parent */
if ((err = vparent->ops.mknod(vparent, nodename, mode)) < 0) if (IS_ERR(newnode = vparent->ops.mknod(vparent, nodename, mode)))
return err; return newnode;
// print_vnode(vparent); // print_vnode(vparent);
return 0; return newnode;
} }
/* FIXME: /* FIXME:
* - Is it already open? * - Is it already open?
* - Allocate a copy of path string since lookup destroys it * - Allocate a copy of path string since lookup destroys it
* - Check flags and mode. * - Check flags and mode.
*
* TODO:
* - All return paths should return by destroying pdata.
* - Need another pdata for vfs_create since first lookup destroys it.
* - Or perhaps we check O_CREAT first, and do lookup once, without the
* last path component which is to be created.
*/ */
int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode) int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode)
{ {
@@ -94,7 +100,7 @@ int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode)
struct vnode *v; struct vnode *v;
struct tcb *task; struct tcb *task;
int fd; int fd;
int err; int retval;
/* Get the task */ /* Get the task */
BUG_ON(!(task = find_task(sender))); BUG_ON(!(task = find_task(sender)));
@@ -107,16 +113,17 @@ int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode)
return 0; return 0;
} }
/* Get the vnode */ /* Creating new node, file or directory */
if (IS_ERR(v = vfs_lookup_bypath(pdata))) { if (flags & O_CREAT) {
if (!(flags & O_CREAT)) { if (IS_ERR(v = vfs_create(task, pdata, mode))) {
l4_ipc_return((int)v); retval = (int)v;
return 0; goto out;
} else {
if ((err = vfs_create(task, pdata, mode)) < 0) {
l4_ipc_return(err);
return 0;
} }
} else {
/* Not creating, just opening, get the vnode */
if (IS_ERR(v = vfs_lookup_bypath(pdata))) {
retval = (int)v;
goto out;
} }
} }
@@ -129,8 +136,9 @@ int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode)
/* Tell the pager about opened vnode information */ /* Tell the pager about opened vnode information */
BUG_ON(pager_sys_open(sender, fd, v->vnum, v->size) < 0); BUG_ON(pager_sys_open(sender, fd, v->vnum, v->size) < 0);
out:
pathdata_destroy(pdata); pathdata_destroy(pdata);
l4_ipc_return(fd); l4_ipc_return(retval);
return 0; return 0;
} }
@@ -160,6 +168,7 @@ int sys_mkdir(l4id_t sender, const char *pathname, unsigned int mode)
{ {
struct tcb *task; struct tcb *task;
struct pathdata *pdata; struct pathdata *pdata;
struct vnode *v;
/* Get the task */ /* Get the task */
BUG_ON(!(task = find_task(sender))); BUG_ON(!(task = find_task(sender)));
@@ -173,7 +182,10 @@ int sys_mkdir(l4id_t sender, const char *pathname, unsigned int mode)
} }
/* Create the directory or fail */ /* Create the directory or fail */
l4_ipc_return(vfs_create(task, pdata, mode)); if (IS_ERR(v = vfs_create(task, pdata, mode)))
l4_ipc_return((int)v);
else
l4_ipc_return(0);
/* Destroy extracted path data */ /* Destroy extracted path data */
pathdata_destroy(pdata); pathdata_destroy(pdata);
+1
View File
@@ -268,6 +268,7 @@ 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_write(l4id_t sender, int fd, void *buf, int count)
{ {
BUG();
return 0; return 0;
} }
+32 -3
View File
@@ -12,22 +12,51 @@ int fileio(void)
int fd; int fd;
ssize_t cnt; ssize_t cnt;
int err; int err;
char buf[128];
off_t offset;
char *str = "I WROTE TO THIS FILE\n"; char *str = "I WROTE TO THIS FILE\n";
if ((fd = open("/home/bahadir/newfile.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)) < 0) { if ((fd = open("/home/bahadir/newfile.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)) < 0) {
perror("OPEN"); perror("OPEN");
return 0; return -1;
} }
if ((int)(cnt = write(fd, str, strlen(str))) < 0) { if ((int)(cnt = write(fd, str, strlen(str))) < 0) {
perror("WRITE"); perror("WRITE");
return 0; return -1;
} }
if ((err = close(fd)) < 0) if ((int)(offset = lseek(fd, 0, SEEK_SET)) < 0) {
perror("LSEEK");
return -1;
}
if ((int)(cnt = read(fd, buf, strlen(str))) < 0) {
perror("WRITE");
return -1;
}
printf("Read: %d bytes from file.\n", cnt);
if (cnt) {
printf("Read string: %s\n", buf);
}
if ((err = close(fd)) < 0) {
perror("CLOSE"); perror("CLOSE");
return -1;
}
return 0; return 0;
} }
#if defined(HOST_TESTS)
int main(void)
{
printf("File IO test:\n");
if (fileio() == 0)
printf("-- PASSED --\n");
return 0;
}
#endif