kern
diff src/fs.c @ 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 |
line diff
1.1 --- a/src/fs.c Thu Dec 15 04:39:00 2011 +0200 1.2 +++ b/src/fs.c Sat Dec 17 14:09:17 2011 +0200 1.3 @@ -1,4 +1,11 @@ 1.4 /* This code is used by the kernel AND by userspace filesystem-related tools. */ 1.5 + 1.6 +/* XXX convention: 1.7 + * - functions that accept or return a struct inode, do not read/write it to disk 1.8 + * - functions that accept or return an int ino, do read/write it to disk 1.9 + * other kinds of blocks (data, indirect, etc) always hit the disk directly. 1.10 + */ 1.11 + 1.12 #include <stdio.h> 1.13 #include <stdlib.h> 1.14 #include <string.h> 1.15 @@ -31,10 +38,19 @@ 1.16 static int put_inode(struct filesys *fs, struct inode *inode); 1.17 static int find_free(uint32_t *bm, int sz); 1.18 static int alloc_inode(struct filesys *fs); 1.19 -static void free_inode(struct filesys *fs, int ino); 1.20 +#define free_inode(fs, ino) BM_CLR((fs)->sb->ibm, (ino)) 1.21 static int alloc_block(struct filesys *fs); 1.22 -static void free_block(struct filesys *fs, int ino); 1.23 -static int file_block(struct filesys *fs, struct inode *node, int boffs); 1.24 +#define free_block(fs, bno) BM_CLR((fs)->sb->bm, (bno)) 1.25 +#define zero_block(fs, bno) \ 1.26 + do { \ 1.27 + assert(bno > 0); \ 1.28 + blk_write((fs)->bdev, (bno), 1, (fs)->zeroblock); \ 1.29 + } while(0) 1.30 + 1.31 +static int file_block(struct filesys *fs, struct inode *node, int boffs, int allocate); 1.32 +#define get_file_block(fs, node, boffs) file_block(fs, node, boffs, 0) 1.33 +#define alloc_file_block(fs, node, boffs) file_block(fs, node, boffs, 1) 1.34 + 1.35 1.36 int openfs(struct filesys *fs, dev_t dev) 1.37 { 1.38 @@ -58,12 +74,21 @@ 1.39 return res; 1.40 } 1.41 1.42 + /* allocate the zero-block buffer written to zero-out blocks */ 1.43 + if(!(fs->zeroblock = malloc(fs->sb->blksize))) { 1.44 + blk_close(bdev); 1.45 + free(fs->sb->ibm); 1.46 + free(fs->sb->bm); 1.47 + free(fs->sb->root); 1.48 + return -ENOMEM; 1.49 + } 1.50 + memset(fs->zeroblock, 0xff, fs->sb->blksize); 1.51 + 1.52 return 0; 1.53 } 1.54 1.55 int mkfs(struct filesys *fs, dev_t dev) 1.56 { 1.57 - struct filesys *fs; 1.58 struct superblock *sb; 1.59 struct block_device *bdev; 1.60 int i, bcount; 1.61 @@ -121,6 +146,10 @@ 1.62 /* create the root directory */ 1.63 sb->root = newdir(fs, 0); 1.64 sb->root_ino = sb->root->ino; 1.65 + /* and write the inode to disk */ 1.66 + put_inode(fs, sb->root); 1.67 + 1.68 + return 0; 1.69 } 1.70 1.71 static struct inode *newdir(struct filesys *fs, struct inode *parent) 1.72 @@ -144,15 +173,13 @@ 1.73 addlink(fs, dirnode, dirnode, "."); 1.74 addlink(fs, dirnode, parent ? parent : dirnode, ".."); 1.75 1.76 - /* and write the inode to disk */ 1.77 - put_inode(fs, dirnode); 1.78 return dirnode; 1.79 } 1.80 1.81 static int addlink(struct filesys *fs, struct inode *target, struct inode *node, const char *name) 1.82 { 1.83 struct dir_entry ent, *data; 1.84 - int boffs, bidx, len; 1.85 + int i, boffs, bidx, len; 1.86 1.87 if(!(target->mode & S_IFDIR)) { 1.88 return -ENOTDIR; 1.89 @@ -162,11 +189,11 @@ 1.90 } 1.91 /* TODO check that the link does not already exist (EEXIST) */ 1.92 1.93 - if((len = strlen(name)) > MAX_FNAME) { 1.94 + if((len = strlen(name)) > NAME_MAX) { 1.95 return -ENAMETOOLONG; 1.96 } 1.97 - ent->ino = node->ino; 1.98 - memcpy(newent->name, name, len + 1); 1.99 + ent.ino = node->ino; 1.100 + memcpy(ent.name, name, len + 1); 1.101 1.102 /* find a place to put it */ 1.103 if(!(data = malloc(BLKSZ))) { 1.104 @@ -174,7 +201,7 @@ 1.105 } 1.106 1.107 boffs = 0; 1.108 - while((bidx = file_block(fs, target, boffs)) > 0) { 1.109 + while((bidx = get_file_block(fs, target, boffs)) > 0) { 1.110 /* read the block, and search for an empty entry */ 1.111 blk_read(fs->bdev, bidx, 1, data); 1.112 1.113 @@ -357,61 +384,98 @@ 1.114 return 0; 1.115 } 1.116 1.117 -static void free_inode(struct filesys *fs, int ino) 1.118 -{ 1.119 - BM_CLR(fs->sb->ibm, ino); 1.120 -} 1.121 - 1.122 static int alloc_block(struct filesys *fs) 1.123 { 1.124 - int ino; 1.125 + int bno; 1.126 1.127 - if((ino = find_free(fs->sb->bm, fs->sb->num_blocks)) == -1) { 1.128 + if((bno = find_free(fs->sb->bm, fs->sb->num_blocks)) == -1) { 1.129 return -1; 1.130 } 1.131 - BM_SET(fs->sb->bm, ino); 1.132 + BM_SET(fs->sb->bm, bno); 1.133 return 0; 1.134 } 1.135 1.136 -static void free_block(struct filesys *fs, int ino) 1.137 -{ 1.138 - BM_CLR(fs->sb->bm, ino); 1.139 -} 1.140 - 1.141 #define BLK_BLKID (BLKSZ / sizeof(blkid)) 1.142 #define MAX_IND (NDIRBLK + BLK_BLKID) 1.143 #define MAX_DIND (MAX_IND + BLK_BLKID * BLK_BLKID) 1.144 1.145 -static int file_block(struct filesys *fs, struct inode *node, int boffs) 1.146 +static int file_block(struct filesys *fs, struct inode *node, int boffs, int allocate) 1.147 { 1.148 - int res, idx; 1.149 + int res, idx, node_dirty = 0; 1.150 blkid *barr; 1.151 1.152 + /* out of bounds */ 1.153 + if(boffs < 0 || boffs >= MAX_DIND) { 1.154 + return 0; 1.155 + } 1.156 + 1.157 /* is it a direct block ? */ 1.158 if(boffs < NDIRBLK) { 1.159 - return node->blk[boffs]; 1.160 + if(!(res = node->blk[boffs]) && allocate) { 1.161 + res = node->blk[boffs] = alloc_block(fs); 1.162 + if(res) { 1.163 + zero_block(fs, res); 1.164 + /* also write back the modified inode */ 1.165 + put_inode(fs, node); 1.166 + } 1.167 + } 1.168 + return res; 1.169 } 1.170 1.171 - barr = malloc(BLKSZ); 1.172 + barr = malloc(fs->sb->blksize); 1.173 assert(barr); 1.174 1.175 /* is it an indirect block ? */ 1.176 if(boffs < MAX_IND) { 1.177 - if(!node->ind) { 1.178 - res = 0; 1.179 - goto end; 1.180 + int ind_dirty = 0; 1.181 + 1.182 + if(node->ind) { 1.183 + /* read the indirect block */ 1.184 + blk_read(fs->bdev, node->ind, 1, barr); 1.185 + } else { 1.186 + /* does not exist... try to allocate if requested */ 1.187 + if(!allocate || !(node->ind = alloc_block(fs))) { 1.188 + res = 0; 1.189 + goto end; 1.190 + } 1.191 + 1.192 + /* allocated a block clear the buffer, and invalidate everything */ 1.193 + memset(barr, 0, sizeof fs->sb->blksize); 1.194 + node_dirty = 1; 1.195 + ind_dirty = 1; 1.196 } 1.197 - blk_read(fs->bdev, node->ind, 1, barr); 1.198 - res = barr[boffs - NDIRBLK]; 1.199 + 1.200 + idx = boffs - NDIRBLK; 1.201 + 1.202 + if(!(res = barr[idx])) { 1.203 + if(allocate && (res = barr[idx] = alloc_block(fs))) { 1.204 + ind_dirty = 1; 1.205 + } 1.206 + } 1.207 + 1.208 + /* write back the indirect block if needed */ 1.209 + if(ind_dirty) { 1.210 + blk_write(fs->bdev, node->ind, 1, barr); 1.211 + } 1.212 goto end; 1.213 } 1.214 1.215 + /* TODO check/rewrite this */ 1.216 +#if 0 1.217 /* is it a double-indirect block ? */ 1.218 if(boffs < MAX_DIND) { 1.219 /* first read the dind block and find the index of the ind block */ 1.220 if(!node->dind) { 1.221 - res = 0; 1.222 - goto end; 1.223 + if(allocate) { 1.224 + /* allocate and zero-out the double indirect block */ 1.225 + res = node->dind = alloc_block(fs); 1.226 + if(res) { 1.227 + zero_block(fs, res); 1.228 + } 1.229 + } else { 1.230 + res = 0; 1.231 + goto end; 1.232 + } 1.233 } 1.234 blk_read(fd->bdev, node->dind, 1, barr); 1.235 idx = (boffs - MAX_IND) / BLK_BLKID; 1.236 @@ -424,8 +488,12 @@ 1.237 blk_read(fd->bdev, barr[idx], 1, barr); 1.238 res = barr[(boffs - MAX_IND) % BLK_BLKID]; 1.239 } 1.240 +#endif 1.241 1.242 end: 1.243 + if(node_dirty) { 1.244 + put_inode(fs, node); 1.245 + } 1.246 free(barr); 1.247 return res; 1.248 }