BarryServer : Git

All the code for all my projects
// BarryServer : Git / Orion / commit / e59e4fe0bbf5a3f56db0700ee49a81131b590f9c

// Related

Orion

Barry Adding pipes e59e4fe (2 years, 4 months ago)
diff --git a/task/signal.h b/task/signal.h
new file mode 100644
index 0000000..9811bc6
--- /dev/null
+++ b/task/signal.h
@@ -0,0 +1,10 @@
+#ifndef KERNEL_TASK_SIGNAL_H
+#define KERNEL_TASK_SIGNAL_H
+
+/* Structure for Signal Handlers namespace */
+typedef struct SigHandlers {
+	sighandler_t sig_handler[32];
+	refcount_t usage;
+} SigHandlers;
+
+#endif
diff --git a/task/syscall.c b/task/syscall.c
index 30e1a7b..c1587d3 100644
--- a/task/syscall.c
+++ b/task/syscall.c
@@ -52,6 +52,7 @@ void *syscalls[] = {
 	[SYSCALL_DUP]      = dup,
 	[SYSCALL_DUP2]     = dup2,
 	[SYSCALL_ISATTY]   = isatty,
+	[SYSCALL_PIPE]     = pipe,
 
 	/* File System */
 	[SYSCALL_MOUNT]  = mount,
diff --git a/vfs/ext2fs/block.c b/vfs/ext2fs/block.c
index 28cf480..08f2185 100644
--- a/vfs/ext2fs/block.c
+++ b/vfs/ext2fs/block.c
@@ -23,10 +23,32 @@ ext2_get_data_addr(SuperBlock *super, Ext2Inode *node, uint32_t index)
 {
 	uint32_t tmp;
 	char block[4096];
+	Ext2Super *rsuper = super->data;
+	/* Blocks per indirect block */
+	uint32_t bpib = (1024 << rsuper->blockSize) / sizeof(uint32_t);
 
 	/* Main blocks */
 	if (index < 12)
 		return node->directBlock[index];
 	index -= 12;
+
+	/* Single indirect block */
+	if (index < bpib) {
+		ext2_read_block(super, node->singleBlock, block);
+		return *((uint32_t *) block + index);
+	}
+	index -= bpib;
+
+	/* Double indirect block */
+	if (index < bpib*bpib) {
+		panic("Attempt to read from double indirect block");
+	}
+	index -= bpib*bpib;
+
+	/* Triple indirect block */
+	if (index < bpib*bpib*bpib) {
+		panic("Attempt to read from triple indirect block");
+	}
+
 	return 0;
 }
diff --git a/vfs/file.c b/vfs/file.c
index d3dfdc6..33fd0b7 100644
--- a/vfs/file.c
+++ b/vfs/file.c
@@ -30,6 +30,8 @@ file_put(File *file)
 	ASSERT(file->usage);
 	if (--file->usage)
 		return;
+	if (file->ops && file->ops->release)
+		file->ops->release(file);
 	if (file->inode)
 		inode_put(file->inode);
 	if (file->path)
diff --git a/vfs/inode.c b/vfs/inode.c
index 34b5c65..50d6200 100644
--- a/vfs/inode.c
+++ b/vfs/inode.c
@@ -58,6 +58,8 @@ inode_put(Inode *inode)
 	}
 
 	/* Clean up */
+	if (inode->free_extra)
+		inode->free_extra(inode);
 	if (S_ISDIR(inode->mode))
 		entry_clean(inode);
 	else
