bread
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
This commit is contained in:
parent
2927081628
commit
11a9947f1a
12 changed files with 376 additions and 31 deletions
13
Makefile
13
Makefile
|
@ -16,6 +16,8 @@ OBJS = \
|
||||||
trapasm.o\
|
trapasm.o\
|
||||||
trap.o\
|
trap.o\
|
||||||
vectors.o\
|
vectors.o\
|
||||||
|
bio.o\
|
||||||
|
fs.o\
|
||||||
|
|
||||||
# Cross-compiling (e.g., on Mac OS X)
|
# Cross-compiling (e.g., on Mac OS X)
|
||||||
TOOLPREFIX = i386-jos-elf-
|
TOOLPREFIX = i386-jos-elf-
|
||||||
|
@ -30,7 +32,7 @@ OBJDUMP = $(TOOLPREFIX)objdump
|
||||||
CFLAGS = -fno-builtin -O2 -Wall -MD
|
CFLAGS = -fno-builtin -O2 -Wall -MD
|
||||||
AS = $(TOOLPREFIX)gas
|
AS = $(TOOLPREFIX)gas
|
||||||
|
|
||||||
xv6.img : bootblock kernel
|
xv6.img : bootblock kernel fs.img
|
||||||
dd if=/dev/zero of=xv6.img count=10000
|
dd if=/dev/zero of=xv6.img count=10000
|
||||||
dd if=bootblock of=xv6.img conv=notrunc
|
dd if=bootblock of=xv6.img conv=notrunc
|
||||||
dd if=kernel of=xv6.img seek=1 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)
|
$(LD) -N -e main -Ttext 0 -o userfs userfs.o $(ULIB)
|
||||||
$(OBJDUMP) -S userfs > userfs.asm
|
$(OBJDUMP) -S userfs > userfs.asm
|
||||||
|
|
||||||
|
mkfs : mkfs.c fs.h
|
||||||
|
cc -o mkfs mkfs.c
|
||||||
|
|
||||||
|
fs.img : mkfs
|
||||||
|
./mkfs fs.img
|
||||||
|
|
||||||
-include *.d
|
-include *.d
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm -f *.o *.d *.asm vectors.S parport.out \
|
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
|
||||||
|
|
66
bio.c
Normal file
66
bio.c
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
5
buf.h
Normal file
5
buf.h
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
struct buf {
|
||||||
|
int flags;
|
||||||
|
uchar data[512];
|
||||||
|
};
|
||||||
|
#define B_BUSY 0x1
|
10
defs.h
10
defs.h
|
@ -87,6 +87,14 @@ void fd_incref(struct fd *fd);
|
||||||
// ide.c
|
// ide.c
|
||||||
void ide_init(void);
|
void ide_init(void);
|
||||||
void ide_intr(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 *);
|
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);
|
||||||
|
|
73
fs.c
Normal file
73
fs.c
Normal file
|
@ -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);
|
||||||
|
}
|
28
fs.h
Normal file
28
fs.h
Normal file
|
@ -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];
|
||||||
|
};
|
||||||
|
|
12
fsvar.h
Normal file
12
fsvar.h
Normal file
|
@ -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];
|
||||||
|
};
|
16
ide.c
16
ide.c
|
@ -84,7 +84,7 @@ ide_start_request (void)
|
||||||
{
|
{
|
||||||
struct ide_request *r;
|
struct ide_request *r;
|
||||||
|
|
||||||
if (head == tail) {
|
if (head != tail) {
|
||||||
r = &request[tail];
|
r = &request[tail];
|
||||||
ide_wait_ready(0);
|
ide_wait_ready(0);
|
||||||
outb(0x3f6, 0);
|
outb(0x3f6, 0);
|
||||||
|
@ -98,7 +98,7 @@ ide_start_request (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
struct ide_request *r;
|
||||||
if(!holding(&ide_lock))
|
if(!holding(&ide_lock))
|
||||||
|
@ -114,12 +114,12 @@ ide_start_read(uint secno, void *dst, uint nsecs)
|
||||||
r->secno = secno;
|
r->secno = secno;
|
||||||
r->dst = dst;
|
r->dst = dst;
|
||||||
r->nsecs = nsecs;
|
r->nsecs = nsecs;
|
||||||
r->diskno = 0;
|
r->diskno = diskno;
|
||||||
|
|
||||||
ide_start_request();
|
|
||||||
|
|
||||||
head = (head + 1) % NREQUEST;
|
head = (head + 1) % NREQUEST;
|
||||||
|
|
||||||
|
ide_start_request();
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +129,9 @@ ide_finish_read(void *c)
|
||||||
int r = 0;
|
int r = 0;
|
||||||
struct ide_request *req = (struct ide_request *) c;
|
struct ide_request *req = (struct ide_request *) c;
|
||||||
|
|
||||||
|
if(c != &request[tail])
|
||||||
|
panic("ide_finish_read");
|
||||||
|
|
||||||
if(!holding(&ide_lock))
|
if(!holding(&ide_lock))
|
||||||
panic("ide_start_read: not holding ide_lock");
|
panic("ide_start_read: not holding ide_lock");
|
||||||
for (; req->nsecs > 0; req->nsecs--, req->dst += 512) {
|
for (; req->nsecs > 0; req->nsecs--, req->dst += 512) {
|
||||||
|
@ -148,10 +151,9 @@ ide_finish_read(void *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ide_write(uint secno, const void *src, uint nsecs)
|
ide_write(int diskno, uint secno, const void *src, uint nsecs)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
int diskno = 0;
|
|
||||||
|
|
||||||
if(nsecs > 256)
|
if(nsecs > 256)
|
||||||
panic("ide_write");
|
panic("ide_write");
|
||||||
|
|
140
mkfs.c
Normal file
140
mkfs.c
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
2
mmu.h
2
mmu.h
|
@ -125,7 +125,7 @@ struct segdesc {
|
||||||
// Task state segment format (as described by the Pentium architecture book)
|
// Task state segment format (as described by the Pentium architecture book)
|
||||||
struct taskstate {
|
struct taskstate {
|
||||||
uint link; // Old ts selector
|
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 ss0; // after an increase in privilege level
|
||||||
ushort padding1;
|
ushort padding1;
|
||||||
uint * esp1;
|
uint * esp1;
|
||||||
|
|
2
param.h
2
param.h
|
@ -5,3 +5,5 @@
|
||||||
#define NOFILE 16 // file descriptors per process
|
#define NOFILE 16 // file descriptors per process
|
||||||
#define NFD 100 // file descriptors per system
|
#define NFD 100 // file descriptors per system
|
||||||
#define NREQUEST 100 // outstanding disk requests
|
#define NREQUEST 100 // outstanding disk requests
|
||||||
|
#define NBUF 10
|
||||||
|
#define NINODE 100
|
||||||
|
|
40
syscall.c
40
syscall.c
|
@ -7,6 +7,9 @@
|
||||||
#include "traps.h"
|
#include "traps.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
|
#include "buf.h"
|
||||||
|
#include "fs.h"
|
||||||
|
#include "fsvar.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* User code makes a system call with INT T_SYSCALL.
|
* User code makes a system call with INT T_SYSCALL.
|
||||||
|
@ -224,30 +227,27 @@ sys_cons_puts(void)
|
||||||
int
|
int
|
||||||
sys_block(void)
|
sys_block(void)
|
||||||
{
|
{
|
||||||
char buf[512];
|
|
||||||
int i, j;
|
int i, j;
|
||||||
void *c;
|
struct buf *b;
|
||||||
extern struct spinlock ide_lock;
|
struct inode *ip;
|
||||||
|
|
||||||
cprintf("%d: call sys_block\n", cpu());
|
for (i = 0; i < 2; i++) {
|
||||||
for (i = 0; i < 100; i++) {
|
b = bread(1, i);
|
||||||
acquire(&ide_lock);
|
|
||||||
if ((c = ide_start_read(i, buf, 1)) == 0) {
|
cprintf("disk 1 sector %d: ", i);
|
||||||
panic("couldn't start read\n");
|
for (j = 0; j < 4; j++)
|
||||||
}
|
cprintf("%x ", b->data[j] & 0xff);
|
||||||
#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);
|
|
||||||
cprintf("\n");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue