I'm bring up a reasonable set of C libraries (libc, libcurses etc.) plus a set of system utilities on the xv6 OS. In doing so, I'm starting to hit the 70K filesize limit imposed by the kernel (512 byte blocks, only one level of block indirection).
I believe strongly in keeping the xv6 kernel small and I don't want to touch it as possible. If I could double the block size, that would be great.
The vanilla xv6 code is at https://github.com/mit-pdos/xv6-public. My code is at https://github.com/DoctorWkt/xv6-minix2. I've moved some files around.
The kernel seems set up to change the block size. However, when I change the blocksize (BSIZE in include/xv6/fs.h) from 512 to 1024, the kernel doesn't boot. I can see the system trying to load /etc/init but that never happens.
By using gdb on the system running on Qemu, I can see the kernel calling idestart() [ in kern/ide.c ], which sends the PIO commands to the IDE controller. I don't know enough about IDE and PIO mode, but from what I've learned it looks OK.
I can see ideintr() field the first interrupt and copy the first 1K block into the kernel. Then idestart() is called to read a second block, but ideintr() never gets called a second time, so this seems to indicate that there is no second interrupt to indicate that the second IDE command was successful.
The system works fine with a block size of 512. I'd really appreciate ideas, suggestions, things I can try to diagnose the problem. Remember, I want to make as minimal changes to the kernel once we work out how to fix the problem!
Thanks in advance, Warren
[Solved] Increasing the filesystem block size in the xv6 OS
[Solved] Increasing the filesystem block size in the xv6 OS
Last edited by DoctorWkt on Sat Jul 23, 2016 6:02 am, edited 1 time in total.
Re: Increasing the filesystem block size in the xv6 OS
Is it possible that the implementation assumes that the block translates into a single physical sector? Disk sectors are 512-bytes long.
Re: Increasing the filesystem block size in the xv6 OS
Here's the relevant code from the xv6 kernel
The lines outsl(0x1f0, b->data, BSIZE/4); and insl(0x1f0, b->data, BSIZE/4); are writing/reading the buffer in 32-bit word units, so yes it does look like the code is trying to read/write the correct amount of data. And outb(0x1f2, sector_per_block); is setting up the transfer to be the correct number of 512-byte sectors in each block.
Hope this helps. Thanks! Warren
Code: Select all
#define BSIZE 512 // block size
struct buf {
int flags;
uint dev;
uint blockno;
struct buf *prev; // LRU cache list
struct buf *next;
struct buf *qnext; // disk queue
uchar data[BSIZE];
};
#define SECTOR_SIZE 512
// Start the request for b. Caller must hold idelock.
static void
idestart(struct buf *b)
{
if(b == 0)
panic("idestart");
if(b->blockno >= FSSIZE)
panic("incorrect blockno");
int sector_per_block = BSIZE/SECTOR_SIZE;
int sector = b->blockno * sector_per_block;
if (sector_per_block > 7) panic("idestart");
idewait(0);
outb(0x3f6, 0); // generate interrupt
outb(0x1f2, sector_per_block); // number of sectors
outb(0x1f3, sector & 0xff);
outb(0x1f4, (sector >> 8) & 0xff);
outb(0x1f5, (sector >> 16) & 0xff);
outb(0x1f6, 0xe0 | ((b->dev&1)<<4) | ((sector>>24)&0x0f));
if(b->flags & B_DIRTY){
outb(0x1f7, IDE_CMD_WRITE);
outsl(0x1f0, b->data, BSIZE/4);
} else {
outb(0x1f7, IDE_CMD_READ);
}
}
// Interrupt handler.
void
ideintr(void)
{
struct buf *b;
// First queued buffer is the active request.
acquire(&idelock);
if((b = idequeue) == 0){
release(&idelock);
// cprintf("spurious IDE interrupt\n");
return;
}
idequeue = b->qnext;
// Read data if needed.
if(!(b->flags & B_DIRTY) && idewait(1) >= 0)
insl(0x1f0, b->data, BSIZE/4);
// Wake process waiting for this buf.
b->flags |= B_VALID;
b->flags &= ~B_DIRTY;
wakeup(b);
// Start disk on next buf in queue.
if(idequeue != 0)
idestart(idequeue);
release(&idelock);
}
static inline void
insl(int port, void *addr, int cnt)
{
asm volatile("cld; rep insl" :
"=D" (addr), "=c" (cnt) :
"d" (port), "0" (addr), "1" (cnt) :
"memory", "cc");
}
static inline void
outsl(int port, const void *addr, int cnt)
{
asm volatile("cld; rep outsl" :
"=S" (addr), "=c" (cnt) :
"d" (port), "0" (addr), "1" (cnt) :
"cc");
}
Hope this helps. Thanks! Warren
Re: Increasing the filesystem block size in the xv6 OS
Ha, I worked it out. The code wasn't issuing the ATA commands for multiple sectors. Here's my working changes:
Cheers, Warren
Code: Select all
#define IDE_CMD_READ 0x20
#define IDE_CMD_WRITE 0x30
#define IDE_CMD_RDMUL 0xC4
#define IDE_CMD_WRMUL 0xC5
. . .
int sector_per_block = BSIZE/SECTOR_SIZE;
int sector = b->blockno * sector_per_block;
uchar read_cmd= (sector_per_block ==1) ? IDE_CMD_READ : IDE_CMD_RDMUL;
uchar write_cmd= (sector_per_block ==1) ? IDE_CMD_WRITE : IDE_CMD_WRMUL;
. . .
if(b->flags & B_DIRTY){
outb(0x1f7, write_cmd);
outsl(0x1f0, b->data, BSIZE/4);
} else {
outb(0x1f7, read_cmd);
}
Re: Increasing the filesystem block size in the xv6 OS
With 128-140KB file size limits you may be able to run a rather usable C compiler in the system!
The sizes of my Smaller C compiler's binaries for Linux (self-compiled):
smlrc 131072
smlrpp 126976
smlrl 53248
smlrcc 40960
n2f 28672
The C library for Linux (self-compiled):
lcl.a 178000 (compiled using NASM (debug info retained))
lcl.a 124472 (compiled using n2f + FASM)
FASM for Linux:
fasm 103342
I see you've added some missing stuff, e.g. lseek.
These are the system calls used in my library/compiler, very conservative use:
The sizes of my Smaller C compiler's binaries for Linux (self-compiled):
smlrc 131072
smlrpp 126976
smlrl 53248
smlrcc 40960
n2f 28672
The C library for Linux (self-compiled):
lcl.a 178000 (compiled using NASM (debug info retained))
lcl.a 124472 (compiled using n2f + FASM)
FASM for Linux:
fasm 103342
I see you've added some missing stuff, e.g. lseek.
These are the system calls used in my library/compiler, very conservative use:
Code: Select all
>findstr sys_ *.c
clock.c: asm("mov eax, 43\n" // sys_times
close.c: asm("mov eax, 6\n" // sys_close
exit.c: asm("mov eax, 1\n" // sys_exit
isatty.c: asm("mov eax, 54\n" // sys_ioctl
localtim.c: asm("mov eax, 78\n" // sys_gettimeofday
lseek.c: asm("mov eax, 19\n" // sys_lseek
malloc.c: asm("mov eax, 45\n" // sys_brk
mktime.c: asm("mov eax, 78\n" // sys_gettimeofday
open.c: asm("mov eax, 5\n" // sys_open
read.c: asm("mov eax, 3\n" // sys_read
rename.c: asm("mov eax, 38\n" // sys_rename
system.c: asm("mov eax, 2\n" // sys_fork
system.c: asm("mov eax, 7\n" // sys_waitpid
system.c: asm("mov eax, 11\n" // sys_execve
time.c: asm("mov eax, 13\n" // sys_time
tmpnam.c: asm("mov eax, 33\n" // sys_access
unlink.c: asm("mov eax, 10\n" // sys_unlink
write.c: asm("mov eax, 4\n" // sys_write
Re: Increasing the filesystem block size in the xv6 OS
Looks good. I'll add it to the list of things to try and bring up on the system
Thanks, Warren
Thanks, Warren
Re: Increasing the filesystem block size in the xv6 OS
Feel free to ask questions about the code.
Re: Increasing the filesystem block size in the xv6 OS
Hi, did you ever get around to this?DoctorWkt wrote:Looks good. I'll add it to the list of things to try and bring up on the system