kern
changeset 96:07fe6a614185
filesystem
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 15 Dec 2011 04:39:00 +0200 |
parents | ec62cbe00b55 |
children | 8717eb590727 |
files | include/kdef.h src/fs.c src/fs.h src/proc.c src/proc.h |
diffstat | 5 files changed, 314 insertions(+), 31 deletions(-) [+] |
line diff
1.1 --- a/include/kdef.h Sun Dec 11 21:15:35 2011 +0200 1.2 +++ b/include/kdef.h Thu Dec 15 04:39:00 2011 +0200 1.3 @@ -31,13 +31,16 @@ 1.4 #if defined(KERNEL) || defined(KDEF_ERRNO_H) 1.5 #define EFOO 1 /* I just like to return -1 some times :) */ 1.6 1.7 -#define EAGAIN 2 1.8 -#define EINVAL 3 1.9 -#define ECHILD 4 1.10 -#define EBUSY 5 1.11 -#define ENOMEM 6 1.12 -#define EIO 7 1.13 -#define ENOENT 8 1.14 +#define EAGAIN 2 1.15 +#define EINVAL 3 1.16 +#define ECHILD 4 1.17 +#define EBUSY 5 1.18 +#define ENOMEM 6 1.19 +#define EIO 7 1.20 +#define ENOENT 8 1.21 +#define ENAMETOOLONG 9 1.22 +#define ENOSPC 10 1.23 +#define EPERM 11 1.24 1.25 #define EBUG 127 /* for missing features and known bugs */ 1.26 #endif /* errno.h */ 1.27 @@ -68,4 +71,36 @@ 1.28 1.29 #endif /* syscall.h */ 1.30 1.31 +/* --- defines for sys/stat.h */ 1.32 +#if defined(KERNEL) || defined(STAT_H) 1.33 + 1.34 +#define S_IFMT 0170000 /* bit mask for the file type bit fields */ 1.35 +#define S_IFSOCK 0140000 /* socket */ 1.36 +#define S_IFLNK 0120000 /* symbolic link */ 1.37 +#define S_IFREG 0100000 /* regular file */ 1.38 +#define S_IFBLK 0060000 /* block device */ 1.39 +#define S_IFDIR 0040000 /* directory */ 1.40 +#define S_IFCHR 0020000 /* character device */ 1.41 +#define S_IFIFO 0010000 /* FIFO */ 1.42 + 1.43 +#define S_ISUID 0004000 /* set UID bit */ 1.44 +#define S_ISGID 0002000 /* set-group-ID bit (see below) */ 1.45 +#define S_ISVTX 0001000 /* sticky bit (see below) */ 1.46 + 1.47 +#define S_IRWXU 00700 /* mask for file owner permissions */ 1.48 +#define S_IRUSR 00400 /* owner has read permission */ 1.49 +#define S_IWUSR 00200 /* owner has write permission */ 1.50 +#define S_IXUSR 00100 /* owner has execute permission */ 1.51 +#define S_IRWXG 00070 /* mask for group permissions */ 1.52 +#define S_IRGRP 00040 /* group has read permission */ 1.53 +#define S_IWGRP 00020 /* group has write permission */ 1.54 +#define S_IXGRP 00010 /* group has execute permission */ 1.55 +#define S_IRWXO 00007 /* mask for permissions for others (not in group) */ 1.56 +#define S_IROTH 00004 /* others have read permission */ 1.57 +#define S_IWOTH 00002 /* others have write permission */ 1.58 +#define S_IXOTH 00001 /* others have execute permission */ 1.59 + 1.60 +#endif /* sys/stat.h */ 1.61 + 1.62 + 1.63 #endif /* KERNEL_DEFS_H_ */
2.1 --- a/src/fs.c Sun Dec 11 21:15:35 2011 +0200 2.2 +++ b/src/fs.c Thu Dec 15 04:39:00 2011 +0200 2.3 @@ -1,7 +1,4 @@ 2.4 -/* This code is used by the kernel AND by userspace filesystem-related tools. 2.5 - * The kernel-specific parts are conditionally compiled in #ifdef KERNEL blocks 2.6 - * the rest of the code should be independent. 2.7 - */ 2.8 +/* This code is used by the kernel AND by userspace filesystem-related tools. */ 2.9 #include <stdio.h> 2.10 #include <stdlib.h> 2.11 #include <string.h> 2.12 @@ -9,6 +6,14 @@ 2.13 #include <assert.h> 2.14 #include "fs.h" 2.15 #include "bdev.h" 2.16 +#include "kdef.h" 2.17 + 2.18 +/* number of inodes in a block */ 2.19 +#define BLK_INODES (BLKSZ / sizeof(struct inode)) 2.20 +/* number of directory entries in a block */ 2.21 +#define BLK_DIRENT (BLKSZ / sizeof(struct dir_entry)) 2.22 + 2.23 +#define BLKBITS (BLKSZ * 8) 2.24 2.25 #define BM_IDX(x) ((x) / 32) 2.26 #define BM_BIT(x) ((x) & 0x1f) 2.27 @@ -18,11 +23,18 @@ 2.28 #define BM_CLR(bm, x) ((bm)[BM_IDX(x)] &= ~(1 << BM_BIT(x))) 2.29 2.30 2.31 -int openfs(struct filesys *fs, dev_t dev); 2.32 +static struct inode *newdir(struct filesys *fs, struct inode *parent); 2.33 +static int addlink(struct filesys *fs, struct inode *target, struct inode *node, const char *name); 2.34 static int read_superblock(struct filesys *fs); 2.35 static int write_superblock(struct filesys *fs); 2.36 static int get_inode(struct filesys *fs, int ino, struct inode *inode); 2.37 static int put_inode(struct filesys *fs, struct inode *inode); 2.38 +static int find_free(uint32_t *bm, int sz); 2.39 +static int alloc_inode(struct filesys *fs); 2.40 +static void free_inode(struct filesys *fs, int ino); 2.41 +static int alloc_block(struct filesys *fs); 2.42 +static void free_block(struct filesys *fs, int ino); 2.43 +static int file_block(struct filesys *fs, struct inode *node, int boffs); 2.44 2.45 int openfs(struct filesys *fs, dev_t dev) 2.46 { 2.47 @@ -38,19 +50,164 @@ 2.48 2.49 /* read the superblock */ 2.50 if(!(fs->sb = malloc(BLKSZ))) { 2.51 - res = -ENOMEM; 2.52 - goto done; 2.53 + blk_close(bdev); 2.54 + return -ENOMEM; 2.55 } 2.56 if((res = read_superblock(fs)) != 0) { 2.57 - goto done; 2.58 + blk_close(bdev); 2.59 + return res; 2.60 } 2.61 2.62 + return 0; 2.63 +} 2.64 2.65 -done: 2.66 - blk_close(bdev); 2.67 - return res; 2.68 +int mkfs(struct filesys *fs, dev_t dev) 2.69 +{ 2.70 + struct filesys *fs; 2.71 + struct superblock *sb; 2.72 + struct block_device *bdev; 2.73 + int i, bcount; 2.74 + 2.75 + if(!(bdev = blk_open(dev))) { 2.76 + return -1; 2.77 + } 2.78 + fs->bdev = bdev; 2.79 + 2.80 + if(!(sb = malloc(BLKSZ))) { 2.81 + blk_close(bdev); 2.82 + return -1; 2.83 + } 2.84 + fs->sb = sb; 2.85 + 2.86 + /* populate the superblock */ 2.87 + sb->magic = MAGIC; 2.88 + sb->ver = FS_VER; 2.89 + sb->blksize = BLKSZ; 2.90 + 2.91 + sb->num_blocks = bdev->size; 2.92 + sb->num_inodes = sb->num_blocks / 4; 2.93 + 2.94 + /* inode bitmap just after the superblock */ 2.95 + sb->ibm_start = 2; 2.96 + sb->ibm_count = (sb->num_inodes + BLKBITS - 1) / BLKBITS; 2.97 + /* also allocate and initialize in-memory inode bitmap */ 2.98 + sb->ibm = malloc(sb->ibm_count * BLKSZ); 2.99 + assert(sb->ibm); 2.100 + memset(sb->ibm, 0, sb->ibm_count * BLKSZ); 2.101 + 2.102 + /* XXX mark inode 0 as used always */ 2.103 + BM_SET(sb->ibm, 0); 2.104 + 2.105 + /* block bitmap just after the inode bitmap */ 2.106 + sb->bm_start = sb->ibm_start + sb->ibm_count; 2.107 + sb->bm_count = (sb->num_blocks + BLKBITS - 1) / BLKBITS; 2.108 + /* also allocate and initialize in-memory block bitmap */ 2.109 + sb->bm = malloc(sb->bm_count * BLKSZ); 2.110 + assert(sb->bm); 2.111 + memset(sb->bm, 0, sb->bm_count * BLKSZ); 2.112 + 2.113 + /* inode table, just after the block bitmap */ 2.114 + sb->itbl_start = sb->bm_start + sb->bm_count; 2.115 + sb->itbl_count = (sb->num_inodes * sizeof(struct inode) + BLKSZ - 1) / BLKSZ; 2.116 + 2.117 + /* mark all used blocks as used */ 2.118 + bcount = sb->itbl_start + sb->itbl_count; 2.119 + memset(sb->bm, 0xff, bcount / 8); 2.120 + for(i=0; i<bcount % 8; i++) { 2.121 + int bit = bcount / 8 + i; 2.122 + BM_SET(sb->bm, bit); 2.123 + } 2.124 + 2.125 + /* create the root directory */ 2.126 + sb->root = newdir(fs, 0); 2.127 + sb->root_ino = sb->root->ino; 2.128 } 2.129 2.130 +static struct inode *newdir(struct filesys *fs, struct inode *parent) 2.131 +{ 2.132 + struct inode *dirnode; 2.133 + 2.134 + /* allocate and initialize inode */ 2.135 + if(!(dirnode = malloc(sizeof *dirnode))) { 2.136 + return 0; 2.137 + } 2.138 + memset(dirnode, 0, sizeof *dirnode); 2.139 + 2.140 + if((dirnode->ino = alloc_inode(fs)) == -1) { 2.141 + printf("failed to allocate inode for a new directory\n"); 2.142 + free(dirnode); 2.143 + return 0; 2.144 + } 2.145 + dirnode->mode = S_IFDIR; 2.146 + 2.147 + /* add . and .. links */ 2.148 + addlink(fs, dirnode, dirnode, "."); 2.149 + addlink(fs, dirnode, parent ? parent : dirnode, ".."); 2.150 + 2.151 + /* and write the inode to disk */ 2.152 + put_inode(fs, dirnode); 2.153 + return dirnode; 2.154 +} 2.155 + 2.156 +static int addlink(struct filesys *fs, struct inode *target, struct inode *node, const char *name) 2.157 +{ 2.158 + struct dir_entry ent, *data; 2.159 + int boffs, bidx, len; 2.160 + 2.161 + if(!(target->mode & S_IFDIR)) { 2.162 + return -ENOTDIR; 2.163 + } 2.164 + if(node->mode & S_IFDIR) { 2.165 + return -EPERM; 2.166 + } 2.167 + /* TODO check that the link does not already exist (EEXIST) */ 2.168 + 2.169 + if((len = strlen(name)) > MAX_FNAME) { 2.170 + return -ENAMETOOLONG; 2.171 + } 2.172 + ent->ino = node->ino; 2.173 + memcpy(newent->name, name, len + 1); 2.174 + 2.175 + /* find a place to put it */ 2.176 + if(!(data = malloc(BLKSZ))) { 2.177 + return -ENOMEM; 2.178 + } 2.179 + 2.180 + boffs = 0; 2.181 + while((bidx = file_block(fs, target, boffs)) > 0) { 2.182 + /* read the block, and search for an empty entry */ 2.183 + blk_read(fs->bdev, bidx, 1, data); 2.184 + 2.185 + /* for all directory entries in this block... */ 2.186 + for(i=0; i<BLK_DIRENT; i++) { 2.187 + if(data[i].ino == 0) { 2.188 + /* found empty */ 2.189 + memcpy(data + i, &ent, sizeof ent); 2.190 + goto success; 2.191 + } 2.192 + } 2.193 + boffs++; 2.194 + } 2.195 + 2.196 + /* didn't find any free entries amongst our blocks, allocate a new one */ 2.197 + if(!(bidx = alloc_file_block(fs, target, boffs))) { 2.198 + free(data); 2.199 + return -ENOSPC; 2.200 + } 2.201 + /* zero-fill the new block and add the first entry */ 2.202 + memset(data, 0, BLKSZ); 2.203 + *data = ent; 2.204 + 2.205 +success: 2.206 + /* write to disk */ 2.207 + blk_write(fs->bdev, bidx, 1, data); 2.208 + node->nlink++; /* increase reference count */ 2.209 + 2.210 + free(data); 2.211 + return 0; 2.212 +} 2.213 + 2.214 + 2.215 static int read_superblock(struct filesys *fs) 2.216 { 2.217 struct superblock *sb = fs->sb; 2.218 @@ -123,12 +280,13 @@ 2.219 if(blk_write(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) { 2.220 return -1; 2.221 } 2.222 + /* write the superblock itself */ 2.223 + if(blk_write(fs->bdev, 1, 1, sb) == -1) { 2.224 + return -1; 2.225 + } 2.226 return 0; 2.227 } 2.228 2.229 -/* number of inodes in a block */ 2.230 -#define BLK_INODES (BLKSZ / sizeof(struct inode)) 2.231 - 2.232 /* copy the requested inode from the disk, into the buffer passed in the last arg */ 2.233 static int get_inode(struct filesys *fs, int ino, struct inode *inode) 2.234 { 2.235 @@ -164,21 +322,24 @@ 2.236 return 0; 2.237 } 2.238 2.239 -static int find_free(uint32_t *bm, int sz) 2.240 +/* find a free element in the bitmap and return its number */ 2.241 +static int find_free(uint32_t *bm, int nbits) 2.242 { 2.243 - int i; 2.244 - uint32_t ent; 2.245 + int i, j, nwords = nbits / 32; 2.246 + uint32_t ent = 0; 2.247 2.248 - for(i=0; i<=sz/32; i++) { 2.249 + for(i=0; i<=nwords; i++) { 2.250 if(bm[i] != 0xffffffff) { 2.251 - ent = i * 32; 2.252 for(j=0; j<32; j++) { 2.253 if(BM_ISFREE(bm, ent)) { 2.254 return ent; 2.255 } 2.256 + ent++; 2.257 } 2.258 2.259 panic("shouldn't happen (in find_free:fs.c)"); 2.260 + } else { 2.261 + ent += 32; 2.262 } 2.263 } 2.264 2.265 @@ -189,9 +350,82 @@ 2.266 { 2.267 int ino; 2.268 2.269 - if((ino = find_free(fs->ibm, fs->ibm_count)) == -1) { 2.270 + if((ino = find_free(fs->sb->ibm, fs->sb->num_inodes)) == -1) { 2.271 return -1; 2.272 } 2.273 - BM_SET(fs->ibm, ino); 2.274 + BM_SET(fs->sb->ibm, ino); 2.275 return 0; 2.276 } 2.277 + 2.278 +static void free_inode(struct filesys *fs, int ino) 2.279 +{ 2.280 + BM_CLR(fs->sb->ibm, ino); 2.281 +} 2.282 + 2.283 +static int alloc_block(struct filesys *fs) 2.284 +{ 2.285 + int ino; 2.286 + 2.287 + if((ino = find_free(fs->sb->bm, fs->sb->num_blocks)) == -1) { 2.288 + return -1; 2.289 + } 2.290 + BM_SET(fs->sb->bm, ino); 2.291 + return 0; 2.292 +} 2.293 + 2.294 +static void free_block(struct filesys *fs, int ino) 2.295 +{ 2.296 + BM_CLR(fs->sb->bm, ino); 2.297 +} 2.298 + 2.299 +#define BLK_BLKID (BLKSZ / sizeof(blkid)) 2.300 +#define MAX_IND (NDIRBLK + BLK_BLKID) 2.301 +#define MAX_DIND (MAX_IND + BLK_BLKID * BLK_BLKID) 2.302 + 2.303 +static int file_block(struct filesys *fs, struct inode *node, int boffs) 2.304 +{ 2.305 + int res, idx; 2.306 + blkid *barr; 2.307 + 2.308 + /* is it a direct block ? */ 2.309 + if(boffs < NDIRBLK) { 2.310 + return node->blk[boffs]; 2.311 + } 2.312 + 2.313 + barr = malloc(BLKSZ); 2.314 + assert(barr); 2.315 + 2.316 + /* is it an indirect block ? */ 2.317 + if(boffs < MAX_IND) { 2.318 + if(!node->ind) { 2.319 + res = 0; 2.320 + goto end; 2.321 + } 2.322 + blk_read(fs->bdev, node->ind, 1, barr); 2.323 + res = barr[boffs - NDIRBLK]; 2.324 + goto end; 2.325 + } 2.326 + 2.327 + /* is it a double-indirect block ? */ 2.328 + if(boffs < MAX_DIND) { 2.329 + /* first read the dind block and find the index of the ind block */ 2.330 + if(!node->dind) { 2.331 + res = 0; 2.332 + goto end; 2.333 + } 2.334 + blk_read(fd->bdev, node->dind, 1, barr); 2.335 + idx = (boffs - MAX_IND) / BLK_BLKID; 2.336 + 2.337 + /* then read the ind block and find the index of the block */ 2.338 + if(!barr[idx]) { 2.339 + res = 0; 2.340 + goto end; 2.341 + } 2.342 + blk_read(fd->bdev, barr[idx], 1, barr); 2.343 + res = barr[(boffs - MAX_IND) % BLK_BLKID]; 2.344 + } 2.345 + 2.346 +end: 2.347 + free(barr); 2.348 + return res; 2.349 +}
3.1 --- a/src/fs.h Sun Dec 11 21:15:35 2011 +0200 3.2 +++ b/src/fs.h Thu Dec 15 04:39:00 2011 +0200 3.3 @@ -3,9 +3,12 @@ 3.4 3.5 #include <inttypes.h> 3.6 3.7 -#define MAGIC 0xccf5ccf5 3.8 -#define FS_VER 1 3.9 -#define BLKSZ 1024 3.10 +#define MAGIC 0xccf5ccf5 3.11 +#define FS_VER 1 3.12 +#define BLKSZ 1024 3.13 + 3.14 +#define NAME_MAX 27 /* +1 termin. +4 ino = 32 per dirent */ 3.15 +#define PATH_MAX 256 3.16 3.17 #define SECT_TO_BLK(x) ((x) / (BLKSZ / 512)) 3.18 3.19 @@ -32,6 +35,10 @@ 3.20 blkid dind; /* double-indirect */ 3.21 } __attribute__((packed)); 3.22 3.23 +struct dir_entry { 3.24 + int ino; 3.25 + char name[NAME_MAX + 1]; 3.26 +} __attribute__((packed)); 3.27 3.28 struct superblock { 3.29 uint32_t magic; /* magic number */ 3.30 @@ -74,6 +81,7 @@ 3.31 3.32 /* defined in fs.c */ 3.33 int openfs(struct filesys *fs, dev_t dev); 3.34 +int mkfs(struct filesys *fs, dev_t dev); 3.35 void closefs(struct filesys *fs); 3.36 int find_inode(const char *path); 3.37
4.1 --- a/src/proc.c Sun Dec 11 21:15:35 2011 +0200 4.2 +++ b/src/proc.c Thu Dec 15 04:39:00 2011 +0200 4.3 @@ -77,6 +77,8 @@ 4.4 p->id = 1; 4.5 p->parent = 0; /* no parent for init */ 4.6 4.7 + p->umask = 022; 4.8 + 4.9 p->ticks_left = TIMESLICE_TICKS; 4.10 p->next = p->prev = 0; 4.11 4.12 @@ -168,6 +170,8 @@ 4.13 /* copy file table */ 4.14 memcpy(p->files, parent->files, sizeof p->files); 4.15 4.16 + p->umask = parent->umask; 4.17 + 4.18 /* allocate a kernel stack for the new process */ 4.19 if((p->kern_stack_pg = pgalloc(KERN_STACK_SIZE / PGSIZE, MEM_KERNEL)) == -1) { 4.20 return -EAGAIN;
5.1 --- a/src/proc.h Sun Dec 11 21:15:35 2011 +0200 5.2 +++ b/src/proc.h Thu Dec 15 04:39:00 2011 +0200 5.3 @@ -51,6 +51,8 @@ 5.4 /* open files */ 5.5 struct file files[MAX_FD]; 5.6 5.7 + unsigned int umask; 5.8 + 5.9 struct process *child_list; 5.10 5.11 struct process *next, *prev; /* for the scheduler queues */