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  }
     3.1 --- a/src/fs.h	Thu Dec 15 04:39:00 2011 +0200
     3.2 +++ b/src/fs.h	Sat Dec 17 14:09:17 2011 +0200
     3.3 @@ -76,6 +76,8 @@
     3.4  
     3.5  	struct superblock *sb;
     3.6  
     3.7 +	void *zeroblock;
     3.8 +
     3.9  	struct filesys *next;
    3.10  };
    3.11