diff --git a/vfs/pipe.c b/vfs/pipe.c
new file mode 100644
index 0000000..0566597
--- /dev/null
+++ b/vfs/pipe.c
@@ -0,0 +1,234 @@
+/*
+ * This file implements the VFS pipe mechanism.  It supports both named and
+ * anonymous pipes (FIFOs and pipes), and uses the same underlying operations
+ * for both.  It uses a ring buffer to implement the reading/writing.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include "vfs.h"
+#include "cache.h"
+#include "inode.h"
+#include "../mem/heap.h"
+#include "../mem/paging.h"
+#include "../mem/frame.h"
+#include "../task/task.h"
+
+/* Structure for pipe data */
+typedef struct Pipe {
+	size_t size;
+	off_t head, tail;
+	size_t readers, writers;
+	TaskQueue readQueue, writeQueue;
+} Pipe;
+
+size_t pipe_read(File *file, char *buf, size_t size, off_t offset);
+size_t pipe_write(File *file, char *buf, size_t size, off_t offset);
+int pipe_release(File *file);
+
+FileOps pipeWriteFileOps = {
+	.write = pipe_write,
+	.release = pipe_release,
+};
+FileOps pipeReadFileOps = {
+	.read = pipe_read,
+	.release = pipe_release,
+};
+
+/* Free a Pipe */
+static void
+pipe_free_extra(Inode *inode)
+{
+	Pipe *pipe = inode->extra;
+
+	/* Resume waiting tasks */
+	Task *task;
+	while ((task = pop_from_queue(&pipe->readQueue)) != NULL) {
+		unblock_task(task);
+		send_sig(task, SIGPIPE);
+	}
+	while ((task = pop_from_queue(&pipe->writeQueue)) != NULL) {
+		unblock_task(task);
+		send_sig(task, SIGPIPE);
+	}
+}
+
+/* Open an anonymous pipe */
+int
+pipe(int pipefd[2])
+{
+	if (!verify_access(pipefd, sizeof(int) * 2, PROT_WRITE))
+		return -EFAULT;
+
+	/* Allocate file descriptors */
+	int freefd = 0, i;
+	for (i = 0; i < NFILES; i++)
+		freefd += !current->files->fd[i];
+	if (freefd < 2)
+		return -EMFILE;
+
+	/* Create endpoints */
+	File *file[2];
+	Pipe *pipe = kmalloc(sizeof(Pipe));
+	Inode *inode = kmalloc(sizeof(Inode));
+	for (i = 0; i < 2; i++) {
+		file[i] = kmalloc(sizeof(File));
+
+		/* Install file descriptors */
+		for (pipefd[i] = 0; pipefd[i] < NFILES; pipefd[i]++)
+			if (!current->files->fd[pipefd[i]])
+				break;
+		current->files->fd[pipefd[i]] = file[i];
+
+		/* Build files */
+		file[i]->inode = inode_get(inode);
+		file[i]->mode = S_IFIFO | 0666;
+		file[i]->uid = current->uid;
+		file[i]->gid = current->gid;
+		file[i]->usage = 1;
+	}
+	file[0]->ops = &pipeReadFileOps;
+	file[1]->ops = &pipeWriteFileOps;
+	inode->extra = pipe;
+	pipe->readers = pipe->writers = 1;
+	page_create(inode, alloc_frames(1), 0);
+}
+
+/* Read from a pipe */
+size_t
+pipe_read(File *file, char *buf, size_t size, off_t offset)
+{
+	offset %= 4096;
+
+	Pipe *pipe = file->inode->extra;
+	if (!pipe->writers) {
+		send_sig(current, SIGPIPE);
+		return 0;
+	}
+
+	Task *tmp;
+	Page *page = page_find(file->inode, 0);
+	acquire(&quickPageLock);
+	page_t oldPage = quick_page(page->frame);
+	size_t count = 0, avail, min, minPart;
+	while (size) {
+		avail = pipe->size;
+		if (!avail) {
+			quick_page(oldPage);
+			release(&quickPageLock);
+
+			if (!pipe->writers)
+				goto end;
+
+			while (tmp = pop_from_queue(&pipe->writeQueue))
+				unblock_task(tmp);
+			add_to_queue(&pipe->readQueue, current);
+			block_task(WAITING_FOR_IO);
+
+			acquire(&quickPageLock);
+			oldPage = quick_page(page->frame);
+		}
+		avail = pipe->size;
+		min = (size < avail) ? size : avail;
+		if (pipe->tail + min >= 4096) {
+			minPart = 4096 - pipe->tail;
+			memcpy(buf + count, QUICK_PAGE + pipe->tail, minPart);
+			memcpy(buf + count + minPart, QUICK_PAGE,
+			       min - minPart);
+		} else {
+			memcpy(buf + count, QUICK_PAGE + pipe->tail, min);
+		}
+
+		size -= min;
+		count += min;
+		pipe->tail += min;
+		pipe->tail %= 4096;
+		pipe->size -= min;
+	}
+
+	quick_page(oldPage);
+	release(&quickPageLock);
+
+end:
+	while (tmp = pop_from_queue(&pipe->writeQueue))
+		unblock_task(tmp);
+
+	return count;
+}
+
+/* Write to a pipe */
+size_t
+pipe_write(File *file, char *buf, size_t size, off_t offset)
+{
+	offset %= 4096;
+
+	Pipe *pipe = file->inode->extra;
+	if (!pipe->readers) {
+		send_sig(current, SIGPIPE);
+		return 0;
+	}
+
+	Task *tmp;
+	Page *page = page_find(file->inode, 0);
+	acquire(&quickPageLock);
+	page_t oldPage = quick_page(page->frame);
+	size_t count = 0, space, min, minPart;
+	while (size) {
+		space = 4096 - pipe->size;
+		if (!space) {
+			quick_page(oldPage);
+			release(&quickPageLock);
+
+			while (tmp = pop_from_queue(&pipe->readQueue))
+				unblock_task(tmp);
+			add_to_queue(&pipe->writeQueue, current);
+			block_task(WAITING_FOR_IO);
+
+			acquire(&quickPageLock);
+			oldPage = quick_page(page->frame);
+		}
+		space = 4096 - pipe->size;
+		min = (size < space) ? size : space;
+		if (pipe->head + min >= 4096) {
+			minPart = 4096 - pipe->head;
+			memcpy(QUICK_PAGE + pipe->head, buf + count, minPart);
+			memcpy(QUICK_PAGE, buf + count + minPart,
+			       min - minPart);
+		} else {
+			memcpy(QUICK_PAGE + pipe->head, buf + count, min);
+		}
+
+		size -= min;
+		count += min;
+		pipe->head += min;
+		pipe->head %= 4096;
+		pipe->size += min;
+	}
+
+	quick_page(oldPage);
+	release(&quickPageLock);
+
+	while (tmp = pop_from_queue(&pipe->readQueue))
+		unblock_task(tmp);
+
+	return count;
+}
+
+int
+pipe_release(File *file)
+{
+	Task *tmp;
+	Pipe *pipe = file->inode->extra;
+	TaskQueue *queue = (file->ops == &pipeReadFileOps)
+	                 ? &pipe->writeQueue : &pipe->readQueue;
+	while (tmp = pop_from_queue(queue)) {
+		unblock_task(tmp);
+		send_sig(tmp, SIGPIPE);
+	}
+	if (queue == &pipe->readQueue)
+		pipe->writers--;
+	else
+		pipe->readers--;
+}
diff --git a/vfs/tmpfs/file.c b/vfs/tmpfs/file.c
index 252c88f..bc320ed 100644
--- a/vfs/tmpfs/file.c
+++ b/vfs/tmpfs/file.c
@@ -33,7 +33,7 @@ tmpfs_read(File *file, char *buf, size_t size, off_t offset)
 	if (size + offset > file->inode->size)
 		size = file->inode->size - offset;
 
