summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile13
-rw-r--r--bio.c66
-rw-r--r--buf.h5
-rw-r--r--defs.h10
-rw-r--r--fs.c73
-rw-r--r--fs.h28
-rw-r--r--fsvar.h12
-rw-r--r--ide.c16
-rw-r--r--mkfs.c140
-rw-r--r--mmu.h2
-rw-r--r--param.h2
-rw-r--r--syscall.c42
12 files changed, 377 insertions, 32 deletions
diff --git a/Makefile b/Makefile
index a9ae631..d995429 100644
--- 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
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
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 beed68a..0ed71bb 100644
--- 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
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
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
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 5b75053..291ab83 100644
--- 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
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 fd10ed6..82fb89d 100644
--- 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 bdd8b70..9b5c5e8 100644
--- 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
diff --git a/syscall.c b/syscall.c
index ff5fea6..68af208 100644
--- 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;
}