BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / f97b909e66a1314d3bb9da413cd515cf47672180 / vfs

// Related

Nucleus

Barry New list iteration in VFS f97b909 (3 years, 3 months ago)
diff --git a/vfs/direntry.c b/vfs/direntry.c
index 7a0b559..de7f02a 100644
--- a/vfs/direntry.c
+++ b/vfs/direntry.c
@@ -6,12 +6,6 @@
 #include <nucleus/object.h>
 #include <nucleus/vfs.h>
 
-/* Information for find callback */
-struct FindData {
-	const char *name;
-	DirEntry *result;
-};
-
 static void direntry_delete(Object *);
 
 /* Directory Entry object type */
@@ -41,32 +35,21 @@ direntry_delete(Object *obj)
 		put(entry->inode);
 }
 
-/* Callback for finding a directory entry by name */
-static int
-compare_direntry_name(void *addr, void *data)
-{
-	DirEntry *entry = addr;
-	struct FindData *find = data;
-	uint32_t hash = name_hash(find->name);
-	if (__builtin_expect(!(entry->hash), 0))
-		entry->hash = name_hash(entry->name);
-	if (entry->hash != hash)
-		return 0;
-	if (strcmp(entry->name, find->name))
-		return 0;
-	find->result = get(entry);
-	return 1;
-}
-
 /* Find a Directory Entry by name in a list */
 DirEntry *
 find_direntry(ObjectList *list, const char *name)
 {
-	struct FindData data = {
-		.name = name,
-		.result = NULL,
-	};
-	iterate(list, compare_direntry_name, &data);
-	return data.result;
+	DirEntry *entry;
+	uint32_t hash = name_hash(name);
+	foreach (list, entry) {
+		if (__builtin_expect(!(entry->hash), 0))
+			entry->hash = name_hash(entry->name);
+		if (entry->hash != hash)
+			continue;
+		if (strcmp(entry->name, name))
+			continue;
+		break;
+	}
+	return entry;
 }
 
diff --git a/vfs/file.c b/vfs/file.c
index f73c8e1..0d0f31d 100644
--- a/vfs/file.c
+++ b/vfs/file.c
@@ -7,17 +7,21 @@
  * generic version.
  */
 
+#include <string.h>
+#include <sys/stat.h>
 #include <errno.h>
 #include <nucleus/object.h>
 #include <nucleus/vfs.h>
 
 static void file_delete(Object *);
+static void file_copy(Object *, Object *);
 
 /* File object type */
 ObjectType fileType = {
 	.name = "FILE",
 	.size = sizeof(File),
 	.delete = file_delete,
+	.copy = file_copy,
 };
 
 /* Destroy a file */
@@ -31,6 +35,20 @@ file_delete(Object *obj)
 		destroy_list(file->path);
 }
 
+/* Copy a file */
+static void
+file_copy(Object *a, Object *b)
+{
+	File *parent = (void *) a, *child = (void *) b;
+	if (parent->inode)
+		child->inode = copy(parent->inode);
+	child->flags = parent->flags;
+	child->pos = parent->pos;
+	child->ops = parent->ops;
+	if (parent->path)
+		child->path = copy_list(parent->path);
+}
+
 /* Open a file */
 int
 file_open(File *file)
@@ -45,10 +63,43 @@ size_t
 file_read(File *file, char *buf, size_t size)
 {
 	size_t count = 0;
-	if (!file->ops || !file->ops->read)
-		return count;
-	count = file->ops->read(file, buf, size, file->pos);
+	lock(file);
+	/* Irregular files cannot be cached */
+	if (!S_ISREG(file->inode->mode)) {
+		if (file->ops && file->ops->read)
+			count = file->ops->read(file, buf, size, file->pos);
+		goto end;
+	}
+
+	if (file->pos > file->inode->size)
+		goto end;
+	if (file->pos + size > file->inode->size)
+		size = file->inode->size - file->pos;
+
+	/* Read with cache */
+	Page *page;
+	char *data;
+	uint16_t min, indent = file->pos % PAGE_SIZE;
+	while (size) {
+		min = (size > PAGE_SIZE) ? PAGE_SIZE : size;
+		page = find_page(file->inode->pages,
+		                 file->pos + (count % PAGE_SIZE));
+		if (page) {
+			/* Cache hit */
+			data = map_page(page);
+			memcpy(buf + count, data + indent, min);
+		} else if (file->ops && file->ops->read) {
+			/* Cache miss */
+			file->ops->read(file, buf + count, min,
+			                file->pos + count);
+		}
+		indent = 0;
+		size -= min;
+		count += min;
+	}
+end:
 	file->pos += count;
+	unlock(file);
 	return count;
 }
 
@@ -57,9 +108,52 @@ size_t
 file_write(File *file, char *buf, size_t size)
 {
 	size_t count = 0;
-	if (!file->ops || !file->ops->write)
-		return count;
-	count = file->ops->write(file, buf, size, file->pos);
+	lock(file);
+	/* Irregular files cannot be cached */
+	if (!S_ISREG(file->inode->mode)) {
+		if (file->ops && file->ops->write)
+			count = file->ops->write(file, buf, size, file->pos);
+		goto end;
+	}
+
+	if (file->pos + size > file->inode->size)
+		file->inode->size = size + file->pos;
+
+	/* Write with cache */
+	Page *page;
+	char *data;
+	uint16_t min, indent = file->pos % PAGE_SIZE;
+	while (size) {
+		min = (size > PAGE_SIZE) ? PAGE_SIZE : size;
+		page = find_page(file->inode->pages,
+		                 file->pos + (count % PAGE_SIZE));
+		if (page) {
+			/* Cache hit */
+			data = map_page(page);
+			memcpy(data + indent, buf + count, min);
+		} else if (file->ops && file->ops->write) {
+			/* Cache miss */
+			file->ops->read(file, buf + count, min,
+			                file->pos + count);
+		}
+		indent = 0;
+		size -= min;
+		count += min;
+	}
+end:
 	file->pos += count;
+	unlock(file);
 	return count;
 }
