Skip to content

Commit f36f35a

Browse files
committed
Chapter 6
1 parent e0c7abe commit f36f35a

34 files changed

+2223
-310
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ build
55
target
66
/user
77
link_app.S
8+
initproc.S
89
kernel_app.ld
910
*.o
1011
*.d
1112
*.asm
1213
*.sym
14+
nfs/*.img
15+
nfs/fs

Makefile

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
all: build
33

44
K = os
5+
U = user
6+
F = nfs
57

68
TOOLPREFIX = riscv64-unknown-elf-
79
CC = $(TOOLPREFIX)gcc
@@ -21,11 +23,15 @@ OBJS = $(C_OBJS) $(AS_OBJS)
2123

2224
HEADER_DEP = $(addsuffix .d, $(basename $(C_OBJS)))
2325

24-
ifeq (,$(findstring link_app.o,$(OBJS)))
25-
AS_OBJS += $(BUILDDIR)/$K/link_app.o
26+
ifeq (,$(findstring initproc.o,$(OBJS)))
27+
AS_OBJS += $(BUILDDIR)/$K/initproc.o
2628
endif
2729

28-
-include $(HEADER_DEP)
30+
INIT_PROC ?= usershell
31+
32+
$(K)/initproc.o: $K/initproc.S
33+
$(K)/initproc.S: scripts/initproc.py .FORCE
34+
@$(PY) scripts/initproc.py $(INIT_PROC)
2935

3036
CFLAGS = -Wall -Werror -O -fno-omit-frame-pointer -ggdb
3137
CFLAGS += -MD
@@ -34,7 +40,6 @@ CFLAGS += -ffreestanding -fno-common -nostdlib -mno-relax
3440
CFLAGS += -I$K
3541
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
3642

37-
3843
LOG ?= error
3944

4045
ifeq ($(LOG), error)
@@ -78,22 +83,17 @@ $(HEADER_DEP): $(BUILDDIR)/$K/%.d : $K/%.c
7883

7984
INIT_PROC ?= usershell
8085

81-
os/link_app.o: $K/link_app.S
82-
os/link_app.S: scripts/pack.py .FORCE
83-
@$(PY) scripts/pack.py $(INIT_PROC)
84-
os/kernel_app.ld: scripts/kernelld.py .FORCE
85-
@$(PY) scripts/kernelld.py
86-
8786
build: build/kernel
8887

89-
build/kernel: $(OBJS) os/kernel_app.ld
90-
$(LD) $(LDFLAGS) -T os/kernel_app.ld -o $(BUILDDIR)/kernel $(OBJS)
88+
build/kernel: $(OBJS) os/kernel.ld
89+
$(LD) $(LDFLAGS) -T os/kernel.ld -o $(BUILDDIR)/kernel $(OBJS)
9190
$(OBJDUMP) -S $(BUILDDIR)/kernel > $(BUILDDIR)/kernel.asm
9291
$(OBJDUMP) -t $(BUILDDIR)/kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(BUILDDIR)/kernel.sym
9392
@echo 'Build kernel done'
9493

9594
clean:
96-
rm -rf $(BUILDDIR) os/kernel_app.ld os/link_app.S
95+
rm -rf $(BUILDDIR) os/initproc.S
96+
rm -f $(F)/*.img
9797

9898
# BOARD
9999
BOARD ?= qemu
@@ -106,16 +106,24 @@ QEMUOPTS = \
106106
-machine virt \
107107
-bios $(BOOTLOADER) \
108108
-kernel build/kernel \
109+
-drive file=$(F)/fs-copy.img,if=none,format=raw,id=x0 \
110+
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
111+
112+
$(F)/fs.img:
113+
make -C $(F)
114+
115+
$(F)/fs-copy.img: $(F)/fs.img
116+
@$(CP) $< $@
109117

110-
run: build/kernel
118+
run: build/kernel $(F)/fs-copy.img
111119
$(QEMU) $(QEMUOPTS)
112120

113121
# QEMU's gdb stub command line changed in 0.11
114122
QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
115123
then echo "-gdb tcp::15234"; \
116124
else echo "-s -p 15234"; fi)
117125

118-
debug: build/kernel .gdbinit
126+
debug: build/kernel .gdbinit $(F)/fs-copy.img
119127
$(QEMU) $(QEMUOPTS) -S $(QEMUGDB) &
120128
sleep 1
121129
$(GDB)

nfs/Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.DEFAULT_GOAL = fs.img
2+
3+
U := ../user
4+
USER_BIN_DIR := target/bin
5+
6+
FS_FUSE := fs
7+
8+
$(FS_FUSE): fs.c fs.h types.h
9+
10+
fs.img: $(FS_FUSE)
11+
./$(FS_FUSE) $@ $(wildcard $(U)/$(USER_BIN_DIR)/*)
12+
13+
clean:
14+
rm *.img $(FS_FUSE)

nfs/fs.c

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
#include <assert.h>
2+
#include <fcntl.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <string.h>
6+
#include <unistd.h>
7+
8+
#include "fs.h"
9+
10+
#ifndef static_assert
11+
#define static_assert(a, b) \
12+
do { \
13+
switch (0) \
14+
case 0: \
15+
case (a):; \
16+
} while (0)
17+
#endif
18+
19+
#define NINODES 200
20+
21+
// Disk layout:
22+
// [ boot block | sb block | inode blocks | free bit map | data blocks ]
23+
24+
int nbitmap = FSSIZE / (BSIZE * 8) + 1;
25+
int ninodeblocks = NINODES / IPB + 1;
26+
int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap)
27+
int nblocks; // Number of data blocks
28+
29+
int fsfd;
30+
struct superblock sb;
31+
char zeroes[BSIZE];
32+
uint freeinode = 1;
33+
uint freeblock;
34+
35+
char *basename(char *);
36+
void balloc(int);
37+
void wsect(uint, void *);
38+
void winode(uint, struct dinode *);
39+
void rinode(uint inum, struct dinode *ip);
40+
void rsect(uint sec, void *buf);
41+
uint ialloc(ushort type);
42+
void iappend(uint inum, void *p, int n);
43+
44+
// convert to intel byte order
45+
ushort xshort(ushort x)
46+
{
47+
ushort y;
48+
uchar *a = (uchar *)&y;
49+
a[0] = x;
50+
a[1] = x >> 8;
51+
return y;
52+
}
53+
54+
uint xint(uint x)
55+
{
56+
uint y;
57+
uchar *a = (uchar *)&y;
58+
a[0] = x;
59+
a[1] = x >> 8;
60+
a[2] = x >> 16;
61+
a[3] = x >> 24;
62+
return y;
63+
}
64+
65+
int main(int argc, char *argv[])
66+
{
67+
int i, cc, fd;
68+
uint rootino, inum, off;
69+
struct dirent de;
70+
char buf[BSIZE];
71+
struct dinode din;
72+
static_assert(sizeof(int) == 4, "Integers must be 4 bytes!");
73+
if (argc < 2) {
74+
fprintf(stderr, "Usage: mkfs fs.img files...\n");
75+
exit(1);
76+
}
77+
assert((BSIZE % sizeof(struct dinode)) == 0);
78+
fsfd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0666);
79+
if (fsfd < 0) {
80+
perror(argv[1]);
81+
exit(1);
82+
}
83+
// 1 fs block = 1 disk sector
84+
nmeta = 2 + ninodeblocks + nbitmap;
85+
nblocks = FSSIZE - nmeta;
86+
87+
sb.magic = FSMAGIC;
88+
sb.size = xint(FSSIZE);
89+
sb.nblocks = xint(nblocks);
90+
sb.ninodes = xint(NINODES);
91+
sb.inodestart = xint(2);
92+
sb.bmapstart = xint(2 + ninodeblocks);
93+
94+
printf("nmeta %d (boot, super, inode blocks %u, bitmap blocks %u) blocks %d "
95+
"total %d\n",
96+
nmeta, ninodeblocks, nbitmap, nblocks, FSSIZE);
97+
98+
freeblock = nmeta; // the first free block that we can allocate
99+
100+
for (i = 0; i < FSSIZE; i++)
101+
wsect(i, zeroes);
102+
103+
memset(buf, 0, sizeof(buf));
104+
memmove(buf, &sb, sizeof(sb));
105+
wsect(1, buf);
106+
107+
rootino = ialloc(T_DIR);
108+
109+
for (i = 2; i < argc; i++) {
110+
char *shortname = basename(argv[i]);
111+
assert(index(shortname, '/') == 0);
112+
113+
if ((fd = open(argv[i], 0)) < 0) {
114+
perror(argv[i]);
115+
exit(1);
116+
}
117+
118+
inum = ialloc(T_FILE);
119+
120+
bzero(&de, sizeof(de));
121+
de.inum = xshort(inum);
122+
strncpy(de.name, shortname, DIRSIZ);
123+
iappend(rootino, &de, sizeof(de));
124+
125+
while ((cc = read(fd, buf, sizeof(buf))) > 0)
126+
iappend(inum, buf, cc);
127+
128+
close(fd);
129+
}
130+
131+
// fix size of root inode dir
132+
rinode(rootino, &din);
133+
off = xint(din.size);
134+
off = ((off / BSIZE) + 1) * BSIZE;
135+
din.size = xint(off);
136+
winode(rootino, &din);
137+
138+
balloc(freeblock);
139+
return 0;
140+
}
141+
142+
char *basename(char *path)
143+
{
144+
while (index(path, '/') != 0) {
145+
path = index(path, '/') + 1;
146+
}
147+
return path;
148+
}
149+
150+
void wsect(uint sec, void *buf)
151+
{
152+
if (lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE) {
153+
perror("lseek");
154+
exit(1);
155+
}
156+
if (write(fsfd, buf, BSIZE) != BSIZE) {
157+
perror("write");
158+
exit(1);
159+
}
160+
}
161+
162+
void winode(uint inum, struct dinode *ip)
163+
{
164+
char buf[BSIZE];
165+
uint bn;
166+
struct dinode *dip;
167+
168+
bn = IBLOCK(inum, sb);
169+
rsect(bn, buf);
170+
dip = ((struct dinode *)buf) + (inum % IPB);
171+
*dip = *ip;
172+
wsect(bn, buf);
173+
}
174+
175+
void rinode(uint inum, struct dinode *ip)
176+
{
177+
char buf[BSIZE];
178+
uint bn;
179+
struct dinode *dip;
180+
181+
bn = IBLOCK(inum, sb);
182+
rsect(bn, buf);
183+
dip = ((struct dinode *)buf) + (inum % IPB);
184+
*ip = *dip;
185+
}
186+
187+
void rsect(uint sec, void *buf)
188+
{
189+
if (lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE) {
190+
perror("lseek");
191+
exit(1);
192+
}
193+
if (read(fsfd, buf, BSIZE) != BSIZE) {
194+
perror("read");
195+
exit(1);
196+
}
197+
}
198+
199+
uint ialloc(ushort type)
200+
{
201+
uint inum = freeinode++;
202+
struct dinode din;
203+
204+
bzero(&din, sizeof(din));
205+
din.type = xshort(type);
206+
din.size = xint(0);
207+
// LAB4: You may want to init link count here
208+
winode(inum, &din);
209+
return inum;
210+
}
211+
212+
void balloc(int used)
213+
{
214+
uchar buf[BSIZE];
215+
int i;
216+
assert(used < BSIZE * 8);
217+
bzero(buf, BSIZE);
218+
for (i = 0; i < used; i++) {
219+
buf[i / 8] = buf[i / 8] | (0x1 << (i % 8));
220+
}
221+
wsect(sb.bmapstart, buf);
222+
}
223+
224+
#define min(a, b) ((a) < (b) ? (a) : (b))
225+
226+
void iappend(uint inum, void *xp, int n)
227+
{
228+
char *p = (char *)xp;
229+
uint fbn, off, n1;
230+
struct dinode din;
231+
char buf[BSIZE];
232+
uint indirect[NINDIRECT];
233+
uint x;
234+
235+
rinode(inum, &din);
236+
off = xint(din.size);
237+
while (n > 0) {
238+
fbn = off / BSIZE;
239+
assert(fbn < MAXFILE);
240+
if (fbn < NDIRECT) {
241+
if (xint(din.addrs[fbn]) == 0) {
242+
din.addrs[fbn] = xint(freeblock++);
243+
}
244+
x = xint(din.addrs[fbn]);
245+
} else {
246+
if (xint(din.addrs[NDIRECT]) == 0) {
247+
din.addrs[NDIRECT] = xint(freeblock++);
248+
}
249+
rsect(xint(din.addrs[NDIRECT]), (char *)indirect);
250+
if (indirect[fbn - NDIRECT] == 0) {
251+
indirect[fbn - NDIRECT] = xint(freeblock++);
252+
wsect(xint(din.addrs[NDIRECT]),
253+
(char *)indirect);
254+
}
255+
x = xint(indirect[fbn - NDIRECT]);
256+
}
257+
n1 = min(n, (fbn + 1) * BSIZE - off);
258+
rsect(x, buf);
259+
bcopy(p, buf + off - (fbn * BSIZE), n1);
260+
wsect(x, buf);
261+
n -= n1;
262+
off += n1;
263+
p += n1;
264+
}
265+
din.size = xint(off);
266+
winode(inum, &din);
267+
}

0 commit comments

Comments
 (0)