Skip to content

Commit e6b3fab

Browse files
committed
feat: init Lab5
1 parent 289a520 commit e6b3fab

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+4738
-21
lines changed

GNUmakefile

+3
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ include boot/Makefrag
141141
include kern/Makefrag
142142
include lib/Makefrag
143143
include user/Makefrag
144+
include fs/Makefrag
144145

145146

146147
CPUS ?= 1
@@ -149,6 +150,8 @@ QEMUOPTS = -drive file=$(OBJDIR)/kern/kernel.img,index=0,media=disk,format=raw -
149150
QEMUOPTS += $(shell if $(QEMU) -nographic -help | grep -q '^-D '; then echo '-D qemu.log'; fi)
150151
IMAGES = $(OBJDIR)/kern/kernel.img
151152
QEMUOPTS += -smp $(CPUS)
153+
QEMUOPTS += -drive file=$(OBJDIR)/fs/fs.img,index=1,media=disk,format=raw
154+
IMAGES += $(OBJDIR)/fs/fs.img
152155
QEMUOPTS += $(QEMUEXTRA)
153156

154157
.gdbinit: .gdbinit.tmpl

conf/lab.mk

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
LAB=4
2-
PACKAGEDATE=Mon Oct 8 21:31:51 PDT 2018
1+
LAB=5
2+
PACKAGEDATE=Wed Oct 24 20:44:37 EDT 2018

fs/Makefrag

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
2+
OBJDIRS += fs
3+
4+
FSOFILES := $(OBJDIR)/fs/ide.o \
5+
$(OBJDIR)/fs/bc.o \
6+
$(OBJDIR)/fs/fs.o \
7+
$(OBJDIR)/fs/serv.o \
8+
$(OBJDIR)/fs/test.o \
9+
10+
USERAPPS := $(OBJDIR)/user/init
11+
12+
FSIMGTXTFILES := fs/newmotd \
13+
fs/motd
14+
15+
16+
USERAPPS := $(USERAPPS) \
17+
$(OBJDIR)/user/cat \
18+
$(OBJDIR)/user/echo \
19+
$(OBJDIR)/user/init \
20+
$(OBJDIR)/user/ls \
21+
$(OBJDIR)/user/lsfd \
22+
$(OBJDIR)/user/num \
23+
$(OBJDIR)/user/forktree \
24+
$(OBJDIR)/user/primes \
25+
$(OBJDIR)/user/primespipe \
26+
$(OBJDIR)/user/sh \
27+
$(OBJDIR)/user/testfdsharing \
28+
$(OBJDIR)/user/testkbd \
29+
$(OBJDIR)/user/testpipe \
30+
$(OBJDIR)/user/testpteshare \
31+
$(OBJDIR)/user/testshell \
32+
$(OBJDIR)/user/hello \
33+
$(OBJDIR)/user/faultio \
34+
35+
FSIMGTXTFILES := $(FSIMGTXTFILES) \
36+
fs/lorem \
37+
fs/script \
38+
fs/testshell.key \
39+
fs/testshell.sh
40+
41+
42+
FSIMGFILES := $(FSIMGTXTFILES) $(USERAPPS)
43+
44+
$(OBJDIR)/fs/%.o: fs/%.c fs/fs.h inc/lib.h $(OBJDIR)/.vars.USER_CFLAGS
45+
@echo + cc[USER] $<
46+
@mkdir -p $(@D)
47+
$(V)$(CC) -nostdinc $(USER_CFLAGS) -c -o $@ $<
48+
49+
$(OBJDIR)/fs/fs: $(FSOFILES) $(OBJDIR)/lib/entry.o $(OBJDIR)/lib/libjos.a user/user.ld
50+
@echo + ld $@
51+
$(V)mkdir -p $(@D)
52+
$(V)$(LD) -o $@ $(ULDFLAGS) $(LDFLAGS) -nostdlib \
53+
$(OBJDIR)/lib/entry.o $(FSOFILES) \
54+
-L$(OBJDIR)/lib -ljos $(GCC_LIB)
55+
$(V)$(OBJDUMP) -S $@ >[email protected]
56+
57+
# How to build the file system image
58+
$(OBJDIR)/fs/fsformat: fs/fsformat.c
59+
@echo + mk $(OBJDIR)/fs/fsformat
60+
$(V)mkdir -p $(@D)
61+
$(V)$(NCC) $(NATIVE_CFLAGS) -o $(OBJDIR)/fs/fsformat fs/fsformat.c
62+
63+
$(OBJDIR)/fs/clean-fs.img: $(OBJDIR)/fs/fsformat $(FSIMGFILES)
64+
@echo + mk $(OBJDIR)/fs/clean-fs.img
65+
$(V)mkdir -p $(@D)
66+
$(V)$(OBJDIR)/fs/fsformat $(OBJDIR)/fs/clean-fs.img 1024 $(FSIMGFILES)
67+
68+
$(OBJDIR)/fs/fs.img: $(OBJDIR)/fs/clean-fs.img
69+
@echo + cp $(OBJDIR)/fs/clean-fs.img $@
70+
$(V)cp $(OBJDIR)/fs/clean-fs.img $@
71+
72+
all: $(OBJDIR)/fs/fs.img
73+
74+
#all: $(addsuffix .sym, $(USERAPPS))
75+
76+
#all: $(addsuffix .asm, $(USERAPPS))
77+

