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:
rtm 2006-07-21 13:18:04 +00:00
parent 2927081628
commit 11a9947f1a
12 changed files with 376 additions and 31 deletions

View file

@ -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
View 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
View file

@ -0,0 +1,5 @@
struct buf {
int flags;
uchar data[512];
};
#define B_BUSY 0x1

10
defs.h
View file

@ -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
View 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
View 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
View 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
View file

@ -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
View 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
View file

@ -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;

View file

@ -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

View file

@ -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;
} }