diff --git a/include/sys/blk.h b/include/sys/blk.h index 3dc590f..db85812 100644 --- a/include/sys/blk.h +++ b/include/sys/blk.h @@ -2,6 +2,8 @@ #include "sys/types.h" #include "sys/dev.h" +struct vfs_node; + struct blkdev { void *dev_data; struct dev_entry *ent; @@ -15,6 +17,7 @@ struct blkdev { ssize_t blk_read(struct blkdev *blk, void *buf, size_t off, size_t count); ssize_t blk_write(struct blkdev *blk, const void *buf, size_t off, size_t count); +int blk_mount_auto(struct vfs_node *at, struct blkdev *blkdev, const char *opt); struct blkdev *blk_by_name(const char *name); int blk_enumerate_partitions(struct blkdev *blk); diff --git a/include/sys/fs/vfs.h b/include/sys/fs/vfs.h index c70e762..945084a 100644 --- a/include/sys/fs/vfs.h +++ b/include/sys/fs/vfs.h @@ -91,6 +91,7 @@ void vfs_node_free(struct vfs_node *n); */ struct vfs_node *vfs_node_create(const char *name, vnode_t *vn); +int vfs_mount_internal(struct vfs_node *at, void *blkdev, const char *fs_name, const char *opt); /** * @brief Create a mountpoint in a filesystem tree so that * a "source" directory actually refers to the root diff --git a/sys/amd64/sys/sched.c b/sys/amd64/sys/sched.c index b159fd4..4ef29b1 100644 --- a/sys/amd64/sys/sched.c +++ b/sys/amd64/sys/sched.c @@ -6,6 +6,7 @@ #include "sys/debug.h" #include "sys/heap.h" #include "sys/spin.h" +#include "sys/fs/ext2.h" #include "sys/fs/vfs.h" #include "sys/fcntl.h" #include "sys/errno.h" @@ -50,6 +51,7 @@ void init_func(void *arg) { struct ofile fd; struct stat st; int res; + ext2_class_init(); if (root_blk) { if ((res = vfs_mount(&ioctx, "/", root_blk, "ustar", NULL)) != 0) { @@ -61,6 +63,16 @@ void init_func(void *arg) { panic("mount devfs: %s\n", kstrerror(res)); } + // Try to mount /dev/sda1 at /mnt (don't panic on failure, though) + struct blkdev *sda1_blk = blk_by_name("sda1"); + if (sda1_blk) { + kinfo("Trying to mount /dev/sda1 -> /mnt\n"); + + if ((res = vfs_mount(&ioctx, "/mnt", sda1_blk, "auto", NULL)) != 0) { + kwarn("/dev/sda1: %s\n", kstrerror(res)); + } + } + if ((res = vfs_stat(&ioctx, "/init", &st)) != 0) { panic("/init: %s\n", kstrerror(res)); } diff --git a/sys/blk.c b/sys/blk.c index 1c3b433..9b2ae52 100644 --- a/sys/blk.c +++ b/sys/blk.c @@ -4,6 +4,10 @@ #include "sys/errno.h" #include "sys/string.h" #include "sys/heap.h" +#include "sys/fs/vfs.h" + +// Taken as-is from MBR partition types +#define PART_HINT_LINUX 0x83 ssize_t blk_read(struct blkdev *blk, void *buf, size_t off, size_t lim) { _assert(blk); @@ -48,6 +52,16 @@ struct blk_part { uint64_t lba_size; }; +int blk_mount_auto(struct vfs_node *at, struct blkdev *blk, const char *opt) { + int res; + + if ((res = vfs_mount_internal(at, blk, "ext2", opt)) == 0) { + return 0; + } + + return -1; +} + static ssize_t blk_part_read(struct blkdev *dev, void *buf, size_t off, size_t count) { struct blk_part *part = (struct blk_part *) dev->dev_data; size_t part_size_bytes = part->lba_size * 512; diff --git a/sys/vfs/ext2/ext2vnop.c b/sys/vfs/ext2/ext2vnop.c index bb34638..829055f 100644 --- a/sys/vfs/ext2/ext2vnop.c +++ b/sys/vfs/ext2/ext2vnop.c @@ -474,6 +474,7 @@ static int ext2_vnode_readdir(struct ofile *fd) { vnode_t *vn = fd->vnode; struct ext2_inode *inode = (struct ext2_inode *) vn->fs_data; struct ext2_extsb *sb = vn->fs->fs_private; + ssize_t res; if (fd->pos >= inode->size_lower) { return -1; @@ -482,8 +483,8 @@ static int ext2_vnode_readdir(struct ofile *fd) { size_t block_number = fd->pos / sb->block_size; char block_buffer[sb->block_size]; - if (ext2_read_inode_block(vn->fs, inode, block_number, block_buffer) < 0) { - return -EIO; + if ((res = ext2_read_inode_block(vn->fs, inode, block_number, block_buffer)) < 0) { + return res; } size_t block_offset = fd->pos % sb->block_size; @@ -501,7 +502,43 @@ static int ext2_vnode_readdir(struct ofile *fd) { strncpy(vfsdir->d_name, ext2dir->name, ext2dir->name_len); vfsdir->d_name[ext2dir->name_len] = 0; vfsdir->d_reclen = ext2dir->len; - vfsdir->d_type = ext2dir->type_ind; + if (sb->required_features & 2 /* Directory entries contain type field */) { + switch (ext2dir->type_ind) { + case 1: + // Regular file + vfsdir->d_type = DT_REG; + break; + case 2: + // Directory + vfsdir->d_type = DT_DIR; + break; + // XXX: Don't know if I should have ANY devices in ext2, we have devfs for that + // kind of shit + case 0: + default: + vfsdir->d_type = DT_UNKNOWN; + break; + } + } else { + // Have to read each fucking inode to sort this mess out + struct ext2_inode ent_inode_buf; + + if ((res = ext2_read_inode(vn->fs, &ent_inode_buf, ext2dir->ino)) < 0) { + return res; + } + + switch (ent_inode_buf.type_perm & 0xF000) { + case EXT2_TYPE_REG: + vfsdir->d_type = DT_REG; + break; + case EXT2_TYPE_DIR: + vfsdir->d_type = DT_DIR; + break; + default: + vfsdir->d_type = DT_UNKNOWN; + break; + } + } // Not implemented, I guess vfsdir->d_off = 0; diff --git a/sys/vfs/vfs.c b/sys/vfs/vfs.c index 20922fe..d176536 100644 --- a/sys/vfs/vfs.c +++ b/sys/vfs/vfs.c @@ -7,6 +7,7 @@ #include "sys/errno.h" #include "sys/panic.h" #include "sys/heap.h" +#include "sys/blk.h" #include "sys/chr.h" // #include @@ -393,10 +394,15 @@ void vfs_vnode_path(char *path, vnode_t *vn) { path[0] = 0; } -static int vfs_mount_internal(struct vfs_node *at, void *blkdev, const char *fs_name, const char *opt) { +int vfs_mount_internal(struct vfs_node *at, void *blkdev, const char *fs_name, const char *opt) { struct fs_class *fs_class; + if (!strcmp(fs_name, "auto")) { + return blk_mount_auto(at, blkdev, opt); + } + if ((fs_class = fs_class_by_name(fs_name)) == NULL) { + kdebug("Unknown filesystem class: %s\n", fs_name); return -EINVAL; } diff --git a/usr/Makefile b/usr/Makefile index 8b94c1e..405dc78 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -46,7 +46,7 @@ mkdirs: mkdir -p $(DIRS) mkstage-etc: - mkdir -p $(STAGE)/dev + mkdir -p $(STAGE)/dev $(STAGE)/mnt cp -r etc $(STAGE) # Application building