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\
|
||||
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
|
||||
|
|
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
|
||||
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);
|
||||
|
|
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;
|
||||
|
||||
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");
|
||||
|
|
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)
|
||||
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;
|
||||
|
|
2
param.h
2
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
|
||||
|
|
40
syscall.c
40
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;
|
||||
struct buf *b;
|
||||
struct inode *ip;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue