kern

changeset 98:921a264297a4 tip

merged the filesystem stuff
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 17 Apr 2014 17:03:30 +0300
parents b4264d173aae 8717eb590727
children
files
diffstat 9 files changed, 697 insertions(+), 129 deletions(-) [+]
line diff
     1.1 --- a/fstools/mkfs/mkfs.c	Thu Apr 17 12:30:02 2014 +0300
     1.2 +++ b/fstools/mkfs/mkfs.c	Thu Apr 17 17:03:30 2014 +0300
     1.3 @@ -47,10 +47,12 @@
     1.4  {
     1.5  	struct superblock *sb;
     1.6  
     1.7 -	if(!(sb = malloc(BLKSZ))) {
     1.8 -		perror("failed to allocate memory");
     1.9 -		return -1;
    1.10 -	}
    1.11 +	sb = malloc(BLKSZ);
    1.12 +	assert(sb);
    1.13 +
    1.14 +	sb->magic = MAGIC;
    1.15 +	sb->ver = 0;
    1.16 +	sb->num_blocks = nblocks;
    1.17  }
    1.18  
    1.19  uint32_t get_block_count(int fd, int blksize)
    1.20 @@ -84,23 +86,23 @@
    1.21  	return 0;
    1.22  }
    1.23  
    1.24 -int user_readblock(int dev, uint32_t blk, void *buf)
    1.25 +int blk_read(void*, uint32_t blk, int count, void *buf)
    1.26  {
    1.27  	if(lseek(fd, blk * BLKSZ, SEEK_SET) == -1) {
    1.28  		return -1;
    1.29  	}
    1.30 -	if(read(fd, buf, BLKSZ) < BLKSZ) {
    1.31 +	if(read(fd, buf, BLKSZ * count) < BLKSZ * count) {
    1.32  		return -1;
    1.33  	}
    1.34  	return 0;
    1.35  }
    1.36  
    1.37 -int user_writeblock(int dev, uint32_t blk, void *buf)
    1.38 +int blk_write(void*, uint32_t blk, int count, void *buf)
    1.39  {
    1.40  	if(lseek(fd, blk * BLKSZ, SEEK_SET) == -1) {
    1.41  		return -1;
    1.42  	}
    1.43 -	if(write(fd, buf, BLKSZ) < BLKSZ) {
    1.44 +	if(write(fd, buf, BLKSZ * count) < BLKSZ * count) {
    1.45  		return -1;
    1.46  	}
    1.47  	return 0;
     2.1 --- a/include/kdef.h	Thu Apr 17 12:30:02 2014 +0300
     2.2 +++ b/include/kdef.h	Thu Apr 17 17:03:30 2014 +0300
     2.3 @@ -29,11 +29,21 @@
     2.4  
     2.5  /* --- defines for errno.h */
     2.6  #if defined(KERNEL) || defined(KDEF_ERRNO_H)
     2.7 -#define EAGAIN		1
     2.8 -#define EINVAL		2
     2.9 -#define ECHILD		3
    2.10 +#define EFOO		1 /* I just like to return -1 some times :) */
    2.11  
    2.12 -#define EBUG		255	/* not implemented yet */
    2.13 +#define EAGAIN			2
    2.14 +#define EINVAL			3
    2.15 +#define ECHILD			4
    2.16 +#define EBUSY			5
    2.17 +#define ENOMEM			6
    2.18 +#define EIO				7
    2.19 +#define ENOENT			8
    2.20 +#define ENAMETOOLONG	9
    2.21 +#define ENOSPC			10
    2.22 +#define EPERM			11
    2.23 +#define ENOTDIR			12
    2.24 +
    2.25 +#define EBUG		127	/* for missing features and known bugs */
    2.26  #endif	/* errno.h */
    2.27  
    2.28  
    2.29 @@ -62,4 +72,36 @@
    2.30  
    2.31  #endif	/* syscall.h */
    2.32  
    2.33 +/* --- defines for sys/stat.h */
    2.34 +#if defined(KERNEL) || defined(STAT_H)
    2.35 +
    2.36 +#define S_IFMT		0170000	/* bit mask for the file type bit fields */
    2.37 +#define S_IFSOCK	0140000	/* socket */
    2.38 +#define S_IFLNK		0120000	/* symbolic link */
    2.39 +#define S_IFREG		0100000	/* regular file */
    2.40 +#define S_IFBLK		0060000	/* block device */
    2.41 +#define S_IFDIR		0040000	/* directory */
    2.42 +#define S_IFCHR		0020000	/* character device */
    2.43 +#define S_IFIFO		0010000	/* FIFO */
    2.44 +
    2.45 +#define S_ISUID		0004000	/* set UID bit */
    2.46 +#define S_ISGID		0002000	/* set-group-ID bit (see below) */
    2.47 +#define S_ISVTX		0001000	/* sticky bit (see below) */
    2.48 +
    2.49 +#define S_IRWXU		00700	/* mask for file owner permissions */
    2.50 +#define S_IRUSR		00400	/* owner has read permission */
    2.51 +#define S_IWUSR		00200	/* owner has write permission */
    2.52 +#define S_IXUSR		00100	/* owner has execute permission */
    2.53 +#define S_IRWXG		00070	/* mask for group permissions */
    2.54 +#define S_IRGRP		00040	/* group has read permission */
    2.55 +#define S_IWGRP		00020	/* group has write permission */
    2.56 +#define S_IXGRP		00010	/* group has execute permission */
    2.57 +#define S_IRWXO		00007	/* mask for permissions for others (not in group) */
    2.58 +#define S_IROTH		00004	/* others have read permission */
    2.59 +#define S_IWOTH		00002	/* others have write permission */
    2.60 +#define S_IXOTH		00001	/* others have execute permission */
    2.61 +
    2.62 +#endif	/* sys/stat.h */
    2.63 +
    2.64 +
    2.65  #endif	/* KERNEL_DEFS_H_ */
     3.1 --- a/src/bdev.c	Thu Apr 17 12:30:02 2014 +0300
     3.2 +++ b/src/bdev.c	Thu Apr 17 17:03:30 2014 +0300
     3.3 @@ -40,11 +40,13 @@
     3.4  
     3.5  		bdev->offset = SECT_TO_BLK(plist->start_sect);
     3.6  		bdev->size = SECT_TO_BLK(plist->size_sect);
     3.7 +		bdev->ptype = get_part_type(plist);
     3.8  
     3.9  		free_part_list(plist);
    3.10  	} else {
    3.11  		bdev->offset = 0;
    3.12  		bdev->size = SECT_TO_BLK(ata_num_sectors(devno));
    3.13 +		bdev->ptype = 0;
    3.14  	}
    3.15  
    3.16  	return bdev;
    3.17 @@ -57,13 +59,13 @@
    3.18  
    3.19  #define NSECT	(BLKSZ / 512)
    3.20  
    3.21 -int blk_read(struct block_device *bdev, uint32_t blk, void *buf)
    3.22 +int blk_read(struct block_device *bdev, uint32_t blk, int count, void *buf)
    3.23  {
    3.24  	int i;
    3.25  	char *ptr = buf;
    3.26 -	uint32_t sect = blk * NSECT;
    3.27 +	uint32_t sect = blk * NSECT + bdev->offset;
    3.28  
    3.29 -	for(i=0; i<NSECT; i++) {
    3.30 +	for(i=0; i<NSECT * count; i++) {
    3.31  		if(ata_read_pio(bdev->ata_dev, sect++, ptr) == -1) {
    3.32  			return -1;
    3.33  		}
    3.34 @@ -72,13 +74,13 @@
    3.35  	return 0;
    3.36  }
    3.37  
    3.38 -int blk_write(struct block_device *bdev, uint32_t blk, void *buf)
    3.39 +int blk_write(struct block_device *bdev, uint32_t blk, int count, void *buf)
    3.40  {
    3.41  	int i;
    3.42  	char *ptr = buf;
    3.43 -	uint32_t sect = blk * NSECT;
    3.44 +	uint32_t sect = blk * NSECT + bdev->offset;
    3.45  
    3.46 -	for(i=0; i<NSECT; i++) {
    3.47 +	for(i=0; i<NSECT * count; i++) {
    3.48  		if(ata_write_pio(bdev->ata_dev, sect++, ptr) == -1) {
    3.49  			return -1;
    3.50  		}
    3.51 @@ -116,5 +118,5 @@
    3.52  	}
    3.53  
    3.54  	minor = MKMINOR(atadev, part);
    3.55 -	return DEVNO(0, minor);
    3.56 +	return DEVNO(1, minor);
    3.57  }
     4.1 --- a/src/bdev.h	Thu Apr 17 12:30:02 2014 +0300
     4.2 +++ b/src/bdev.h	Thu Apr 17 17:03:30 2014 +0300
     4.3 @@ -8,13 +8,19 @@
     4.4  struct block_device {
     4.5  	int ata_dev;
     4.6  	uint32_t offset, size;
     4.7 +
     4.8 +	/* Partition type (if the blkdev is a partition), otherwise 0.
     4.9 +	 * Used as just an extra sanity check to make sure we don't
    4.10 +	 * try to mount the wrong filesystem.
    4.11 +	 */
    4.12 +	int ptype;
    4.13  };
    4.14  
    4.15  struct block_device *blk_open(dev_t dev);
    4.16  void blk_close(struct block_device *bdev);
    4.17  
    4.18 -int blk_read(struct block_device *bdev, uint32_t blk, void *buf);
    4.19 -int blk_write(struct block_device *bdev, uint32_t blk, void *buf);
    4.20 +int blk_read(struct block_device *bdev, uint32_t blk, int count, void *buf);
    4.21 +int blk_write(struct block_device *bdev, uint32_t blk, int count, void *buf);
    4.22  
    4.23  dev_t bdev_by_name(const char *name);
    4.24  
     5.1 --- a/src/fs.c	Thu Apr 17 12:30:02 2014 +0300
     5.2 +++ b/src/fs.c	Thu Apr 17 17:03:30 2014 +0300
     5.3 @@ -1,120 +1,499 @@
     5.4 -/* This code is used by the kernel AND by userspace filesystem-related tools.
     5.5 - * The kernel-specific parts are conditionally compiled in #ifdef KERNEL blocks
     5.6 - * the rest of the code should be independent.
     5.7 +/* This code is used by the kernel AND by userspace filesystem-related tools. */
     5.8 +
     5.9 +/* XXX convention:
    5.10 + * - functions that accept or return a struct inode, do not read/write it to disk
    5.11 + * - functions that accept or return an int ino, do read/write it to disk
    5.12 + * other kinds of blocks (data, indirect, etc) always hit the disk directly.
    5.13   */
    5.14 +
    5.15  #include <stdio.h>
    5.16  #include <stdlib.h>
    5.17 +#include <string.h>
    5.18 +#include <errno.h>
    5.19  #include <assert.h>
    5.20 -#include <errno.h>
    5.21  #include "fs.h"
    5.22 -#include "part.h"
    5.23 +#include "bdev.h"
    5.24 +#include "kdef.h"
    5.25  
    5.26 -#ifdef KERNEL
    5.27 -#include "ata.h"
    5.28 -#include "panic.h"
    5.29 -#endif
    5.30 +/* number of inodes in a block */
    5.31 +#define BLK_INODES		(BLKSZ / sizeof(struct inode))
    5.32 +/* number of directory entries in a block */
    5.33 +#define BLK_DIRENT		(BLKSZ / sizeof(struct dir_entry))
    5.34  
    5.35 -struct filesys {
    5.36 -	int dev;
    5.37 -	struct partition part;
    5.38 +#define BLKBITS				(BLKSZ * 8)
    5.39  
    5.40 -	struct superblock *sb;
    5.41 +#define BM_IDX(x)			((x) / 32)
    5.42 +#define BM_BIT(x)			((x) & 0x1f)
    5.43  
    5.44 -	struct filesys *next;
    5.45 -};
    5.46 +#define BM_ISFREE(bm, x)	(((bm)[BM_IDX(x)] & (1 << BM_BIT(x))) == 0)
    5.47 +#define BM_SET(bm, x)		((bm)[BM_IDX(x)] |= (1 << BM_BIT(x)))
    5.48 +#define BM_CLR(bm, x)		((bm)[BM_IDX(x)] &= ~(1 << BM_BIT(x)))
    5.49  
    5.50 -static int find_rootfs(struct filesys *fs);
    5.51 -static int readblock(int dev, uint32_t blk, void *buf);
    5.52 -static int writeblock(int dev, uint32_t blk, void *buf);
    5.53  
    5.54 -/* root device & partition */
    5.55 -static struct filesys *fslist;
    5.56 +static struct inode *newdir(struct filesys *fs, struct inode *parent);
    5.57 +static int addlink(struct filesys *fs, struct inode *target, struct inode *node, const char *name);
    5.58 +static int read_superblock(struct filesys *fs);
    5.59 +static int write_superblock(struct filesys *fs);
    5.60 +static int get_inode(struct filesys *fs, int ino, struct inode *inode);
    5.61 +static int put_inode(struct filesys *fs, struct inode *inode);
    5.62 +static int find_free(uint32_t *bm, int sz);
    5.63 +static int alloc_inode(struct filesys *fs);
    5.64 +#define free_inode(fs, ino)		BM_CLR((fs)->sb->ibm, (ino))
    5.65 +static int alloc_block(struct filesys *fs);
    5.66 +#define free_block(fs, bno)		BM_CLR((fs)->sb->bm, (bno))
    5.67 +#define zero_block(fs, bno) \
    5.68 +	do { \
    5.69 +		assert(bno > 0); \
    5.70 +		blk_write((fs)->bdev, (bno), 1, (fs)->zeroblock); \
    5.71 +	} while(0)
    5.72  
    5.73 -int sys_mount(char *mtpt, char *devname, unsigned int flags)
    5.74 +static int file_block(struct filesys *fs, struct inode *node, int boffs, int allocate);
    5.75 +#define get_file_block(fs, node, boffs)		file_block(fs, node, boffs, 0)
    5.76 +#define alloc_file_block(fs, node, boffs)	file_block(fs, node, boffs, 1)
    5.77 +
    5.78 +
    5.79 +int openfs(struct filesys *fs, dev_t dev)
    5.80  {
    5.81 -	if(strcmp(mtpt, "/") != 0) {
    5.82 -		printf("mount: only root can be mounted at the moment\n");
    5.83 -		return -EBUG;
    5.84 +	int res;
    5.85 +	struct block_device *bdev;
    5.86 +
    5.87 +	assert(BLKSZ % sizeof(struct inode) == 0);
    5.88 +
    5.89 +	if(!(bdev = blk_open(dev))) {
    5.90 +		return -ENOENT;
    5.91 +	}
    5.92 +	fs->bdev = bdev;
    5.93 +
    5.94 +	/* read the superblock */
    5.95 +	if(!(fs->sb = malloc(BLKSZ))) {
    5.96 +		blk_close(bdev);
    5.97 +		return -ENOMEM;
    5.98 +	}
    5.99 +	if((res = read_superblock(fs)) != 0) {
   5.100 +		blk_close(bdev);
   5.101 +		return res;
   5.102  	}
   5.103  
   5.104 -	/* mounting root filesystem */
   5.105 -	if(fslist) {
   5.106 +	/* allocate the zero-block buffer written to zero-out blocks */
   5.107 +	if(!(fs->zeroblock = malloc(fs->sb->blksize))) {
   5.108 +		blk_close(bdev);
   5.109 +		free(fs->sb->ibm);
   5.110 +		free(fs->sb->bm);
   5.111 +		free(fs->sb->root);
   5.112 +		return -ENOMEM;
   5.113 +	}
   5.114 +	memset(fs->zeroblock, 0xff, fs->sb->blksize);
   5.115  
   5.116 +	return 0;
   5.117  }
   5.118  
   5.119 -void init_fs(void)
   5.120 +int mkfs(struct filesys *fs, dev_t dev)
   5.121  {
   5.122 -	root.sb = malloc(512);
   5.123 -	assert(root.sb);
   5.124 +	struct superblock *sb;
   5.125 +	struct block_device *bdev;
   5.126 +	int i, bcount;
   5.127  
   5.128 -#ifdef KERNEL
   5.129 -	if(find_rootfs(&root) == -1) {
   5.130 -		panic("can't find root filesystem\n");
   5.131 +	if(!(bdev = blk_open(dev))) {
   5.132 +		return -1;
   5.133  	}
   5.134 -#endif
   5.135 +	fs->bdev = bdev;
   5.136 +
   5.137 +	if(!(sb = malloc(BLKSZ))) {
   5.138 +		blk_close(bdev);
   5.139 +		return -1;
   5.140 +	}
   5.141 +	fs->sb = sb;
   5.142 +
   5.143 +	/* populate the superblock */
   5.144 +	sb->magic = MAGIC;
   5.145 +	sb->ver = FS_VER;
   5.146 +	sb->blksize = BLKSZ;
   5.147 +
   5.148 +	sb->num_blocks = bdev->size;
   5.149 +	sb->num_inodes = sb->num_blocks / 4;
   5.150 +
   5.151 +	/* inode bitmap just after the superblock */
   5.152 +	sb->ibm_start = 2;
   5.153 +	sb->ibm_count = (sb->num_inodes + BLKBITS - 1) / BLKBITS;
   5.154 +	/* also allocate and initialize in-memory inode bitmap */
   5.155 +	sb->ibm = malloc(sb->ibm_count * BLKSZ);
   5.156 +	assert(sb->ibm);
   5.157 +	memset(sb->ibm, 0, sb->ibm_count * BLKSZ);
   5.158 +
   5.159 +	/* XXX mark inode 0 as used always */
   5.160 +	BM_SET(sb->ibm, 0);
   5.161 +
   5.162 +	/* block bitmap just after the inode bitmap */
   5.163 +	sb->bm_start = sb->ibm_start + sb->ibm_count;
   5.164 +	sb->bm_count = (sb->num_blocks + BLKBITS - 1) / BLKBITS;
   5.165 +	/* also allocate and initialize in-memory block bitmap */
   5.166 +	sb->bm = malloc(sb->bm_count * BLKSZ);
   5.167 +	assert(sb->bm);
   5.168 +	memset(sb->bm, 0, sb->bm_count * BLKSZ);
   5.169 +
   5.170 +	/* inode table, just after the block bitmap */
   5.171 +	sb->itbl_start = sb->bm_start + sb->bm_count;
   5.172 +	sb->itbl_count = (sb->num_inodes * sizeof(struct inode) + BLKSZ - 1) / BLKSZ;
   5.173 +
   5.174 +	/* mark all used blocks as used */
   5.175 +	bcount = sb->itbl_start + sb->itbl_count;
   5.176 +	memset(sb->bm, 0xff, bcount / 8);
   5.177 +	for(i=0; i<bcount % 8; i++) {
   5.178 +		int bit = bcount / 8 + i;
   5.179 +		BM_SET(sb->bm, bit);
   5.180 +	}
   5.181 +
   5.182 +	/* create the root directory */
   5.183 +	sb->root = newdir(fs, 0);
   5.184 +	sb->root_ino = sb->root->ino;
   5.185 +	/* and write the inode to disk */
   5.186 +	put_inode(fs, sb->root);
   5.187 +
   5.188 +	return 0;
   5.189  }
   5.190  
   5.191 +static struct inode *newdir(struct filesys *fs, struct inode *parent)
   5.192 +{
   5.193 +	struct inode *dirnode;
   5.194  
   5.195 -#ifdef KERNEL
   5.196 -#define PART_TYPE	0xcc
   5.197 -static int find_rootfs(struct filesys *fs)
   5.198 +	/* allocate and initialize inode */
   5.199 +	if(!(dirnode = malloc(sizeof *dirnode))) {
   5.200 +		return 0;
   5.201 +	}
   5.202 +	memset(dirnode, 0, sizeof *dirnode);
   5.203 +
   5.204 +	if((dirnode->ino = alloc_inode(fs)) == -1) {
   5.205 +		printf("failed to allocate inode for a new directory\n");
   5.206 +		free(dirnode);
   5.207 +		return 0;
   5.208 +	}
   5.209 +	dirnode->mode = S_IFDIR;
   5.210 +
   5.211 +	/* add . and .. links */
   5.212 +	addlink(fs, dirnode, dirnode, ".");
   5.213 +	addlink(fs, dirnode, parent ? parent : dirnode, "..");
   5.214 +
   5.215 +	return dirnode;
   5.216 +}
   5.217 +
   5.218 +static int addlink(struct filesys *fs, struct inode *target, struct inode *node, const char *name)
   5.219  {
   5.220 -	int i, num_dev, partid;
   5.221 -	struct partition *plist, *p;
   5.222 +	struct dir_entry ent, *data;
   5.223 +	int i, boffs, bidx, len;
   5.224  
   5.225 -	num_dev = ata_num_devices();
   5.226 -	for(i=0; i<num_dev; i++) {
   5.227 -		plist = p = get_part_list(i);
   5.228 +	if(!(target->mode & S_IFDIR)) {
   5.229 +		return -ENOTDIR;
   5.230 +	}
   5.231 +	if(node->mode & S_IFDIR) {
   5.232 +		return -EPERM;
   5.233 +	}
   5.234 +	/* TODO check that the link does not already exist (EEXIST) */
   5.235  
   5.236 -		partid = 0;
   5.237 -		while(p) {
   5.238 -			if(get_part_type(p) == PART_TYPE) {
   5.239 -				/* found the correct partition, now read the superblock
   5.240 -				 * and make sure it's got the correct magic id
   5.241 -				 */
   5.242 -				readblock(i, p->start_sect / 2 + 1, fs->sb);
   5.243 +	if((len = strlen(name)) > NAME_MAX) {
   5.244 +		return -ENAMETOOLONG;
   5.245 +	}
   5.246 +	ent.ino = node->ino;
   5.247 +	memcpy(ent.name, name, len + 1);
   5.248  
   5.249 -				if(fs->sb->magic == MAGIC) {
   5.250 -					printf("found root ata%dp%d\n", i, partid);
   5.251 -					fs->dev = i;
   5.252 -					fs->part = *p;
   5.253 -					return 0;
   5.254 +	/* find a place to put it */
   5.255 +	if(!(data = malloc(BLKSZ))) {
   5.256 +		return -ENOMEM;
   5.257 +	}
   5.258 +
   5.259 +	boffs = 0;
   5.260 +	while((bidx = get_file_block(fs, target, boffs)) > 0) {
   5.261 +		/* read the block, and search for an empty entry */
   5.262 +		blk_read(fs->bdev, bidx, 1, data);
   5.263 +
   5.264 +		/* for all directory entries in this block... */
   5.265 +		for(i=0; i<BLK_DIRENT; i++) {
   5.266 +			if(data[i].ino == 0) {
   5.267 +				/* found empty */
   5.268 +				memcpy(data + i, &ent, sizeof ent);
   5.269 +				goto success;
   5.270 +			}
   5.271 +		}
   5.272 +		boffs++;
   5.273 +	}
   5.274 +
   5.275 +	/* didn't find any free entries amongst our blocks, allocate a new one */
   5.276 +	if(!(bidx = alloc_file_block(fs, target, boffs))) {
   5.277 +		free(data);
   5.278 +		return -ENOSPC;
   5.279 +	}
   5.280 +	/* zero-fill the new block and add the first entry */
   5.281 +	memset(data, 0, BLKSZ);
   5.282 +	*data = ent;
   5.283 +
   5.284 +success:
   5.285 +	/* write to disk */
   5.286 +	blk_write(fs->bdev, bidx, 1, data);
   5.287 +	node->nlink++;	/* increase reference count */
   5.288 +
   5.289 +	free(data);
   5.290 +	return 0;
   5.291 +}
   5.292 +
   5.293 +
   5.294 +static int read_superblock(struct filesys *fs)
   5.295 +{
   5.296 +	struct superblock *sb = fs->sb;
   5.297 +
   5.298 +	/* read superblock and verify */
   5.299 +	if(blk_read(fs->bdev, 1, 1, sb) == -1) {
   5.300 +		printf("failed to read superblock\n");
   5.301 +		return -EIO;
   5.302 +	}
   5.303 +	if(sb->magic != MAGIC) {
   5.304 +		printf("invalid magic\n");
   5.305 +		return -EINVAL;
   5.306 +	}
   5.307 +	if(sb->ver > FS_VER) {
   5.308 +		printf("invalid version: %d\n", sb->ver);
   5.309 +		return -EINVAL;
   5.310 +	}
   5.311 +	if(sb->blksize != BLKSZ) {
   5.312 +		printf("invalid block size: %d\n", sb->blksize);
   5.313 +		return -EINVAL;
   5.314 +	}
   5.315 +
   5.316 +	/* allocate and populate in-memory bitmaps */
   5.317 +	if(!(sb->ibm = malloc(sb->ibm_count * sb->blksize))) {
   5.318 +		return -ENOMEM;
   5.319 +	}
   5.320 +	if(blk_read(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) {
   5.321 +		printf("failed to read inode bitmap\n");
   5.322 +		free(sb->ibm);
   5.323 +		return -EIO;
   5.324 +	}
   5.325 +	if(!(sb->bm = malloc(sb->bm_count * sb->blksize))) {
   5.326 +		free(sb->ibm);
   5.327 +		return -ENOMEM;
   5.328 +	}
   5.329 +	if(blk_read(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) {
   5.330 +		printf("failed to read block bitmap\n");
   5.331 +		free(sb->ibm);
   5.332 +		free(sb->bm);
   5.333 +		return -EIO;
   5.334 +	}
   5.335 +
   5.336 +	/* read the root inode */
   5.337 +	if(!(sb->root = malloc(sizeof *sb->root))) {
   5.338 +		free(sb->ibm);
   5.339 +		free(sb->bm);
   5.340 +		return -ENOMEM;
   5.341 +	}
   5.342 +	if(get_inode(fs, sb->root_ino, sb->root) == -1) {
   5.343 +		printf("failed to read root inode\n");
   5.344 +		return -1;
   5.345 +	}
   5.346 +
   5.347 +	return 0;
   5.348 +}
   5.349 +
   5.350 +static int write_superblock(struct filesys *fs)
   5.351 +{
   5.352 +	struct superblock *sb = fs->sb;
   5.353 +
   5.354 +	/* write back any changes in the root inode */
   5.355 +	if(put_inode(fs, sb->root) == -1) {
   5.356 +		return -1;
   5.357 +	}
   5.358 +	/* write back the block bitmap */
   5.359 +	if(blk_write(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) {
   5.360 +		return -1;
   5.361 +	}
   5.362 +	/* write back the inode bitmap */
   5.363 +	if(blk_write(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) {
   5.364 +		return -1;
   5.365 +	}
   5.366 +	/* write the superblock itself */
   5.367 +	if(blk_write(fs->bdev, 1, 1, sb) == -1) {
   5.368 +		return -1;
   5.369 +	}
   5.370 +	return 0;
   5.371 +}
   5.372 +
   5.373 +/* copy the requested inode from the disk, into the buffer passed in the last arg */
   5.374 +static int get_inode(struct filesys *fs, int ino, struct inode *inode)
   5.375 +{
   5.376 +	struct inode *buf = malloc(BLKSZ);
   5.377 +	assert(buf);
   5.378 +
   5.379 +	if(blk_read(fs->bdev, fs->sb->itbl_start + ino / BLK_INODES, 1, buf) == -1) {
   5.380 +		free(buf);
   5.381 +		return -1;
   5.382 +	}
   5.383 +	memcpy(inode, buf + ino % BLK_INODES, sizeof *inode);
   5.384 +	free(buf);
   5.385 +	return 0;
   5.386 +}
   5.387 +
   5.388 +/* write the inode to the disk */
   5.389 +static int put_inode(struct filesys *fs, struct inode *inode)
   5.390 +{
   5.391 +	struct inode *buf = malloc(BLKSZ);
   5.392 +	assert(buf);
   5.393 +
   5.394 +	if(blk_read(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) {
   5.395 +		free(buf);
   5.396 +		return -1;
   5.397 +	}
   5.398 +	memcpy(buf + inode->ino % BLK_INODES, inode, sizeof *inode);
   5.399 +
   5.400 +	if(blk_write(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) {
   5.401 +		free(buf);
   5.402 +		return -1;
   5.403 +	}
   5.404 +	free(buf);
   5.405 +	return 0;
   5.406 +}
   5.407 +
   5.408 +/* find a free element in the bitmap and return its number */
   5.409 +static int find_free(uint32_t *bm, int nbits)
   5.410 +{
   5.411 +	int i, j, nwords = nbits / 32;
   5.412 +	uint32_t ent = 0;
   5.413 +
   5.414 +	for(i=0; i<=nwords; i++) {
   5.415 +		if(bm[i] != 0xffffffff) {
   5.416 +			for(j=0; j<32; j++) {
   5.417 +				if(BM_ISFREE(bm, ent)) {
   5.418 +					return ent;
   5.419  				}
   5.420 +				ent++;
   5.421  			}
   5.422 -			p = p->next;
   5.423 -			partid++;
   5.424 +
   5.425 +			panic("shouldn't happen (in find_free:fs.c)");
   5.426 +		} else {
   5.427 +			ent += 32;
   5.428  		}
   5.429 -		free_part_list(plist);
   5.430  	}
   5.431 +
   5.432  	return -1;
   5.433  }
   5.434  
   5.435 -#define NSECT	(BLKSZ / 512)
   5.436 +static int alloc_inode(struct filesys *fs)
   5.437 +{
   5.438 +	int ino;
   5.439  
   5.440 -static int readblock(struct block_device *bdev, uint32_t blk, void *buf)
   5.441 -{
   5.442 -	return blk_read(bdev, blk, buf);
   5.443 +	if((ino = find_free(fs->sb->ibm, fs->sb->num_inodes)) == -1) {
   5.444 +		return -1;
   5.445 +	}
   5.446 +	BM_SET(fs->sb->ibm, ino);
   5.447 +	return 0;
   5.448  }
   5.449  
   5.450 -static int writeblock(struct block_device *bdev, uint32_t blk, void *buf)
   5.451 +static int alloc_block(struct filesys *fs)
   5.452  {
   5.453 -	return blk_write(bdev, blk, buf);
   5.454 -}
   5.455 -#else
   5.456 +	int bno;
   5.457  
   5.458 -/* if this is compiled as part of the user-space tools instead of the kernel
   5.459 - * forward the call to a user read/write block function supplied by the app.
   5.460 - */
   5.461 -int user_readblock(uint32_t, void*);
   5.462 -int user_writeblock(uint32_t, void*);
   5.463 -
   5.464 -static int readblock(struct block_device *bdev, uint32_t blk, void *buf)
   5.465 -{
   5.466 -	return user_readblock(blk, buf);
   5.467 +	if((bno = find_free(fs->sb->bm, fs->sb->num_blocks)) == -1) {
   5.468 +		return -1;
   5.469 +	}
   5.470 +	BM_SET(fs->sb->bm, bno);
   5.471 +	return 0;
   5.472  }
   5.473  
   5.474 -static int writeblock(struct block_device *bdev, uint32_t blk, void *buf)
   5.475 +#define BLK_BLKID	(BLKSZ / sizeof(blkid))
   5.476 +#define MAX_IND		(NDIRBLK + BLK_BLKID)
   5.477 +#define MAX_DIND	(MAX_IND + BLK_BLKID * BLK_BLKID)
   5.478 +
   5.479 +static int file_block(struct filesys *fs, struct inode *node, int boffs, int allocate)
   5.480  {
   5.481 -	return user_writeblock(blk, buf);
   5.482 +	int res, idx, node_dirty = 0;
   5.483 +	blkid *barr;
   5.484 +
   5.485 +	/* out of bounds */
   5.486 +	if(boffs < 0 || boffs >= MAX_DIND) {
   5.487 +		return 0;
   5.488 +	}
   5.489 +
   5.490 +	/* is it a direct block ? */
   5.491 +	if(boffs < NDIRBLK) {
   5.492 +		if(!(res = node->blk[boffs]) && allocate) {
   5.493 +			res = node->blk[boffs] = alloc_block(fs);
   5.494 +			if(res) {
   5.495 +				zero_block(fs, res);
   5.496 +				/* also write back the modified inode */
   5.497 +				put_inode(fs, node);
   5.498 +			}
   5.499 +		}
   5.500 +		return res;
   5.501 +	}
   5.502 +
   5.503 +	barr = malloc(fs->sb->blksize);
   5.504 +	assert(barr);
   5.505 +
   5.506 +	/* is it an indirect block ? */
   5.507 +	if(boffs < MAX_IND) {
   5.508 +		int ind_dirty = 0;
   5.509 +
   5.510 +		if(node->ind) {
   5.511 +			/* read the indirect block */
   5.512 +			blk_read(fs->bdev, node->ind, 1, barr);
   5.513 +		} else {
   5.514 +			/* does not exist... try to allocate if requested */
   5.515 +			if(!allocate || !(node->ind = alloc_block(fs))) {
   5.516 +				res = 0;
   5.517 +				goto end;
   5.518 +			}
   5.519 +
   5.520 +			/* allocated a block clear the buffer, and invalidate everything */
   5.521 +			memset(barr, 0, sizeof fs->sb->blksize);
   5.522 +			node_dirty = 1;
   5.523 +			ind_dirty = 1;
   5.524 +		}
   5.525 +
   5.526 +		idx = boffs - NDIRBLK;
   5.527 +
   5.528 +		if(!(res = barr[idx])) {
   5.529 +			if(allocate && (res = barr[idx] = alloc_block(fs))) {
   5.530 +				ind_dirty = 1;
   5.531 +			}
   5.532 +		}
   5.533 +
   5.534 +		/* write back the indirect block if needed */
   5.535 +		if(ind_dirty) {
   5.536 +			blk_write(fs->bdev, node->ind, 1, barr);
   5.537 +		}
   5.538 +		goto end;
   5.539 +	}
   5.540 +
   5.541 +	/* TODO check/rewrite this */
   5.542 +#if 0
   5.543 +	/* is it a double-indirect block ? */
   5.544 +	if(boffs < MAX_DIND) {
   5.545 +		/* first read the dind block and find the index of the ind block */
   5.546 +		if(!node->dind) {
   5.547 +			if(allocate) {
   5.548 +				/* allocate and zero-out the double indirect block */
   5.549 +				res = node->dind = alloc_block(fs);
   5.550 +				if(res) {
   5.551 +					zero_block(fs, res);
   5.552 +				}
   5.553 +			} else {
   5.554 +				res = 0;
   5.555 +				goto end;
   5.556 +			}
   5.557 +		}
   5.558 +		blk_read(fd->bdev, node->dind, 1, barr);
   5.559 +		idx = (boffs - MAX_IND) / BLK_BLKID;
   5.560 +
   5.561 +		/* then read the ind block and find the index of the block */
   5.562 +		if(!barr[idx]) {
   5.563 +			res = 0;
   5.564 +			goto end;
   5.565 +		}
   5.566 +		blk_read(fd->bdev, barr[idx], 1, barr);
   5.567 +		res = barr[(boffs - MAX_IND) % BLK_BLKID];
   5.568 +	}
   5.569 +#endif
   5.570 +
   5.571 +end:
   5.572 +	if(node_dirty) {
   5.573 +		put_inode(fs, node);
   5.574 +	}
   5.575 +	free(barr);
   5.576 +	return res;
   5.577  }
   5.578 -#endif	/* KERNEL */
     6.1 --- a/src/fs.h	Thu Apr 17 12:30:02 2014 +0300
     6.2 +++ b/src/fs.h	Thu Apr 17 17:03:30 2014 +0300
     6.3 @@ -3,8 +3,12 @@
     6.4  
     6.5  #include <inttypes.h>
     6.6  
     6.7 -#define MAGIC	0xccf5ccf5
     6.8 -#define BLKSZ	1024
     6.9 +#define MAGIC		0xccf5ccf5
    6.10 +#define FS_VER		1
    6.11 +#define BLKSZ		1024
    6.12 +
    6.13 +#define NAME_MAX	27	/* +1 termin. +4 ino = 32 per dirent */
    6.14 +#define PATH_MAX	256
    6.15  
    6.16  #define SECT_TO_BLK(x)	((x) / (BLKSZ / 512))
    6.17  
    6.18 @@ -16,34 +20,6 @@
    6.19  typedef uint32_t dev_t;
    6.20  typedef uint32_t blkid;
    6.21  
    6.22 -struct superblock {
    6.23 -	uint32_t magic;	/* magic number */
    6.24 -	int ver;		/* filesystem version */
    6.25 -	int blksize;	/* only BLKSZ supported at the moment */
    6.26 -
    6.27 -	/* total number of blocks */
    6.28 -	unsigned int num_blocks;
    6.29 -	/* inode allocation bitmap start and count */
    6.30 -	blkid ibm_start;
    6.31 -	unsigned int ibm_count;
    6.32 -	/* inode table start and count */
    6.33 -	blkid itbl_start;
    6.34 -	unsigned int itbl_count;
    6.35 -	/* data block allocation bitmap start and count */
    6.36 -	blkid dbm_start;
    6.37 -	unsigned int dbm_count;
    6.38 -	/* data blocks start and count */
    6.39 -	blkid data_start;
    6.40 -	unsigned int data_count;
    6.41 -
    6.42 -	int root_ino;	/* root direcotry inode */
    6.43 -
    6.44 -	/* the following are valid only at runtime, ignored on disk */
    6.45 -	uint32_t *ibm;	/* memory inode bitmap */
    6.46 -	uint32_t *dbm;	/* memory datablock bitmap */
    6.47 -
    6.48 -} __attribute__((packed));
    6.49 -
    6.50  
    6.51  /* 20 direct blocks + 10 attributes + 2 indirect = 128 bytes per inode */
    6.52  #define NDIRBLK	20
    6.53 @@ -59,7 +35,59 @@
    6.54  	blkid dind;			/* double-indirect */
    6.55  } __attribute__((packed));
    6.56  
    6.57 +struct dir_entry {
    6.58 +	int ino;
    6.59 +	char name[NAME_MAX + 1];
    6.60 +} __attribute__((packed));
    6.61  
    6.62 +struct superblock {
    6.63 +	uint32_t magic;	/* magic number */
    6.64 +	int ver;		/* filesystem version */
    6.65 +	int blksize;	/* only BLKSZ supported at the moment */
    6.66 +
    6.67 +	/* total number of blocks */
    6.68 +	unsigned int num_blocks;
    6.69 +	/* total number of inodes */
    6.70 +	unsigned int num_inodes;
    6.71 +
    6.72 +	/* inode allocation bitmap start and count */
    6.73 +	blkid ibm_start;
    6.74 +	unsigned int ibm_count;
    6.75 +	/* inode table start and count */
    6.76 +	blkid itbl_start;
    6.77 +	unsigned int itbl_count;
    6.78 +	/* block allocation bitmap start and count */
    6.79 +	blkid bm_start;
    6.80 +	unsigned int bm_count;
    6.81 +
    6.82 +	int root_ino;	/* root direcotry inode number */
    6.83 +
    6.84 +	/* the following are valid only at runtime, ignored on disk */
    6.85 +	uint32_t *ibm;	/* in-memory inode bitmap */
    6.86 +	uint32_t *bm;	/* in-memory block bitmap */
    6.87 +	struct inode *root;	/* in-memory root inode */
    6.88 +
    6.89 +} __attribute__((packed));
    6.90 +
    6.91 +
    6.92 +
    6.93 +struct filesys {
    6.94 +	struct block_device *bdev;
    6.95 +
    6.96 +	struct superblock *sb;
    6.97 +
    6.98 +	void *zeroblock;
    6.99 +
   6.100 +	struct filesys *next;
   6.101 +};
   6.102 +
   6.103 +/* defined in fs.c */
   6.104 +int openfs(struct filesys *fs, dev_t dev);
   6.105 +int mkfs(struct filesys *fs, dev_t dev);
   6.106 +void closefs(struct filesys *fs);
   6.107 +int find_inode(const char *path);
   6.108 +
   6.109 +/* defined in fs_sys.c */
   6.110  int sys_mount(char *mntpt, char *devname, unsigned int flags);
   6.111  int sys_umount(char *devname);
   6.112  
   6.113 @@ -70,7 +98,5 @@
   6.114  int sys_write(int fd, void *buf, int sz);
   6.115  long sys_lseek(int fd, long offs, int from);
   6.116  
   6.117 -int lookup_path(const char *path);
   6.118 -
   6.119  
   6.120  #endif	/* FS_H_ */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/fs_sys.c	Thu Apr 17 17:03:30 2014 +0300
     7.3 @@ -0,0 +1,105 @@
     7.4 +/* implementation of the filesystem-related syscalls */
     7.5 +
     7.6 +#include <stdio.h>
     7.7 +#include <stdlib.h>
     7.8 +#include <string.h>
     7.9 +#include <assert.h>
    7.10 +#include <errno.h>
    7.11 +#include "fs.h"
    7.12 +#include "part.h"
    7.13 +#include "panic.h"
    7.14 +#include "bdev.h"
    7.15 +
    7.16 +static dev_t find_rootfs(void);
    7.17 +
    7.18 +/* list of mounted filesystems
    7.19 + * XXX currently only one, the root filesystem
    7.20 + */
    7.21 +static struct filesys *fslist;
    7.22 +
    7.23 +
    7.24 +int sys_mount(char *mtpt, char *devname, unsigned int flags)
    7.25 +{
    7.26 +	dev_t dev;
    7.27 +	int err;
    7.28 +	struct filesys *fs;
    7.29 +
    7.30 +	if(strcmp(mtpt, "/") != 0) {
    7.31 +		printf("only root can be mounted at the moment\n");
    7.32 +		return -EBUG;
    7.33 +	}
    7.34 +
    7.35 +	/* mounting root filesystem */
    7.36 +	if(fslist) {
    7.37 +		printf("root already mounted\n");
    7.38 +		return -EBUSY;
    7.39 +	}
    7.40 +
    7.41 +	if(devname) {
    7.42 +		dev = bdev_by_name(devname);
    7.43 +	} else {
    7.44 +		/* try to autodetect it */
    7.45 +		dev = find_rootfs();
    7.46 +	}
    7.47 +	if(!dev) {
    7.48 +		err = -ENOENT;
    7.49 +		goto rootfail;
    7.50 +	}
    7.51 +
    7.52 +	if(!(fs = malloc(sizeof *fslist))) {
    7.53 +		err = -ENOMEM;
    7.54 +		goto rootfail;
    7.55 +	}
    7.56 +	if((err = openfs(fs, dev)) != 0) {
    7.57 +		free(fs);
    7.58 +		goto rootfail;
    7.59 +	}
    7.60 +
    7.61 +	fslist = fs;
    7.62 +	return 0;
    7.63 +
    7.64 +rootfail:
    7.65 +	panic("failed to mount root filesystem: %d\n", -err);
    7.66 +	return err;	/* unreachable */
    7.67 +}
    7.68 +
    7.69 +#define PART_TYPE	0xcc
    7.70 +static dev_t find_rootfs(void)
    7.71 +{
    7.72 +	dev_t dev = 0;
    7.73 +	int i, num_dev, partid;
    7.74 +	struct partition *plist, *p;
    7.75 +	struct superblock *sb = malloc(BLKSZ);
    7.76 +	char name[16];
    7.77 +
    7.78 +	assert(sb);
    7.79 +
    7.80 +	num_dev = ata_num_devices();
    7.81 +	for(i=0; i<num_dev; i++) {
    7.82 +		plist = p = get_part_list(i);
    7.83 +
    7.84 +		partid = 0;
    7.85 +		while(p) {
    7.86 +			if(get_part_type(p) == PART_TYPE) {
    7.87 +				/* found the correct partition, now read the superblock
    7.88 +				 * and make sure it's got the correct magic id
    7.89 +				 */
    7.90 +				blk_read(i, p->start_sect / 2 + 1, BLKSZ, sb);
    7.91 +
    7.92 +				if(sb->magic == MAGIC) {
    7.93 +					sprintf(name, "ata%dp%d", i, partid);
    7.94 +					printf("found root: %s\n", name);
    7.95 +					dev = bdev_by_name(name);
    7.96 +					break;
    7.97 +				}
    7.98 +			}
    7.99 +			p = p->next;
   7.100 +			partid++;
   7.101 +		}
   7.102 +		free_part_list(plist);
   7.103 +		if(dev) break;
   7.104 +	}
   7.105 +
   7.106 +	free(sb);
   7.107 +	return dev;
   7.108 +}
     8.1 --- a/src/proc.c	Thu Apr 17 12:30:02 2014 +0300
     8.2 +++ b/src/proc.c	Thu Apr 17 17:03:30 2014 +0300
     8.3 @@ -77,6 +77,8 @@
     8.4  	p->id = 1;
     8.5  	p->parent = 0;	/* no parent for init */
     8.6  
     8.7 +	p->umask = 022;
     8.8 +
     8.9  	p->ticks_left = TIMESLICE_TICKS;
    8.10  	p->next = p->prev = 0;
    8.11  
    8.12 @@ -168,6 +170,8 @@
    8.13  	/* copy file table */
    8.14  	memcpy(p->files, parent->files, sizeof p->files);
    8.15  
    8.16 +	p->umask = parent->umask;
    8.17 +
    8.18  	/* allocate a kernel stack for the new process */
    8.19  	if((p->kern_stack_pg = pgalloc(KERN_STACK_SIZE / PGSIZE, MEM_KERNEL)) == -1) {
    8.20  		return -EAGAIN;
     9.1 --- a/src/proc.h	Thu Apr 17 12:30:02 2014 +0300
     9.2 +++ b/src/proc.h	Thu Apr 17 17:03:30 2014 +0300
     9.3 @@ -51,6 +51,8 @@
     9.4  	/* open files */
     9.5  	struct file files[MAX_FD];
     9.6  
     9.7 +	unsigned int umask;
     9.8 +
     9.9  	struct process *child_list;
    9.10  
    9.11  	struct process *next, *prev;	/* for the scheduler queues */