void fs_test(void) { struct File *f; int r; char *blk; uint32_t *bits; // back up bitmap if ((r = sys_page_alloc(0, (void*) PGSIZE, PTE_P|PTE_U|PTE_W)) < 0) panic("sys_page_alloc: %e", r); bits = (uint32_t*) PGSIZE; memmove(bits, bitmap, PGSIZE); // allocate block if ((r = alloc_block()) < 0) panic("alloc_block: %e", r); // check that block was free assert(bits[r/32] & (1 << (r%32))); // and is not free any more assert(!(bitmap[r/32] & (1 << (r%32)))); cprintf("alloc_block is good\n"); if ((r = file_open("/not-found", &f)) < 0 && r != -E_NOT_FOUND) panic("file_open /not-found: %e", r); else if (r == 0) panic("file_open /not-found succeeded!"); if ((r = file_open("/newmotd", &f)) < 0) panic("file_open /newmotd: %e", r); cprintf("file_open is good\n"); if ((r = file_get_block(f, 0, &blk)) < 0) panic("file_get_block: %e", r); if (strcmp(blk, msg) != 0) panic("file_get_block returned wrong data"); cprintf("file_get_block is good\n"); *(volatile char*)blk = *(volatile char*)blk; assert((vpt[PPN(blk)] & PTE_D)); file_flush(f); assert(!(vpt[PPN(blk)] & PTE_D)); cprintf("file_flush is good\n"); if ((r = file_set_size(f, 0)) < 0) panic("file_set_size: %e", r); assert(f->f_direct[0] == 0); assert(!(vpt[PPN(f)] & PTE_D)); cprintf("file_truncate is good\n"); if ((r = file_set_size(f, strlen(msg))) < 0) panic("file_set_size 2: %e", r); assert(!(vpt[PPN(f)] & PTE_D)); if ((r = file_get_block(f, 0, &blk)) < 0) panic("file_get_block 2: %e", r); strcpy(blk, msg); assert((vpt[PPN(blk)] & PTE_D)); file_flush(f); assert(!(vpt[PPN(blk)] & PTE_D)); assert(!(vpt[PPN(f)] & PTE_D)); cprintf("file rewrite is good\n"); }
// Set *file to point at a free File structure in dir. The caller is // responsible for filling in the File fields. static int dir_alloc_file(struct File *dir, struct File **file) { int r; uint32_t nblock, i, j; char *blk; struct File *f; assert((dir->f_size % BLKSIZE) == 0); nblock = dir->f_size / BLKSIZE; for (i = 0; i < nblock; i++) { if ((r = file_get_block(dir, i, &blk)) < 0) return r; f = (struct File*) blk; for (j = 0; j < BLKFILES; j++) if (f[j].f_name[0] == '\0') { *file = &f[j]; return 0; } } dir->f_size += BLKSIZE; if ((r = file_get_block(dir, i, &blk)) < 0) return r; f = (struct File*) blk; *file = &f[0]; return 0; }
// Read count bytes from f into buf, starting from seek position // offset. This meant to mimic the standard pread function. // Returns the number of bytes read, < 0 on error. ssize_t file_read(struct File *f, void *buf, size_t count, off_t offset) { //cprintf("In file_read %x %x \n", count, offset); int r, bn; off_t pos; char *blk; if (offset >= f->f_size) return 0; count = MIN(count, f->f_size - offset); for (pos = offset; pos < offset + count; ) { //cprintf("In file_read %x\n", pos); if ((r = file_get_block(f, pos / BLKSIZE, &blk)) < 0) return r; //cprintf("\t\t\t\t\tfile_read : blk : %x\n", blk); bn = MIN(BLKSIZE - pos % BLKSIZE, offset + count - pos); memmove(buf, blk + pos % BLKSIZE, bn); pos += bn; buf += bn; } return count; }
// Try to find a file named "name" in dir. If so, set *file to it. // // Returns 0 and sets *file on success, < 0 on error. Errors are: // -E_NOT_FOUND if the file is not found static int dir_lookup(struct File *dir, const char *name, struct File **file) { int r; uint32_t i, j, nblock; char *blk; struct File *f; // Search dir for name. // We maintain the invariant that the size of a directory-file // is always a multiple of the file system's block size. assert((dir->f_size % BLKSIZE) == 0); nblock = dir->f_size / BLKSIZE; for (i = 0; i < nblock; i++) { if ((r = file_get_block(dir, i, &blk)) < 0) return r; f = (struct File*) blk; for (j = 0; j < BLKFILES; j++) if (strcmp(f[j].f_name, name) == 0) { *file = &f[j]; return 0; } } return -E_NOT_FOUND; }
// Read count bytes from f into buf, starting from seek position // offset. This meant to mimic the standard pread function. // Returns the number of bytes read, < 0 on error. ssize_t file_read(struct File *f, void *buf, size_t count, off_t offset) { int r, bn; off_t pos; char *blk; // void *org = buf; if (offset >= f->f_size) return 0; count = MIN(count, f->f_size - offset); for (pos = offset; pos < offset + count; ) { if ((r = file_get_block(f, pos / BLKSIZE, &blk)) < 0) return r; bn = MIN(BLKSIZE - pos % BLKSIZE, offset + count - pos); memmove(buf, blk + pos % BLKSIZE, bn); pos += bn; buf += bn; } /*if (count > 4){ cprintf("fs/fs.c get %d bytes %x: ", count, org); for (r = 0; r < 16; r++){ cprintf("%02x ", ((unsigned char *)org)[r]); } cprintf("\n"); }*/ return count; }
void serve_map(u_int envid, struct Fsreq_map *rq) { if (debug) { writef("serve_map %08x %08x %08x\n", envid, rq->req_fileid, rq->req_offset); } struct Open *pOpen; u_int filebno; void *blk; int r; // Your code here if ((r = open_lookup(envid, rq->req_fileid, &pOpen)) < 0) { ipc_send(envid, r, 0, 0); return; } filebno = rq->req_offset / BY2BLK; if ((r = file_get_block(pOpen->o_file, filebno, &blk)) < 0) { ipc_send(envid, r, 0, 0); return; } ipc_send(envid, 0, (u_int)blk, PTE_V | PTE_R | PTE_LIBRARY); return; // user_panic("serve_map not implemented"); }
void serve_map(envid_t envid, struct Fsreq_map *rq) { int r; char *blk; struct OpenFile *o; int perm; if (debug) cprintf("serve_map %08x %08x %08x\n", envid, rq->req_fileid, rq->req_offset); // Map the requested block in the client's address space // by using ipc_send. // Map read-only unless the file's open mode (o->o_mode) allows writes // (see the O_ flags in inc/lib.h). // LAB 5: Your code here. if ((r = openfile_lookup(envid, rq->req_fileid, &o)) < 0) goto out; if ((r = file_get_block(o->o_file, rq->req_offset/BLKSIZE, &blk)) < 0) goto out; if(o->o_mode & O_RDONLY) ipc_send(envid, 0, (void *)blk, PTE_P|PTE_U); else ipc_send(envid, 0, (void *)blk, PTE_P|PTE_U|PTE_W); return; out: ipc_send(envid, r, 0, 0); //panic("serve_map not implemented"); }
// Map the requested block in the client's address space // by using ipc_send. void serve_map(envid_t envid, struct Fsreq_map *rq) { int r; char *blk = NULL; struct OpenFile *o; int perm = 0; if (debug) cprintf("serve_map %08x %08x %08x\n", envid, rq->req_fileid, rq->req_offset); if ((r = openfile_lookup(envid, rq->req_fileid, &o)) < 0) goto out; // Map read-only unless the file's open mode (o->o_mode) allows writes // (see the O_ flags in inc/lib.h). perm = PTE_U | PTE_P | PTE_SHARE; if (o->o_mode & (O_WRONLY|O_RDWR)) perm |= PTE_W; r = file_get_block(o->o_file, rq->req_offset/BLKSIZE, &blk); out: ipc_send(envid, r, blk, perm); }
// Mark the offset/BLKSIZE'th block dirty in file f // by writing its first word to itself. int file_dirty(struct File *f, off_t offset) { int r; char *blk; if ((r = file_get_block(f, offset/BLKSIZE, &blk)) < 0) return r; *(volatile char*)blk = *(volatile char*)blk; return 0; }
int file_data_write(struct File *f, char *buf, size_t count, int block_no) { int err; int pblk, hash_addr; int addr; int hash_second_table_addr; int second_table_offset; int flag = 0; uint32_t hash = generate_hash(buf, BLKSIZE); int hash_first_table_addr = HashBlock_Start + (hash & HashLowBits); fseek(fp,hash_first_table_addr,SEEK_SET); fread(&addr, sizeof(int), 1, fp); if(addr == 0) { if(alloc_block(&hash_addr) < 0) { printf("\n error in block allocation for write"); return -1; } fseek(fp,hash_first_table_addr,SEEK_SET); fwrite(&hash_addr, sizeof(int), 1, fp); flush_block(hash_addr); if((err = file_get_block(f, block_no, &pblk)) < 0) { printf("\n error in getting block for write"); return -1; } flush_block(pblk); fseek(fp,pblk,SEEK_SET); fwrite(buf, count, 1, fp); f->f_size += count; f->f_written += count; f->n_blocks += 1; super->total_blocks+=1; super->written_blocks+=1; second_table_offset = (hash & HashHighBits) >> 25; hash_second_table_addr = (int)((int *)hash_addr + second_table_offset); fseek(fp,hash_second_table_addr,SEEK_SET); fwrite(&pblk, sizeof(int), 1, fp); } else {
void serve_map(u_int envid, struct Fsreq_map *rq) { struct Open *o; void *blk; int r = 0; if (debug) printf("serve_map %08x %08x %08x\n", envid, rq->req_fileid, rq->req_offset); if((r = open_lookup(envid, rq->req_fileid, &o)) < 0) goto out_map; if((r = file_get_block(&o->o_ff->f_file, rq->req_offset/BY2BLK, &blk)) < 0) goto out_map; ipc_send(envid, 0, (u_long)blk, PTE_P|PTE_U|PTE_W|PTE_LIBRARY); return; out_map: ipc_send(envid, r, 0, 0); // Your code here // panic("serve_map not implemented"); }
// Write count bytes from buf into f, starting at seek position // offset. This is meant to mimic the standard pwrite function. // Extends the file if necessary. // Returns the number of bytes written, < 0 on error. int file_write(struct File *f, const void *buf, size_t count, off_t offset) { int r, bn; off_t pos; char *blk; // Extend file if necessary if (offset + count > f->f_size) if ((r = file_set_size(f, offset + count)) < 0) return r; for (pos = offset; pos < offset + count; ) { if ((r = file_get_block(f, pos / BLKSIZE, &blk)) < 0) return r; bn = MIN(BLKSIZE - pos % BLKSIZE, offset + count - pos); memmove(blk + pos % BLKSIZE, buf, bn); pos += bn; buf += bn; } return count; }
void serve_map(envid_t envid, struct Fsreq_map *rq) { int r; char *blk; struct OpenFile *o; int perm = PTE_U | PTE_P | PTE_AVAIL; uint32_t *pdiskbno; if (debug) cprintf("serve_map %08x %08x %08x\n", envid, rq->req_fileid, rq->req_offset); // Map the requested block in the client's address space // by using ipc_send. // Map read-only unless the file's open mode (o->o_mode) allows writes // (see the O_ flags in inc/lib.h). // LAB 5: Your code here. r = openfile_lookup(envid, rq->req_fileid, &o); if (r<0) { cprintf("serv.c:serve_map--openfile_lookup failed.\n"); ipc_send(envid, r, 0, 0); return; } r = file_get_block(o->o_file, rq->req_offset, &blk); if (r<0) { cprintf("serv.c:serve_map--file_get_walk failed.\n"); goto out; } if (o->o_mode&O_RDWR) {//what happens if O_WRONLY? perm = PTE_USER; } out: ipc_send(envid, r, blk, perm); //panic("serve_map not implemented"); }