fs/bc.c

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
2+
#include "fs.h"
3+
4+
// Return the virtual address of this disk block.
5+
void*
6+
diskaddr(uint32_t blockno)
7+
{
8+
if (blockno == 0 || (super && blockno >= super->s_nblocks))
9+
panic("bad block number %08x in diskaddr", blockno);
10+
return (char*) (DISKMAP + blockno * BLKSIZE);
11+
}
12+
13+
// Is this virtual address mapped?
14+
bool
15+
va_is_mapped(void *va)
16+
{
17+
return (uvpd[PDX(va)] & PTE_P) && (uvpt[PGNUM(va)] & PTE_P);
18+
}
19+
20+
// Is this virtual address dirty?
21+
bool
22+
va_is_dirty(void *va)
23+
{
24+
return (uvpt[PGNUM(va)] & PTE_D) != 0;
25+
}
26+
27+
// Fault any disk block that is read in to memory by
28+
// loading it from disk.
29+
static void
30+
bc_pgfault(struct UTrapframe *utf)
31+
{
32+
void *addr = (void *) utf->utf_fault_va;
33+
uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE;
34+
int r;
35+
36+
// Check that the fault was within the block cache region
37+
if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE))
38+
panic("page fault in FS: eip %08x, va %08x, err %04x",
39+
utf->utf_eip, addr, utf->utf_err);
40+
41+
// Sanity check the block number.
42+
if (super && blockno >= super->s_nblocks)
43+
panic("reading non-existent block %08x\n", blockno);
44+
45+
// Allocate a page in the disk map region, read the contents
46+
// of the block from the disk into that page.
47+
// Hint: first round addr to page boundary. fs/ide.c has code to read
48+
// the disk.
49+
//
50+
// LAB 5: you code here:
51+
52+
// Clear the dirty bit for the disk block page since we just read the
53+
// block from disk
54+
if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0)
55+
panic("in bc_pgfault, sys_page_map: %e", r);
56+
57+
// Check that the block we read was allocated. (exercise for
58+
// the reader: why do we do this *after* reading the block
59+
// in?)
60+
if (bitmap && block_is_free(blockno))
61+
panic("reading free block %08x\n", blockno);
62+
}
63+
64+
// Flush the contents of the block containing VA out to disk if
65+
// necessary, then clear the PTE_D bit using sys_page_map.
66+
// If the block is not in the block cache or is not dirty, does
67+
// nothing.
68+
// Hint: Use va_is_mapped, va_is_dirty, and ide_write.
69+
// Hint: Use the PTE_SYSCALL constant when calling sys_page_map.
70+
// Hint: Don't forget to round addr down.
71+
void
72+
flush_block(void *addr)
73+
{
74+
uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE;
75+
76+
if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE))
77+
panic("flush_block of bad va %08x", addr);
78+
79+
// LAB 5: Your code here.
80+
panic("flush_block not implemented");
81+
}
82+
83+
// Test that the block cache works, by smashing the superblock and
84+
// reading it back.
85+
static void
86+
check_bc(void)
87+
{
88+
struct Super backup;
89+
90+
// back up super block
91+
memmove(&backup, diskaddr(1), sizeof backup);
92+
93+
// smash it
94+
strcpy(diskaddr(1), "OOPS!\n");
95+
flush_block(diskaddr(1));
96+
assert(va_is_mapped(diskaddr(1)));
97+
assert(!va_is_dirty(diskaddr(1)));
98+
99+
// clear it out
100+
sys_page_unmap(0, diskaddr(1));
101+
assert(!va_is_mapped(diskaddr(1)));
102+
103+
// read it back in
104+
assert(strcmp(diskaddr(1), "OOPS!\n") == 0);
105+
106+
// fix it
107+
memmove(diskaddr(1), &backup, sizeof backup);
108+
flush_block(diskaddr(1));
109+
110+
// Now repeat the same experiment, but pass an unaligned address to
111+
// flush_block.
112+
113+
// back up super block
114+
memmove(&backup, diskaddr(1), sizeof backup);
115+
116+
// smash it
117+
strcpy(diskaddr(1), "OOPS!\n");
118+
119+
// Pass an unaligned address to flush_block.
120+
flush_block(diskaddr(1) + 20);
121+
assert(va_is_mapped(diskaddr(1)));
122+
123+
// Skip the !va_is_dirty() check because it makes the bug somewhat
124+
// obscure and hence harder to debug.
125+
//assert(!va_is_dirty(diskaddr(1)));
126+
127+
// clear it out
128+
sys_page_unmap(0, diskaddr(1));
129+
assert(!va_is_mapped(diskaddr(1)));
130+
131+
// read it back in
132+
assert(strcmp(diskaddr(1), "OOPS!\n") == 0);
133+
134+
// fix it
135+
memmove(diskaddr(1), &backup, sizeof backup);
136+
flush_block(diskaddr(1));
137+
138+
cprintf("block cache is good\n");
139+
}
140+
141+
void
142+
bc_init(void)
143+
{
144+
struct Super super;
145+
set_pgfault_handler(bc_pgfault);
146+
check_bc();
147+
148+
// cache the super block by reading it once
149+
memmove(&super, diskaddr(1), sizeof super);
150+
}
151+

0 commit comments

Comments
 (0)