From d4fb02e2b43c588372284d69e9c602b6aa33f19f Mon Sep 17 00:00:00 2001 From: Ali Mashtizadeh Date: Tue, 21 Nov 2023 21:37:17 -0500 Subject: [PATCH 1/3] Implemented write support in the file system and added fiotest, and stat --- SConstruct | 3 + bin/stat/SConscript | 23 +++ bin/stat/stat.c | 42 ++++++ release/bootdisk.manifest | 2 + sbin/newfs_o2fs/newfs_o2fs.c | 38 +++++ sys/dev/x86/ide.c | 74 +++++++--- sys/fs/o2fs/o2fs.c | 273 ++++++++++++++++++++++++++++++++++- sys/fs/o2fs/o2fs.h | 14 +- sys/include/vfs.h | 3 + sys/kern/vfsuio.c | 2 +- tests/SConscript | 6 + tests/fiotest.c | 24 +++ 12 files changed, 472 insertions(+), 32 deletions(-) create mode 100644 bin/stat/SConscript create mode 100644 bin/stat/stat.c create mode 100644 tests/fiotest.c diff --git a/SConstruct b/SConstruct index 592035d..08533bd 100644 --- a/SConstruct +++ b/SConstruct @@ -180,6 +180,7 @@ SConscript('bin/ethinject/SConscript', variant_dir='build/bin/ethinject') SConscript('bin/false/SConscript', variant_dir='build/bin/false') SConscript('bin/ls/SConscript', variant_dir='build/bin/ls') 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('sbin/ifconfig/SConscript', variant_dir='build/sbin/ifconfig') SConscript('sbin/init/SConscript', variant_dir='build/sbin/init') @@ -212,12 +213,14 @@ if env["BOOTDISK"] == "1": Depends(bootdisk, "#build/bin/false/false") Depends(bootdisk, "#build/bin/ls/ls") Depends(bootdisk, "#build/bin/shell/shell") + Depends(bootdisk, "#build/bin/stat/stat") Depends(bootdisk, "#build/bin/true/true") Depends(bootdisk, "#build/sbin/ifconfig/ifconfig") Depends(bootdisk, "#build/sbin/init/init") Depends(bootdisk, "#build/sbin/sysctl/sysctl") Depends(bootdisk, "#build/sys/castor") #Depends(bootdisk, "#build/tests/lwiptest") + Depends(bootdisk, "#build/tests/fiotest") Depends(bootdisk, "#build/tests/pthreadtest") Depends(bootdisk, "#build/tests/spawnanytest") Depends(bootdisk, "#build/tests/spawnmultipletest") diff --git a/bin/stat/SConscript b/bin/stat/SConscript new file mode 100644 index 0000000..3c38171 --- /dev/null +++ b/bin/stat/SConscript @@ -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) + diff --git a/bin/stat/stat.c b/bin/stat/stat.c new file mode 100644 index 0000000..4c4a0f8 --- /dev/null +++ b/bin/stat/stat.c @@ -0,0 +1,42 @@ + +#include +#include +#include +#include +#include + +// Castor Only +#include + +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; +} + diff --git a/release/bootdisk.manifest b/release/bootdisk.manifest index fa384da..cce7202 100644 --- a/release/bootdisk.manifest +++ b/release/bootdisk.manifest @@ -11,6 +11,7 @@ DIR / FILE false build/bin/false/false FILE ls build/bin/ls/ls FILE shell build/bin/shell/shell + FILE stat build/bin/stat/stat FILE true build/bin/true/true END DIR sbin @@ -21,6 +22,7 @@ DIR / FILE sysctl build/sbin/sysctl/sysctl END DIR tests + FILE fiotest build/tests/fiotest FILE pthreadtest build/tests/pthreadtest FILE spawnsingletest build/tests/spawnsingletest FILE spawnmultipletest build/tests/spawnmultipletest diff --git a/sbin/newfs_o2fs/newfs_o2fs.c b/sbin/newfs_o2fs/newfs_o2fs.c index f12b08c..1260be1 100644 --- a/sbin/newfs_o2fs/newfs_o2fs.c +++ b/sbin/newfs_o2fs/newfs_o2fs.c @@ -15,6 +15,8 @@ #include +#define ROUND_UP(_a, _b) (((_a) + (_b) - 1)/(_b)) + #define MAXBLOCKSIZE (64*1024*1024) char tempbuf[MAXBLOCKSIZE]; @@ -25,6 +27,7 @@ bool hasManifest = false; uint64_t diskSize = 0; uint64_t diskOffset = 0; uint64_t blockSize = 16*1024; +uint64_t bitmapSize; int diskfd; struct stat diskstat; @@ -230,6 +233,30 @@ ObjID *AddDirectory() 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) { SuperBlock sb; @@ -242,6 +269,8 @@ void Superblock(ObjID *objid) sb.versionMinor = O2FS_VERSION_MINOR; sb.blockCount = diskSize / blockSize; sb.blockSize = blockSize; + sb.bitmapSize = sb.blockCount; + sb.bitmapOffset = 1; if (objid) memcpy(&sb.root, objid, sizeof(ObjID)); @@ -332,10 +361,16 @@ int main(int argc, char * const *argv) lseek(diskfd, 0, SEEK_SET); } + /* Skip superblock */ diskOffset = blockSize; lseek(diskfd, diskOffset, SEEK_SET); 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; if (hasManifest) { int tok; @@ -359,6 +394,9 @@ int main(int argc, char * const *argv) } } + /* Write bitmap */ + BlockBitmap(); + Superblock(root); free(root); diff --git a/sys/dev/x86/ide.c b/sys/dev/x86/ide.c index e0c56a5..8275b20 100644 --- a/sys/dev/x86/ide.c +++ b/sys/dev/x86/ide.c @@ -34,10 +34,10 @@ #define IDE_COMMAND 7 /* Write */ #define IDE_STATUS 7 /* Read */ -// IDE Commands +// IDE Commands (PIO) #define IDE_CMD_READ 0x20 #define IDE_CMD_READ_EXT 0x24 -#define IDE_CMD_WRITE +#define IDE_CMD_WRITE 0x30 #define IDE_CMD_WRITE_EXT 0x34 #define IDE_CMD_FLUSH 0xE7 #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_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_WriteOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len); IDE primary; IDEDrive primaryDrives[2]; @@ -291,7 +292,23 @@ IDE_Read(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg) int 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 @@ -401,7 +418,7 @@ IDE_WriteOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len) uint8_t status; 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); @@ -425,33 +442,46 @@ IDE_WriteOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len) } 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 - while (1) { - status = inb(ide->base + IDE_STATUS); - if ((status & IDE_STATUS_BSY) == 0) - break; + if (lba48) { + 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 & 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) { 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; } + + 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); - // XXX: Loop on outw(ide->base, b + sectorOffset); - - // XXX: CACHE FLUSH + // XXX: Flush cache ... return 0; } diff --git a/sys/fs/o2fs/o2fs.c b/sys/fs/o2fs/o2fs.c index 209af02..b3f5794 100644 --- a/sys/fs/o2fs/o2fs.c +++ b/sys/fs/o2fs/o2fs.c @@ -71,11 +71,30 @@ O2FS_Mount(Disk *disk) return NULL; } + // Read bitmap + for (int i = 0; i < (sb->bitmapSize / sb->blockSize); 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, "Root @ 0x%llx\n", sb->root.offset); fs->fsptr = entry; fs->fsval = sb->root.offset; + fs->blksize = sb->bitmapSize; // Setup VFS structure fs->op = &O2FSOperations; @@ -101,6 +120,86 @@ O2FS_Unmount(VFS *fs) 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) { + /* 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 # + */ + return fs->blksize*8*i + 8*b + bi; + } + } + } + } + + 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); + + 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 * O2FSLoadVNode(VFS *fs, ObjID *objid) { @@ -143,12 +242,59 @@ O2FSLoadVNode(VFS *fs, ObjID *objid) 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) + bn->direct[i].offset = O2FSBAlloc(vfs) * vfs->blksize; + } + + bn->size = filesz; + + BufCache_Write(vnEntry); + + return 0; +} + +/** + * O2FSRetainVNode -- + * + * Increment VNode reference count. + * + * @param [in] vn VNode. + */ void O2FSRetainVNode(VNode *vn) { vn->refCount++; } +/** + * O2FSReleaseVNode -- + * + * Decrement VNode reference count and release it if reaches zero. + * + * @param [in] vn VNode. + */ void O2FSReleaseVNode(VNode *vn) { @@ -160,6 +306,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 O2FS_GetRoot(VFS *fs, VNode **dn) { @@ -212,6 +368,17 @@ O2FSDumpDirEntry(BDirEntry *entry) 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 O2FS_Lookup(VNode *dn, VNode **fn, const char *name) { @@ -266,6 +433,16 @@ O2FS_Close(VNode *fn) 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 O2FS_Stat(VNode *fn, struct stat *statinfo) { @@ -275,14 +452,28 @@ O2FS_Stat(VNode *fn, struct stat *statinfo) BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr; BNode *fileBN = fileEntry->buffer; + DLOG(o2fs, "O2FS %p %d\n", fileBN, fileBN->size); + + statinfo->st_ino = fileEntry->diskOffset; statinfo->st_size = fileBN->size; - // XXX: support other fields statinfo->st_blocks = (fileBN->size + sb->blockSize - 1) / sb->blockSize; statinfo->st_blksize = sb->blockSize; 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 O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len) { @@ -337,13 +528,89 @@ O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len) 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 O2FS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len) { - NOT_IMPLEMENTED(); - return -EINVAL; + int status; + 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); + + if (off > fileBN->size) { + return 0; + } + + // 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, "READ %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 O2FS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off) { diff --git a/sys/fs/o2fs/o2fs.h b/sys/fs/o2fs/o2fs.h index 18dd9b9..ce83cf6 100644 --- a/sys/fs/o2fs/o2fs.h +++ b/sys/fs/o2fs/o2fs.h @@ -44,13 +44,15 @@ typedef struct ObjID { */ typedef struct SuperBlock { - uint8_t magic[8]; - uint16_t versionMajor; - uint16_t versionMinor; + uint8_t magic[8]; /* Superblock Magic */ + uint16_t versionMajor; /* Major Version Number */ + uint16_t versionMinor; /* Minor Version Number */ uint32_t _rsvd0; - uint64_t features; - uint64_t blockCount; - uint64_t blockSize; + uint64_t features; /* Feature Flags */ + uint64_t blockCount; /* Total Blocks */ + 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 */ ObjID root; /* Root Tree */ diff --git a/sys/include/vfs.h b/sys/include/vfs.h index f54bfe0..f55ee9d 100644 --- a/sys/include/vfs.h +++ b/sys/include/vfs.h @@ -16,7 +16,9 @@ typedef struct VFS { // FS Fields void *fsptr; uint64_t fsval; + uint64_t blksize; VNode *root; + void *bitmap[16]; } VFS; typedef struct VNode { @@ -54,6 +56,7 @@ int VFS_Stat(const char *path, struct stat *sb); int VFS_Open(VNode *fn); int VFS_Close(VNode *fn); 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); #endif /* __SYS_VFS_H__ */ diff --git a/sys/kern/vfsuio.c b/sys/kern/vfsuio.c index c297b1d..9fb686d 100644 --- a/sys/kern/vfsuio.c +++ b/sys/kern/vfsuio.c @@ -29,7 +29,7 @@ VFSUIO_Write(Handle *handle, void *buf, uint64_t len, uint64_t off) // XXX: Need to pin memory - return -EINVAL; + return VFS_Write(handle->vnode, buf, len, off); } static int diff --git a/tests/SConscript b/tests/SConscript index 7bb73d6..95c5a26 100644 --- a/tests/SConscript +++ b/tests/SConscript @@ -9,6 +9,12 @@ test_env.Append(CPPFLAGS = ['-fno-builtin', '-nostdinc']) test_env.Append(CPPPATH = ['#build/include']) 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.append(env["CRTBEGIN"]) threadtest_src.append(["threadtest.c"]) diff --git a/tests/fiotest.c b/tests/fiotest.c new file mode 100644 index 0000000..a139578 --- /dev/null +++ b/tests/fiotest.c @@ -0,0 +1,24 @@ + +#include +#include +#include +#include + +// Castor Only +#include + +int +main(int argc, const char *argv[]) +{ + printf("FIO Test\n"); + uint64_t fd = OSOpen("/LICENSE", 0); + + for (int i = 0; i < 100; i++) { + OSWrite(fd, "123456789\n", i*10, 10); + } + + printf("Success!\n"); + + return 0; +} + From 3e2470553759304f017efadc28e2c17d6ffc19dc Mon Sep 17 00:00:00 2001 From: Ali Mashtizadeh Date: Tue, 21 Nov 2023 21:45:06 -0500 Subject: [PATCH 2/3] Remove warning from spawn tests. --- tests/spawnanytest.c | 2 +- tests/spawnmultipletest.c | 2 +- tests/spawnsingletest.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/spawnanytest.c b/tests/spawnanytest.c index af8d1f9..a60f0d2 100644 --- a/tests/spawnanytest.c +++ b/tests/spawnanytest.c @@ -10,7 +10,7 @@ int main(int argc, const char *argv[]) { - char *program; + const char *program; int pid[10]; int status; diff --git a/tests/spawnmultipletest.c b/tests/spawnmultipletest.c index 8ac5da5..cfbb35c 100644 --- a/tests/spawnmultipletest.c +++ b/tests/spawnmultipletest.c @@ -11,7 +11,7 @@ int main(int argc, const char *argv[]) { int origpid[10], pid[10]; - char *program; + const char *program; int status; printf("Spawn parallel test wait any: "); diff --git a/tests/spawnsingletest.c b/tests/spawnsingletest.c index f4dc097..46c3332 100644 --- a/tests/spawnsingletest.c +++ b/tests/spawnsingletest.c @@ -11,7 +11,7 @@ int main(int argc, const char *argv[]) { int origpid, pid; - char *program; + const char *program; int status; printf("Spawn parallel test wait any: "); From 5fc993d8473a31cae8710ae91712f0b3752e8ed2 Mon Sep 17 00:00:00 2001 From: Ali Mashtizadeh Date: Tue, 21 Nov 2023 22:52:10 -0500 Subject: [PATCH 3/3] Fix the logic for block allocations and check for errors in fiotest. --- include/errno.h | 1 + sbin/newfs_o2fs/newfs_o2fs.c | 4 ++-- sys/fs/o2fs/o2fs.c | 32 ++++++++++++++++++++------------ tests/fiotest.c | 6 +++++- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/include/errno.h b/include/errno.h index cc8f0ce..37be525 100644 --- a/include/errno.h +++ b/include/errno.h @@ -25,6 +25,7 @@ int *__error(); #define ETIMEDOUT 0x1BAD0010 #define EACCES 0x1BAD0011 #define EPERM 0x1BAD0012 +#define ENOSPC 0x1BAD0013 #define EAFNOSUPPORT 0x1BAD0020 #define ENOPROTOOPT 0x1BAD0021 diff --git a/sbin/newfs_o2fs/newfs_o2fs.c b/sbin/newfs_o2fs/newfs_o2fs.c index 1260be1..08797ea 100644 --- a/sbin/newfs_o2fs/newfs_o2fs.c +++ b/sbin/newfs_o2fs/newfs_o2fs.c @@ -269,8 +269,8 @@ void Superblock(ObjID *objid) sb.versionMinor = O2FS_VERSION_MINOR; sb.blockCount = diskSize / blockSize; sb.blockSize = blockSize; - sb.bitmapSize = sb.blockCount; - sb.bitmapOffset = 1; + sb.bitmapSize = bitmapSize; + sb.bitmapOffset = blockSize; if (objid) memcpy(&sb.root, objid, sizeof(ObjID)); diff --git a/sys/fs/o2fs/o2fs.c b/sys/fs/o2fs/o2fs.c index b3f5794..1740f0b 100644 --- a/sys/fs/o2fs/o2fs.c +++ b/sys/fs/o2fs/o2fs.c @@ -72,11 +72,11 @@ O2FS_Mount(Disk *disk) } // Read bitmap - for (int i = 0; i < (sb->bitmapSize / sb->blockSize); i++) { + for (int i = 0; i < sb->bitmapSize; i++) { ASSERT(i < 16); BufCacheEntry *bentry; - uint64_t offset = (sb->bitmapOffset + i) * sb->blockSize; + uint64_t offset = sb->bitmapOffset + i * sb->blockSize; if (BufCache_Read(disk, offset, &bentry) < 0) { Alert(o2fs, "Bitmap read failed\n"); @@ -94,7 +94,7 @@ O2FS_Mount(Disk *disk) fs->fsptr = entry; fs->fsval = sb->root.offset; - fs->blksize = sb->bitmapSize; + fs->blksize = sb->blockSize; // Setup VFS structure fs->op = &O2FSOperations; @@ -143,7 +143,7 @@ O2FSBAlloc(VFS *fs) // 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) { + if (((bitmap[b] >> bi) & 0x1) == 0) { /* Set bit */ bitmap[b] |= (1 << bi); @@ -156,12 +156,15 @@ O2FSBAlloc(VFS *fs) * 8 blocks per bitmap byte * bit # */ - return fs->blksize*8*i + 8*b + bi; + 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; } @@ -180,6 +183,8 @@ O2FSBFree(VFS *fs, uint64_t block) 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); @@ -264,10 +269,17 @@ O2FSGrowVNode(VNode *vn, uint64_t filesz) return -EINVAL; for (int i = 0; i < ((filesz + vfs->blksize - 1) / vfs->blksize); i++) { - if (bn->direct[i].offset == 0) - bn->direct[i].offset = O2FSBAlloc(vfs) * vfs->blksize; + 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); @@ -554,10 +566,6 @@ O2FS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len) DLOG(o2fs, "Write %lld %d\n", fileBN->size, blocks); - if (off > fileBN->size) { - return 0; - } - // XXX: Check permissions if (fileBN->size < (off+len)) { @@ -582,7 +590,7 @@ O2FS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len) if (status < 0) return status; - DLOG(o2fs, "READ %lx %lx %lld\n", buf, entry->buffer, bLen); + DLOG(o2fs, "WRITE %lx %lx %lld\n", buf, entry->buffer, bLen); memcpy(entry->buffer + bOff, buf, bLen); BufCache_Write(entry); BufCache_Release(entry); diff --git a/tests/fiotest.c b/tests/fiotest.c index a139578..ca9fe41 100644 --- a/tests/fiotest.c +++ b/tests/fiotest.c @@ -14,7 +14,11 @@ main(int argc, const char *argv[]) uint64_t fd = OSOpen("/LICENSE", 0); for (int i = 0; i < 100; i++) { - OSWrite(fd, "123456789\n", i*10, 10); + int status = OSWrite(fd, "123456789\n", i*10, 10); + if (status < 0) { + printf("Error: %x\n", -status); + return 1; + } } printf("Success!\n");