]> Devi Nivas Git - cs3210-lab1.git/commitdiff
bread
authorrtm <rtm>
Fri, 21 Jul 2006 13:18:04 +0000 (13:18 +0000)
committerrtm <rtm>
Fri, 21 Jul 2006 13:18:04 +0000 (13:18 +0000)
iget
mkfs makes a file system image
put this in your .bochsrc:
ata0-slave: type=disk, mode=flat, path="fs.img", cylinders=1024, heads=1, spt=1

12 files changed:
Makefile
bio.c [new file with mode: 0644]
buf.h [new file with mode: 0644]
defs.h
fs.c [new file with mode: 0644]
fs.h [new file with mode: 0644]
fsvar.h [new file with mode: 0644]
ide.c
mkfs.c [new file with mode: 0644]
mmu.h
param.h
syscall.c

index a9ae631b4240e0b168192f8aa44578dd39301119..d9954295bc6f503fe388203815ae1afe6d943e1c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/bio.c b/bio.c
new file mode 100644 (file)
index 0000000..9be11df
--- /dev/null
+++ b/bio.c
@@ -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);
+}
+
diff --git a/buf.h b/buf.h
new file mode 100644 (file)
index 0000000..a4cea5e
--- /dev/null
+++ b/buf.h
@@ -0,0 +1,5 @@
+struct buf {
+  int flags;
+  uchar data[512];
+};
+#define B_BUSY 0x1
diff --git a/defs.h b/defs.h
index beed68a940f8f0a6c79b6928ee122dee4e4576b9..0ed71bb7ae6060d78afdbcd31f3f8d2e65a3a81e 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -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);
diff --git a/fs.c b/fs.c
new file mode 100644 (file)
index 0000000..48c943a
--- /dev/null
+++ b/fs.c
@@ -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);
+}
diff --git a/fs.h b/fs.h
new file mode 100644 (file)
index 0000000..b710e1c
--- /dev/null
+++ b/fs.h
@@ -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];
+};
+
diff --git a/fsvar.h b/fsvar.h
new file mode 100644 (file)
index 0000000..4388f75
--- /dev/null
+++ b/fsvar.h
@@ -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];
+};
diff --git a/ide.c b/ide.c
index 5b750539f867f08b740df664a6b1498a5acb67af..291ab8325a7603dadf945e7b1ae405ddd00ee778 100644 (file)
--- a/ide.c
+++ b/ide.c
@@ -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");
diff --git a/mkfs.c b/mkfs.c
new file mode 100644 (file)
index 0000000..033e064
--- /dev/null
+++ b/mkfs.c
@@ -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);
+  }
+}
diff --git a/mmu.h b/mmu.h
index fd10ed6fd5a97e6976c72e06c44f94b39c8eb114..82fb89db54b5849873f95796739c3ef53a158621 100644 (file)
--- a/mmu.h
+++ b/mmu.h
@@ -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;
diff --git a/param.h b/param.h
index bdd8b70822529b9ed22c84f3c8e654719fdaa246..9b5c5e82f60af4067beb1ba983be54ac0bb3d337 100644 (file)
--- a/param.h
+++ b/param.h
@@ -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
index ff5fea6fd927e7e23cf87c08f519a105d9a639d4..68af208c098643c1725926945ae560ff12e5ebbb 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -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;
 }