// Test that write_block works, by smashing the superblock and reading it back. void check_write_block(void) { super = 0; // back up super block read_block(0, 0); memcpy(diskaddr(0), diskaddr(1), PGSIZE); // smash it strcpy(diskaddr(1), "OOPS!\n"); write_block(1); assert(block_is_mapped(1)); assert(!va_is_dirty(diskaddr(1))); // clear it out sys_page_unmap(0, diskaddr(1)); assert(!block_is_mapped(1)); // read it back in read_block(1, 0); assert(strcmp(diskaddr(1), "OOPS!\n") == 0); // fix it memcpy(diskaddr(1), diskaddr(0), PGSIZE); write_block(1); super = (struct Super*)diskaddr(1); cprintf("write_block is good\n"); }
// Make sure this block is unmapped. void unmap_block(uint32_t blockno) { int r; if (!block_is_mapped(blockno)) return; assert(block_is_free(blockno) || !block_is_dirty(blockno)); if ((r = sys_page_unmap(0, diskaddr(blockno))) < 0) panic("unmap_block: sys_mem_unmap: %e", r); assert(!block_is_mapped(blockno)); }
// Make sure a particular disk block is loaded into memory. // Returns 0 on success, or a negative error code on error. // // If blk != 0, set *blk to the address of the block in memory. // // Hint: Use diskaddr, map_block, and ide_read. static int read_block(uint32_t blockno, char **blk) { int r; char *addr; if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); // LAB 5: Your code here. addr = diskaddr(blockno); if(!block_is_mapped(blockno)){ if ((r = sys_page_alloc(sys_getenvid(), diskaddr(blockno), PTE_U|PTE_P|PTE_W)) < 0) return r; if((r = ide_read(blockno*(BLKSIZE/SECTSIZE), addr, (size_t) BLKSIZE/SECTSIZE)) < 0) return r; } if(blk != 0) *blk = addr; return 0; }
// Allocate a page to hold the disk block int map_block(uint32_t blockno) { if (block_is_mapped(blockno)) return 0; return sys_page_alloc(0, diskaddr(blockno), PTE_U|PTE_P|PTE_W); }
// Make sure a particular disk block is loaded into memory. // Returns 0 on success, or a negative error code on error. // // If blk != 0, set *blk to the address of the block in memory. // // Hint: Use diskaddr, map_block, and ide_read. static int read_block(uint32_t blockno, char **blk) { int r; char *addr; if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); // LAB 5: Your code here. addr = diskaddr(blockno); if (block_is_mapped(blockno)) { goto succeeded; } // now that the block is not in memory, allocate memory and read it in. if ((r = map_block(blockno)) < 0) return r; if ((r = ide_read(blockno * BLKSECTS, addr, BLKSECTS)) < 0) return r; succeeded: if (blk) *blk = addr; return 0; }
// Make sure a particular disk block is loaded into memory. // Returns 0 on success, or a negative error code on error. // // If blk != 0, set *blk to the address of the block in memory. // // Hint: Use diskaddr, map_block, and ide_read. static int read_block(uint32_t blockno, char **blk) { int r; char *addr; if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); addr = diskaddr(blockno); if(!block_is_mapped(blockno)){ if((r = map_block(blockno)) < 0) return r; r = ide_read(blockno*BLKSECTS, (void *)addr, BLKSECTS); if(r < 0) return r; } if(blk) *blk = addr; return 0; }
// Copy the current contents of the block out to disk. // Then clear the PTE_D bit using sys_page_map. // Hint: Use ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. void write_block(uint32_t blockno) { char *addr; if (!block_is_mapped(blockno)) panic("write unmapped block %08x", blockno); // Write the disk block and clear PTE_D. // LAB 5: Your code here. // We will use the VM hardware to keep track of whether a // disk block has been modified since it was last read from // or written to disk. To see whether a block needs writing, // we can just look to see if the PTE_D "dirty" bit is set // in the vpt entry. addr = diskaddr(blockno); if(!va_is_dirty(addr)) return; int error; int secno = blockno*BLKSECTS; error = ide_write(secno, addr, BLKSECTS); if(error<0) panic("write block error on writing"); int env_id = sys_getenvid(); error = sys_page_map(env_id, addr, env_id, addr, ((PTE_U|PTE_P|PTE_W) & ~PTE_D)); if(error<0) panic("write block error on clearing PTE_D"); // panic("write_block not implemented"); }
// Set *blk to point at the filebno'th block in file 'f'. // Allocate the block if it doesn't yet exist. // Returns 0 on success, < 0 on error. int file_get_block(struct File *f, uint32_t filebno, char **blk) { int r; uint32_t diskbno; // Read in the block, leaving the pointer in *blk. // Hint: Use file_map_block and read_block. // LAB 5: Your code here. r = file_map_block(f, filebno, &diskbno, 1); if (r) return r; // If the block is already mapped we return it // instead of reading the block from disk again. // XXX: I'm not sure whether this is the right // thing to do, however, looks like lab5 says // to do that (p. 7). if (block_is_mapped(diskbno)) { if (blk) *blk = diskaddr(diskbno); return 0; } return read_block(diskbno, blk); }
// Copy the current contents of the block out to disk. // Then clear the PTE_D bit using sys_page_map. // Hint: Use ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. void write_block(uint32_t blockno) { int r; char *addr; if (!block_is_mapped(blockno)) panic("write unmapped block %08x", blockno); // Write the disk block and clear PTE_D. // LAB 5: Your code here. addr = diskaddr(blockno); if ((r = ide_write(blockno * BLKSECTS, addr, BLKSECTS)) < 0) panic("write_block: ide_write failed: %e.\n", r); if ((r = sys_page_map(0, addr, 0, addr, PTE_USER)) < 0) panic("write_block: sys_page_map failed: %e.\n", r); }
// Set *blk to point at the filebno'th block in file 'f'. // Allocate the block if it doesn't yet exist. // Returns 0 on success, < 0 on error. int file_get_block(struct File *f, uint32_t filebno, char **blk) { int r; uint32_t diskbno; // Read in the block, leaving the pointer in *blk. // Hint: Use file_map_block and read_block. // LAB 5: Your code here. r = file_map_block(f, filebno, &diskbno, 1); if(r < 0) return r; if(!block_is_mapped(diskbno)) read_block(diskbno, blk); else *blk = diskaddr(diskbno); //panic("file_get_block not implemented"); return 0; }
// Copy the current contents of the block out to disk. // Then clear the PTE_D bit using sys_page_map. // Hint: Use ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. void write_block(uint32_t blockno) { int r; char *addr; if (!block_is_mapped(blockno)) panic("write unmapped block %08x", blockno); // Write the disk block and clear PTE_D. // LAB 5: Your code here. addr = diskaddr(blockno); r = ide_write(blockno * BLKSECTS, addr, BLKSECTS); if (r) panic("write_block(): ide_write() failed: %e\n", r); r = sys_page_map(0, addr, 0, addr, vpt[VPN(addr)] & PTE_USER); if (r) panic("write_block(): sys_page_map() failed: %e\n", r); }
// Copy the current contents of the block out to disk. // Then clear the PTE_D bit using sys_page_map. // Hint: Use ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. void write_block(uint32_t blockno) { char *addr; if (!block_is_mapped(blockno)) panic("write unmapped block %08x", blockno); // Write the disk block and clear PTE_D. // LAB 5: Your code here. addr = diskaddr(blockno); if(va_is_dirty(addr) == 0){ cprintf("va isn't dirty!\n"); return; } if(ide_write(blockno * BLKSECTS, addr, BLKSECTS) < 0) panic("write_block ide_write fail!\n"); if(sys_page_map(0,addr,0,addr, PTE_USER) < 0) panic("write_block sys_page_map fail!\n"); return; }
// Copy the current contents of the block out to disk. // Then clear the PTE_D bit using sys_page_map. // Hint: Use ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. void write_block(uint32_t blockno) { char *addr; int r; if (!block_is_mapped(blockno)) panic("write unmapped block %08x", blockno); // Write the disk block and clear PTE_D. // LAB 5: Your code here. addr = diskaddr(blockno); if(va_is_dirty(addr)){ r = ide_write(blockno*BLKSECTS, (void *)addr, BLKSECTS); if(r < 0) panic("GZ write block fault !!\n"); r = sys_page_map(0, addr, 0, addr, PTE_USER); if(r < 0) panic("GZ can not clear PTE_D!!\n"); } //panic("write_block not implemented"); }
// Copy the current contents of the block out to disk. // Then clear the PTE_D bit using sys_page_map. // Hint: Use ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. int write_block(uint32_t blockno) { char *addr; int r; if (!block_is_mapped(blockno)) panic("write unmapped block %08x", blockno); // Write the disk block and clear PTE_D. // LAB 5: Your code here. addr = diskaddr(blockno); if((r = ide_write(blockno*(BLKSIZE/SECTSIZE), (const void *)addr, (size_t) BLKSIZE/SECTSIZE)) < 0) return r; if(block_is_dirty(blockno)) if ((r = sys_page_map(sys_getenvid(), addr, sys_getenvid(), addr, (PTE_U|PTE_P|PTE_W) & ~PTE_D)) < 0) return r; return 0; }
// Make sure a particular disk block is loaded into memory. // Returns 0 on success, or a negative error code on error. // // If blk != 0, set *blk to the address of the block in memory. // // Hint: Use diskaddr, map_block, and ide_read. static int read_block(uint32_t blockno, char **blk) { int r; char *addr; if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); addr = diskaddr(blockno); // the block has already been read if (block_is_mapped(blockno)) { if (blk) *blk = addr; return 0; } // otherwise, allocate a new page, // and read it into memory r = sys_page_alloc(0, addr, PTE_U| PTE_P| PTE_W |PTE_SHARE); if (r < 0) return r; r = ide_read(blockno * BLKSECTS, addr, BLKSECTS); if (r < 0) return r; if (blk) *blk = addr; return 0; }