Merge /home/ali/working/CastorOS-FS
This commit is contained in:
commit
0cba356b78
@ -185,6 +185,7 @@ SConscript('bin/ethinject/SConscript', variant_dir='build/bin/ethinject')
|
|||||||
SConscript('bin/false/SConscript', variant_dir='build/bin/false')
|
SConscript('bin/false/SConscript', variant_dir='build/bin/false')
|
||||||
SConscript('bin/ls/SConscript', variant_dir='build/bin/ls')
|
SConscript('bin/ls/SConscript', variant_dir='build/bin/ls')
|
||||||
SConscript('bin/shell/SConscript', variant_dir='build/bin/shell')
|
SConscript('bin/shell/SConscript', variant_dir='build/bin/shell')
|
||||||
|
SConscript('bin/stat/SConscript', variant_dir='build/bin/stat')
|
||||||
SConscript('bin/true/SConscript', variant_dir='build/bin/true')
|
SConscript('bin/true/SConscript', variant_dir='build/bin/true')
|
||||||
SConscript('sbin/ifconfig/SConscript', variant_dir='build/sbin/ifconfig')
|
SConscript('sbin/ifconfig/SConscript', variant_dir='build/sbin/ifconfig')
|
||||||
SConscript('sbin/init/SConscript', variant_dir='build/sbin/init')
|
SConscript('sbin/init/SConscript', variant_dir='build/sbin/init')
|
||||||
@ -217,12 +218,14 @@ if env["BOOTDISK"] == "1":
|
|||||||
Depends(bootdisk, "#build/bin/false/false")
|
Depends(bootdisk, "#build/bin/false/false")
|
||||||
Depends(bootdisk, "#build/bin/ls/ls")
|
Depends(bootdisk, "#build/bin/ls/ls")
|
||||||
Depends(bootdisk, "#build/bin/shell/shell")
|
Depends(bootdisk, "#build/bin/shell/shell")
|
||||||
|
Depends(bootdisk, "#build/bin/stat/stat")
|
||||||
Depends(bootdisk, "#build/bin/true/true")
|
Depends(bootdisk, "#build/bin/true/true")
|
||||||
Depends(bootdisk, "#build/sbin/ifconfig/ifconfig")
|
Depends(bootdisk, "#build/sbin/ifconfig/ifconfig")
|
||||||
Depends(bootdisk, "#build/sbin/init/init")
|
Depends(bootdisk, "#build/sbin/init/init")
|
||||||
Depends(bootdisk, "#build/sbin/sysctl/sysctl")
|
Depends(bootdisk, "#build/sbin/sysctl/sysctl")
|
||||||
Depends(bootdisk, "#build/sys/castor")
|
Depends(bootdisk, "#build/sys/castor")
|
||||||
#Depends(bootdisk, "#build/tests/lwiptest")
|
#Depends(bootdisk, "#build/tests/lwiptest")
|
||||||
|
Depends(bootdisk, "#build/tests/fiotest")
|
||||||
Depends(bootdisk, "#build/tests/pthreadtest")
|
Depends(bootdisk, "#build/tests/pthreadtest")
|
||||||
Depends(bootdisk, "#build/tests/spawnanytest")
|
Depends(bootdisk, "#build/tests/spawnanytest")
|
||||||
Depends(bootdisk, "#build/tests/spawnmultipletest")
|
Depends(bootdisk, "#build/tests/spawnmultipletest")
|
||||||
|
23
bin/stat/SConscript
Normal file
23
bin/stat/SConscript
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
|
||||||
|
init_env = env.Clone()
|
||||||
|
|
||||||
|
src = [ ]
|
||||||
|
|
||||||
|
src_common = [
|
||||||
|
"stat.c"
|
||||||
|
]
|
||||||
|
|
||||||
|
src.append(env["CRTBEGIN"])
|
||||||
|
src.append(src_common)
|
||||||
|
src.append(env["CRTEND"])
|
||||||
|
|
||||||
|
init_env.Append(LINKFLAGS = ['-nostdlib'])
|
||||||
|
init_env.Append(CPPFLAGS = ['-fno-builtin', '-nostdinc'])
|
||||||
|
init_env.Append(CPPPATH = ['#build/include'])
|
||||||
|
init_env.Append(LIBPATH = ['#build/lib/libc'], LIBS = ['c'])
|
||||||
|
|
||||||
|
init_env.Program("stat", src)
|
||||||
|
|
42
bin/stat/stat.c
Normal file
42
bin/stat/stat.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
// Castor Only
|
||||||
|
#include <syscall.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int status, fd;
|
||||||
|
struct stat sb;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
fputs("Requires an argument\n", stdout);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 2) {
|
||||||
|
fputs("Too many arguments, expected one\n", stdout);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = OSStat(argv[1], &sb);
|
||||||
|
if (status != 0) {
|
||||||
|
fputs("Cannot stat file\n", stdout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" File: \"%s\"\n", argv[1]);
|
||||||
|
printf(" Size: %d\n", sb.st_size);
|
||||||
|
printf("Blocks: %d\n", sb.st_blocks);
|
||||||
|
printf(" Inode: %d\n", sb.st_ino);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -25,6 +25,7 @@ int *__error();
|
|||||||
#define ETIMEDOUT 0x1BAD0010
|
#define ETIMEDOUT 0x1BAD0010
|
||||||
#define EACCES 0x1BAD0011
|
#define EACCES 0x1BAD0011
|
||||||
#define EPERM 0x1BAD0012
|
#define EPERM 0x1BAD0012
|
||||||
|
#define ENOSPC 0x1BAD0013
|
||||||
|
|
||||||
#define EAFNOSUPPORT 0x1BAD0020
|
#define EAFNOSUPPORT 0x1BAD0020
|
||||||
#define ENOPROTOOPT 0x1BAD0021
|
#define ENOPROTOOPT 0x1BAD0021
|
||||||
|
@ -11,6 +11,7 @@ DIR /
|
|||||||
FILE false build/bin/false/false
|
FILE false build/bin/false/false
|
||||||
FILE ls build/bin/ls/ls
|
FILE ls build/bin/ls/ls
|
||||||
FILE shell build/bin/shell/shell
|
FILE shell build/bin/shell/shell
|
||||||
|
FILE stat build/bin/stat/stat
|
||||||
FILE true build/bin/true/true
|
FILE true build/bin/true/true
|
||||||
END
|
END
|
||||||
DIR sbin
|
DIR sbin
|
||||||
@ -21,6 +22,7 @@ DIR /
|
|||||||
FILE sysctl build/sbin/sysctl/sysctl
|
FILE sysctl build/sbin/sysctl/sysctl
|
||||||
END
|
END
|
||||||
DIR tests
|
DIR tests
|
||||||
|
FILE fiotest build/tests/fiotest
|
||||||
FILE pthreadtest build/tests/pthreadtest
|
FILE pthreadtest build/tests/pthreadtest
|
||||||
FILE spawnsingletest build/tests/spawnsingletest
|
FILE spawnsingletest build/tests/spawnsingletest
|
||||||
FILE spawnmultipletest build/tests/spawnmultipletest
|
FILE spawnmultipletest build/tests/spawnmultipletest
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
#include <o2fs.h>
|
#include <o2fs.h>
|
||||||
|
|
||||||
|
#define ROUND_UP(_a, _b) (((_a) + (_b) - 1)/(_b))
|
||||||
|
|
||||||
#define MAXBLOCKSIZE (64*1024*1024)
|
#define MAXBLOCKSIZE (64*1024*1024)
|
||||||
|
|
||||||
char tempbuf[MAXBLOCKSIZE];
|
char tempbuf[MAXBLOCKSIZE];
|
||||||
@ -25,6 +27,7 @@ bool hasManifest = false;
|
|||||||
uint64_t diskSize = 0;
|
uint64_t diskSize = 0;
|
||||||
uint64_t diskOffset = 0;
|
uint64_t diskOffset = 0;
|
||||||
uint64_t blockSize = 16*1024;
|
uint64_t blockSize = 16*1024;
|
||||||
|
uint64_t bitmapSize;
|
||||||
int diskfd;
|
int diskfd;
|
||||||
struct stat diskstat;
|
struct stat diskstat;
|
||||||
|
|
||||||
@ -230,6 +233,30 @@ ObjID *AddDirectory()
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlockBitmap()
|
||||||
|
{
|
||||||
|
off_t off = lseek(diskfd, 0, SEEK_CUR) / blockSize;
|
||||||
|
|
||||||
|
/* Code below only supports using the first 16K blocks */
|
||||||
|
assert(off < blockSize);
|
||||||
|
|
||||||
|
memset(tempbuf, 0, MAXBLOCKSIZE);
|
||||||
|
|
||||||
|
/* Mark the blocks in use up to the current offset */
|
||||||
|
assert(off > 8);
|
||||||
|
for (off_t i = 0; i < (off / 8); i++) {
|
||||||
|
tempbuf[i] = 0xFF;
|
||||||
|
}
|
||||||
|
for (off_t i = 0; i < (off % 8); i++) {
|
||||||
|
tempbuf[off / 8] |= 1 << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
lseek(diskfd, blockSize, SEEK_SET);
|
||||||
|
|
||||||
|
for (int i = 0; i < bitmapSize; i++)
|
||||||
|
AppendBlock(tempbuf + (blockSize * i), blockSize);
|
||||||
|
}
|
||||||
|
|
||||||
void Superblock(ObjID *objid)
|
void Superblock(ObjID *objid)
|
||||||
{
|
{
|
||||||
SuperBlock sb;
|
SuperBlock sb;
|
||||||
@ -242,6 +269,8 @@ void Superblock(ObjID *objid)
|
|||||||
sb.versionMinor = O2FS_VERSION_MINOR;
|
sb.versionMinor = O2FS_VERSION_MINOR;
|
||||||
sb.blockCount = diskSize / blockSize;
|
sb.blockCount = diskSize / blockSize;
|
||||||
sb.blockSize = blockSize;
|
sb.blockSize = blockSize;
|
||||||
|
sb.bitmapSize = bitmapSize;
|
||||||
|
sb.bitmapOffset = blockSize;
|
||||||
|
|
||||||
if (objid)
|
if (objid)
|
||||||
memcpy(&sb.root, objid, sizeof(ObjID));
|
memcpy(&sb.root, objid, sizeof(ObjID));
|
||||||
@ -332,10 +361,16 @@ int main(int argc, char * const *argv)
|
|||||||
lseek(diskfd, 0, SEEK_SET);
|
lseek(diskfd, 0, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Skip superblock */
|
||||||
diskOffset = blockSize;
|
diskOffset = blockSize;
|
||||||
lseek(diskfd, diskOffset, SEEK_SET);
|
lseek(diskfd, diskOffset, SEEK_SET);
|
||||||
memset(zerobuf, 0, MAXBLOCKSIZE);
|
memset(zerobuf, 0, MAXBLOCKSIZE);
|
||||||
|
|
||||||
|
/* Zero the bitmap (and skip past it) */
|
||||||
|
bitmapSize = ROUND_UP(diskSize / (blockSize * 8), blockSize);
|
||||||
|
for (int i = 0; i < bitmapSize; i++)
|
||||||
|
AppendBlock(zerobuf, blockSize);
|
||||||
|
|
||||||
ObjID *root = NULL;
|
ObjID *root = NULL;
|
||||||
if (hasManifest) {
|
if (hasManifest) {
|
||||||
int tok;
|
int tok;
|
||||||
@ -359,6 +394,9 @@ int main(int argc, char * const *argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write bitmap */
|
||||||
|
BlockBitmap();
|
||||||
|
|
||||||
Superblock(root);
|
Superblock(root);
|
||||||
free(root);
|
free(root);
|
||||||
|
|
||||||
|
@ -34,10 +34,10 @@
|
|||||||
#define IDE_COMMAND 7 /* Write */
|
#define IDE_COMMAND 7 /* Write */
|
||||||
#define IDE_STATUS 7 /* Read */
|
#define IDE_STATUS 7 /* Read */
|
||||||
|
|
||||||
// IDE Commands
|
// IDE Commands (PIO)
|
||||||
#define IDE_CMD_READ 0x20
|
#define IDE_CMD_READ 0x20
|
||||||
#define IDE_CMD_READ_EXT 0x24
|
#define IDE_CMD_READ_EXT 0x24
|
||||||
#define IDE_CMD_WRITE
|
#define IDE_CMD_WRITE 0x30
|
||||||
#define IDE_CMD_WRITE_EXT 0x34
|
#define IDE_CMD_WRITE_EXT 0x34
|
||||||
#define IDE_CMD_FLUSH 0xE7
|
#define IDE_CMD_FLUSH 0xE7
|
||||||
#define IDE_CMD_IDENTIFY 0xEC
|
#define IDE_CMD_IDENTIFY 0xEC
|
||||||
@ -77,6 +77,7 @@ int IDE_Read(Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg);
|
|||||||
int IDE_Write(Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg);
|
int IDE_Write(Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg);
|
||||||
int IDE_Flush(Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg);
|
int IDE_Flush(Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg);
|
||||||
int IDE_ReadOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len);
|
int IDE_ReadOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len);
|
||||||
|
int IDE_WriteOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len);
|
||||||
|
|
||||||
IDE primary;
|
IDE primary;
|
||||||
IDEDrive primaryDrives[2];
|
IDEDrive primaryDrives[2];
|
||||||
@ -291,7 +292,23 @@ IDE_Read(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg)
|
|||||||
int
|
int
|
||||||
IDE_Write(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg)
|
IDE_Write(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg)
|
||||||
{
|
{
|
||||||
return -1;
|
int i;
|
||||||
|
int status;
|
||||||
|
IDEDrive *idedrive;
|
||||||
|
|
||||||
|
idedrive = disk->handle;
|
||||||
|
|
||||||
|
for (i = 0; i < sga->len; i++) {
|
||||||
|
status = IDE_WriteOne(idedrive,
|
||||||
|
buf,
|
||||||
|
sga->entries[i].offset / 512,
|
||||||
|
sga->entries[i].length / 512);
|
||||||
|
buf += sga->entries[i].length;
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -401,7 +418,7 @@ IDE_WriteOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len)
|
|||||||
uint8_t status;
|
uint8_t status;
|
||||||
IDE *ide = drive->ide;
|
IDE *ide = drive->ide;
|
||||||
|
|
||||||
Log(ide, "Write %llx %llx\n", off, len);
|
DLOG(ide, "read %llx %llx\n", off, len);
|
||||||
|
|
||||||
ASSERT(drive->drive == 0 || drive->drive == 1);
|
ASSERT(drive->drive == 0 || drive->drive == 1);
|
||||||
|
|
||||||
@ -425,33 +442,46 @@ IDE_WriteOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len)
|
|||||||
}
|
}
|
||||||
ide->lastDriveCode = driveCode;
|
ide->lastDriveCode = driveCode;
|
||||||
}
|
}
|
||||||
outb(ide->base + IDE_SECTORCOUNT, len >> 8);
|
|
||||||
outb(ide->base + IDE_LBALOW, off >> 24);
|
|
||||||
outb(ide->base + IDE_LBAMID, off >> 32);
|
|
||||||
outb(ide->base + IDE_LBAHIGH, off >> 40);
|
|
||||||
outb(ide->base + IDE_SECTORCOUNT, len);
|
|
||||||
outb(ide->base + IDE_LBALOW, off);
|
|
||||||
outb(ide->base + IDE_LBAMID, off >> 8);
|
|
||||||
outb(ide->base + IDE_LBAHIGH, off >> 16);
|
|
||||||
outb(ide->base + IDE_COMMAND, IDE_CMD_WRITE_EXT);
|
|
||||||
|
|
||||||
// XXX: Need timeout
|
if (lba48) {
|
||||||
while (1) {
|
outb(ide->base + IDE_SECTORCOUNT, len >> 8);
|
||||||
status = inb(ide->base + IDE_STATUS);
|
outb(ide->base + IDE_LBALOW, off >> 24);
|
||||||
if ((status & IDE_STATUS_BSY) == 0)
|
outb(ide->base + IDE_LBAMID, off >> 32);
|
||||||
break;
|
outb(ide->base + IDE_LBAHIGH, off >> 40);
|
||||||
}
|
}
|
||||||
|
outb(ide->base + IDE_SECTORCOUNT, len);
|
||||||
|
outb(ide->base + IDE_LBALOW, off & 0xff);
|
||||||
|
outb(ide->base + IDE_LBAMID, (off >> 8) & 0xff);
|
||||||
|
outb(ide->base + IDE_LBAHIGH, (off >> 16) & 0xff);
|
||||||
|
|
||||||
|
if (lba48)
|
||||||
|
outb(ide->base + IDE_COMMAND, IDE_CMD_WRITE_EXT);
|
||||||
|
else
|
||||||
|
outb(ide->base + IDE_COMMAND, IDE_CMD_WRITE);
|
||||||
|
|
||||||
|
status = IDEWaitForBusy(ide, false);
|
||||||
if ((status & IDE_STATUS_ERR) != 0) {
|
if ((status & IDE_STATUS_ERR) != 0) {
|
||||||
Spinlock_Unlock(&ide->lock);
|
Spinlock_Unlock(&ide->lock);
|
||||||
Log(ide, "Error trying write from drive %d\n", drive);
|
Log(ide, "Error trying read from drive %d\n", drive->drive);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sectors;
|
||||||
|
for (sectors = 0; sectors < len; sectors++)
|
||||||
|
{
|
||||||
|
uint8_t *b = buf + sectors * IDE_SECTOR_SIZE;
|
||||||
|
outsw(ide->base + IDE_DATAPORT, b, 256);
|
||||||
|
|
||||||
|
status = IDEWaitForBusy(ide, true);
|
||||||
|
if ((status & IDE_STATUS_ERR) != 0) {
|
||||||
|
Spinlock_Unlock(&ide->lock);
|
||||||
|
Log(ide, "Error reading from drive %d\n", drive->drive);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
Spinlock_Unlock(&ide->lock);
|
Spinlock_Unlock(&ide->lock);
|
||||||
|
|
||||||
// XXX: Loop on outw(ide->base, b + sectorOffset);
|
// XXX: Flush cache ...
|
||||||
|
|
||||||
// XXX: CACHE FLUSH
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -71,11 +71,30 @@ O2FS_Mount(Disk *disk)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read bitmap
|
||||||
|
for (int i = 0; i < sb->bitmapSize; i++) {
|
||||||
|
ASSERT(i < 16);
|
||||||
|
|
||||||
|
BufCacheEntry *bentry;
|
||||||
|
uint64_t offset = sb->bitmapOffset + i * sb->blockSize;
|
||||||
|
|
||||||
|
if (BufCache_Read(disk, offset, &bentry) < 0) {
|
||||||
|
Alert(o2fs, "Bitmap read failed\n");
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
BufCache_Release(fs->bitmap[i]);
|
||||||
|
BufCache_Release(entry);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs->bitmap[i] = bentry;
|
||||||
|
}
|
||||||
|
|
||||||
DLOG(o2fs, "File system mounted\n");
|
DLOG(o2fs, "File system mounted\n");
|
||||||
DLOG(o2fs, "Root @ 0x%llx\n", sb->root.offset);
|
DLOG(o2fs, "Root @ 0x%llx\n", sb->root.offset);
|
||||||
|
|
||||||
fs->fsptr = entry;
|
fs->fsptr = entry;
|
||||||
fs->fsval = sb->root.offset;
|
fs->fsval = sb->root.offset;
|
||||||
|
fs->blksize = sb->blockSize;
|
||||||
|
|
||||||
// Setup VFS structure
|
// Setup VFS structure
|
||||||
fs->op = &O2FSOperations;
|
fs->op = &O2FSOperations;
|
||||||
@ -101,6 +120,91 @@ O2FS_Unmount(VFS *fs)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FSBAlloc --
|
||||||
|
*
|
||||||
|
* Allocate a block.
|
||||||
|
*
|
||||||
|
* @param [in] vfs VFS Instance.
|
||||||
|
*
|
||||||
|
* @return Block number.
|
||||||
|
*/
|
||||||
|
uint64_t
|
||||||
|
O2FSBAlloc(VFS *fs)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
char *bitmap;
|
||||||
|
BufCacheEntry *bentry = fs->bitmap[i];
|
||||||
|
|
||||||
|
if (fs->bitmap[i] == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bitmap = bentry->buffer;
|
||||||
|
// XXX: Check for end of disk
|
||||||
|
for (int b = 0; b < fs->blksize; b++) {
|
||||||
|
for (int bi = 0; bi < 8; bi++) {
|
||||||
|
if (((bitmap[b] >> bi) & 0x1) == 0) {
|
||||||
|
/* Set bit */
|
||||||
|
bitmap[b] |= (1 << bi);
|
||||||
|
|
||||||
|
/* Write bitmap */
|
||||||
|
BufCache_Write(bentry);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Block index is the sum of:
|
||||||
|
* blksize*8 blocks per bitmap entry
|
||||||
|
* 8 blocks per bitmap byte
|
||||||
|
* bit #
|
||||||
|
*/
|
||||||
|
uint64_t blk = fs->blksize*8*i + 8*b + bi;
|
||||||
|
DLOG(o2fs, "BAlloc %lu\n", blk);
|
||||||
|
return blk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Alert(o2fs, "Out of space!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FSBFree --
|
||||||
|
*
|
||||||
|
* Free a block.
|
||||||
|
*
|
||||||
|
* @param [in] vfs VFS Instance.
|
||||||
|
* @param [in] block Block number.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
O2FSBFree(VFS *fs, uint64_t block)
|
||||||
|
{
|
||||||
|
uint64_t bitoff = block & 0x7;
|
||||||
|
uint64_t bytoff = (block >> 8) % fs->blksize;
|
||||||
|
uint64_t bufoff = block / (fs->blksize*8);
|
||||||
|
|
||||||
|
DLOG(o2fs, "BFree %lu\n", block);
|
||||||
|
|
||||||
|
BufCacheEntry *bentry = fs->bitmap[bufoff];
|
||||||
|
ASSERT(bentry != NULL);
|
||||||
|
|
||||||
|
char *bitmap = bentry->buffer;
|
||||||
|
|
||||||
|
/* Mask out the bit */
|
||||||
|
bitmap[bytoff] &= ~(1 << bitoff);
|
||||||
|
|
||||||
|
/* Write the bitmap */
|
||||||
|
BufCache_Write(bentry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FSLoadVNode --
|
||||||
|
*
|
||||||
|
* Load a VNode from the disk given an ObjID.
|
||||||
|
*
|
||||||
|
* @param [in] vfs VFS Instance.
|
||||||
|
* @param [in] oobjid Object ID.
|
||||||
|
*/
|
||||||
VNode *
|
VNode *
|
||||||
O2FSLoadVNode(VFS *fs, ObjID *objid)
|
O2FSLoadVNode(VFS *fs, ObjID *objid)
|
||||||
{
|
{
|
||||||
@ -143,12 +247,66 @@ O2FSLoadVNode(VFS *fs, ObjID *objid)
|
|||||||
return vn;
|
return vn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FSGrowVNode --
|
||||||
|
*
|
||||||
|
* Grow a VNode.
|
||||||
|
*
|
||||||
|
* @param [in] vfs VFS Instance.
|
||||||
|
* @param [in] bn BNode for the object.
|
||||||
|
* @param [in] filesz New file size.
|
||||||
|
*
|
||||||
|
* @return 0 on success, otherwise error code.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
O2FSGrowVNode(VNode *vn, uint64_t filesz)
|
||||||
|
{
|
||||||
|
VFS *vfs = vn->vfs;
|
||||||
|
BufCacheEntry *vnEntry = (BufCacheEntry *)vn->fsptr;
|
||||||
|
BNode *bn = vnEntry->buffer;
|
||||||
|
|
||||||
|
if (filesz > (vfs->blksize * 64))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (int i = 0; i < ((filesz + vfs->blksize - 1) / vfs->blksize); i++) {
|
||||||
|
if (bn->direct[i].offset == 0) {
|
||||||
|
uint64_t blkno = O2FSBAlloc(vfs);
|
||||||
|
if (blkno == 0) {
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
bn->direct[i].offset = blkno * vfs->blksize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DLOG(o2fs, "Growing: %d\n", filesz);
|
||||||
|
bn->size = filesz;
|
||||||
|
|
||||||
|
BufCache_Write(vnEntry);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FSRetainVNode --
|
||||||
|
*
|
||||||
|
* Increment VNode reference count.
|
||||||
|
*
|
||||||
|
* @param [in] vn VNode.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
O2FSRetainVNode(VNode *vn)
|
O2FSRetainVNode(VNode *vn)
|
||||||
{
|
{
|
||||||
vn->refCount++;
|
vn->refCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FSReleaseVNode --
|
||||||
|
*
|
||||||
|
* Decrement VNode reference count and release it if reaches zero.
|
||||||
|
*
|
||||||
|
* @param [in] vn VNode.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
O2FSReleaseVNode(VNode *vn)
|
O2FSReleaseVNode(VNode *vn)
|
||||||
{
|
{
|
||||||
@ -160,6 +318,16 @@ O2FSReleaseVNode(VNode *vn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FS_GetRoot --
|
||||||
|
*
|
||||||
|
* Read the root directory Inode.
|
||||||
|
*
|
||||||
|
* @param [in] fs VFS Instance.
|
||||||
|
* @param [out] dn VNode of the root directory.
|
||||||
|
*
|
||||||
|
* @return 0 on success, otherwise error.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
O2FS_GetRoot(VFS *fs, VNode **dn)
|
O2FS_GetRoot(VFS *fs, VNode **dn)
|
||||||
{
|
{
|
||||||
@ -212,6 +380,17 @@ O2FSDumpDirEntry(BDirEntry *entry)
|
|||||||
VLOG(o2fs, "%16s %08llx %08llx\n", entry->name, entry->objId.offset, entry->size);
|
VLOG(o2fs, "%16s %08llx %08llx\n", entry->name, entry->objId.offset, entry->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FS_Lookup --
|
||||||
|
*
|
||||||
|
* Lookup a directory entry within a given directory.
|
||||||
|
*
|
||||||
|
* @param [in] vn VNode of the directory to look through.
|
||||||
|
* @param [out] fn VNode of the entry if found.
|
||||||
|
* @param [in] name Name of the file.
|
||||||
|
*
|
||||||
|
* @return 0 on success, otherwise error.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
O2FS_Lookup(VNode *dn, VNode **fn, const char *name)
|
O2FS_Lookup(VNode *dn, VNode **fn, const char *name)
|
||||||
{
|
{
|
||||||
@ -266,6 +445,16 @@ O2FS_Close(VNode *fn)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FS_Stat --
|
||||||
|
*
|
||||||
|
* Stat a VNode.
|
||||||
|
*
|
||||||
|
* @param [in] fn VNode of the file to stat.
|
||||||
|
* @param [out] statinfo Stat structure.
|
||||||
|
*
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
O2FS_Stat(VNode *fn, struct stat *statinfo)
|
O2FS_Stat(VNode *fn, struct stat *statinfo)
|
||||||
{
|
{
|
||||||
@ -275,14 +464,28 @@ O2FS_Stat(VNode *fn, struct stat *statinfo)
|
|||||||
BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr;
|
BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr;
|
||||||
BNode *fileBN = fileEntry->buffer;
|
BNode *fileBN = fileEntry->buffer;
|
||||||
|
|
||||||
|
DLOG(o2fs, "O2FS %p %d\n", fileBN, fileBN->size);
|
||||||
|
|
||||||
|
statinfo->st_ino = fileEntry->diskOffset;
|
||||||
statinfo->st_size = fileBN->size;
|
statinfo->st_size = fileBN->size;
|
||||||
// XXX: support other fields
|
|
||||||
statinfo->st_blocks = (fileBN->size + sb->blockSize - 1) / sb->blockSize;
|
statinfo->st_blocks = (fileBN->size + sb->blockSize - 1) / sb->blockSize;
|
||||||
statinfo->st_blksize = sb->blockSize;
|
statinfo->st_blksize = sb->blockSize;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FS_Read --
|
||||||
|
*
|
||||||
|
* Read from a VNode.
|
||||||
|
*
|
||||||
|
* @param [in] fn VNode of the file.
|
||||||
|
* @param [out] buf Buffer to read into.
|
||||||
|
* @param [in] off Offset within the file.
|
||||||
|
* @param [in] len Length of the buffer to read.
|
||||||
|
*
|
||||||
|
* @return number of bytes on success, otherwise negative error code.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
||||||
{
|
{
|
||||||
@ -337,13 +540,85 @@ O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
|||||||
return readBytes;
|
return readBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FS_Write --
|
||||||
|
*
|
||||||
|
* Write to a VNode.
|
||||||
|
*
|
||||||
|
* @param [in] fn VNode of the file.
|
||||||
|
* @param [in] buf Buffer to write out.
|
||||||
|
* @param [in] off Offset within the file.
|
||||||
|
* @param [in] len Length of the buffer to write.
|
||||||
|
*
|
||||||
|
* @return number of bytes on success, otherwise negative error code.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
O2FS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
O2FS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
||||||
{
|
{
|
||||||
NOT_IMPLEMENTED();
|
int status;
|
||||||
return -EINVAL;
|
VFS *vfs = fn->vfs;
|
||||||
|
BufCacheEntry *sbEntry = (BufCacheEntry *)vfs->fsptr;
|
||||||
|
SuperBlock *sb = sbEntry->buffer;
|
||||||
|
BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr;
|
||||||
|
BNode *fileBN = fileEntry->buffer;
|
||||||
|
uint64_t blocks = (fileBN->size + sb->blockSize - 1) / sb->blockSize;
|
||||||
|
uint64_t readBytes = 0;
|
||||||
|
|
||||||
|
DLOG(o2fs, "Write %lld %d\n", fileBN->size, blocks);
|
||||||
|
|
||||||
|
// XXX: Check permissions
|
||||||
|
|
||||||
|
if (fileBN->size < (off+len)) {
|
||||||
|
status = O2FSGrowVNode(fn, off+len);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint64_t b = off / sb->blockSize;
|
||||||
|
uint64_t bOff = off % sb->blockSize;
|
||||||
|
uint64_t bLen;
|
||||||
|
BufCacheEntry *entry;
|
||||||
|
|
||||||
|
if (bOff + len > sb->blockSize) {
|
||||||
|
bLen = sb->blockSize - bOff;
|
||||||
|
} else {
|
||||||
|
bLen = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = BufCache_Read(fn->disk, fileBN->direct[b].offset, &entry);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
DLOG(o2fs, "WRITE %lx %lx %lld\n", buf, entry->buffer, bLen);
|
||||||
|
memcpy(entry->buffer + bOff, buf, bLen);
|
||||||
|
BufCache_Write(entry);
|
||||||
|
BufCache_Release(entry);
|
||||||
|
|
||||||
|
readBytes += bLen;
|
||||||
|
buf += bLen;
|
||||||
|
off += bLen;
|
||||||
|
len -= bLen;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return readBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* O2FS_ReadDir --
|
||||||
|
*
|
||||||
|
* Read a directory entry.
|
||||||
|
*
|
||||||
|
* @param [in] fn VNode of the directory.
|
||||||
|
* @param [out] buf Buffer to read the directory entry into.
|
||||||
|
* @param [in] len Length of the buffer.
|
||||||
|
* @param [inout] off Offset to start from and return the next offset.
|
||||||
|
*
|
||||||
|
* @return 0 on success, otherwise error.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
O2FS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off)
|
O2FS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off)
|
||||||
{
|
{
|
||||||
|
@ -44,13 +44,15 @@ typedef struct ObjID {
|
|||||||
*/
|
*/
|
||||||
typedef struct SuperBlock
|
typedef struct SuperBlock
|
||||||
{
|
{
|
||||||
uint8_t magic[8];
|
uint8_t magic[8]; /* Superblock Magic */
|
||||||
uint16_t versionMajor;
|
uint16_t versionMajor; /* Major Version Number */
|
||||||
uint16_t versionMinor;
|
uint16_t versionMinor; /* Minor Version Number */
|
||||||
uint32_t _rsvd0;
|
uint32_t _rsvd0;
|
||||||
uint64_t features;
|
uint64_t features; /* Feature Flags */
|
||||||
uint64_t blockCount;
|
uint64_t blockCount; /* Total Blocks */
|
||||||
uint64_t blockSize;
|
uint64_t blockSize; /* Block Size in Bytes */
|
||||||
|
uint64_t bitmapSize; /* Free Bitmap Size in Bytes */
|
||||||
|
uint64_t bitmapOffset; /* Free Bitmap Offset */
|
||||||
|
|
||||||
uint64_t version; /* Snapshot version */
|
uint64_t version; /* Snapshot version */
|
||||||
ObjID root; /* Root Tree */
|
ObjID root; /* Root Tree */
|
||||||
|
@ -16,7 +16,9 @@ typedef struct VFS {
|
|||||||
// FS Fields
|
// FS Fields
|
||||||
void *fsptr;
|
void *fsptr;
|
||||||
uint64_t fsval;
|
uint64_t fsval;
|
||||||
|
uint64_t blksize;
|
||||||
VNode *root;
|
VNode *root;
|
||||||
|
void *bitmap[16];
|
||||||
} VFS;
|
} VFS;
|
||||||
|
|
||||||
typedef struct VNode {
|
typedef struct VNode {
|
||||||
@ -54,6 +56,7 @@ int VFS_Stat(const char *path, struct stat *sb);
|
|||||||
int VFS_Open(VNode *fn);
|
int VFS_Open(VNode *fn);
|
||||||
int VFS_Close(VNode *fn);
|
int VFS_Close(VNode *fn);
|
||||||
int VFS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len);
|
int VFS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len);
|
||||||
|
int VFS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len);
|
||||||
int VFS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off);
|
int VFS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off);
|
||||||
|
|
||||||
#endif /* __SYS_VFS_H__ */
|
#endif /* __SYS_VFS_H__ */
|
||||||
|
@ -29,7 +29,7 @@ VFSUIO_Write(Handle *handle, void *buf, uint64_t len, uint64_t off)
|
|||||||
|
|
||||||
// XXX: Need to pin memory
|
// XXX: Need to pin memory
|
||||||
|
|
||||||
return -EINVAL;
|
return VFS_Write(handle->vnode, buf, len, off);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -9,6 +9,12 @@ test_env.Append(CPPFLAGS = ['-fno-builtin', '-nostdinc'])
|
|||||||
test_env.Append(CPPPATH = ['#build/include'])
|
test_env.Append(CPPPATH = ['#build/include'])
|
||||||
test_env.Append(LIBPATH = ['#build/lib/libc'], LIBS = ['c'])
|
test_env.Append(LIBPATH = ['#build/lib/libc'], LIBS = ['c'])
|
||||||
|
|
||||||
|
fiotest_src = []
|
||||||
|
fiotest_src.append(env["CRTBEGIN"])
|
||||||
|
fiotest_src.append(["fiotest.c"])
|
||||||
|
fiotest_src.append(env["CRTEND"])
|
||||||
|
test_env.Program("fiotest", fiotest_src)
|
||||||
|
|
||||||
threadtest_src = []
|
threadtest_src = []
|
||||||
threadtest_src.append(env["CRTBEGIN"])
|
threadtest_src.append(env["CRTBEGIN"])
|
||||||
threadtest_src.append(["threadtest.c"])
|
threadtest_src.append(["threadtest.c"])
|
||||||
|
28
tests/fiotest.c
Normal file
28
tests/fiotest.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
// Castor Only
|
||||||
|
#include <syscall.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
printf("FIO Test\n");
|
||||||
|
uint64_t fd = OSOpen("/LICENSE", 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
int status = OSWrite(fd, "123456789\n", i*10, 10);
|
||||||
|
if (status < 0) {
|
||||||
|
printf("Error: %x\n", -status);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Success!\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -10,7 +10,7 @@
|
|||||||
int
|
int
|
||||||
main(int argc, const char *argv[])
|
main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
char *program;
|
const char *program;
|
||||||
int pid[10];
|
int pid[10];
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ int
|
|||||||
main(int argc, const char *argv[])
|
main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
int origpid[10], pid[10];
|
int origpid[10], pid[10];
|
||||||
char *program;
|
const char *program;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
printf("Spawn parallel test wait any: ");
|
printf("Spawn parallel test wait any: ");
|
||||||
|
@ -11,7 +11,7 @@ int
|
|||||||
main(int argc, const char *argv[])
|
main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
int origpid, pid;
|
int origpid, pid;
|
||||||
char *program;
|
const char *program;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
printf("Spawn parallel test wait any: ");
|
printf("Spawn parallel test wait any: ");
|
||||||
|
Loading…
Reference in New Issue
Block a user