-	uint16_t min;
+	uint16_t min, indent = offset % 4096;
 	size_t count = 0;
 	Page *page;
 	page_t oldPage;
@@ -44,11 +44,12 @@ tmpfs_read(File *file, char *buf, size_t size, off_t offset)
 			break;
 		acquire(&quickPageLock);
 		oldPage = quick_page(page->frame);
-		memcpy(buf + count, QUICK_PAGE, min);
+		memcpy(buf + count, QUICK_PAGE + indent, min);
 		quick_page(oldPage);
 		release(&quickPageLock);
 		size -= min;
 		count += min;
+		indent = 0;
 	}
 	return count;
 }
@@ -60,7 +61,7 @@ tmpfs_write(File *file, char *buf, size_t size, off_t offset)
 	if (size + offset > file->inode->size)
 		file->inode->size = size + offset;
 
-	uint16_t min;
+	uint16_t min, indent = offset % 4096;
 	size_t count = 0;
 	Page *page;
 	page_t oldPage;
@@ -72,11 +73,12 @@ tmpfs_write(File *file, char *buf, size_t size, off_t offset)
 		                           offset);
 		acquire(&quickPageLock);
 		oldPage = quick_page(page->frame);
-		memcpy(QUICK_PAGE, buf + count, min);
+		memcpy(QUICK_PAGE + indent, buf + count, min);
 		quick_page(oldPage);
 		release(&quickPageLock);
 		size -= min;
 		count += min;
+		indent = 0;
 	}
 	return count;
 }
