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  }