// Release (erase) a data block static void data_release_block(unsigned int block_n) { unsigned int block_group = (block_n - 1) / sb->s_blocks_per_group; // Write the bitmap in the disk bitmap_write(bm_blocks, block_n - 1, 0); block_write(&g_block_bmps[block_group], bgroup_blockbmp(bgroup_get(block_group))); }
/* Makes CNT sectors starting at SECTOR available for use. */ void free_map_release (block_sector_t sector, size_t cnt) { ASSERT (bitmap_all (free_map, sector, cnt)); bitmap_set_multiple (free_map, sector, cnt, false); bitmap_write (free_map, free_map_file); }
/* Writes the free map to disk and closes the free map file. */ void free_map_close (void) { if (!bitmap_write (free_map, free_map_file)) PANIC ("can't write free map"); file_close (free_map_file); }
void SA1::bus_write(unsigned addr, uint8 data) { if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff return mmio_write(addr, data); } if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff return mmc_sa1_write(addr, data); } if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff synchronize_cpu(); return iram.write(addr & 2047, data); } if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff synchronize_cpu(); return iram.write(addr & 2047, data); } if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff synchronize_cpu(); return bwram.write(addr & (bwram.size() - 1), data); } if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff synchronize_cpu(); return bitmap_write(addr & 0x0fffff, data); } }
// Deletes the internal nodes of a block when deleting the file. // The internal nodes are the blocks used to make the indirects void delete_internal_inodes(int log_block) { int indirects = inode_get_indir_level(log_block); if (indirects == 0) { bitmap_write(bm_blocks, n.data_blocks[log_block] - 1, 0); } int i1_delete = 1; int i2_delete = 1; int i3_delete = 1; int i1_ptr; int i2_ptr; int i3_ptr; int * data = (int *) &bi; block_clear(&bi); if (indirects >= 1) { data_read_block(&bi, (i1_ptr = n.data_blocks[inode_get_dir_block(log_block)]) ); i1_delete = inode_get_1indir_block(log_block) == 0; if (indirects >= 2) { data_read_block(&bi, (i2_ptr = data[inode_get_1indir_block(log_block)]) ); i2_delete = inode_get_2indir_block(log_block) == 0; if (indirects >= 3) { i3_ptr = data[inode_get_1indir_block(log_block)]; i3_delete = inode_get_3indir_block(log_block) == 0; if (i3_delete) { bitmap_write(bm_blocks, i3_ptr - 1, 0); } } i2_delete = i2_delete && i3_delete; if (i2_delete) { bitmap_write(bm_blocks, i2_ptr - 1, 0); } } i1_delete = i1_delete && i2_delete; if (i1_delete) { bitmap_write(bm_blocks, i1_ptr - 1, 0); } } }
// Writes a logical block from an inode void log_block_read(inode * n, int * log_block) { int ph_block = 0; make_ph_block(n, &ph_block, log_block); // Write the data inside the data block data_read_block(&b, ph_block); bitmap_write(bm_blocks, ph_block - 1, 1); }
// Reads a logical block from an inode void log_block_write(inode * n, int * log_block) { int ph_block; make_ph_block(n, &ph_block, log_block); // Write the data inside the data block bitmap_write(bm_blocks, ph_block - 1, 1); data_write_block(&b, ph_block); }
/* Makes CNT sectors starting at SECTOR available for use. */ void free_map_release (disk_sector_t sector, size_t cnt) { // lås id 6 lock_acquire(&free_map_lock); ASSERT (bitmap_all (free_map, sector, cnt)); bitmap_set_multiple (free_map, sector, cnt, false); bitmap_write (free_map, free_map_file); lock_release(&free_map_lock); }
/* Creates a new free map file on disk and writes the free map to it. */ void free_map_create (void) { /* Create inode. */ if (!inode_create (FREE_MAP_SECTOR, bitmap_file_size (free_map),0,1)) PANIC ("free map creation failed"); /* Write bitmap to file. */ free_map_file = file_open (inode_open (FREE_MAP_SECTOR)); if (free_map_file == NULL) PANIC ("can't open free map"); if (!bitmap_write (free_map, free_map_file)) PANIC ("can't write free map"); }
// Write a data block given a data block number static void data_write_block(void * data, unsigned int block_n) { unsigned int block_group = (block_n - 1) / sb->s_blocks_per_group; unsigned int block_in_disk = data_get_block(block_n); // Write the data in the disk block_write(data, block_in_disk); // Write the bitmap in the disk bitmap_write(bm_blocks, block_n - 1, 1); //block_write(&g_block_bmps[block_group], bgroup_blockbmp(bgroup_get(block_group))); // The data is only persisted after it's saved in the bitmap. }
/* Allocates CNT consecutive sectors from the free map and stores the first into *SECTORP. Returns true if successful, false if not enough consecutive sectors were available or if the free_map file could not be written. */ bool free_map_allocate (size_t cnt, block_sector_t *sectorp) { block_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false); if (sector != BITMAP_ERROR && free_map_file != NULL && !bitmap_write (free_map, free_map_file)) { bitmap_set_multiple (free_map, sector, cnt, false); sector = BITMAP_ERROR; } if (sector != BITMAP_ERROR) *sectorp = sector; return sector != BITMAP_ERROR; }
/* Creates a new free map file on disk and writes the free map to it. */ void free_map_create (void) { /* Create inode. */ printf("free_map_create(): free_map_file_size: %d\n", bitmap_file_size (free_map)); if (!inode_create (FREE_MAP_SECTOR, bitmap_file_size (free_map))) PANIC ("free map creation failed"); struct inode_disk* buff = (struct inode_disk*)malloc(BLOCK_SECTOR_SIZE); block_read(fs_device, FREE_MAP_SECTOR, buff); ASSERT (buff->direct[0] != 0); /* Write bitmap to file. */ free_map_file = file_open (inode_open (FREE_MAP_SECTOR)); if (free_map_file == NULL) PANIC ("can't open free map"); if (!bitmap_write (free_map, free_map_file)) PANIC ("can't write free map"); }
/* Allocates CNT consecutive sectors from the free map and stores the first into *SECTORP. Returns true if successful, false if not enough consecutive sectors were available or if the free_map file could not be written. */ bool free_map_allocate (size_t cnt, block_sector_t *sectorp) { block_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false); if (sector != BITMAP_ERROR && free_map_file != NULL && !bitmap_write (free_map, free_map_file)) { bitmap_set_multiple (free_map, sector, cnt, false); sector = BITMAP_ERROR; } if (sector != BITMAP_ERROR){ *sectorp = sector; char zeroes[BLOCK_SECTOR_SIZE]; //Assignment 4 block_write(fs_device, sector,zeroes); //Assignment 4 } return sector != BITMAP_ERROR; }
/* Allocates CNT consecutive sectors from the free map and stores the first into *SECTORP. Returns true if successful, false if all sectors were available. */ bool free_map_allocate (size_t cnt, disk_sector_t *sectorp) { // lås id 6 lock_acquire(&free_map_lock); disk_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false); if (sector != BITMAP_ERROR && free_map_file != NULL && !bitmap_write (free_map, free_map_file)) { bitmap_set_multiple (free_map, sector, cnt, false); sector = BITMAP_ERROR; } if (sector != BITMAP_ERROR) *sectorp = sector; lock_release(&free_map_lock); return sector != BITMAP_ERROR; }
/*! * \brief Create NSEC RR set. * * \param from Node that should contain the new RRSet * \param to Node that should be pointed to from 'from' * \param ttl Record TTL (SOA's minimum TTL). * * \return NSEC RR set, NULL on error. */ static knot_rrset_t *create_nsec_rrset(const zone_node_t *from, const zone_node_t *to, uint32_t ttl) { assert(from); assert(to); knot_rrset_t *rrset = knot_rrset_new(from->owner, KNOT_RRTYPE_NSEC, KNOT_CLASS_IN, NULL); if (!rrset) { return NULL; } // Create bitmap bitmap_t rr_types = { 0 }; bitmap_add_node_rrsets(&rr_types, from); bitmap_add_type(&rr_types, KNOT_RRTYPE_NSEC); bitmap_add_type(&rr_types, KNOT_RRTYPE_RRSIG); if (node_rrtype_exists(from, KNOT_RRTYPE_SOA)) { bitmap_add_type(&rr_types, KNOT_RRTYPE_DNSKEY); } // Create RDATA assert(to->owner); size_t next_owner_size = knot_dname_size(to->owner); size_t rdata_size = next_owner_size + bitmap_size(&rr_types); uint8_t rdata[rdata_size]; // Fill RDATA memcpy(rdata, to->owner, next_owner_size); bitmap_write(&rr_types, rdata + next_owner_size); int ret = knot_rrset_add_rdata(rrset, rdata, rdata_size, ttl, NULL); if (ret != KNOT_EOK) { knot_rrset_free(&rrset, NULL); return NULL; } return rrset; }
// MAGIC: Translates a logical block from a file (block 0 to N), to a physical block in the disk void make_ph_block(inode * n, int * ph_block, int * log_block) { int indirects = inode_get_indir_level(*log_block); // Gets the level of indirects inside the direction. int old_ph = * ph_block; int dirty = 0; * ph_block = n->data_blocks[inode_get_dir_block(*log_block)]; // If we've got no block, then we alloc one if(!* ph_block) { * ph_block = bitmap_first_valued(bm_blocks, FS_DATA_BITMAP_SIZE, 0) + 1; bitmap_write(bm_blocks, (* ph_block) - 1, 1); n->data_blocks[inode_get_dir_block(*log_block)] = * ph_block; dirty = 1; } if (indirects > 0) { block_clear(&bi); if (!dirty) { // If it's dirty, then probably it's new and we want the block to be absolutely clear data_read_block(&bi, * ph_block); } dirty = 0; indirect_block_data = (int *) &bi; old_ph = * ph_block; * ph_block = indirect_block_data[inode_get_1indir_block(*log_block)]; // If we've got no block, then we alloc one if(!* ph_block) { bitmap_write(bm_blocks, old_ph - 1, 1); * ph_block = bitmap_first_valued(bm_blocks, FS_DATA_BITMAP_SIZE, 0) + 1; bitmap_write(bm_blocks, (* ph_block) - 1, 1); indirect_block_data[inode_get_1indir_block(*log_block)] = * ph_block; data_write_block(&bi, old_ph); dirty = 1; } if (indirects > 1) { block_clear(&bi); if (!dirty) { // If it's dirty, then probably it's new and we want the block to be absolutely clear data_read_block(&bi, * ph_block); } dirty = 0; old_ph = * ph_block; * ph_block = indirect_block_data[inode_get_2indir_block(*log_block)]; // If we've got no block, then we alloc one if(!* ph_block) { bitmap_write(bm_blocks, old_ph - 1, 1); * ph_block = bitmap_first_valued(bm_blocks, FS_DATA_BITMAP_SIZE, 0) + 1; bitmap_write(bm_blocks, (* ph_block) - 1, 1); indirect_block_data[inode_get_2indir_block(*log_block)] = * ph_block; data_write_block(&bi, old_ph); dirty = 1; } if (indirects > 2) { block_clear(&bi); if (!dirty) { // If it's dirty, then probably it's new and we want the block to be absolutely clear data_read_block(&bi, * ph_block); } dirty = 0; old_ph = * ph_block; * ph_block = indirect_block_data[inode_get_3indir_block(*log_block)]; // If we've got no block, then we alloc one if(!* ph_block) { bitmap_write(bm_blocks, old_ph - 1, 1); * ph_block = bitmap_first_valued(bm_blocks, FS_DATA_BITMAP_SIZE, 0) + 1; bitmap_write(bm_blocks, (* ph_block) - 1, 1); indirect_block_data[inode_get_3indir_block(*log_block)] = * ph_block; data_write_block(&bi, old_ph); } } } } }
/* Saves the free map to disk */ void free_map_save (void) { if (!bitmap_write (free_map, free_map_file)) PANIC ("can't write free map"); }
// Makes a new directory unsigned int fs_mkdir(char * name, unsigned int parent_inode) { unsigned int inode_id = 0; if ((inode_id = fs_indir(name, parent_inode))) { return 0; } inode_id = bitmap_first_valued(bm_inodes, FS_INODE_BITMAP_SIZE, 0) + 1; if (!parent_inode) { parent_inode = inode_id; } int log_block; if (parent_inode != inode_id) { inode_read(parent_inode, &n); if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; } log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, inode_id, name, &log_block); log_block_write(&n, &log_block); inode_write(parent_inode, &n); } bitmap_write(bm_inodes, inode_id - 1, 1); inode_clear(&n); if(!fs_done) { n.uid = 0; } else { n.uid = current_ttyc()->uid; } n.mode = EXT2_S_IFDIR; n.size = 0; n.blocks = 0; // Beware! This represents the SECTORS! log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; add_dir_entry(&n, EXT2_FT_DIR, inode_id, ".", &log_block); add_dir_entry(&n, EXT2_FT_DIR, parent_inode, "..", &log_block); log_block_write(&n, &log_block); n.blocks = (log_block) * 2; n.i_file_acl = 511; n._dir_inode = parent_inode; n._last_write_offset = dir_op_offset; inode_write(inode_id, &n); fs_bitmaps_write_all(); return inode_id; }
// Opens a file unsigned int fs_open_file(char * name, unsigned int folder_inode, int mode, int type) { unsigned int inode_id = 0; if(strcmp(name, "/") == 0 && strlen(name) == strlen("/")) { return 1; // root } if(name[0] == 0) { inode_id = current_ttyc()->pwd; } else { inode_id = fs_indir(name, folder_inode); } if (inode_id) { if (mode & O_CREAT) { int _rm_res = fs_rm(inode_id, 0); if(_rm_res < 0) { return _rm_res; } } else if(mode & O_NEW) { inode_read(inode_id, &n); if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; } else { inode_read(inode_id, &n); int can = 1; if((mode & O_RD) && !fs_has_perms(&n, ACTION_READ)) { can = 0; } if((mode & O_WR) && !fs_has_perms(&n, ACTION_WRITE)) { can = 0; } if(can || !fs_done) { if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; } else { return ERR_PERMS; } } } else if (!(mode & (O_NEW | O_CREAT))) { return ERR_NO_EXIST; } inode_id = bitmap_first_valued(bm_inodes, FS_INODE_BITMAP_SIZE, 0) + 1; if (!folder_inode) { folder_inode = inode_id; } int log_block; if (folder_inode != inode_id) { inode_read(folder_inode, &n); if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; } log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, inode_id, name, &log_block); log_block_write(&n, &log_block); inode_write(folder_inode, &n); } bitmap_write(bm_inodes, inode_id - 1, 1); inode_clear(&n); if(!fs_done) { n.uid = 0; } else { n.uid = current_ttyc()->uid; } n.mode = type; n.size = 0; n.blocks = 0; // Beware! This represents the SECTORS! n._last_write_offset = 0; n.i_file_acl = 511; n._dir_inode = folder_inode; inode_write(inode_id, &n); inode_clear(&n); if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; }
// Removes an inode from the filesystem, documented in header unsigned int fs_rm(unsigned int inode, int inside_recursion) { inode_read(inode, &n); if(!(inode > 1)) { return ERR_PERMS; // Permissions check } if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; // If you can't write you can't delete... } if (!inside_recursion) { // I'm not sure about this, but well... at least it's just a security flaw. inode_read(n._dir_inode, &n); if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; // If you can't write on the parent folder you can't delete } inode_read(inode, &n); } int log_block = n.blocks / 2 + 1; // Logical block top int ph_block = 0; // Go from top to bottom to delete everything. while(log_block > 0) { log_block--; make_ph_block(&n, &ph_block, &log_block); if (n.mode & EXT2_S_IFDIR) { // If it's a directory... then... RECURSION! D: block entries; data_read_block(&entries, ph_block); int off = 0; dir_op_offset = 0; dir_entry * old_dot = NULL; dir_entry * dot = iterate_dir_entry(&entries); // Iterates dir entries while (dot != NULL) { if (dot == NULL) { break; } else { if (dot->name_len > 0 && dot->inode != inode && dot->inode != n._dir_inode) { // If we get an error we don't actually make anything :D, but we might delete other files. int _rm = fs_rm(dot->inode, 1); if(_rm < 0) { data_write_block(&entries, ph_block); bitmap_write(bm_blocks, ph_block - 1, 0); return _rm; } off = dir_op_offset; dot->name_len = 0; dir_op_offset = off; inode_read(inode, &n); } } old_dot = dot; dot = iterate_dir_entry(&entries); } data_write_block(&entries, ph_block); } bitmap_write(bm_blocks, ph_block - 1, 0); // This deletes the stuff actually delete_internal_inodes(log_block); // This deletes the EXT2 ugly but wise indirects. } // Delete the directory entry of the file. if (!inside_recursion) { inode_read(inode, &n); unsigned int folder_inode = n._dir_inode; inode_read(folder_inode, &n); folder_rem_direntry(inode, folder_inode); } bitmap_write(bm_inodes, inode - 1, 0); // Persist the directory liberation. fs_bitmaps_write_all(); // Persist in the FS. return 1; }