From 8320d61be5613fb2875be859695752b1487fda20 Mon Sep 17 00:00:00 2001 From: Frans Kaashoek Date: Sat, 27 Jun 2015 12:39:13 -0400 Subject: [PATCH] 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. --- defs.h | 4 ++-- fs.c | 26 ++++++++++++-------------- fs.h | 21 +++++++++++---------- log.c | 8 ++++---- main.c | 1 - mkfs.c | 29 ++++++++++++++++------------- proc.c | 3 ++- 7 files changed, 47 insertions(+), 45 deletions(-) diff --git a/defs.h b/defs.h index 43431e3..b47372b 100644 --- a/defs.h +++ b/defs.h @@ -39,7 +39,7 @@ int dirlink(struct inode*, char*, uint); struct inode* dirlookup(struct inode*, char*, uint*); struct inode* ialloc(uint, short); struct inode* idup(struct inode*); -void iinit(void); +void iinit(int dev); void ilock(struct inode*); void iput(struct inode*); void iunlock(struct inode*); @@ -81,7 +81,7 @@ void lapicstartap(uchar, uint); void microdelay(int); // log.c -void initlog(void); +void initlog(int dev); void log_write(struct buf*); void begin_op(); void end_op(); diff --git a/fs.c b/fs.c index 286252d..025b326 100644 --- a/fs.c +++ b/fs.c @@ -22,6 +22,7 @@ #define min(a, b) ((a) < (b) ? (a) : (b)) static void itrunc(struct inode*); +struct superblock sb; // there should be one per dev, but we run with one dev // Read the super block. void @@ -54,12 +55,10 @@ balloc(uint dev) { int b, bi, m; struct buf *bp; - struct superblock sb; bp = 0; - readsb(dev, &sb); 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++){ m = 1 << (bi % 8); if((bp->data[bi/8] & m) == 0){ // Is block free? @@ -80,11 +79,10 @@ static void bfree(int dev, uint b) { struct buf *bp; - struct superblock sb; int bi, m; readsb(dev, &sb); - bp = bread(dev, BBLOCK(b, sb.ninodes)); + bp = bread(dev, BBLOCK(b, sb)); bi = b % BPB; m = 1 << (bi % 8); 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 // list of blocks holding the file's content. // -// The inodes are laid out sequentially on disk immediately after -// the superblock. Each inode has a number, indicating its +// The inodes are laid out sequentially on disk at +// sb.startinode. Each inode has a number, indicating its // position on the disk. // // The kernel keeps a cache of in-use inodes in memory @@ -162,9 +160,12 @@ struct { } icache; void -iinit(void) +iinit(int dev) { 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); @@ -178,12 +179,9 @@ ialloc(uint dev, short type) int inum; struct buf *bp; struct dinode *dip; - struct superblock sb; - - readsb(dev, &sb); 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; if(dip->type == 0){ // a free inode memset(dip, 0, sizeof(*dip)); @@ -204,7 +202,7 @@ iupdate(struct inode *ip) struct buf *bp; 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->type = ip->type; dip->major = ip->major; @@ -281,7 +279,7 @@ ilock(struct inode *ip) release(&icache.lock); 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; ip->type = dip->type; ip->major = dip->major; diff --git a/fs.h b/fs.h index f191d43..e1d7d09 100644 --- a/fs.h +++ b/fs.h @@ -1,22 +1,23 @@ // On-disk file system format. // 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 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 { uint size; // Size of file system image (blocks) uint nblocks; // Number of data blocks uint ninodes; // Number of inodes. 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 @@ -37,13 +38,13 @@ struct dinode { #define IPB (BSIZE / sizeof(struct dinode)) // Block containing inode i -#define IBLOCK(i) ((i) / IPB + 2) +#define IBLOCK(i, sb) ((i) / IPB + sb.inodestart) // Bitmap bits per block #define BPB (BSIZE*8) -// Block containing bit for block b -#define BBLOCK(b, ninodes) (b/BPB + (ninodes)/IPB + 3) +// Block of free map containing bit for block b +#define BBLOCK(b, sb) (b/BPB + sb.bmapstart) // Directory is a file containing a sequence of dirent structures. #define DIRSIZ 14 diff --git a/log.c b/log.c index 01aa580..12db8ca 100644 --- a/log.c +++ b/log.c @@ -50,17 +50,17 @@ static void recover_from_log(void); static void commit(); void -initlog(void) +initlog(int dev) { if (sizeof(struct logheader) >= BSIZE) panic("initlog: too big logheader"); struct superblock sb; initlock(&log.lock, "log"); - readsb(ROOTDEV, &sb); - log.start = sb.size - sb.nlog; + readsb(dev, &sb); + log.start = sb.logstart; log.size = sb.nlog; - log.dev = ROOTDEV; + log.dev = dev; recover_from_log(); } diff --git a/main.c b/main.c index 8a73c0f..40facc4 100644 --- a/main.c +++ b/main.c @@ -31,7 +31,6 @@ main(void) tvinit(); // trap vectors binit(); // buffer cache fileinit(); // file table - iinit(); // inode cache ideinit(); // disk if(!ismp) timerinit(); // uniprocessor timer diff --git a/mkfs.c b/mkfs.c index 7197bc1..957460a 100644 --- a/mkfs.c +++ b/mkfs.c @@ -16,12 +16,12 @@ #define NINODES 200 // 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 ninodeblocks = NINODES / IPB + 1; 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 fsfd; @@ -88,15 +88,20 @@ main(int argc, char *argv[]) exit(1); } - nmeta = 2 + ninodeblocks + nbitmap; - nblocks = FSSIZE - nlog - nmeta; + // 1 fs block = 1 disk sector + nmeta = 2 + nlog + ninodeblocks + nbitmap; + nblocks = FSSIZE - nmeta; sb.size = xint(FSSIZE); - sb.nblocks = xint(nblocks); // so whole disk is size sectors + sb.nblocks = xint(nblocks); sb.ninodes = xint(NINODES); 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 @@ -180,7 +185,7 @@ winode(uint inum, struct dinode *ip) uint bn; struct dinode *dip; - bn = IBLOCK(inum); + bn = IBLOCK(inum, sb); rsect(bn, buf); dip = ((struct dinode*)buf) + (inum % IPB); *dip = *ip; @@ -194,7 +199,7 @@ rinode(uint inum, struct dinode *ip) uint bn; struct dinode *dip; - bn = IBLOCK(inum); + bn = IBLOCK(inum, sb); rsect(bn, buf); dip = ((struct dinode*)buf) + (inum % IPB); *ip = *dip; @@ -239,8 +244,8 @@ balloc(int used) for(i = 0; i < used; i++){ buf[i/8] = buf[i/8] | (0x1 << (i%8)); } - printf("balloc: write bitmap block at sector %d\n", ninodeblocks+2); - wsect(ninodeblocks+2, buf); + printf("balloc: write bitmap block at sector %d\n", sb.bmapstart); + wsect(sb.bmapstart, buf); } #define min(a, b) ((a) < (b) ? (a) : (b)) @@ -256,8 +261,8 @@ iappend(uint inum, void *xp, int n) uint x; rinode(inum, &din); - off = xint(din.size); + // printf("append inum %d at off %d sz %d\n", inum, off, n); while(n > 0){ fbn = off / BSIZE; assert(fbn < MAXFILE); @@ -268,10 +273,8 @@ iappend(uint inum, void *xp, int n) x = xint(din.addrs[fbn]); } else { if(xint(din.addrs[NDIRECT]) == 0){ - // printf("allocate indirect block\n"); din.addrs[NDIRECT] = xint(freeblock++); } - // printf("read indirect block\n"); rsect(xint(din.addrs[NDIRECT]), (char*)indirect); if(indirect[fbn - NDIRECT] == 0){ indirect[fbn - NDIRECT] = xint(freeblock++); diff --git a/proc.c b/proc.c index a642f5a..3ac41f6 100644 --- a/proc.c +++ b/proc.c @@ -339,7 +339,8 @@ forkret(void) // of a regular process (e.g., they call sleep), and thus cannot // be run from main(). first = 0; - initlog(); + iinit(ROOTDEV); + initlog(ROOTDEV); } // Return to "caller", actually trapret (see allocproc).