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"); }
/* * Initialize a tty device. The driver should not be NULL, but we don't * need a line descriptor yet. To initialize the byte device in the tty * struct, use the MKDEVID macro and the correct byte device function * table for a tty. */ tty_device_t * tty_create(tty_driver_t *driver, int id) { KASSERT(driver != NULL); //slab_allocator_t * device_allocator = slab_allocator_create("device", sizeof(tty_device_t)); tty_device_t * dev = (tty_device_t *)kmalloc(sizeof(tty_device_t)); dev->tty_driver = driver; dev->tty_id = id; dev->tty_cdev = *((bytedev_t *)kmalloc(sizeof(bytedev_t))); dev->tty_cdev.cd_id = MKDEVID(2, MINOR(id)); //dbg_print("%d, %d\n", id, MINOR(1)); dev->tty_cdev.cd_ops = &tty_bytedev_ops; list_link_init(&(dev->tty_cdev.cd_link)); NOT_YET_IMPLEMENTED("DRIVERS: tty_create"); return dev; }
/* * Initialize a tty device. The driver should not be NULL, but we don't * need a line descriptor yet. To initialize the byte device in the tty * struct, use the MKDEVID macro and the correct byte device function * table for a tty. */ tty_device_t * tty_create(tty_driver_t *driver, int id) { /* DRIVERS {{{ */ tty_device_t *tty; KASSERT(NULL != driver); tty = (tty_device_t *)kmalloc(sizeof(tty_device_t)); if (NULL == tty) return NULL; tty->tty_driver = driver; tty->tty_ldisc = NULL; tty->tty_id = id; tty->tty_cdev.cd_id = MKDEVID(TTY_MAJOR, id); tty->tty_cdev.cd_ops = &tty_bytedev_ops; return tty; /* DRIVERS }}} */ return 0; }
int vfs_selftest(kshell_t *kshell, int argc, char **argv) { int fd1,fd2; char *y="/ab/fil"; char x[2]; int err; do_mkdir("/ab"); do_mknod("/ab/new", S_IFCHR,MKDEVID(1,1)); fd1=do_open("/ab/new",2); fd2=do_dup2(fd1,NFILES+1); if(fd2<0) { dbg(DBG_PRINT,"File not created\n"); } do_mknod("/ab/notmade",4096,MKDEVID(1,1)); do_mknod("/ab/new/not",S_IFCHR,MKDEVID(1,1)); do_mknod("/ab/new", S_IFCHR,MKDEVID(1,1)); do_mknod("", S_IFCHR,MKDEVID(1,1)); /*do_close(fd1);*/ for(fd2=1;fd2<35;fd2++) { sprintf(x,"%d",fd2); strcat(y,x); do_mknod(y,S_IFCHR,MKDEVID(1,0)); err=do_open(y,2); if(err<0) { break; } if(fd2<10) { y[strlen(y)-1]='\0'; } else { y[strlen(y)-2]='\0'; } } do_mknod("/ab/new1", S_IFCHR,MKDEVID(1,1)); err=do_dup(fd1); do_unlink("/ab/new/ab"); do_unlink("/ab/new"); do_close(fd1); for(fd2=NFILES-1;fd2>0;fd2--) { err=do_close(fd2); sprintf(x,"%d",fd2); strcat(y,x); do_unlink(y); if(err<0) { break; } if(fd2<10) { y[strlen(y)-1]='\0'; } else { y[strlen(y)-2]='\0'; } } do_link("/a","/dev"); do_link("/dev","/a"); do_link("/dev","/a"); do_rmdir("/a"); /* mkdir("/k"); do_link("/ab","/k");*/ do_rmdir("/ab"); /*do_rmdir("/k");*/ /*GS: SELF TESTS*/ dbg(DBG_PRINT,"\n*************************************************************\n"); dbg(DBG_PRINT,"\n\n\n\n(GRADING2C)(kmain.c)(selftest_proc_run) selftests begin\n"); int retVal = 0; int i = 0; /* 1. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_stat) strlen too long, return -ENAMETOOLONG\n");*/ char longPath[1024 + 1] = {0}; for(i = 0; i < 1025; i++) longPath[i] = 'a'; struct stat buf; retVal = do_stat(longPath, &buf); retVal=do_chdir(longPath); /*2. dbg(DBG_PRINT, "(GRADING2B) ENOTDIR or ENOENT\n");*/ retVal = do_stat("", &buf); /*3. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_getdent) Invalid file descriptor fd, return -EBADF\n");*/ struct dirent dirp; retVal = do_getdent(-1, &dirp); /*4. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_getdent) Invalid file descriptor fd, return -EBADF\n");*/ retVal = do_getdent(1, &dirp); /*5. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_getdent) File descriptor does not refer to a directory, return -ENOTDIR\n");*/ do_mknod("/./file", S_IFCHR,MKDEVID(1,1)); fd1 = do_open("/./file",2); retVal = do_getdent(fd1, &dirp); do_unlink("/./file"); do_close(fd1); /*6. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_rename) Both are valid names \n");*/ /* and */ /*7. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_rename) error do_link, return error\n"); \n");*/ retVal = do_rename("/./aaa", "/./bbb"); dbg(DBG_PRINT,"\n\nretVal=%d",retVal); dbg(DBG_PRINT,"\n*************************************************************\n"); return 0; }
/** * Once we're inside of idleproc_run(), we are executing in the context of the * first process-- a real context, so we can finally begin running * meaningful code. * * This is the body of process 0. It should initialize all that we didn't * already initialize in kmain(), launch the init process (initproc_run), * wait for the init process to exit, then halt the machine. * * @param arg1 the first argument (unused) * @param arg2 the second argument (unused) */ static void *idleproc_run(int arg1, void *arg2) { int status; pid_t child; /* create init proc */ kthread_t *initthr = initproc_create(); init_call_all(); GDB_CALL_HOOK(initialized); /* Create other kernel threads (in order) */ #ifdef __VFS__ curproc->p_cwd=vfs_root_vn; vref(vfs_root_vn); if(initthr!=NULL) { initthr->kt_proc->p_cwd=vfs_root_vn; vref(vfs_root_vn); } KASSERT(do_mkdir("/dev") == 0); KASSERT(do_mknod("/dev/null", S_IFCHR, MKDEVID(1, 0)) == 0); KASSERT(do_mknod("/dev/zero", S_IFCHR, MKDEVID(1, 1)) == 0); KASSERT(do_mknod("/dev/tty0", S_IFCHR, MKDEVID(2, 0)) == 0); KASSERT(do_mknod("/dev/tty1", S_IFCHR, MKDEVID(2, 1)) == 0); KASSERT(do_mknod("/dev/tty2", S_IFCHR, MKDEVID(2, 3)) == 0); /* Once you have VFS remember to set the current working directory * of the idle and init processes */ /* Here you need to make the null, zero, and tty devices using mknod */ /* You can't do this until you have VFS, check the include/drivers/dev.h * file for macros with the device ID's you will need to pass to mknod */ #endif /* Finally, enable interrupts (we want to make sure interrupts * are enabled AFTER all drivers are initialized) */ intr_enable(); /* Run initproc */ sched_make_runnable(initthr); /* dbg_print("\nidleproc_run returned from sched_make_rinnable and calling do wait_pid \n");*/ /* Now wait for it */ child = do_waitpid(-1, 0, &status); dbg(DBG_INIT,"Process %d cleaned successfully\n", child); KASSERT(PID_INIT == child); #ifdef __MTP__ kthread_reapd_shutdown(); #endif #ifdef __VFS__ /* Shutdown the vfs: */ dbg_print("weenix: vfs shutdown...\n"); vput(curproc->p_cwd); if (vfs_shutdown()) panic("vfs shutdown FAILED!!\n"); #endif dbg_print("weenix: vfs shutdown...\n"); /* Shutdown the pframe system */ #ifdef __S5FS__ pframe_shutdown(); #endif dbg_print("\nweenix: halted cleanly!\n"); GDB_CALL_HOOK(shutdown); hard_shutdown(); return NULL; }
/** * Once we're inside of idleproc_run(), we are executing in the context of the * first process-- a real context, so we can finally begin running * meaningful code. * * This is the body of process 0. It should initialize all that we didn't * already initialize in kmain(), launch the init process (initproc_run), * wait for the init process to exit, then halt the machine. * * @param arg1 the first argument (unused) * @param arg2 the second argument (unused) */ static void * idleproc_run(int arg1, void *arg2) { int status; pid_t child; /* create init proc */ kthread_t *initthr = initproc_create(); /* dbg(DBG_INIT,"created initproc"); dbg(DBG_INIT,"%d",curproc->p_pid);*/ init_call_all(); GDB_CALL_HOOK(initialized); /* Create other kernel threads (in order) */ #ifdef __VFS__ /* Once you have VFS remember to set the current working directory * of the idle and init processes */ curproc->p_cwd = vfs_root_vn; initthr->kt_proc->p_cwd = vfs_root_vn; vref(vfs_root_vn); vref(vfs_root_vn); /* Here you need to make the null, zero, and tty devices using mknod */ /* You can't do this until you have VFS, check the include/drivers/dev.h * file for macros with the device ID's you will need to pass to mknod */ /*NOT_YET_IMPLEMENTED("VFS: idleproc_run");*/ /*TODO Dont know When VFS will be formed*/ if(do_mkdir("/dev") >= 0) { dbg(DBG_PRINT,"(GRADING2C) Creating null, zero and tty0\n"); /*do_mkdir("/dev");*/ /*Block devices*/ int status1=do_mknod("/dev/null", S_IFCHR, MEM_NULL_DEVID); int status2=do_mknod("/dev/zero", S_IFCHR, MEM_ZERO_DEVID); int status3=do_mknod("/dev/tty0", S_IFCHR, MKDEVID(2, 0)); } #endif /* Finally, enable interrupts (we want to make sure interrupts * are enabled AFTER all drivers are initialized) */ intr_enable(); /* Run initproc */ sched_make_runnable(initthr); /* Now wait for it */ child = do_waitpid(-1, 0, &status); KASSERT(PID_INIT == child); #ifdef __MTP__ kthread_reapd_shutdown(); #endif #ifdef __VFS__ /* Shutdown the vfs: */ dbg_print("weenix: vfs shutdown...\n"); vput(curproc->p_cwd); if (vfs_shutdown()) panic("vfs shutdown FAILED!!\n"); #endif /* Shutdown the pframe system */ #ifdef __S5FS__ pframe_shutdown(); #endif dbg_print("\nweenix: halted cleanly!\n"); GDB_CALL_HOOK(shutdown); hard_shutdown(); return NULL; }
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"); }
/** * Once we're inside of idleproc_run(), we are executing in the context of the * first process-- a real context, so we can finally begin running * meaningful code. * * This is the body of process 0. It should initialize all that we didn't * already initialize in kmain(), launch the init process (initproc_run), * wait for the init process to exit, then halt the machine. * * @param arg1 the first argument (unused) * @param arg2 the second argument (unused) */ static void * idleproc_run(int arg1, void *arg2) { int status; pid_t child; /* create init proc */ kthread_t *initthr = initproc_create(); init_call_all(); GDB_CALL_HOOK(initialized); /* Create other kernel threads (in order) */ /* PROCS BLANK {{{ */ #ifdef __SHADOWD__ /* TODO port this - alvin */ #endif /* PROCS BLANK }}} */ #ifdef __VFS__ /* Once you have VFS remember to set the current working directory * of the idle and init processes */ /* PROCS BLANK {{{ */ proc_t *idle = proc_lookup(PID_IDLE); proc_t *init = proc_lookup(PID_INIT); KASSERT(NULL != idle); KASSERT(NULL != init); idle->p_cwd = vfs_root_vn; init->p_cwd = vfs_root_vn; vref(vfs_root_vn); vref(vfs_root_vn); /* PROCS BLANK }}} */ /* Here you need to make the null, zero, and tty devices using mknod */ /* You can't do this until you have VFS, check the include/drivers/dev.h * file for macros with the device ID's you will need to pass to mknod */ /* PROCS BLANK {{{ */ int fd, ii; char path[32]; struct stat statbuf; if (do_stat("/dev", &statbuf) < 0) { KASSERT(!(status = do_mkdir("/dev"))); } if ((fd = do_open("/dev/null", O_RDONLY)) < 0) { KASSERT(!(status = do_mknod("/dev/null", S_IFCHR, MEM_NULL_DEVID))); } else { do_close(fd); } if ((fd = do_open("/dev/zero", O_RDONLY)) < 0) { KASSERT(!(status = do_mknod("/dev/zero", S_IFCHR, MEM_ZERO_DEVID))); } else { do_close(fd); } memset(path, '\0', 32); for (ii = 0; ii < __NTERMS__; ii++) { sprintf(path, "/dev/tty%d", ii); dbg(DBG_INIT, "Creating tty mknod with path %s\n", path); if ((fd = do_open(path, O_RDONLY)) < 0) { KASSERT(!do_mknod(path, S_IFCHR, MKDEVID(2, ii))); } else { do_close(fd); } } for (ii = 0; ii < __NDISKS__; ii++) { sprintf(path, "/dev/hda%d", ii); dbg(DBG_INIT, "Creating disk mknod with path %s\n", path); if ((fd = do_open(path, O_RDONLY)) < 0) { KASSERT(!do_mknod(path, S_IFBLK, MKDEVID(1, ii))); } else { do_close(fd); } } /* PROCS BLANK }}} */ #endif /* Finally, enable interrupts (we want to make sure interrupts * are enabled AFTER all drivers are initialized) */ intr_enable(); /* Run initproc */ sched_make_runnable(initthr); /* Now wait for it */ child = do_waitpid(-1, 0, &status); KASSERT(PID_INIT == child); #ifdef __MTP__ kthread_reapd_shutdown(); #endif #ifdef __SHADOWD__ /* wait for shadowd to shutdown */ shadowd_shutdown(); #endif #ifdef __VFS__ /* Shutdown the vfs: */ dbg_print("weenix: vfs shutdown...\n"); vput(curproc->p_cwd); if (vfs_shutdown()) panic("vfs shutdown FAILED!!\n"); #endif /* Shutdown the pframe system */ #ifdef __S5FS__ pframe_shutdown(); #endif dbg_print("\nweenix: halted cleanly!\n"); GDB_CALL_HOOK(shutdown); hard_shutdown(); return NULL; }