# HG changeset patch # User John Tsiombikas # Date 1397743410 -10800 # Node ID 921a264297a4a57d3d10664e251303d2280e0c89 # Parent b4264d173aae391076755e9ab8a4c580726f3397# Parent 8717eb590727682aff46ce087c96ca46777cc7ac merged the filesystem stuff diff -r b4264d173aae -r 921a264297a4 fstools/mkfs/mkfs.c --- a/fstools/mkfs/mkfs.c Thu Apr 17 12:30:02 2014 +0300 +++ b/fstools/mkfs/mkfs.c Thu Apr 17 17:03:30 2014 +0300 @@ -47,10 +47,12 @@ { struct superblock *sb; - if(!(sb = malloc(BLKSZ))) { - perror("failed to allocate memory"); - return -1; - } + sb = malloc(BLKSZ); + assert(sb); + + sb->magic = MAGIC; + sb->ver = 0; + sb->num_blocks = nblocks; } uint32_t get_block_count(int fd, int blksize) @@ -84,23 +86,23 @@ return 0; } -int user_readblock(int dev, uint32_t blk, void *buf) +int blk_read(void*, uint32_t blk, int count, void *buf) { if(lseek(fd, blk * BLKSZ, SEEK_SET) == -1) { return -1; } - if(read(fd, buf, BLKSZ) < BLKSZ) { + if(read(fd, buf, BLKSZ * count) < BLKSZ * count) { return -1; } return 0; } -int user_writeblock(int dev, uint32_t blk, void *buf) +int blk_write(void*, uint32_t blk, int count, void *buf) { if(lseek(fd, blk * BLKSZ, SEEK_SET) == -1) { return -1; } - if(write(fd, buf, BLKSZ) < BLKSZ) { + if(write(fd, buf, BLKSZ * count) < BLKSZ * count) { return -1; } return 0; diff -r b4264d173aae -r 921a264297a4 include/kdef.h --- a/include/kdef.h Thu Apr 17 12:30:02 2014 +0300 +++ b/include/kdef.h Thu Apr 17 17:03:30 2014 +0300 @@ -29,11 +29,21 @@ /* --- defines for errno.h */ #if defined(KERNEL) || defined(KDEF_ERRNO_H) -#define EAGAIN 1 -#define EINVAL 2 -#define ECHILD 3 +#define EFOO 1 /* I just like to return -1 some times :) */ -#define EBUG 255 /* not implemented yet */ +#define EAGAIN 2 +#define EINVAL 3 +#define ECHILD 4 +#define EBUSY 5 +#define ENOMEM 6 +#define EIO 7 +#define ENOENT 8 +#define ENAMETOOLONG 9 +#define ENOSPC 10 +#define EPERM 11 +#define ENOTDIR 12 + +#define EBUG 127 /* for missing features and known bugs */ #endif /* errno.h */ @@ -62,4 +72,36 @@ #endif /* syscall.h */ +/* --- defines for sys/stat.h */ +#if defined(KERNEL) || defined(STAT_H) + +#define S_IFMT 0170000 /* bit mask for the file type bit fields */ +#define S_IFSOCK 0140000 /* socket */ +#define S_IFLNK 0120000 /* symbolic link */ +#define S_IFREG 0100000 /* regular file */ +#define S_IFBLK 0060000 /* block device */ +#define S_IFDIR 0040000 /* directory */ +#define S_IFCHR 0020000 /* character device */ +#define S_IFIFO 0010000 /* FIFO */ + +#define S_ISUID 0004000 /* set UID bit */ +#define S_ISGID 0002000 /* set-group-ID bit (see below) */ +#define S_ISVTX 0001000 /* sticky bit (see below) */ + +#define S_IRWXU 00700 /* mask for file owner permissions */ +#define S_IRUSR 00400 /* owner has read permission */ +#define S_IWUSR 00200 /* owner has write permission */ +#define S_IXUSR 00100 /* owner has execute permission */ +#define S_IRWXG 00070 /* mask for group permissions */ +#define S_IRGRP 00040 /* group has read permission */ +#define S_IWGRP 00020 /* group has write permission */ +#define S_IXGRP 00010 /* group has execute permission */ +#define S_IRWXO 00007 /* mask for permissions for others (not in group) */ +#define S_IROTH 00004 /* others have read permission */ +#define S_IWOTH 00002 /* others have write permission */ +#define S_IXOTH 00001 /* others have execute permission */ + +#endif /* sys/stat.h */ + + #endif /* KERNEL_DEFS_H_ */ diff -r b4264d173aae -r 921a264297a4 src/bdev.c --- a/src/bdev.c Thu Apr 17 12:30:02 2014 +0300 +++ b/src/bdev.c Thu Apr 17 17:03:30 2014 +0300 @@ -40,11 +40,13 @@ bdev->offset = SECT_TO_BLK(plist->start_sect); bdev->size = SECT_TO_BLK(plist->size_sect); + bdev->ptype = get_part_type(plist); free_part_list(plist); } else { bdev->offset = 0; bdev->size = SECT_TO_BLK(ata_num_sectors(devno)); + bdev->ptype = 0; } return bdev; @@ -57,13 +59,13 @@ #define NSECT (BLKSZ / 512) -int blk_read(struct block_device *bdev, uint32_t blk, void *buf) +int blk_read(struct block_device *bdev, uint32_t blk, int count, void *buf) { int i; char *ptr = buf; - uint32_t sect = blk * NSECT; + uint32_t sect = blk * NSECT + bdev->offset; - for(i=0; iata_dev, sect++, ptr) == -1) { return -1; } @@ -72,13 +74,13 @@ return 0; } -int blk_write(struct block_device *bdev, uint32_t blk, void *buf) +int blk_write(struct block_device *bdev, uint32_t blk, int count, void *buf) { int i; char *ptr = buf; - uint32_t sect = blk * NSECT; + uint32_t sect = blk * NSECT + bdev->offset; - for(i=0; iata_dev, sect++, ptr) == -1) { return -1; } @@ -116,5 +118,5 @@ } minor = MKMINOR(atadev, part); - return DEVNO(0, minor); + return DEVNO(1, minor); } diff -r b4264d173aae -r 921a264297a4 src/bdev.h --- a/src/bdev.h Thu Apr 17 12:30:02 2014 +0300 +++ b/src/bdev.h Thu Apr 17 17:03:30 2014 +0300 @@ -8,13 +8,19 @@ struct block_device { int ata_dev; uint32_t offset, size; + + /* Partition type (if the blkdev is a partition), otherwise 0. + * Used as just an extra sanity check to make sure we don't + * try to mount the wrong filesystem. + */ + int ptype; }; struct block_device *blk_open(dev_t dev); void blk_close(struct block_device *bdev); -int blk_read(struct block_device *bdev, uint32_t blk, void *buf); -int blk_write(struct block_device *bdev, uint32_t blk, void *buf); +int blk_read(struct block_device *bdev, uint32_t blk, int count, void *buf); +int blk_write(struct block_device *bdev, uint32_t blk, int count, void *buf); dev_t bdev_by_name(const char *name); diff -r b4264d173aae -r 921a264297a4 src/fs.c --- a/src/fs.c Thu Apr 17 12:30:02 2014 +0300 +++ b/src/fs.c Thu Apr 17 17:03:30 2014 +0300 @@ -1,120 +1,499 @@ -/* This code is used by the kernel AND by userspace filesystem-related tools. - * The kernel-specific parts are conditionally compiled in #ifdef KERNEL blocks - * the rest of the code should be independent. +/* This code is used by the kernel AND by userspace filesystem-related tools. */ + +/* XXX convention: + * - functions that accept or return a struct inode, do not read/write it to disk + * - functions that accept or return an int ino, do read/write it to disk + * other kinds of blocks (data, indirect, etc) always hit the disk directly. */ + #include #include +#include +#include #include -#include #include "fs.h" -#include "part.h" +#include "bdev.h" +#include "kdef.h" -#ifdef KERNEL -#include "ata.h" -#include "panic.h" -#endif +/* number of inodes in a block */ +#define BLK_INODES (BLKSZ / sizeof(struct inode)) +/* number of directory entries in a block */ +#define BLK_DIRENT (BLKSZ / sizeof(struct dir_entry)) -struct filesys { - int dev; - struct partition part; +#define BLKBITS (BLKSZ * 8) - struct superblock *sb; +#define BM_IDX(x) ((x) / 32) +#define BM_BIT(x) ((x) & 0x1f) - struct filesys *next; -}; +#define BM_ISFREE(bm, x) (((bm)[BM_IDX(x)] & (1 << BM_BIT(x))) == 0) +#define BM_SET(bm, x) ((bm)[BM_IDX(x)] |= (1 << BM_BIT(x))) +#define BM_CLR(bm, x) ((bm)[BM_IDX(x)] &= ~(1 << BM_BIT(x))) -static int find_rootfs(struct filesys *fs); -static int readblock(int dev, uint32_t blk, void *buf); -static int writeblock(int dev, uint32_t blk, void *buf); -/* root device & partition */ -static struct filesys *fslist; +static struct inode *newdir(struct filesys *fs, struct inode *parent); +static int addlink(struct filesys *fs, struct inode *target, struct inode *node, const char *name); +static int read_superblock(struct filesys *fs); +static int write_superblock(struct filesys *fs); +static int get_inode(struct filesys *fs, int ino, struct inode *inode); +static int put_inode(struct filesys *fs, struct inode *inode); +static int find_free(uint32_t *bm, int sz); +static int alloc_inode(struct filesys *fs); +#define free_inode(fs, ino) BM_CLR((fs)->sb->ibm, (ino)) +static int alloc_block(struct filesys *fs); +#define free_block(fs, bno) BM_CLR((fs)->sb->bm, (bno)) +#define zero_block(fs, bno) \ + do { \ + assert(bno > 0); \ + blk_write((fs)->bdev, (bno), 1, (fs)->zeroblock); \ + } while(0) -int sys_mount(char *mtpt, char *devname, unsigned int flags) +static int file_block(struct filesys *fs, struct inode *node, int boffs, int allocate); +#define get_file_block(fs, node, boffs) file_block(fs, node, boffs, 0) +#define alloc_file_block(fs, node, boffs) file_block(fs, node, boffs, 1) + + +int openfs(struct filesys *fs, dev_t dev) { - if(strcmp(mtpt, "/") != 0) { - printf("mount: only root can be mounted at the moment\n"); - return -EBUG; + int res; + struct block_device *bdev; + + assert(BLKSZ % sizeof(struct inode) == 0); + + if(!(bdev = blk_open(dev))) { + return -ENOENT; + } + fs->bdev = bdev; + + /* read the superblock */ + if(!(fs->sb = malloc(BLKSZ))) { + blk_close(bdev); + return -ENOMEM; + } + if((res = read_superblock(fs)) != 0) { + blk_close(bdev); + return res; } - /* mounting root filesystem */ - if(fslist) { + /* allocate the zero-block buffer written to zero-out blocks */ + if(!(fs->zeroblock = malloc(fs->sb->blksize))) { + blk_close(bdev); + free(fs->sb->ibm); + free(fs->sb->bm); + free(fs->sb->root); + return -ENOMEM; + } + memset(fs->zeroblock, 0xff, fs->sb->blksize); + return 0; } -void init_fs(void) +int mkfs(struct filesys *fs, dev_t dev) { - root.sb = malloc(512); - assert(root.sb); + struct superblock *sb; + struct block_device *bdev; + int i, bcount; -#ifdef KERNEL - if(find_rootfs(&root) == -1) { - panic("can't find root filesystem\n"); + if(!(bdev = blk_open(dev))) { + return -1; } -#endif + fs->bdev = bdev; + + if(!(sb = malloc(BLKSZ))) { + blk_close(bdev); + return -1; + } + fs->sb = sb; + + /* populate the superblock */ + sb->magic = MAGIC; + sb->ver = FS_VER; + sb->blksize = BLKSZ; + + sb->num_blocks = bdev->size; + sb->num_inodes = sb->num_blocks / 4; + + /* inode bitmap just after the superblock */ + sb->ibm_start = 2; + sb->ibm_count = (sb->num_inodes + BLKBITS - 1) / BLKBITS; + /* also allocate and initialize in-memory inode bitmap */ + sb->ibm = malloc(sb->ibm_count * BLKSZ); + assert(sb->ibm); + memset(sb->ibm, 0, sb->ibm_count * BLKSZ); + + /* XXX mark inode 0 as used always */ + BM_SET(sb->ibm, 0); + + /* block bitmap just after the inode bitmap */ + sb->bm_start = sb->ibm_start + sb->ibm_count; + sb->bm_count = (sb->num_blocks + BLKBITS - 1) / BLKBITS; + /* also allocate and initialize in-memory block bitmap */ + sb->bm = malloc(sb->bm_count * BLKSZ); + assert(sb->bm); + memset(sb->bm, 0, sb->bm_count * BLKSZ); + + /* inode table, just after the block bitmap */ + sb->itbl_start = sb->bm_start + sb->bm_count; + sb->itbl_count = (sb->num_inodes * sizeof(struct inode) + BLKSZ - 1) / BLKSZ; + + /* mark all used blocks as used */ + bcount = sb->itbl_start + sb->itbl_count; + memset(sb->bm, 0xff, bcount / 8); + for(i=0; ibm, bit); + } + + /* create the root directory */ + sb->root = newdir(fs, 0); + sb->root_ino = sb->root->ino; + /* and write the inode to disk */ + put_inode(fs, sb->root); + + return 0; } +static struct inode *newdir(struct filesys *fs, struct inode *parent) +{ + struct inode *dirnode; -#ifdef KERNEL -#define PART_TYPE 0xcc -static int find_rootfs(struct filesys *fs) + /* allocate and initialize inode */ + if(!(dirnode = malloc(sizeof *dirnode))) { + return 0; + } + memset(dirnode, 0, sizeof *dirnode); + + if((dirnode->ino = alloc_inode(fs)) == -1) { + printf("failed to allocate inode for a new directory\n"); + free(dirnode); + return 0; + } + dirnode->mode = S_IFDIR; + + /* add . and .. links */ + addlink(fs, dirnode, dirnode, "."); + addlink(fs, dirnode, parent ? parent : dirnode, ".."); + + return dirnode; +} + +static int addlink(struct filesys *fs, struct inode *target, struct inode *node, const char *name) { - int i, num_dev, partid; - struct partition *plist, *p; + struct dir_entry ent, *data; + int i, boffs, bidx, len; - num_dev = ata_num_devices(); - for(i=0; imode & S_IFDIR)) { + return -ENOTDIR; + } + if(node->mode & S_IFDIR) { + return -EPERM; + } + /* TODO check that the link does not already exist (EEXIST) */ - partid = 0; - while(p) { - if(get_part_type(p) == PART_TYPE) { - /* found the correct partition, now read the superblock - * and make sure it's got the correct magic id - */ - readblock(i, p->start_sect / 2 + 1, fs->sb); + if((len = strlen(name)) > NAME_MAX) { + return -ENAMETOOLONG; + } + ent.ino = node->ino; + memcpy(ent.name, name, len + 1); - if(fs->sb->magic == MAGIC) { - printf("found root ata%dp%d\n", i, partid); - fs->dev = i; - fs->part = *p; - return 0; + /* find a place to put it */ + if(!(data = malloc(BLKSZ))) { + return -ENOMEM; + } + + boffs = 0; + while((bidx = get_file_block(fs, target, boffs)) > 0) { + /* read the block, and search for an empty entry */ + blk_read(fs->bdev, bidx, 1, data); + + /* for all directory entries in this block... */ + for(i=0; ibdev, bidx, 1, data); + node->nlink++; /* increase reference count */ + + free(data); + return 0; +} + + +static int read_superblock(struct filesys *fs) +{ + struct superblock *sb = fs->sb; + + /* read superblock and verify */ + if(blk_read(fs->bdev, 1, 1, sb) == -1) { + printf("failed to read superblock\n"); + return -EIO; + } + if(sb->magic != MAGIC) { + printf("invalid magic\n"); + return -EINVAL; + } + if(sb->ver > FS_VER) { + printf("invalid version: %d\n", sb->ver); + return -EINVAL; + } + if(sb->blksize != BLKSZ) { + printf("invalid block size: %d\n", sb->blksize); + return -EINVAL; + } + + /* allocate and populate in-memory bitmaps */ + if(!(sb->ibm = malloc(sb->ibm_count * sb->blksize))) { + return -ENOMEM; + } + if(blk_read(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) { + printf("failed to read inode bitmap\n"); + free(sb->ibm); + return -EIO; + } + if(!(sb->bm = malloc(sb->bm_count * sb->blksize))) { + free(sb->ibm); + return -ENOMEM; + } + if(blk_read(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) { + printf("failed to read block bitmap\n"); + free(sb->ibm); + free(sb->bm); + return -EIO; + } + + /* read the root inode */ + if(!(sb->root = malloc(sizeof *sb->root))) { + free(sb->ibm); + free(sb->bm); + return -ENOMEM; + } + if(get_inode(fs, sb->root_ino, sb->root) == -1) { + printf("failed to read root inode\n"); + return -1; + } + + return 0; +} + +static int write_superblock(struct filesys *fs) +{ + struct superblock *sb = fs->sb; + + /* write back any changes in the root inode */ + if(put_inode(fs, sb->root) == -1) { + return -1; + } + /* write back the block bitmap */ + if(blk_write(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) { + return -1; + } + /* write back the inode bitmap */ + if(blk_write(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) { + return -1; + } + /* write the superblock itself */ + if(blk_write(fs->bdev, 1, 1, sb) == -1) { + return -1; + } + return 0; +} + +/* copy the requested inode from the disk, into the buffer passed in the last arg */ +static int get_inode(struct filesys *fs, int ino, struct inode *inode) +{ + struct inode *buf = malloc(BLKSZ); + assert(buf); + + if(blk_read(fs->bdev, fs->sb->itbl_start + ino / BLK_INODES, 1, buf) == -1) { + free(buf); + return -1; + } + memcpy(inode, buf + ino % BLK_INODES, sizeof *inode); + free(buf); + return 0; +} + +/* write the inode to the disk */ +static int put_inode(struct filesys *fs, struct inode *inode) +{ + struct inode *buf = malloc(BLKSZ); + assert(buf); + + if(blk_read(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) { + free(buf); + return -1; + } + memcpy(buf + inode->ino % BLK_INODES, inode, sizeof *inode); + + if(blk_write(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) { + free(buf); + return -1; + } + free(buf); + return 0; +} + +/* find a free element in the bitmap and return its number */ +static int find_free(uint32_t *bm, int nbits) +{ + int i, j, nwords = nbits / 32; + uint32_t ent = 0; + + for(i=0; i<=nwords; i++) { + if(bm[i] != 0xffffffff) { + for(j=0; j<32; j++) { + if(BM_ISFREE(bm, ent)) { + return ent; } + ent++; } - p = p->next; - partid++; + + panic("shouldn't happen (in find_free:fs.c)"); + } else { + ent += 32; } - free_part_list(plist); } + return -1; } -#define NSECT (BLKSZ / 512) +static int alloc_inode(struct filesys *fs) +{ + int ino; -static int readblock(struct block_device *bdev, uint32_t blk, void *buf) -{ - return blk_read(bdev, blk, buf); + if((ino = find_free(fs->sb->ibm, fs->sb->num_inodes)) == -1) { + return -1; + } + BM_SET(fs->sb->ibm, ino); + return 0; } -static int writeblock(struct block_device *bdev, uint32_t blk, void *buf) +static int alloc_block(struct filesys *fs) { - return blk_write(bdev, blk, buf); -} -#else + int bno; -/* if this is compiled as part of the user-space tools instead of the kernel - * forward the call to a user read/write block function supplied by the app. - */ -int user_readblock(uint32_t, void*); -int user_writeblock(uint32_t, void*); - -static int readblock(struct block_device *bdev, uint32_t blk, void *buf) -{ - return user_readblock(blk, buf); + if((bno = find_free(fs->sb->bm, fs->sb->num_blocks)) == -1) { + return -1; + } + BM_SET(fs->sb->bm, bno); + return 0; } -static int writeblock(struct block_device *bdev, uint32_t blk, void *buf) +#define BLK_BLKID (BLKSZ / sizeof(blkid)) +#define MAX_IND (NDIRBLK + BLK_BLKID) +#define MAX_DIND (MAX_IND + BLK_BLKID * BLK_BLKID) + +static int file_block(struct filesys *fs, struct inode *node, int boffs, int allocate) { - return user_writeblock(blk, buf); + int res, idx, node_dirty = 0; + blkid *barr; + + /* out of bounds */ + if(boffs < 0 || boffs >= MAX_DIND) { + return 0; + } + + /* is it a direct block ? */ + if(boffs < NDIRBLK) { + if(!(res = node->blk[boffs]) && allocate) { + res = node->blk[boffs] = alloc_block(fs); + if(res) { + zero_block(fs, res); + /* also write back the modified inode */ + put_inode(fs, node); + } + } + return res; + } + + barr = malloc(fs->sb->blksize); + assert(barr); + + /* is it an indirect block ? */ + if(boffs < MAX_IND) { + int ind_dirty = 0; + + if(node->ind) { + /* read the indirect block */ + blk_read(fs->bdev, node->ind, 1, barr); + } else { + /* does not exist... try to allocate if requested */ + if(!allocate || !(node->ind = alloc_block(fs))) { + res = 0; + goto end; + } + + /* allocated a block clear the buffer, and invalidate everything */ + memset(barr, 0, sizeof fs->sb->blksize); + node_dirty = 1; + ind_dirty = 1; + } + + idx = boffs - NDIRBLK; + + if(!(res = barr[idx])) { + if(allocate && (res = barr[idx] = alloc_block(fs))) { + ind_dirty = 1; + } + } + + /* write back the indirect block if needed */ + if(ind_dirty) { + blk_write(fs->bdev, node->ind, 1, barr); + } + goto end; + } + + /* TODO check/rewrite this */ +#if 0 + /* is it a double-indirect block ? */ + if(boffs < MAX_DIND) { + /* first read the dind block and find the index of the ind block */ + if(!node->dind) { + if(allocate) { + /* allocate and zero-out the double indirect block */ + res = node->dind = alloc_block(fs); + if(res) { + zero_block(fs, res); + } + } else { + res = 0; + goto end; + } + } + blk_read(fd->bdev, node->dind, 1, barr); + idx = (boffs - MAX_IND) / BLK_BLKID; + + /* then read the ind block and find the index of the block */ + if(!barr[idx]) { + res = 0; + goto end; + } + blk_read(fd->bdev, barr[idx], 1, barr); + res = barr[(boffs - MAX_IND) % BLK_BLKID]; + } +#endif + +end: + if(node_dirty) { + put_inode(fs, node); + } + free(barr); + return res; } -#endif /* KERNEL */ diff -r b4264d173aae -r 921a264297a4 src/fs.h --- a/src/fs.h Thu Apr 17 12:30:02 2014 +0300 +++ b/src/fs.h Thu Apr 17 17:03:30 2014 +0300 @@ -3,8 +3,12 @@ #include -#define MAGIC 0xccf5ccf5 -#define BLKSZ 1024 +#define MAGIC 0xccf5ccf5 +#define FS_VER 1 +#define BLKSZ 1024 + +#define NAME_MAX 27 /* +1 termin. +4 ino = 32 per dirent */ +#define PATH_MAX 256 #define SECT_TO_BLK(x) ((x) / (BLKSZ / 512)) @@ -16,34 +20,6 @@ typedef uint32_t dev_t; typedef uint32_t blkid; -struct superblock { - uint32_t magic; /* magic number */ - int ver; /* filesystem version */ - int blksize; /* only BLKSZ supported at the moment */ - - /* total number of blocks */ - unsigned int num_blocks; - /* inode allocation bitmap start and count */ - blkid ibm_start; - unsigned int ibm_count; - /* inode table start and count */ - blkid itbl_start; - unsigned int itbl_count; - /* data block allocation bitmap start and count */ - blkid dbm_start; - unsigned int dbm_count; - /* data blocks start and count */ - blkid data_start; - unsigned int data_count; - - int root_ino; /* root direcotry inode */ - - /* the following are valid only at runtime, ignored on disk */ - uint32_t *ibm; /* memory inode bitmap */ - uint32_t *dbm; /* memory datablock bitmap */ - -} __attribute__((packed)); - /* 20 direct blocks + 10 attributes + 2 indirect = 128 bytes per inode */ #define NDIRBLK 20 @@ -59,7 +35,59 @@ blkid dind; /* double-indirect */ } __attribute__((packed)); +struct dir_entry { + int ino; + char name[NAME_MAX + 1]; +} __attribute__((packed)); +struct superblock { + uint32_t magic; /* magic number */ + int ver; /* filesystem version */ + int blksize; /* only BLKSZ supported at the moment */ + + /* total number of blocks */ + unsigned int num_blocks; + /* total number of inodes */ + unsigned int num_inodes; + + /* inode allocation bitmap start and count */ + blkid ibm_start; + unsigned int ibm_count; + /* inode table start and count */ + blkid itbl_start; + unsigned int itbl_count; + /* block allocation bitmap start and count */ + blkid bm_start; + unsigned int bm_count; + + int root_ino; /* root direcotry inode number */ + + /* the following are valid only at runtime, ignored on disk */ + uint32_t *ibm; /* in-memory inode bitmap */ + uint32_t *bm; /* in-memory block bitmap */ + struct inode *root; /* in-memory root inode */ + +} __attribute__((packed)); + + + +struct filesys { + struct block_device *bdev; + + struct superblock *sb; + + void *zeroblock; + + struct filesys *next; +}; + +/* defined in fs.c */ +int openfs(struct filesys *fs, dev_t dev); +int mkfs(struct filesys *fs, dev_t dev); +void closefs(struct filesys *fs); +int find_inode(const char *path); + +/* defined in fs_sys.c */ int sys_mount(char *mntpt, char *devname, unsigned int flags); int sys_umount(char *devname); @@ -70,7 +98,5 @@ int sys_write(int fd, void *buf, int sz); long sys_lseek(int fd, long offs, int from); -int lookup_path(const char *path); - #endif /* FS_H_ */ diff -r b4264d173aae -r 921a264297a4 src/fs_sys.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/fs_sys.c Thu Apr 17 17:03:30 2014 +0300 @@ -0,0 +1,105 @@ +/* implementation of the filesystem-related syscalls */ + +#include +#include +#include +#include +#include +#include "fs.h" +#include "part.h" +#include "panic.h" +#include "bdev.h" + +static dev_t find_rootfs(void); + +/* list of mounted filesystems + * XXX currently only one, the root filesystem + */ +static struct filesys *fslist; + + +int sys_mount(char *mtpt, char *devname, unsigned int flags) +{ + dev_t dev; + int err; + struct filesys *fs; + + if(strcmp(mtpt, "/") != 0) { + printf("only root can be mounted at the moment\n"); + return -EBUG; + } + + /* mounting root filesystem */ + if(fslist) { + printf("root already mounted\n"); + return -EBUSY; + } + + if(devname) { + dev = bdev_by_name(devname); + } else { + /* try to autodetect it */ + dev = find_rootfs(); + } + if(!dev) { + err = -ENOENT; + goto rootfail; + } + + if(!(fs = malloc(sizeof *fslist))) { + err = -ENOMEM; + goto rootfail; + } + if((err = openfs(fs, dev)) != 0) { + free(fs); + goto rootfail; + } + + fslist = fs; + return 0; + +rootfail: + panic("failed to mount root filesystem: %d\n", -err); + return err; /* unreachable */ +} + +#define PART_TYPE 0xcc +static dev_t find_rootfs(void) +{ + dev_t dev = 0; + int i, num_dev, partid; + struct partition *plist, *p; + struct superblock *sb = malloc(BLKSZ); + char name[16]; + + assert(sb); + + num_dev = ata_num_devices(); + for(i=0; istart_sect / 2 + 1, BLKSZ, sb); + + if(sb->magic == MAGIC) { + sprintf(name, "ata%dp%d", i, partid); + printf("found root: %s\n", name); + dev = bdev_by_name(name); + break; + } + } + p = p->next; + partid++; + } + free_part_list(plist); + if(dev) break; + } + + free(sb); + return dev; +} diff -r b4264d173aae -r 921a264297a4 src/proc.c --- a/src/proc.c Thu Apr 17 12:30:02 2014 +0300 +++ b/src/proc.c Thu Apr 17 17:03:30 2014 +0300 @@ -77,6 +77,8 @@ p->id = 1; p->parent = 0; /* no parent for init */ + p->umask = 022; + p->ticks_left = TIMESLICE_TICKS; p->next = p->prev = 0; @@ -168,6 +170,8 @@ /* copy file table */ memcpy(p->files, parent->files, sizeof p->files); + p->umask = parent->umask; + /* allocate a kernel stack for the new process */ if((p->kern_stack_pg = pgalloc(KERN_STACK_SIZE / PGSIZE, MEM_KERNEL)) == -1) { return -EAGAIN; diff -r b4264d173aae -r 921a264297a4 src/proc.h --- a/src/proc.h Thu Apr 17 12:30:02 2014 +0300 +++ b/src/proc.h Thu Apr 17 17:03:30 2014 +0300 @@ -51,6 +51,8 @@ /* open files */ struct file files[MAX_FD]; + unsigned int umask; + struct process *child_list; struct process *next, *prev; /* for the scheduler queues */