// If this is the file server (type == ENV_TYPE_FS) give it I/O privileges. // LAB 5: Your code here. if(type == ENV_TYPE_FS) e->env_tf.tf_eflags |= FL_IOPL_MASK;
// Allocate a page in the disk map region, read the contents // of the block from the disk into that page. // Hint: first round addr to page boundary. fs/ide.c has code to read // the disk. // // LAB 5: you code here: addr = ROUNDDOWN(addr, BLKSIZE); if((r = sys_page_alloc(0, addr, PTE_U | PTE_P | PTE_W)) < 0) panic("in bc_pgfault, sys_page_alloc: %e", r); if((r = ide_read(blockno << 3, addr, 8)) < 0) panic("in_bc_pgfault, ide_read: %e", r);
// Mark a block free in the bitmap void free_block(uint32_t blockno) { // Blockno zero is the null pointer of block numbers. if (blockno == 0) panic("attempt to free zero block"); bitmap[blockno/32] |= 1<<(blockno%32); }
// Search the bitmap for a free block and allocate it. When you // allocate a block, immediately flush the changed bitmap block // to disk. // // Return block number allocated on success, // -E_NO_DISK if we are out of blocks. // // Hint: use free_block as an example for manipulating the bitmap. int alloc_block(void) { // The bitmap consists of one or more blocks. A single bitmap block // contains the in-use bits for BLKBITSIZE blocks. There are // super->s_nblocks blocks in the disk altogether.
// Find the disk block number slot for the 'filebno'th block in file 'f'. // Set '*ppdiskbno' to point to that slot. // The slot will be one of the f->f_direct[] entries, // or an entry in the indirect block. // When 'alloc' is set, this function will allocate an indirect block // if necessary. // // Returns: // 0 on success (but note that *ppdiskbno might equal 0). // -E_NOT_FOUND if the function needed to allocate an indirect block, but // alloc was 0. // -E_NO_DISK if there's no space on the disk for an indirect block. // -E_INVAL if filebno is out of range (it's >= NDIRECT + NINDIRECT). // // Analogy: This is like pgdir_walk for files. // Hint: Don't forget to clear any block you allocate. staticint file_block_walk(struct File *f, uint32_t filebno, uint32_t **ppdiskbno, bool alloc) { // LAB 5: Your code here. int r;
// Set *blk to the address in memory where the filebno'th // block of file 'f' would be mapped. // // Returns 0 on success, < 0 on error. Errors are: // -E_NO_DISK if a block needed to be allocated but the disk is full. // -E_INVAL if filebno is out of range. // // Hint: Use file_block_walk and alloc_block. int file_get_block(struct File *f, uint32_t filebno, char **blk) { // LAB 5: Your code here. uint32_t * pdiskbno; int r; if((r = file_block_walk(f, filebno, &pdiskbno, true)) < 0) return r; if(*pdiskbno == 0){ if((r = alloc_block()) < 0) return r; *pdiskbno = r; } *blk = (char *)diskaddr(*pdiskbno); flush_block(*blk); return0; }
// Read at most ipc->read.req_n bytes from the current seek position // in ipc->read.req_fileid. Return the bytes read from the file to // the caller in ipc->readRet, then update the seek position. Returns // the number of bytes successfully read, or < 0 on error. int serve_read(envid_t envid, union Fsipc *ipc) { structFsreq_read *req = &ipc->read; structFsret_read *ret = &ipc->readRet;
if (debug) cprintf("serve_read %08x %08x %08x\n", envid, req->req_fileid, req->req_n);
// Write req->req_n bytes from req->req_buf to req_fileid, starting at // the current seek position, and update the seek position // accordingly. Extend the file if necessary. Returns the number of // bytes written, or < 0 on error. int serve_write(envid_t envid, struct Fsreq_write *req) { if (debug) cprintf("serve_write %08x %08x %08x\n", envid, req->req_fileid, req->req_n);
// Write at most 'n' bytes from 'buf' to 'fd' at the current seek position. // // Returns: // The number of bytes successfully written. // < 0 on error. staticssize_t devfile_write(struct Fd *fd, constvoid *buf, size_t n) { // Make an FSREQ_WRITE request to the file system server. Be // careful: fsipcbuf.write.req_buf is only so large, but // remember that write is always allowed to write *fewer* // bytes than requested. // LAB 5: Your code here int r; fsipcbuf.write.req_fileid = fd->fd_file.id; fsipcbuf.write.req_n = n; memmove(fsipcbuf.write.req_buf, buf, n); if((r = fsipc(FSREQ_WRITE, NULL)) < 0) return r; assert(r <= n); assert(r <= PGSIZE); return r; }
// Set envid's trap frame to 'tf'. // tf is modified to make sure that user environments always run at code // protection level 3 (CPL 3), interrupts enabled, and IOPL of 0. // // Returns 0 on success, < 0 on error. Errors are: // -E_BAD_ENV if environment envid doesn't currently exist, // or the caller doesn't have permission to change envid. staticint sys_env_set_trapframe(envid_t envid, struct Trapframe *tf) { // LAB 5: Your code here. // Remember to check whether the user has supplied us with a good // address! structEnv* env; if(envid2env(envid, &env, 1)) return -E_BAD_ENV; env->env_tf = *tf; env->env_tf.tf_eflags |= FL_IF; env->env_tf.tf_eflags &= ~FL_IOPL_MASK; env->env_tf.tf_cs |= 3; return0; panic("sys_env_set_trapframe not implemented"); }
case'>': // Output redirection // Grab the filename from the argument list if (gettoken(0, &t) != 'w') { cprintf("syntax error: > not followed by word\n"); exit(); } if ((fd = open(t, O_WRONLY|O_CREAT|O_TRUNC)) < 0) { cprintf("open %s for write: %e", t, fd); exit(); } if (fd != 1) { dup(fd, 1); close(fd); } break;
internal FS tests [fs/test.c]: OK (1.0s) fs i/o: OK check_bc: OK check_super: OK check_bitmap: OK alloc_block: OK file_open: OK file_get_block: OK file_flush/file_truncate/file rewrite: OK testfile: OK (1.6s) serve_open/file_stat/file_close: OK file_read: OK file_write: OK file_read after file_write: OK open: OK large file: OK spawn via spawnhello: OK (1.8s) Protection I/O space: OK (1.6s) PTE_SHARE [testpteshare]: OK (0.9s) PTE_SHARE [testfdsharing]: OK (1.4s) start the shell [icode]: Timeout! OK (31.5s) testshell: OK (2.4s) (Old jos.out.testshell failure log removed) primespipe: OK (7.2s) Score: 150/150