diff options
| -rw-r--r-- | Makefile | 13 | ||||
| -rw-r--r-- | bio.c | 66 | ||||
| -rw-r--r-- | buf.h | 5 | ||||
| -rw-r--r-- | defs.h | 10 | ||||
| -rw-r--r-- | fs.c | 73 | ||||
| -rw-r--r-- | fs.h | 28 | ||||
| -rw-r--r-- | fsvar.h | 12 | ||||
| -rw-r--r-- | ide.c | 16 | ||||
| -rw-r--r-- | mkfs.c | 140 | ||||
| -rw-r--r-- | mmu.h | 2 | ||||
| -rw-r--r-- | param.h | 2 | ||||
| -rw-r--r-- | syscall.c | 42 | 
12 files changed, 377 insertions, 32 deletions
| @@ -16,6 +16,8 @@ OBJS = \  	trapasm.o\  	trap.o\  	vectors.o\ +	bio.o\ +	fs.o\  # Cross-compiling (e.g., on Mac OS X)  TOOLPREFIX = i386-jos-elf- @@ -30,7 +32,7 @@ OBJDUMP = $(TOOLPREFIX)objdump  CFLAGS = -fno-builtin -O2 -Wall -MD  AS = $(TOOLPREFIX)gas -xv6.img : bootblock kernel +xv6.img : bootblock kernel fs.img  	dd if=/dev/zero of=xv6.img count=10000  	dd if=bootblock of=xv6.img conv=notrunc  	dd if=kernel of=xv6.img seek=1 conv=notrunc @@ -68,8 +70,15 @@ userfs : userfs.o $(ULIB)  	$(LD) -N -e main -Ttext 0 -o userfs userfs.o $(ULIB)  	$(OBJDUMP) -S userfs > userfs.asm +mkfs : mkfs.c fs.h +	cc -o mkfs mkfs.c + +fs.img : mkfs +	./mkfs fs.img +  -include *.d  clean :   	rm -f *.o *.d *.asm vectors.S parport.out \ -		bootblock kernel xv6.img user1 userfs usertests +		bootblock kernel xv6.img user1 userfs usertests \ +		fs.img mkfs @@ -0,0 +1,66 @@ +#include "types.h" +#include "param.h" +#include "x86.h" +#include "mmu.h" +#include "proc.h" +#include "defs.h" +#include "spinlock.h" +#include "buf.h" + +struct buf buf[NBUF]; +struct spinlock buf_table_lock; + +struct buf * +getblk() +{ +  int i; + +  acquire(&buf_table_lock); + +  // XXX need to lock the block even if not caching, to +  // avoid read modify write problems. + +  while(1){ +    for(i = 0; i < NBUF; i++){ +      if((buf[i].flags & B_BUSY) == 0){ +        buf[i].flags |= B_BUSY; +        release(&buf_table_lock); +        return buf + i; +      } +    } +    sleep(buf, &buf_table_lock); +  } +} + +struct buf * +bread(uint dev, uint sector) +{ +  void *c; +  struct buf *b; +  extern struct spinlock ide_lock; + +  b = getblk(); + +  acquire(&ide_lock); +  c = ide_start_read(dev & 0xff, sector, b->data, 1); +  // sleep (c, &ide_lock); +  ide_finish_read(c); +  release(&ide_lock); + +  return b; +} + +void +brelse(struct buf *b) +{ +  if((b->flags & B_BUSY) == 0) +    panic("brelse"); +   +  acquire(&buf_table_lock); + +  b->flags &= ~B_BUSY; +  wakeup(buf); + +  release(&buf_table_lock); +} + @@ -0,0 +1,5 @@ +struct buf { +  int flags; +  uchar data[512]; +}; +#define B_BUSY 0x1 @@ -87,6 +87,14 @@ void fd_incref(struct fd *fd);  // ide.c  void ide_init(void);  void ide_intr(void); -void* ide_start_read(uint secno, void *dst, uint nsecs); +void* ide_start_read(int diskno, uint secno, void *dst, uint nsecs);  int ide_finish_read(void *); +// bio.c +struct buf; +struct buf *bread(uint, uint); +void brelse(struct buf *); + +// fs.c +struct inode * iget(uint dev, uint inum); +void iput(struct inode *ip); @@ -0,0 +1,73 @@ +#include "types.h" +#include "param.h" +#include "x86.h" +#include "mmu.h" +#include "proc.h" +#include "defs.h" +#include "spinlock.h" +#include "buf.h" +#include "fs.h" +#include "fsvar.h" + +// these are inodes currently in use +// an entry is free if count == 0 +struct inode inode[NINODE]; +struct spinlock inode_table_lock; + +struct inode * +iget(uint dev, uint inum) +{ +  struct inode *ip, *nip = 0; +  struct dinode *dip; +  struct buf *bp; + +  acquire(&inode_table_lock); + + loop: +  for(ip = &inode[0]; ip < &inode[NINODE]; ip++){ +    if(ip->count > 0 && ip->dev == dev && ip->inum == inum){ +      if(ip->busy){ +        sleep(ip, &inode_table_lock); +        goto loop; +      } +      ip->count++; +      release(&inode_table_lock); +      return ip; +    } +    if(nip == 0 && ip->count == 0) +      nip = ip; +  } + +  if(nip == 0) +    panic("out of inodes"); + +  nip->dev = dev; +  nip->inum = inum; +  nip->count = 1; +  nip->busy = 1; + +  release(&inode_table_lock); + +  bp = bread(dev, inum / IPB + 2); +  dip = &((struct dinode *)(bp->data))[inum % IPB]; +  nip->type = dip->type; +  nip->nlink = dip->nlink; +  nip->size = dip->size; +  memmove(nip->addrs, dip->addrs, sizeof(nip->addrs)); +  cprintf("bn %d off %d\n", inum / IPB + 2, (unsigned)dip - (unsigned)bp->data); +  brelse(bp); + +  return nip; +} + +void +iput(struct inode *ip) +{ +  acquire(&inode_table_lock); + +  ip->count -= 1; +  ip->busy = 0; +  wakeup(ip); + +  release(&inode_table_lock); +} @@ -0,0 +1,28 @@ +// on-disk file system format + +// second sector +struct superblock{ +  int nblocks; +  int ninodes; +}; + +#define NDIRECT 14 + +// inodes start at the third sector +// and blocks start at (ninodes * sizeof(dinode) + 511) / 512 +struct dinode { +  short type; +  short nlink; +  uint size; +  uint addrs[NDIRECT]; +}; +#define T_DIR 1 +#define T_FILE 2 + +#define IPB (512 / sizeof(struct dinode)) + +struct dirent { +  ushort inum; +  char name[14]; +}; + @@ -0,0 +1,12 @@ +// in-core file system types + +struct inode { +  uint dev; +  uint inum; +  int count; +  int busy; +  short type; +  short nlink; +  uint size; +  uint addrs[NDIRECT]; +}; @@ -84,7 +84,7 @@ ide_start_request (void)  {    struct ide_request *r; -  if (head == tail) { +  if (head != tail) {      r = &request[tail];      ide_wait_ready(0);      outb(0x3f6, 0); @@ -98,7 +98,7 @@ ide_start_request (void)  }  void * -ide_start_read(uint secno, void *dst, uint nsecs) +ide_start_read(int diskno, uint secno, void *dst, uint nsecs)  {    struct ide_request *r;    if(!holding(&ide_lock)) @@ -114,12 +114,12 @@ ide_start_read(uint secno, void *dst, uint nsecs)    r->secno = secno;    r->dst = dst;    r->nsecs = nsecs; -  r->diskno = 0; - -  ide_start_request(); +  r->diskno = diskno;    head = (head + 1) % NREQUEST; +  ide_start_request(); +    return r;  } @@ -129,6 +129,9 @@ ide_finish_read(void *c)    int r = 0;    struct ide_request *req = (struct ide_request *) c; +  if(c != &request[tail]) +    panic("ide_finish_read"); +    if(!holding(&ide_lock))      panic("ide_start_read: not holding ide_lock");    for (; req->nsecs > 0; req->nsecs--, req->dst += 512) { @@ -148,10 +151,9 @@ ide_finish_read(void *c)  }  int -ide_write(uint secno, const void *src, uint nsecs) +ide_write(int diskno, uint secno, const void *src, uint nsecs)  {    int r; -  int diskno = 0;    if(nsecs > 256)      panic("ide_write"); @@ -0,0 +1,140 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include "types.h" +#include "param.h" +#include "fs.h" + +int nblocks = 1009; +int ninodes = 100; + +int fd; +struct superblock sb; +char zeroes[512]; +uint freeblock; + +void wsect(uint, void *); +void winode(uint, struct dinode *); +void rsect(uint sec, void *buf); + +// convert to intel byte order +ushort +xshort(ushort x) +{ +  ushort y; +  uchar *a = &y; +  a[0] = x; +  a[1] = x >> 8; +  return y; +} + +uint +xint(uint x) +{ +  uint y; +  uchar *a = &y; +  a[0] = x; +  a[1] = x >> 8; +  a[2] = x >> 16; +  a[3] = x >> 24; +  return y; +} + +main(int argc, char *argv[]) +{ +  int i; +  struct dinode din; +  char dbuf[512]; + +  if(argc != 2){ +    fprintf(stderr, "Usage: mkfs fs.img\n"); +    exit(1); +  } + +  if(sizeof(struct dinode) * IPB != 512){ +    fprintf(stderr, "sizeof(dinode) must divide 512\n"); +    exit(1); +  } + +  fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); +  if(fd < 0){ +    perror(argv[1]); +    exit(1); +  } + +  sb.nblocks = xint(nblocks); // so whole disk is 1024 sectors +  sb.ninodes = xint(ninodes); + +  freeblock = ninodes / IPB + 2; + +  for(i = 0; i < nblocks + (ninodes / IPB) + 3; i++) +    wsect(i, zeroes); + +  wsect(1, &sb); + +  bzero(&din, sizeof(din)); +  din.type = xshort(T_DIR); +  din.nlink = xshort(2); +  din.size = xint(512); +  din.addrs[0] = xint(freeblock++); +  winode(1, &din); + +  bzero(dbuf, sizeof(dbuf)); +  ((struct dirent *) dbuf)[0].inum = xshort(1); +  strcpy(((struct dirent *) dbuf)[0].name, "."); +  ((struct dirent *) dbuf)[1].inum = xshort(1); +  strcpy(((struct dirent *) dbuf)[1].name, ".."); +  wsect(din.addrs[0], dbuf); + +  exit(0); +} + +void +wsect(uint sec, void *buf) +{ +  if(lseek(fd, sec * 512L, 0) != sec * 512L){ +    perror("lseek"); +    exit(1); +  } +  if(write(fd, buf, 512) != 512){ +    perror("write"); +    exit(1); +  } +} + +uint +i2b(uint inum) +{ +  return (inum / IPB) + 2; +} + +void +winode(uint inum, struct dinode *ip) +{ +  char buf[512]; +  uint bn; +  struct dinode *dip; + +  bn = i2b(inum); +  rsect(bn, buf); +  dip = ((struct dinode *) buf) + (inum % IPB); +  *dip = *ip; +  printf("bn %d off %d\n", +         bn, (unsigned)dip - (unsigned) buf); +  wsect(bn, buf); +} + +void +rsect(uint sec, void *buf) +{ +  if(lseek(fd, sec * 512L, 0) != sec * 512L){ +    perror("lseek"); +    exit(1); +  } +  if(read(fd, buf, 512) != 512){ +    perror("read"); +    exit(1); +  } +} @@ -125,7 +125,7 @@ struct segdesc {  // Task state segment format (as described by the Pentium architecture book)  struct taskstate {  	uint link;	// Old ts selector -	uint * esp0;	// Stack pointers and segment selectors +	uint esp0;	// Stack pointers and segment selectors  	ushort ss0;	//   after an increase in privilege level  	ushort padding1;  	uint * esp1; @@ -5,3 +5,5 @@  #define NOFILE 16 // file descriptors per process  #define NFD 100 // file descriptors per system  #define NREQUEST 100 // outstanding disk requests +#define NBUF 10 +#define NINODE 100 @@ -7,6 +7,9 @@  #include "traps.h"  #include "syscall.h"  #include "spinlock.h" +#include "buf.h" +#include "fs.h" +#include "fsvar.h"  /*   * User code makes a system call with INT T_SYSCALL. @@ -224,30 +227,27 @@ sys_cons_puts(void)  int  sys_block(void)  { -  char buf[512];    int i, j; -  void *c; -  extern struct spinlock ide_lock; - -  cprintf("%d: call sys_block\n", cpu()); -  for (i = 0; i < 100; i++) { -    acquire(&ide_lock); -    if ((c = ide_start_read(i, buf, 1)) == 0) { -      panic("couldn't start read\n"); -    } -#if 0 -    cprintf("call sleep\n"); -    sleep (c, &ide_lock); -#endif -    if (ide_finish_read(c)) { -      panic("couldn't do read\n"); -    } -    release(&ide_lock); -    cprintf("sector %d: ", i); -    for (j = 0; j < 2; j++) -      cprintf("%x ", buf[j] & 0xff); +  struct buf *b; +  struct inode *ip; + +  for (i = 0; i < 2; i++) { +    b = bread(1, i); + +    cprintf("disk 1 sector %d: ", i); +    for (j = 0; j < 4; j++) +      cprintf("%x ", b->data[j] & 0xff);      cprintf("\n"); + +    brelse(b);    } + +  ip = iget(1, 1); +  cprintf("%d %d %d %d %d %d %d %d\n", +          ip->dev, ip->inum, ip->count, ip->busy, +          ip->type, ip->nlink, ip->size, ip->addrs[0]); +  iput(ip); +    return 0;  } | 