diff --git a/vfs/vfs.c b/vfs/vfs.c
index 68f4b34..c4784f2 100644
--- a/vfs/vfs.c
+++ b/vfs/vfs.c
@@ -322,7 +322,7 @@ close(int fd)
 }
 
 /* Read a file */
-size_t
+int
 read(int fd, void *buf, size_t count)
 {
 	if (!verify_access(buf, count, PROT_WRITE))
@@ -336,11 +336,12 @@ read(int fd, void *buf, size_t count)
 	if (S_ISDIR(file->mode))
 		return -EISDIR;
 
-	return file_read(file, buf, count);
+	int sz = (int) file_read(file, buf, count);
+	return sz;
 }
 
 /* Write a file */
-size_t
+int
 write(int fd, void *buf, size_t count)
 {
 	if (!verify_access(buf, count, PROT_READ))
@@ -354,7 +355,8 @@ write(int fd, void *buf, size_t count)
 	if (S_ISDIR(file->mode))
 		return -EISDIR;
 
-	return file_write(file, buf, count);
+	int sz = (int) file_write(file, buf, count);
+	return sz;
 }
 
 /* I/O Control */
@@ -414,12 +416,13 @@ stat(const char *pathname, struct stat *statbuf)
 	if (!inode)
 		return -ENOENT;
 	if (statbuf) {
-		statbuf->inode = inode->ino;
-		statbuf->mode = inode->mode;
-		statbuf->nlink = inode->nlink;
-		statbuf->uid = inode->uid;
-		statbuf->gid = inode->gid;
-		statbuf->size = inode->size;
+		statbuf->st_dev = inode->dev;
+		statbuf->st_ino = inode->ino;
+		statbuf->st_mode = inode->mode;
+		statbuf->st_nlink = inode->nlink;
+		statbuf->st_uid = inode->uid;
+		statbuf->st_gid = inode->gid;
+		statbuf->st_size = inode->size;
 	}
 	inode_put(inode);
 	return 0;
@@ -437,9 +440,15 @@ fstat(int fd, struct stat *statbuf)
 	if (!file)
 		return -EBADF;
 	Inode *inode = file->inode;
-	statbuf->inode = inode->ino;
-	statbuf->mode = inode->mode;
-	statbuf->size = inode->size;
+	if (statbuf) {
+		statbuf->st_dev = inode->dev;
+		statbuf->st_ino = inode->ino;
+		statbuf->st_mode = inode->mode;
+		statbuf->st_nlink = inode->nlink;
+		statbuf->st_uid = inode->uid;
+		statbuf->st_gid = inode->gid;
+		statbuf->st_size = inode->size;
+	}
 	return 0;
 }
 
diff --git a/vfs/vfs.h b/vfs/vfs.h
index ece5679..6997bf3 100644
--- a/vfs/vfs.h
+++ b/vfs/vfs.h
@@ -68,12 +68,14 @@ struct Inode {
 	Spinlock lock;
 	InodeOps *ops;
 	FileOps *fileOps;
+	void *extra;
+	void (*free_extra)(Inode *);
 	SuperBlock *super;
 	union {
 		DirEntry *dirEntries; /* List of Directory Entries */
 		PageCache *pages; /* List of Pages */
 	};
-	Inode *lnext; /* Next inode in super list */
+	Inode *lnext; /* Next inode in super's list */
 };
 struct InodeOps {
 	int (*create)(Inode *, DirEntry *, mode_t);
@@ -163,8 +165,8 @@ Inode *lookup(const char *name, CustodyChain *chain);
 
 int open(const char *name, int flags, ...); /* mode_t mode */
 int close(int fd);
-size_t read(int fd, void *buf, size_t count);
-size_t write(int fd, void *buf, size_t count);
+int read(int fd, void *buf, size_t count);
+int write(int fd, void *buf, size_t count);
 int ioctl(int fd, unsigned long request, ...);
 off_t lseek(int fd, off_t offset, int whence);
 int stat(const char *pathname, struct stat *statbuf);
@@ -175,6 +177,7 @@ int mknod(const char *pathname, mode_t mode, dev_t dev);
 int rename(const char *oldpath, const char *newpath);
 int dup(int oldfd);
 int dup2(int oldfd, int newfd);
+int pipe(int pipefd[2]);
 int mount(const char *src, const char *target, const char *type,
           unsigned long flags, void *data);
 int chdir(const char *path);