kern
changeset 97:8717eb590727
ok stopping with the filesystem to manage to write the article in time
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 17 Dec 2011 14:09:17 +0200 |
parents | 07fe6a614185 |
children | 921a264297a4 |
files | include/kdef.h src/fs.c src/fs.h |
diffstat | 3 files changed, 106 insertions(+), 35 deletions(-) [+] |
line diff
1.1 --- a/include/kdef.h Thu Dec 15 04:39:00 2011 +0200 1.2 +++ b/include/kdef.h Sat Dec 17 14:09:17 2011 +0200 1.3 @@ -41,6 +41,7 @@ 1.4 #define ENAMETOOLONG 9 1.5 #define ENOSPC 10 1.6 #define EPERM 11 1.7 +#define ENOTDIR 12 1.8 1.9 #define EBUG 127 /* for missing features and known bugs */ 1.10 #endif /* errno.h */
2.1 --- a/src/fs.c Thu Dec 15 04:39:00 2011 +0200 2.2 +++ b/src/fs.c Sat Dec 17 14:09:17 2011 +0200 2.3 @@ -1,4 +1,11 @@ 2.4 /* This code is used by the kernel AND by userspace filesystem-related tools. */ 2.5 + 2.6 +/* XXX convention: 2.7 + * - functions that accept or return a struct inode, do not read/write it to disk 2.8 + * - functions that accept or return an int ino, do read/write it to disk 2.9 + * other kinds of blocks (data, indirect, etc) always hit the disk directly. 2.10 + */ 2.11 + 2.12 #include <stdio.h> 2.13 #include <stdlib.h> 2.14 #include <string.h> 2.15 @@ -31,10 +38,19 @@ 2.16 static int put_inode(struct filesys *fs, struct inode *inode); 2.17 static int find_free(uint32_t *bm, int sz); 2.18 static int alloc_inode(struct filesys *fs); 2.19 -static void free_inode(struct filesys *fs, int ino); 2.20 +#define free_inode(fs, ino) BM_CLR((fs)->sb->ibm, (ino)) 2.21 static int alloc_block(struct filesys *fs); 2.22 -static void free_block(struct filesys *fs, int ino); 2.23 -static int file_block(struct filesys *fs, struct inode *node, int boffs); 2.24 +#define free_block(fs, bno) BM_CLR((fs)->sb->bm, (bno)) 2.25 +#define zero_block(fs, bno) \ 2.26 + do { \ 2.27 + assert(bno > 0); \ 2.28 + blk_write((fs)->bdev, (bno), 1, (fs)->zeroblock); \ 2.29 + } while(0) 2.30 + 2.31 +static int file_block(struct filesys *fs, struct inode *node, int boffs, int allocate); 2.32 +#define get_file_block(fs, node, boffs) file_block(fs, node, boffs, 0) 2.33 +#define alloc_file_block(fs, node, boffs) file_block(fs, node, boffs, 1) 2.34 + 2.35 2.36 int openfs(struct filesys *fs, dev_t dev) 2.37 { 2.38 @@ -58,12 +74,21 @@ 2.39 return res; 2.40 } 2.41 2.42 + /* allocate the zero-block buffer written to zero-out blocks */ 2.43 + if(!(fs->zeroblock = malloc(fs->sb->blksize))) { 2.44 + blk_close(bdev); 2.45 + free(fs->sb->ibm); 2.46 + free(fs->sb->bm); 2.47 + free(fs->sb->root); 2.48 + return -ENOMEM; 2.49 + } 2.50 + memset(fs->zeroblock, 0xff, fs->sb->blksize); 2.51 + 2.52 return 0; 2.53 } 2.54 2.55 int mkfs(struct filesys *fs, dev_t dev) 2.56 { 2.57 - struct filesys *fs; 2.58 struct superblock *sb; 2.59 struct block_device *bdev; 2.60 int i, bcount; 2.61 @@ -121,6 +146,10 @@ 2.62 /* create the root directory */ 2.63 sb->root = newdir(fs, 0); 2.64 sb->root_ino = sb->root->ino; 2.65 + /* and write the inode to disk */ 2.66 + put_inode(fs, sb->root); 2.67 + 2.68 + return 0; 2.69 } 2.70 2.71 static struct inode *newdir(struct filesys *fs, struct inode *parent) 2.72 @@ -144,15 +173,13 @@ 2.73 addlink(fs, dirnode, dirnode, "."); 2.74 addlink(fs, dirnode, parent ? parent : dirnode, ".."); 2.75 2.76 - /* and write the inode to disk */ 2.77 - put_inode(fs, dirnode); 2.78 return dirnode; 2.79 } 2.80 2.81 static int addlink(struct filesys *fs, struct inode *target, struct inode *node, const char *name) 2.82 { 2.83 struct dir_entry ent, *data; 2.84 - int boffs, bidx, len; 2.85 + int i, boffs, bidx, len; 2.86 2.87 if(!(target->mode & S_IFDIR)) { 2.88 return -ENOTDIR; 2.89 @@ -162,11 +189,11 @@ 2.90 } 2.91 /* TODO check that the link does not already exist (EEXIST) */ 2.92 2.93 - if((len = strlen(name)) > MAX_FNAME) { 2.94 + if((len = strlen(name)) > NAME_MAX) { 2.95 return -ENAMETOOLONG; 2.96 } 2.97 - ent->ino = node->ino; 2.98 - memcpy(newent->name, name, len + 1); 2.99 + ent.ino = node->ino; 2.100 + memcpy(ent.name, name, len + 1); 2.101 2.102 /* find a place to put it */ 2.103 if(!(data = malloc(BLKSZ))) { 2.104 @@ -174,7 +201,7 @@ 2.105 } 2.106 2.107 boffs = 0; 2.108 - while((bidx = file_block(fs, target, boffs)) > 0) { 2.109 + while((bidx = get_file_block(fs, target, boffs)) > 0) { 2.110 /* read the block, and search for an empty entry */ 2.111 blk_read(fs->bdev, bidx, 1, data); 2.112 2.113 @@ -357,61 +384,98 @@ 2.114 return 0; 2.115 } 2.116 2.117 -static void free_inode(struct filesys *fs, int ino) 2.118 -{ 2.119 - BM_CLR(fs->sb->ibm, ino); 2.120 -} 2.121 - 2.122 static int alloc_block(struct filesys *fs) 2.123 { 2.124 - int ino; 2.125 + int bno; 2.126 2.127 - if((ino = find_free(fs->sb->bm, fs->sb->num_blocks)) == -1) { 2.128 + if((bno = find_free(fs->sb->bm, fs->sb->num_blocks)) == -1) { 2.129 return -1; 2.130 } 2.131 - BM_SET(fs->sb->bm, ino); 2.132 + BM_SET(fs->sb->bm, bno); 2.133 return 0; 2.134 } 2.135 2.136 -static void free_block(struct filesys *fs, int ino) 2.137 -{ 2.138 - BM_CLR(fs->sb->bm, ino); 2.139 -} 2.140 - 2.141 #define BLK_BLKID (BLKSZ / sizeof(blkid)) 2.142 #define MAX_IND (NDIRBLK + BLK_BLKID) 2.143 #define MAX_DIND (MAX_IND + BLK_BLKID * BLK_BLKID) 2.144 2.145 -static int file_block(struct filesys *fs, struct inode *node, int boffs) 2.146 +static int file_block(struct filesys *fs, struct inode *node, int boffs, int allocate) 2.147 { 2.148 - int res, idx; 2.149 + int res, idx, node_dirty = 0; 2.150 blkid *barr; 2.151 2.152 + /* out of bounds */ 2.153 + if(boffs < 0 || boffs >= MAX_DIND) { 2.154 + return 0; 2.155 + } 2.156 + 2.157 /* is it a direct block ? */ 2.158 if(boffs < NDIRBLK) { 2.159 - return node->blk[boffs]; 2.160 + if(!(res = node->blk[boffs]) && allocate) { 2.161 + res = node->blk[boffs] = alloc_block(fs); 2.162 + if(res) { 2.163 + zero_block(fs, res); 2.164 + /* also write back the modified inode */ 2.165 + put_inode(fs, node); 2.166 + } 2.167 + } 2.168 + return res; 2.169 } 2.170 2.171 - barr = malloc(BLKSZ); 2.172 + barr = malloc(fs->sb->blksize); 2.173 assert(barr); 2.174 2.175 /* is it an indirect block ? */ 2.176 if(boffs < MAX_IND) { 2.177 - if(!node->ind) { 2.178 - res = 0; 2.179 - goto end; 2.180 + int ind_dirty = 0; 2.181 + 2.182 + if(node->ind) { 2.183 + /* read the indirect block */ 2.184 + blk_read(fs->bdev, node->ind, 1, barr); 2.185 + } else { 2.186 + /* does not exist... try to allocate if requested */ 2.187 + if(!allocate || !(node->ind = alloc_block(fs))) { 2.188 + res = 0; 2.189 + goto end; 2.190 + } 2.191 + 2.192 + /* allocated a block clear the buffer, and invalidate everything */ 2.193 + memset(barr, 0, sizeof fs->sb->blksize); 2.194 + node_dirty = 1; 2.195 + ind_dirty = 1; 2.196 } 2.197 - blk_read(fs->bdev, node->ind, 1, barr); 2.198 - res = barr[boffs - NDIRBLK]; 2.199 + 2.200 + idx = boffs - NDIRBLK; 2.201 + 2.202 + if(!(res = barr[idx])) { 2.203 + if(allocate && (res = barr[idx] = alloc_block(fs))) { 2.204 + ind_dirty = 1; 2.205 + } 2.206 + } 2.207 + 2.208 + /* write back the indirect block if needed */ 2.209 + if(ind_dirty) { 2.210 + blk_write(fs->bdev, node->ind, 1, barr); 2.211 + } 2.212 goto end; 2.213 } 2.214 2.215 + /* TODO check/rewrite this */ 2.216 +#if 0 2.217 /* is it a double-indirect block ? */ 2.218 if(boffs < MAX_DIND) { 2.219 /* first read the dind block and find the index of the ind block */ 2.220 if(!node->dind) { 2.221 - res = 0; 2.222 - goto end; 2.223 + if(allocate) { 2.224 + /* allocate and zero-out the double indirect block */ 2.225 + res = node->dind = alloc_block(fs); 2.226 + if(res) { 2.227 + zero_block(fs, res); 2.228 + } 2.229 + } else { 2.230 + res = 0; 2.231 + goto end; 2.232 + } 2.233 } 2.234 blk_read(fd->bdev, node->dind, 1, barr); 2.235 idx = (boffs - MAX_IND) / BLK_BLKID; 2.236 @@ -424,8 +488,12 @@ 2.237 blk_read(fd->bdev, barr[idx], 1, barr); 2.238 res = barr[(boffs - MAX_IND) % BLK_BLKID]; 2.239 } 2.240 +#endif 2.241 2.242 end: 2.243 + if(node_dirty) { 2.244 + put_inode(fs, node); 2.245 + } 2.246 free(barr); 2.247 return res; 2.248 }