int kshell_ata_write(kshell_t *k, int argc, char **argv){ if (argc != 3){ dbg(DBG_DISK | DBG_TERM, "received wrong amount of arguments\n"); kprintf(k, "Usage: <read_block> <string>\n"); return -1; } blockdev_t *bd = blockdev_lookup(MKDEVID(1, 0)); int blocknum = toint(argv[1]); char *input_text = argv[2]; char *data = (void *) page_alloc(); if (data == NULL){ kprintf(k, "not enough memory"); return -1; } int i = 0; while (input_text[i] != NULL){ data[i] = input_text[i]; i++; } data[i] = '\0'; int result = bd->bd_ops->write_block(bd, data, blocknum, 1); page_free((void *) data); return result; }
int kshell_ata_read(kshell_t *k, int argc, char **argv){ if (argc != 3){ dbg(DBG_DISK | DBG_TERM, "received wrong amount of arguments\n"); kprintf(k, "Usage: <read_block> <num_blocks>\n"); return -1; } blockdev_t *bd = blockdev_lookup(MKDEVID(1, 0)); int blocknum = toint(argv[1]); int count = toint(argv[2]); char *data = (char *) page_alloc_n(count); if (data == NULL){ kprintf(k, "not enough memory"); return -1; } int result = bd->bd_ops->read_block(bd, data, blocknum, count); char newline[2] = {'\n', '\0'}; kprintf(k, data); kprintf(k, newline); page_free_n((void *) data, count); return result; }
static void test_large_block_reads(){ blockdev_t *bd = blockdev_lookup(MKDEVID(1, 0)); int i; for (i = 1; i < 129; i++){ char *readbuf = (char *) page_alloc_n(i); char *writebuf = (char *) page_alloc_n(i); int j; for (j = 0; j < (i * BLOCK_SIZE); j++){ writebuf[j] = 'f'; } int write_result = bd->bd_ops->write_block(bd, writebuf, 0, i); KASSERT(write_result == 0); int read_result = bd->bd_ops->read_block(bd, readbuf, 0, i); KASSERT(read_result == 0); int k; for (k = 0; k < (i * BLOCK_SIZE); k++){ KASSERT(readbuf[k] == 'f'); } page_free_n((void *) readbuf, i); page_free_n((void *) writebuf, i); } dbg(DBG_TESTPASS, "large read stress tests passed\n"); }
void test_single_rw(){ dbg(DBG_TEST | DBG_DISK, "testing reading and writing to disk\n"); blockdev_t *bd = blockdev_lookup(MKDEVID(1, 0)); KASSERT(bd != NULL); char *writebuf = (char *) page_alloc(); char *readbuf = (char *) page_alloc(); KASSERT(readbuf != NULL && writebuf != NULL && "not enough memory"); unsigned int i; for (i = 0; i < BLOCK_SIZE; i++){ writebuf[i] = 'o'; } int block_to_write = 60; rw_args_t read_args = {bd, readbuf, block_to_write, 1}; rw_args_t write_args = {bd, writebuf, block_to_write, 1}; simple_write(write_args); simple_read(read_args); unsigned int j; for (j = 0; j < BLOCK_SIZE; j++){ KASSERT(readbuf[j] == 'o'); } page_free((void *) readbuf); page_free((void *) writebuf); dbg(DBG_TESTPASS, "all simple ata tests passed\n"); }
/* * Read fs->fs_dev and set fs_op, fs_root, and fs_i. * * Point fs->fs_i to an s5fs_t*, and initialize it. Be sure to * verify the superblock (using s5_check_super()). Use vget() to get * the root vnode for fs_root. * * Return 0 on success, negative on failure. */ int s5fs_mount(struct fs *fs) { int num; blockdev_t *dev; s5fs_t *s5; pframe_t *vp; KASSERT(fs); if (sscanf(fs->fs_dev, "disk%d", &num) != 1) { return -EINVAL; } if (!(dev = blockdev_lookup(MKDEVID(1, num)))) { return -EINVAL; } /* allocate and initialize an s5fs_t: */ s5 = (s5fs_t *)kmalloc(sizeof(s5fs_t)); if (!s5) return -ENOMEM; /* init s5f_disk: */ s5->s5f_bdev = dev; /* init s5f_super: */ pframe_get(S5FS_TO_VMOBJ(s5), S5_SUPER_BLOCK, &vp); KASSERT(vp); s5->s5f_super = (s5_super_t *)(vp->pf_addr); if (s5_check_super(s5->s5f_super)) { /* corrupt */ kfree(s5); return -EINVAL; } pframe_pin(vp); /* init s5f_mutex: */ kmutex_init(&s5->s5f_mutex); /* init s5f_fs: */ s5->s5f_fs = fs; /* Init the members of fs that we (the fs-implementation) are * responsible for initializing: */ fs->fs_i = s5; fs->fs_op = &s5fs_fsops; fs->fs_root = vget(fs, s5->s5f_super->s5s_root_inode); return 0; }
static void read_many_blocks(){ dbg(DBG_TEST, "reading from LOTS of blocks, one at a time\n"); blockdev_t *bd = blockdev_lookup(MKDEVID(1, 0)); char *writebuf = (char *) page_alloc(); char *readbuf = (char *) page_alloc(); KASSERT(writebuf != NULL && readbuf != NULL); unsigned int i; for (i = 0; i < BLOCK_SIZE; i++){ writebuf[i] = 'z'; } dbg(DBG_TEST, "reading from blocks before writing them\n"); int j; for (j = 0; j < 1024; j++){ int read_result = bd->bd_ops->read_block(bd, readbuf, j, 1); KASSERT(read_result == 0); } dbg(DBG_TEST, "writing to all the blocks\n"); int k; for (k = 0; k < 1024; k++){ int write_result = bd->bd_ops->write_block(bd, writebuf, k, 1); KASSERT(write_result == 0); } dbg(DBG_TEST, "reading from all the written-to blocks\n"); int l; for (l = 0; l < 1024; l++){ int read_result = bd->bd_ops->read_block(bd, readbuf, l, 1); KASSERT(read_result == 0); unsigned int m; for (m = 0; m < BLOCK_SIZE; m++){ KASSERT(readbuf[m] == 'z'); } } page_free((void *) writebuf); page_free((void *) readbuf); dbg(DBG_TESTPASS, "single-block stress tests passed\n"); }
int do_open(const char *filename, int oflags) { /*NOT_YET_IMPLEMENTED("VFS: do_open");*/ if (oflags!=O_RDONLY && oflags!=O_WRONLY && oflags!=O_RDWR && oflags!=O_APPEND && oflags!= (O_RDONLY | O_CREAT) && oflags != (O_RDWR | O_CREAT) && oflags != (O_RDWR | O_APPEND)) { return -EINVAL; } int fd = get_empty_fd(curproc); if( fd == -EMFILE){ return -EMFILE; } file_t *f = fget(-1); if( f == NULL){ return -ENOMEM; } curproc->p_files[fd] = f; /*Set file_t->f_mode to OR of FMODE_(READ|WRITE|APPEND) based on * oflags, which can be O_RDONLY, O_WRONLY or O_RDWR, possibly OR'd with * O_APPEND. */ /*FIXME check the logic below*/ if(oflags == O_RDONLY){ f->f_mode = FMODE_READ; }else if(oflags == O_WRONLY){ f->f_mode = FMODE_WRITE; }else if(oflags == O_RDWR){ f->f_mode = FMODE_READ | FMODE_WRITE; }else if(oflags == O_APPEND){ f->f_mode = FMODE_WRITE | FMODE_APPEND; }else if(oflags == (O_RDONLY | O_CREAT)){ f->f_mode = FMODE_READ; }else if(oflags == (O_RDWR | O_CREAT) ){ f->f_mode = FMODE_READ | FMODE_WRITE; }else if(oflags == (O_RDWR | O_APPEND) ){ f->f_mode = FMODE_READ | FMODE_WRITE | FMODE_APPEND; } vnode_t *pVnode; int s = open_namev(filename, oflags, &pVnode, NULL); if(s != 0){ curproc->p_files[fd] = NULL; fput(f); return s; } if(S_ISDIR(pVnode->vn_mode) && ((oflags & O_WRONLY) || (oflags & O_RDWR)) ){ curproc->p_files[fd] = NULL; vput(pVnode); fput(f); return -EISDIR; } if(S_ISBLK(pVnode->vn_mode)){ if(!(pVnode->vn_bdev = blockdev_lookup(pVnode->vn_devid))){ curproc->p_files[fd] = NULL; fput(f); vput(pVnode); return -ENXIO; } } if(S_ISCHR(pVnode->vn_mode)){ if(!(pVnode->vn_cdev = bytedev_lookup(pVnode->vn_devid))){ curproc->p_files[fd] = NULL; fput(f); vput(pVnode); return -ENXIO; } } f->f_pos=0; f->f_vnode = pVnode; return fd; }
/* * s5fs_read_vnode: * s5fs_read_vnode will be passed a vnode_t*, which will have its vn_fs * and vn_vno fields initialized. * param *vnode: the pointer to the vnode object */ static void s5fs_read_vnode(vnode_t *vnode) { dbg(DBG_S5FS, "{\n"); KASSERT(vnode != NULL); KASSERT(vnode->vn_fs != NULL); kmutex_lock(&vnode->vn_mutex); pframe_t* page = NULL; int ret = pframe_get(S5FS_TO_VMOBJ(FS_TO_S5FS(vnode->vn_fs)), S5_INODE_BLOCK(vnode->vn_vno), &page); KASSERT(ret == 0); KASSERT(page != NULL); pframe_pin(page); s5_inode_t* inode = ((s5_inode_t*)page->pf_addr) + S5_INODE_OFFSET(vnode->vn_vno); inode->s5_linkcount++; s5_dirty_inode(VNODE_TO_S5FS(vnode), inode); vnode->vn_i = inode; vnode->vn_len = inode->s5_size; switch(inode->s5_type) { case S5_TYPE_DIR: { vnode->vn_mode = S_IFDIR; vnode->vn_ops = &s5fs_dir_vops; break; } case S5_TYPE_DATA: { vnode->vn_mode = S_IFREG; vnode->vn_ops = &s5fs_file_vops; break; } case S5_TYPE_CHR: { vnode->vn_mode = S_IFCHR; vnode->vn_ops = NULL; vnode->vn_devid = (devid_t)(inode->s5_indirect_block); vnode->vn_cdev = bytedev_lookup(vnode->vn_devid); break; } case S5_TYPE_BLK: { vnode->vn_mode = S_IFBLK; vnode->vn_ops = NULL; vnode->vn_devid = (devid_t)(inode->s5_indirect_block); vnode->vn_bdev = blockdev_lookup(vnode->vn_devid); break; } default: { panic("inode %d has unknown/invalid type %d!!\n", (int)vnode->vn_vno, (int)inode->s5_type); } } kmutex_unlock(&vnode->vn_mutex); dbg(DBG_S5FS, "}\n"); }
void test_multiple_threads(){ dbg(DBG_TEST | DBG_DISK, "testing reading and writing to disk with multiple threads\n"); blockdev_t *bd = blockdev_lookup(MKDEVID(1, 0)); KASSERT (bd != NULL); char *readbuf1 = (char *) page_alloc_n(BLOCKS_TO_READ); char *readbuf2 = (char *) page_alloc_n(BLOCKS_TO_READ); char *writebuf1 = (char *) page_alloc_n(BLOCKS_TO_WRITE); char *writebuf2 = (char *) page_alloc_n(BLOCKS_TO_WRITE); KASSERT(readbuf1 != NULL && readbuf2 != NULL && writebuf2 != NULL && writebuf2 != NULL && "not enough memory"); unsigned int i; for (i = 0; i < (BLOCK_SIZE * BLOCKS_TO_WRITE); i++){ writebuf1[i] = 'a'; writebuf2[i] = 'b'; } /* create and run procs and threads for writing */ rw_args_t write_args_1 = {bd, writebuf1, BLOCKNUM_1, BLOCKS_TO_WRITE}; rw_args_t write_args_2 = {bd, writebuf2, BLOCKNUM_2, BLOCKS_TO_WRITE}; proc_t *wp1 = proc_create("ata_write_proc_1"); proc_t *wp2 = proc_create("ata_write_proc_2"); kthread_t *wt1 = kthread_create(wp1, write_func, 0, (void *) &write_args_1); kthread_t *wt2 = kthread_create(wp2, write_func, 0, (void *) &write_args_2); sched_make_runnable(wt1); sched_make_runnable(wt2); int status; do_waitpid(wp1->p_pid, 0, &status); do_waitpid(wp2->p_pid, 0, &status); /* create and run procs and threads for reading */ rw_args_t read_args_1 = {bd, readbuf1, BLOCKNUM_1, BLOCKS_TO_READ}; rw_args_t read_args_2 = {bd, readbuf2, BLOCKNUM_2, BLOCKS_TO_READ}; proc_t *rp1 = proc_create("ata_read_proc_1"); proc_t *rp2 = proc_create("ata_read_proc_2"); kthread_t *rt1 = kthread_create(rp1, read_func, 0, (void *) &read_args_1); kthread_t *rt2 = kthread_create(rp2, read_func, 0, (void *) &read_args_2); sched_make_runnable(rt1); sched_make_runnable(rt2); do_waitpid(rp1->p_pid, 0, &status); do_waitpid(rp2->p_pid, 0, &status); /* make sure that we wrote and read properly */ unsigned int j; for (j = 0; j < BLOCK_SIZE * BLOCKS_TO_READ; j++){ KASSERT(readbuf1[j] == 'a'); KASSERT(readbuf2[j] == 'b'); } page_free_n((void *) readbuf1, BLOCKS_TO_READ); page_free_n((void *) readbuf2, BLOCKS_TO_READ); page_free_n((void *) writebuf1, BLOCKS_TO_WRITE); page_free_n((void *) writebuf2, BLOCKS_TO_WRITE); dbg(DBG_TESTPASS, "All multi-threaded read/write tests passed\n"); }