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 */