Pick up where i left off in april:

- move log into metadata part of disk, so that marking
that the log's blocks are in use falls out for free
- superblock describes the whole disk (sizes and offets)
- sizes and offsets are computed in one place (mkfs) and
the rest of the code refers to the superblock for these values,
instead of recomputing them.
This commit is contained in:
Frans Kaashoek 2015-06-27 12:39:13 -04:00
parent de4af193c8
commit 8320d61be5
7 changed files with 47 additions and 45 deletions

4
defs.h
View file

@ -39,7 +39,7 @@ int dirlink(struct inode*, char*, uint);
struct inode* dirlookup(struct inode*, char*, uint*); struct inode* dirlookup(struct inode*, char*, uint*);
struct inode* ialloc(uint, short); struct inode* ialloc(uint, short);
struct inode* idup(struct inode*); struct inode* idup(struct inode*);
void iinit(void); void iinit(int dev);
void ilock(struct inode*); void ilock(struct inode*);
void iput(struct inode*); void iput(struct inode*);
void iunlock(struct inode*); void iunlock(struct inode*);
@ -81,7 +81,7 @@ void lapicstartap(uchar, uint);
void microdelay(int); void microdelay(int);
// log.c // log.c
void initlog(void); void initlog(int dev);
void log_write(struct buf*); void log_write(struct buf*);
void begin_op(); void begin_op();
void end_op(); void end_op();

26
fs.c
View file