+
+/* Map a file into memory */
+void
+file_mmap(File *file, void *addr, size_t len, off_t offset)
+{
+	if (!file->ops)
+		return;
+	if (file->ops->mmap)
+		file->ops->mmap(file, addr, len, offset);
+	else if (S_ISREG(file->inode->mode))
+		file->ops->read(file, addr, len, offset);
+}
diff --git a/vfs/fstype.c b/vfs/fstype.c
index 9043ba4..f157a71 100644
--- a/vfs/fstype.c
+++ b/vfs/fstype.c
@@ -16,31 +16,12 @@ struct FSType {
 	Inode *(*mount)(FSType *, int, const char *, void *);
 };
 
-/* Find callback data */
-struct FindData {
-	const char *name;
-	FSType *result;
-};
-
 /* File System Type object type */
 ObjectType fstypeType = {
 	.name = "FILE SYSTEM TYPE",
 	.size = sizeof(FSType),
 };
 
-/* Callback for finding a file system type */
-static int
-compare_fstype_name(void *object, void *data)
-{
-	FSType *type = object;
-	struct FindData *find = data;
-	if (!strcmp(type->name, find->name)) {
-		find->result = type;
-		return 1;
-	}
-	return 0;
-}
-
 /* Create a new file system type */
 void
 register_fstype(const char *name, mount_callback_t mount)
@@ -55,13 +36,13 @@ int
 mount_fstype(const char *name, int flags, const char *src, void *data,
              Inode **root)
 {
-	struct FindData find = {
-		.name = name,
-		.result = NULL,
-	};
-	iterate(fstypeType.objects, compare_fstype_name, &find);
-	if (!find.result)
+	FSType *type;
+	foreach (fstypeType.objects, type) {
+		if (!strcmp(type->name, name))
+			break;
+	}
+	if (!type)
 		return -ENODEV;
-	*root = find.result->mount(find.result, flags, src, data);
+	*root = type->mount(type, flags, src, data);
 	return 0;
 }
diff --git a/vfs/inode.c b/vfs/inode.c
index 3f760e7..03c301d 100644
--- a/vfs/inode.c
+++ b/vfs/inode.c
@@ -17,6 +17,7 @@
 
 static void inode_new(Object *);
 static void inode_delete(Object *);
+static void inode_copy(Object *, Object *);
 
 /* Inode object type */
 ObjectType inodeType = {
@@ -24,6 +25,7 @@ ObjectType inodeType = {
 	.size = sizeof(Inode),
 	.new = inode_new,
 	.delete = inode_delete,
+	.copy = inode_copy,
 };
 
 /* Create a new Inode */
@@ -51,6 +53,28 @@ inode_delete(Object *obj)
 	destroy_list(inode->pages);
 }
 
+/* Copy an Inode */
+static void
+inode_copy(Object *a, Object *b)
+{
+	Inode *parent = (void *) a, *child = (void *) b;
+	child->ino = parent->ino;
+	child->uid = parent->uid;
+	child->gid = parent->gid;
+	child->mode = parent->mode;
+	child->nlink = parent->nlink;
+	child->size = parent->size;
+	child->dev = parent->dev;
+	child->ops = parent->ops;
+	child->fileOps = parent->fileOps;
+	if (parent->super)
+		child->super = get(parent->super);
+	if (parent->dirEntries)
+		child->dirEntries = copy_list(parent->dirEntries);
+	if (parent->pages)
+		child->pages = copy_list(parent->pages);
+}
+
 /* Check if a process has permission to access an inode */
 int
 permission(Inode *inode, int mask)
diff --git a/vfs/superblock.c b/vfs/superblock.c
index 4d90e3d..41f35b3 100644
--- a/vfs/superblock.c
+++ b/vfs/superblock.c
@@ -9,31 +9,12 @@
 #include <sys/types.h>
 #include <nucleus/vfs.h>
 
-/* Data for find callback */
-struct FindData {
-	ino_t ino;
-	Inode *result;
-};
-
 /* Super Block object type */
 ObjectType superBlockType = {
 	.name = "SUPER BLOCK",
 	.size = sizeof(SuperBlock),
 };
 
-/* Find an Inode by ino value */
-static int
-compare_inode_ino(void *addr, void *data)
-{
-	Inode *inode = addr;
-	struct FindData *find = data;
-	if (find->ino == inode->ino){
-		find->result = get(inode);
-		return 1;
-	}
-	return 0;
-}
-
 /* Allocate an Inode */
 Inode *
 super_alloc_inode(SuperBlock *sb)
@@ -48,10 +29,9 @@ Inode *
 super_find_inode(SuperBlock *sb, ino_t ino)
 {
 	Inode *inode;
-	struct FindData find = {
-		.ino = ino,
-		.result = NULL,
-	};
-	iterate(sb->inodes, compare_inode_ino, &find);
-	return find.result;
+	foreach (sb->inodes, inode) {
+		if (inode->ino == ino)
+			break;
+	}
+	return inode;
 }