Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
514579c
p6: add IDE driver + buffer cache
ahilaan Feb 14, 2026
c042007
p6: add IDE driver and buffer cache layer
ahilaan Feb 14, 2026
d373ec5
mkfs implemented
Feb 14, 2026
6dd333f
mkfs implemented
Feb 14, 2026
d46c965
implement inode read path and welcome.txt loading from fs image
Amber-Agarwal Feb 14, 2026
dd458e3
remove rustc ICE dump file
Amber-Agarwal Feb 14, 2026
56d0f11
implement filesystem write path and directory/name operations
Amber-Agarwal Feb 15, 2026
5e2d7e1
Refactor traps module: centralize constants, remove duplicates, decou…
Yash-Rawat-IIT-D Feb 15, 2026
416b5f3
Updated TickCounter struct to pub
Yash-Rawat-IIT-D Feb 15, 2026
b4368bd
p5: add UART interrupt and console input support
ArinjaySinghal19 Feb 16, 2026
f7a426c
p9: add name layer + self-contained Rust mkfs
legends1307 Feb 16, 2026
626cd94
p9: add name layer + self-contained Rust mkfs
legends1307 Feb 16, 2026
f4595fc
p11-rust-done
greninja1947 Feb 17, 2026
08c2e4e
cleaned
greninja1947 Feb 17, 2026
7066535
Cherrypicked Improvements from p3-pic
Yash-Rawat-IIT-D Mar 1, 2026
cf5aed9
Refleted panic changes of p3-pic
Yash-Rawat-IIT-D Mar 1, 2026
9d6fa5a
Fixed Scope Issues
Yash-Rawat-IIT-D Mar 1, 2026
09daea8
p5: add UART interrupt and console input support
ArinjaySinghal19 Feb 16, 2026
c31ec4a
Updated console::consputc function call API
Yash-Rawat-IIT-D Mar 2, 2026
e21d58f
Updated project level config.toml
Yash-Rawat-IIT-D Mar 2, 2026
09318fb
Accumulated older changes
Yash-Rawat-IIT-D Mar 2, 2026
b6642c8
Fixed static mutable warnings
Yash-Rawat-IIT-D Mar 2, 2026
ac785d1
p6: Fixed iderw to use interrupt-driven design
Yash-Rawat-IIT-D Mar 2, 2026
4feb566
Updated port exit status
Yash-Rawat-IIT-D Mar 2, 2026
d2aa22a
Initial commit
namanlp Feb 9, 2026
b2ebc35
p6: add IDE driver + buffer cache
ahilaan Feb 14, 2026
e32b47b
p6: add IDE driver and buffer cache layer
ahilaan Feb 14, 2026
4ced3ca
mkfs implemented
Feb 14, 2026
a0f29fb
mkfs implemented
Feb 14, 2026
6cf3476
p5: add UART interrupt and console input support
ArinjaySinghal19 Feb 16, 2026
2f4af2f
Updated console::consputc function call API
Yash-Rawat-IIT-D Mar 2, 2026
0baee77
Updated project level config.toml
Yash-Rawat-IIT-D Mar 2, 2026
3302f51
Accumulated older changes
Yash-Rawat-IIT-D Mar 2, 2026
7a88867
Fixed static mutable warnings
Yash-Rawat-IIT-D Mar 2, 2026
a8bbbd7
p6: Fixed iderw to use interrupt-driven design
Yash-Rawat-IIT-D Mar 2, 2026
e51630d
Updated port exit status
Yash-Rawat-IIT-D Mar 2, 2026
fff2425
Added constants and fixed welcome() bug
Yash-Rawat-IIT-D Mar 3, 2026
30e13e2
Updated bootblock.ld
Yash-Rawat-IIT-D Mar 3, 2026
f8ccfd5
Updated bootblock.ld
Yash-Rawat-IIT-D Mar 3, 2026
92f1769
Updated bootblock.ld
Yash-Rawat-IIT-D Mar 3, 2026
e3e5322
Update bootblock.ld
Yash-Rawat-IIT-D Mar 3, 2026
375bdf6
p5: add UART interrupt and console input support
ArinjaySinghal19 Feb 16, 2026
f842518
Accumulated older changes
Yash-Rawat-IIT-D Mar 2, 2026
8ad812b
Fixed static mutable warnings
Yash-Rawat-IIT-D Mar 2, 2026
dc7eb6e
Fixed rebase duplication bugs
Yash-Rawat-IIT-D Mar 3, 2026
9fd14db
Merge history onto p5-input
Yash-Rawat-IIT-D Mar 3, 2026
7d3d6dc
Minor bug fixes in traps
Yash-Rawat-IIT-D Mar 3, 2026
42bc9c7
Merged history with p6-ide
Yash-Rawat-IIT-D Mar 3, 2026
bf8b526
Makefile changes
Yash-Rawat-IIT-D Mar 3, 2026
0e4f1b0
Merged p7-mkfs changes
Yash-Rawat-IIT-D Mar 3, 2026
2c352cd
Fixed welcome
Yash-Rawat-IIT-D Mar 3, 2026
05cc2a8
Fixed static mut warnings in fs.rs
Yash-Rawat-IIT-D Mar 3, 2026
7a4cb3f
Merged p8-read-fs changes
Yash-Rawat-IIT-D Mar 3, 2026
0217dcd
Updated LOGSIZE and FSSIZE
Yash-Rawat-IIT-D Mar 3, 2026
2680d3c
Updated LOGSIZE FSSIZE
Yash-Rawat-IIT-D Mar 3, 2026
4f160ca
Updated LOGSIZE FSSIZE
Yash-Rawat-IIT-D Mar 3, 2026
58cb4c3
p9-name-layer: Add dirlookup poff parameter
Yash-Rawat-IIT-D Mar 3, 2026
3e2cd18
Updated trapasm.S
Yash-Rawat-IIT-D Mar 3, 2026
ca5789c
Updated .S files to remove ld GNU-stack warnings
Yash-Rawat-IIT-D Mar 3, 2026
70dd1d8
Updated .S to remove ld GNU-stack warning
Yash-Rawat-IIT-D Mar 3, 2026
c16e5ac
Updated .S to remove ld GNU-stack warnings
Yash-Rawat-IIT-D Mar 3, 2026
7c71f81
Merged p9-name-layer implmentation
Yash-Rawat-IIT-D Mar 3, 2026
e4facf0
Cleaned Constants usage, fixed static mut warnings
Yash-Rawat-IIT-D Mar 3, 2026
d75049b
Merged p10-write-layer changes
Yash-Rawat-IIT-D Mar 3, 2026
979d41b
Updated constants, fix static mut warning
Yash-Rawat-IIT-D Mar 3, 2026
2c7f551
Removed KSTACKSIZE and NCPU redefinition (kept in param.rs)
Yash-Rawat-IIT-D Mar 3, 2026
0879b37
Merge branch 'p4-traps' into p5-input
codenet May 1, 2026
aabee1b
add expect msgs
codenet May 1, 2026
72786db
Merge branch 'p4-traps' into p5-input
codenet May 1, 2026
f09742f
Merge branch 'p5-input' into p6-ide
codenet May 1, 2026
b106bd3
Merge branch 'p6-ide' into p7-mkfs
codenet May 1, 2026
575c606
Merge branch 'p7-mkfs' into p8-read-fs
codenet May 1, 2026
f519a8d
bring back comment diagram
codenet May 1, 2026
73fa6b9
Merge branch 'p8-read-fs' into p9-name-layer
codenet May 1, 2026
811622d
Merge branch 'p9-name-layer' into p10-write-fs
codenet May 1, 2026
f8d136c
fs_h integration changes
Yash-Rawat-IIT-D May 1, 2026
a8b5562
WIP. Does not build. too many unsafe methods
codenet May 1, 2026
f623a53
revert Makefile and json
codenet May 1, 2026
6679c5e
Merge branch 'p8-read-fs' into p9-name-layer
codenet May 1, 2026
193f45e
Merge branch 'p9-name-layer' into p10-write-fs
codenet May 1, 2026
6e4817f
fix build errs
codenet May 1, 2026
6774dd9
Merge branch 'p10-write-fs' into p11-file-layer
codenet May 1, 2026
480ee82
unsafe helpers and &str API
Yash-Rawat-IIT-D May 2, 2026
93d5d76
Removed unused dead code and unnecessary helpers
Yash-Rawat-IIT-D May 2, 2026
1b49748
nits
codenet May 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 35 additions & 38 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ RS = src/*.rs

# Cross-compiling (e.g., on Mac OS X)
#TOOLPREFIX = i386-jos-elf
#TOOLPREFIX = i386-elf-
# TOOLPREFIX = i686-elf-

# Using native tools (e.g., on X86 Linux)
#TOOLPREFIX =
#TOOLPREFIX =

MAC_CCFLAGS := $(shell if [ "$(shell uname -s)" = "Darwin" ] && [ "$(shell uname -m)" = "arm64" ]; then \
echo "-Wno-error=infinite-recursion -Wno-error=array-bounds"; \
Expand All @@ -16,70 +16,65 @@ fi)

# Try to infer the correct TOOLPREFIX if not set
ifndef TOOLPREFIX
TOOLPREFIX := $(shell if i386-jos-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \
TOOLPREFIX := $(shell if command -v i386-jos-elf-gcc >/dev/null 2>&1 && i386-jos-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \
then echo 'i386-jos-elf-'; \
elif objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \
elif command -v i686-elf-gcc >/dev/null 2>&1 && i686-elf-objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \
then echo 'i686-elf-'; \
elif command -v gcc >/dev/null 2>&1 && objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \
then echo ''; \
elif i686-elf-objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \
then echo 'i686-elf-'; \
elif i386-elf-objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \
then echo 'i386-elf-'; \
else echo "***" 1>&2; \
echo "*** Error: Couldn't find an i386-*-elf version of GCC/binutils." 1>&2; \
echo "*** Is the directory with i386-jos-elf-gcc in your PATH?" 1>&2; \
echo "*** If your i386-*-elf toolchain is installed with a command" 1>&2; \
echo "*** prefix other than 'i386-jos-elf-', set your TOOLPREFIX" 1>&2; \
echo "*** environment variable to that prefix and run 'make' again." 1>&2; \
echo "*** To turn off this error, run 'gmake TOOLPREFIX= ...'." 1>&2; \
echo "***" 1>&2; exit 1; fi)
exit 1; fi)
endif

# If the makefile can't find QEMU, specify its path here
# QEMU = qemu-system-i386

# Try to infer the correct QEMU
ifndef QEMU
QEMU = $(shell if which qemu > /dev/null; \
then echo qemu; exit; \
elif which qemu-system-i386 > /dev/null; \
then echo qemu-system-i386; exit; \
elif which qemu-system-x86_64 > /dev/null; \
then echo qemu-system-x86_64; exit; \
else \
qemu=/Applications/Q.app/Contents/MacOS/i386-softmmu.app/Contents/MacOS/i386-softmmu; \
if test -x $$qemu; then echo $$qemu; exit; fi; fi; \
echo "***" 1>&2; \
echo "*** Error: Couldn't find a working QEMU executable." 1>&2; \
echo "*** Is the directory containing the qemu binary in your PATH" 1>&2; \
echo "*** or have you tried setting the QEMU variable in Makefile?" 1>&2; \
echo "***" 1>&2; exit 1)
else echo "*** Error: Couldn't find QEMU." 1>&2; exit 1; fi)
endif

CC = $(TOOLPREFIX)gcc
AS = $(TOOLPREFIX)gas
LD = $(TOOLPREFIX)ld
OBJCOPY = $(TOOLPREFIX)objcopy
OBJDUMP = $(TOOLPREFIX)objdump

CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer
CFLAGS += $(MAC_CCFLAGS)
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)

ASFLAGS = -m32 -gdwarf-2 -Wa,-divide
# FreeBSD ld wants ``elf_i386_fbsd''
LDFLAGS += -m $(shell $(LD) -V | grep elf_i386 2>/dev/null | head -n 1)

# Disable PIE when possible (for Ubuntu 16.10 toolchain)
ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),)
CFLAGS += -fno-pie -no-pie
endif
ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]nopie'),)
CFLAGS += -fno-pie -nopie
endif

# Disk image with bootblock + kernel
xv6.img: bootblock kernel
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

# Build mkfs utility and create filesystem image
mkfs: src/mkfs.rs src/fs_h.rs
rustc --edition=2021 -W warnings -o mkfs src/mkfs.rs


fs.img: mkfs *.txt
./mkfs fs.img *.txt

bootblock: bootasm.S bootmain.c linkers/bootblock.ld
$(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. -c bootmain.c
$(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm.S
Expand All @@ -88,10 +83,15 @@ bootblock: bootasm.S bootmain.c linkers/bootblock.ld
$(OBJCOPY) -S -O binary bootblock.o bootblock

kernel.a: $(RS)
cargo rustc -Z build-std=core -Z build-std-features=compiler-builtins-mem --target ./targets/i686-stage-3.json --lib --release -- -A warnings --emit link=kernel.a
cargo +nightly rustc \
-Z build-std=core \
-Z build-std-features=compiler-builtins-mem \
--target ./targets/i686-stage-3.json \
--lib --release \
-- -A warnings --emit link=kernel.a

kernel: kernel.a $(OBJS) ./linkers/kernel.ld
ld -m elf_i386 -T ./linkers/kernel.ld -o kernel $(OBJS) kernel.a
$(LD) -m elf_i386 -T ./linkers/kernel.ld -o kernel $(OBJS) kernel.a
$(OBJDUMP) -S -D kernel > kernel.asm
$(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym

Expand All @@ -103,35 +103,32 @@ vectors.S: vectors.pl
# details:
# http://www.gnu.org/software/make/manual/html_node/Chained-Rules.html
.PRECIOUS: %.o

-include *.d

clean:
clean:
rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \
*.a *.o *.d *.asm *.sym bootblock kernel xv6.img .gdbinit
*.a *.o *.d *.asm *.sym bootblock kernel xv6.img fs.img mkfs .gdbinit vectors.S
cargo clean

# run in emulators
# try to generate a unique GDB port
GDBPORT = $(shell expr `id -u` % 5000 + 25000)
# QEMU's gdb stub command line changed in 0.11
QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
then echo "-gdb tcp::$(GDBPORT)"; \
else echo "-s -p $(GDBPORT)"; fi)

ifndef CPUS
CPUS := 1
CPUS := 1
endif

# For debugging
# QEMUEXTRA = -no-reboot -d int,cpu_reset
QEMUOPTS = -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA)
QEMUOPTS = -drive file=xv6.img,index=0,media=disk,format=raw \
-drive file=fs.img,index=1,media=disk,format=raw \
-smp $(CPUS) -m 512 $(QEMUEXTRA)

qemu: xv6.img
qemu: xv6.img fs.img
$(QEMU) -nographic $(QEMUOPTS)

.gdbinit: .gdbinit.tmpl
sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@

qemu-gdb: xv6.img .gdbinit
qemu-gdb: xv6.img .gdbinit fs.img
@echo "*** Now run 'gdb'." 1>&2
$(QEMU) -nographic $(QEMUOPTS) -S $(QEMUGDB)
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# COL331RS: p11-file-layer (Rust)

This branch ports the `p11-file-layer` stage from the C repo (`codenet/col331`) into Rust in `codenet/col331rs` style.

## What This Branch Adds

- Rust file descriptor layer (`src/file.rs`):
- `filealloc`, `filedup`, `fileclose`, `filestat`, `fileread`, `filewrite`
- pathname/file ops: `open`, `create`, `unlink`, `isdirempty`
- Open-mode constants (`src/fcntl.rs`):
- `O_RDONLY`, `O_WRONLY`, `O_RDWR`, `O_CREATE`
- File-system lifecycle changes in `src/fs.rs`:
- block free path (`bfree`)
- inode truncation (`itrunc`)
- reference-drop semantics (`iput`) matching p11 behavior
- updated read/path behavior to work with unlink + final `iput`
- Rust `mkfs` integration (`src/mkfs.rs`):
- no dependency on external `../col331/mkfs.c`
- Boot demo update (`src/lib.rs`):
- creates `/foo/hello.txt`, writes and reads it, unlinks it, verifies directory emptiness
- reads `/welcome.txt` through the file layer

## Build And Run

Make sure your cross-toolchain is available (for example `TOOLPREFIX=i686-elf-`).

```bash
make clean
make xv6.img fs.img
make qemu
```

## Source Alignment

- C reference branch: `codenet/col331` -> `p11-file-layer`
- Rust base used: p10 Rust work, then extended to p11 file layer behavior

## Credits

This branch reuses and builds on earlier COL331RS community work:

- **Amber-Agarwal** (`refs/pull/7/head` in `codenet/col331rs`)
- p10-level Rust filesystem write path and directory/name operation groundwork
- **Nipun Goel** (aka **sudoheckbeluga**, `refs/pull/5/head`)
- early Rust `mkfs` implementation used as the basis for later versions
- **legends1307** (`refs/pull/12/head`)
- self-contained Rust `mkfs` adaptation (`FSSIZE=1000`, `LOGSIZE=0`) and related integration improvements
- **COL331 course/staff repository authors** (`codenet/col331`, `codenet/col331rs`)
- original xv6 step-by-step structure and assignment progression

20 changes: 0 additions & 20 deletions main.c

This file was deleted.

1 change: 1 addition & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[toolchain]
channel = "nightly"
components = ["rust-src"]
148 changes: 148 additions & 0 deletions src/bio.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
use core::sync::atomic::Ordering;

use crate::buf::{Buf, B_DIRTY, B_VALID, NBUF};

const HEAD: usize = NBUF; // sentinel index

struct BCache {
buf: [Buf; NBUF],
head_prev: usize,
head_next: usize,
}

impl BCache {
pub const fn new() -> Self {
Self {
buf: [const { Buf::new() }; NBUF],
head_prev: HEAD,
head_next: HEAD,
}
}
}

static mut BCACHE: BCache = BCache::new();

pub fn binit() {
unsafe {
// empty list
BCACHE.head_prev = HEAD;
BCACHE.head_next = HEAD;

// insert all buffers at head (MRU side)
for i in 0..NBUF {
insert_at_head(i);
}
}
}

#[inline]
fn insert_at_head(i: usize) {
unsafe {
let first = BCACHE.head_next;

BCACHE.buf[i].prev = HEAD;
BCACHE.buf[i].next = first;

if first == HEAD {
// list was empty
BCACHE.head_prev = i;
} else {
BCACHE.buf[first].prev = i;
}

BCACHE.head_next = i;
}
}

#[inline]
fn remove_from_list(i: usize) {
unsafe {
let prev = BCACHE.buf[i].prev;
let next = BCACHE.buf[i].next;

if prev == HEAD {
BCACHE.head_next = next;
} else {
BCACHE.buf[prev].next = next;
}

if next == HEAD {
BCACHE.head_prev = prev;
} else {
BCACHE.buf[next].prev = prev;
}
}
}

// Return mutable buf by index.
// Safe to call only when you “own” the buffer logically (like xv6 “locked buf”).
pub fn buf_mut(idx: usize) -> &'static mut Buf {
unsafe { &mut BCACHE.buf[idx] }
}

// Look for cached block; else recycle an unused non-dirty buffer.
fn bget(dev: u32, blockno: u32) -> usize {
unsafe {
// Is the block already cached?
let mut b = BCACHE.head_next;
while b != HEAD {
if BCACHE.buf[b].dev == dev && BCACHE.buf[b].blockno == blockno {
BCACHE.buf[b].refcnt += 1;
return b;
}
b = BCACHE.buf[b].next;
}

// Not cached; recycle from LRU end.
let mut b = BCACHE.head_prev;
while b != HEAD {
let flags = BCACHE.buf[b].flags.load(Ordering::Acquire);
if BCACHE.buf[b].refcnt == 0 && (flags & B_DIRTY) == 0 {
BCACHE.buf[b].dev = dev;
BCACHE.buf[b].blockno = blockno;
BCACHE.buf[b].flags.store(0, Ordering::Release);
BCACHE.buf[b].refcnt = 1;
BCACHE.buf[b].qnext = None;
return b;
}
b = BCACHE.buf[b].prev;
}

panic!("bget: no buffers");
}
}

// Return buffer index with contents of block.
pub fn bread(dev: u32, blockno: u32) -> usize {
let idx = bget(dev, blockno);

let flags = buf_mut(idx).flags.load(Ordering::Acquire);
if (flags & B_VALID) == 0 {
crate::ide::iderw(idx);
}

idx
}

// Mark dirty + write to disk.
pub fn bwrite(idx: usize) {
let b = buf_mut(idx);
b.flags.fetch_or(B_DIRTY, Ordering::AcqRel);
crate::ide::iderw(idx);
}

// Release buffer. If refcnt hits 0, move to MRU head.
pub fn brelse(idx: usize) {
unsafe {
let b = &mut BCACHE.buf[idx];
if b.refcnt == 0 {
panic!("brelse: refcnt underflow");
}

b.refcnt -= 1;
if b.refcnt == 0 {
remove_from_list(idx);
insert_at_head(idx);
}
}
}
Loading