@ -22,6 +22,7 @@
#define min(a, b) ((a) < (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b))
static void itrunc(struct inode*); static void itrunc(struct inode*);
struct superblock sb; // there should be one per dev, but we run with one dev
// Read the super block. // Read the super block.
void void
@ -54,12 +55,10 @@ balloc(uint dev)
{ {
int b, bi, m; int b, bi, m;
struct buf *bp; struct buf *bp;
struct superblock sb;
bp = 0; bp = 0;
readsb(dev, &sb);
for(b = 0; b < sb.size; b += BPB){ for(b = 0; b < sb.size; b += BPB){
bp = bread(dev, BBLOCK(b, sb.ninodes)); bp = bread(dev, BBLOCK(b, sb));
for(bi = 0; bi < BPB && b + bi < sb.size; bi++){ for(bi = 0; bi < BPB && b + bi < sb.size; bi++){
m = 1 << (bi % 8); m = 1 << (bi % 8);
if((bp->data[bi/8] & m) == 0){ // Is block free? if((bp->data[bi/8] & m) == 0){ // Is block free?
@ -80,11 +79,10 @@ static void
bfree(int dev, uint b) bfree(int dev, uint b)
{ {
struct buf *bp; struct buf *bp;
struct superblock sb;
int bi, m; int bi, m;
readsb(dev, &sb); readsb(dev, &sb);
bp = bread(dev, BBLOCK(b, sb.ninodes)); bp = bread(dev, BBLOCK(b, sb));
bi = b % BPB; bi = b % BPB;
m = 1 << (bi % 8); m = 1 << (bi % 8);
if((bp->data[bi/8] & m) == 0) if((bp->data[bi/8] & m) == 0)
@ -101,8 +99,8 @@ bfree(int dev, uint b)
// its size, the number of links referring to it, and the // its size, the number of links referring to it, and the
// list of blocks holding the file's content. // list of blocks holding the file's content.
// //
// The inodes are laid out sequentially on disk immediately after // The inodes are laid out sequentially on disk at
// the superblock. Each inode has a number, indicating its // sb.startinode. Each inode has a number, indicating its
// position on the disk. // position on the disk.
// //
// The kernel keeps a cache of in-use inodes in memory // The kernel keeps a cache of in-use inodes in memory
@ -162,9 +160,12 @@ struct {
} icache; } icache;
void void
iinit(void) iinit(int dev)
{ {
initlock(&icache.lock, "icache"); initlock(&icache.lock, "icache");
readsb(dev, &sb);
cprintf("sb: size %d nblocks %d ninodes %d nlog %d logstart %d inodestart %d bmap start %d\n", sb.size,
sb.nblocks, sb.ninodes, sb.nlog, sb.logstart, sb.inodestart, sb.bmapstart);
} }
static struct inode* iget(uint dev, uint inum); static struct inode* iget(uint dev, uint inum);
@ -178,12 +179,9 @@ ialloc(uint dev, short type)
int inum; int inum;
struct buf *bp; struct buf *bp;
struct dinode *dip; struct dinode *dip;
struct superblock sb;
readsb(dev, &sb);
for(inum = 1; inum < sb.ninodes; inum++){ for(inum = 1; inum < sb.ninodes; inum++){
bp = bread(dev, IBLOCK(inum)); bp = bread(dev, IBLOCK(inum, sb));
dip = (struct dinode*)bp->data + inum%IPB; dip = (struct dinode*)bp->data + inum%IPB;
if(dip->type == 0){ // a free inode if(dip->type == 0){ // a free inode
memset(dip, 0, sizeof(*dip)); memset(dip, 0, sizeof(*dip));
@ -204,7 +202,7 @@ iupdate(struct inode *ip)
struct buf *bp; struct buf *bp;
struct dinode *dip; struct dinode *dip;
bp = bread(ip->dev, IBLOCK(ip->inum)); bp = bread(ip->dev, IBLOCK(ip->inum, sb));
dip = (struct dinode*)bp->data + ip->inum%IPB; dip = (struct dinode*)bp->data + ip->inum%IPB;
dip->type = ip->type; dip->type = ip->type;
dip->major = ip->major; dip->major = ip->major;
@ -281,7 +279,7 @@ ilock(struct inode *ip)
release(&icache.lock); release(&icache.lock);
if(!(ip->flags & I_VALID)){ if(!(ip->flags & I_VALID)){
bp = bread(ip->dev, IBLOCK(ip->inum)); bp = bread(ip->dev, IBLOCK(ip->inum, sb));
dip = (struct dinode*)bp->data + ip->inum%IPB; dip = (struct dinode*)bp->data + ip->inum%IPB;
ip->type = dip->type; ip->type = dip->type;
ip->major = dip->major; ip->major = dip->major;

21
fs.h
View file

@ -1,22 +1,23 @@
// On-disk file system format. // On-disk file system format.
// Both the kernel and user programs use this header file. // Both the kernel and user programs use this header file.
// Block 0 is unused.
// Block 1 is super block.
// Blocks 2 through sb.ninodes/IPB hold inodes.
// Then free bitmap blocks holding sb.size bits.
// Then sb.nblocks data blocks.
// Then sb.nlog log blocks.
#define ROOTINO 1 // root i-number #define ROOTINO 1 // root i-number
#define BSIZE 512 // block size #define BSIZE 512 // block size
// File system super block // Disk layout:
// [ boot block | super block | log | inode blocks | free bit map | data blocks ]
//
// mkfs computes the super block and builds an initial file system. The super describes
// the disk layout:
struct superblock { struct superblock {
uint size; // Size of file system image (blocks) uint size; // Size of file system image (blocks)
uint nblocks; // Number of data blocks uint nblocks; // Number of data blocks
uint ninodes; // Number of inodes. uint ninodes; // Number of inodes.
uint nlog; // Number of log blocks uint nlog; // Number of log blocks
uint logstart; // Block number of first log block
uint inodestart; // Block number of first inode block
uint bmapstart; // Block number of first free map block
}; };
#define NDIRECT 12 #define NDIRECT 12
@ -37,13 +38,13 @@ struct dinode {
#define IPB (BSIZE / sizeof(struct dinode)) #define IPB (BSIZE / sizeof(struct dinode))
// Block containing inode i // Block containing inode i
#define IBLOCK(i) ((i) / IPB + 2) #define IBLOCK(i, sb) ((i) / IPB + sb.inodestart)
// Bitmap bits per block // Bitmap bits per block
#define BPB (BSIZE*8) #define BPB (BSIZE*8)
// Block containing bit for block b // Block of free map containing bit for block b
#define BBLOCK(b, ninodes) (b/BPB + (ninodes)/IPB + 3) #define BBLOCK(b, sb) (b/BPB + sb.bmapstart)
// Directory is a file containing a sequence of dirent structures. // Directory is a file containing a sequence of dirent structures.
#define DIRSIZ 14 #define DIRSIZ 14

8
log.c
View file

@ -50,17 +50,17 @@ static void recover_from_log(void);
static void commit(); static void commit();
void void
initlog(void) initlog(int dev)
{ {
if (sizeof(struct logheader) >= BSIZE) if (sizeof(struct logheader) >= BSIZE)
panic("initlog: too big logheader"); panic("initlog: too big logheader");
struct superblock sb; struct superblock sb;
initlock(&log.lock, "log"); initlock(&log.lock, "log");
readsb(ROOTDEV, &sb); readsb(dev, &sb);
log.start = sb.size - sb.nlog; log.start = sb.logstart;
log.size = sb.nlog; log.size = sb.nlog;
log.dev = ROOTDEV; log.dev = dev;
recover_from_log(); recover_from_log();
} }

1
main.c
View file

@ -31,7 +31,6 @@ main(void)
tvinit(); // trap vectors tvinit(); // trap vectors
binit(); // buffer cache binit(); // buffer cache
fileinit(); // file table fileinit(); // file table
iinit(); // inode cache
ideinit(); // disk ideinit(); // disk
if(!ismp) if(!ismp)
timerinit(); // uniprocessor timer timerinit(); // uniprocessor timer

29
mkfs.c
View file

@ -16,12 +16,12 @@
#define NINODES 200 #define NINODES 200
// Disk layout: // Disk layout:
// [ boot block | sb block | inode blocks | bit map | data blocks | log ] // [ boot block | sb block | log | inode blocks | free bit map | data blocks ]
int nbitmap = FSSIZE/(BSIZE*8) + 1; int nbitmap = FSSIZE/(BSIZE*8) + 1;
int ninodeblocks = NINODES / IPB + 1; int ninodeblocks = NINODES / IPB + 1;
int nlog = LOGSIZE; int nlog = LOGSIZE;
int nmeta; // Number of meta blocks (inode, bitmap, and 2 extra) int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap)
int nblocks; // Number of data blocks int nblocks; // Number of data blocks
int fsfd; int fsfd;
@ -88,15 +88,20 @@ main(int argc, char *argv[])
exit(1); exit(1);
} }
nmeta = 2 + ninodeblocks + nbitmap; // 1 fs block = 1 disk sector
nblocks = FSSIZE - nlog - nmeta; nmeta = 2 + nlog + ninodeblocks + nbitmap;
nblocks = FSSIZE - nmeta;
sb.size = xint(FSSIZE); sb.size = xint(FSSIZE);
sb.nblocks = xint(nblocks); // so whole disk is size sectors sb.nblocks = xint(nblocks);
sb.ninodes = xint(NINODES); sb.ninodes = xint(NINODES);
sb.nlog = xint(nlog); sb.nlog = xint(nlog);
sb.logstart = xint(2);
sb.inodestart = xint(2+nlog);
sb.bmapstart = xint(2+nlog+ninodeblocks);
printf("nmeta %d (boot, super, inode blocks %u, bitmap blocks %u) blocks %d log %u total %d\n", nmeta, ninodeblocks, nbitmap, nblocks, nlog, FSSIZE); printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n",
nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE);
freeblock = nmeta; // the first free block that we can allocate freeblock = nmeta; // the first free block that we can allocate
@ -180,7 +185,7 @@ winode(uint inum, struct dinode *ip)
uint bn; uint bn;
struct dinode *dip; struct dinode *dip;
bn = IBLOCK(inum); bn = IBLOCK(inum, sb);
rsect(bn, buf); rsect(bn, buf);
dip = ((struct dinode*)buf) + (inum % IPB); dip = ((struct dinode*)buf) + (inum % IPB);
*dip = *ip; *dip = *ip;
@ -194,7 +199,7 @@ rinode(uint inum, struct dinode *ip)
uint bn; uint bn;
struct dinode *dip; struct dinode *dip;
bn = IBLOCK(inum); bn = IBLOCK(inum, sb);
rsect(bn, buf); rsect(bn, buf);
dip = ((struct dinode*)buf) + (inum % IPB); dip = ((struct dinode*)buf) + (inum % IPB);
*ip = *dip; *ip = *dip;
@ -239,8 +244,8 @@ balloc(int used)
for(i = 0; i < used; i++){ for(i = 0; i < used; i++){
buf[i/8] = buf[i/8] | (0x1 << (i%8)); buf[i/8] = buf[i/8] | (0x1 << (i%8));
} }
printf("balloc: write bitmap block at sector %d\n", ninodeblocks+2); printf("balloc: write bitmap block at sector %d\n", sb.bmapstart);
wsect(ninodeblocks+2, buf); wsect(sb.bmapstart, buf);
} }
#define min(a, b) ((a) < (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b))
@ -256,8 +261,8 @@ iappend(uint inum, void *xp, int n)
uint x; uint x;
rinode(inum, &din); rinode(inum, &din);
off = xint(din.size); off = xint(din.size);
// printf("append inum %d at off %d sz %d\n", inum, off, n);
while(n > 0){ while(n > 0){
fbn = off / BSIZE; fbn = off / BSIZE;
assert(fbn < MAXFILE); assert(fbn < MAXFILE);
@ -268,10 +273,8 @@ iappend(uint inum, void *xp, int n)
x = xint(din.addrs[fbn]); x = xint(din.addrs[fbn]);
} else { } else {
if(xint(din.addrs[NDIRECT]) == 0){ if(xint(din.addrs[NDIRECT]) == 0){
// printf("allocate indirect block\n");
din.addrs[NDIRECT] = xint(freeblock++); din.addrs[NDIRECT] = xint(freeblock++);
} }
// printf("read indirect block\n");
rsect(xint(din.addrs[NDIRECT]), (char*)indirect); rsect(xint(din.addrs[NDIRECT]), (char*)indirect);
if(indirect[fbn - NDIRECT] == 0){ if(indirect[fbn - NDIRECT] == 0){
indirect[fbn - NDIRECT] = xint(freeblock++); indirect[fbn - NDIRECT] = xint(freeblock++);

3
proc.c
View file

@ -339,7 +339,8 @@ forkret(void)
// of a regular process (e.g., they call sleep), and thus cannot // of a regular process (e.g., they call sleep), and thus cannot
// be run from main(). // be run from main().
first = 0; first = 0;
initlog(); iinit(ROOTDEV);
initlog(ROOTDEV);
} }
// Return to "caller", actually trapret (see allocproc). // Return to "caller", actually trapret (see allocproc).