void swap_in(size_t used_index,void *kaddr) { if(!swap_block||!swap_map)return ; lock_acquire(&swap_lock); if(bitmap_test(swap_map,used_index) == SWAP_FREE); bitmap_flip(swap_map,used_index); size_t i; for(i = 0;i< SECTORS_PER_PAGE;i++) { block_read(swap_block,used_index*SECTORS_PER_PAGE +i, (uint8_t *)kaddr + i*BLOCK_SECTOR_SIZE); } lock_release(&swap_lock); }
void free_slot (void *page, size_t index) { /* Mark the slot as free again */ ASSERT (bitmap_test (swap_slot_map, index)); bitmap_flip (swap_slot_map, index); /* This is almost identical to the loop in pick_slot_and_swap, we're just going the other way */ int i = 0; for (; i < SECTORS_PER_PAGE; ++i) { block_read (block_device, (index * SECTORS_PER_PAGE) + i, page + (BLOCK_SECTOR_SIZE * i)); } }
/* move data from swap slot to frame */ void vm_swap_in(size_t idx, void *page){ lock_acquire(&swap_lock); if (!bitmap_test(swap_partition, idx)){ /* Swap slot is already free */ lock_release(&swap_lock); PANIC("Swap slot is already free\n"); } bitmap_flip(swap_partition, idx); size_t i; for (i = 0; i < SECTORS_PER_PAGE; ++i){ block_read(swap_slot, (idx * SECTORS_PER_PAGE) + i, page + (BLOCK_SECTOR_SIZE * i)); } lock_release(&swap_lock); }
void print_sector_info(struct dir * dir) { block_sector_t bounce[128]; int i,j; block_sector_t sector = byte_to_sector(dir_get_inode(dir),0); printf("Sector num : %d\n",sector); block_read(fs_device,sector,bounce); for(i=0; i<16; i++) { printf("%d : ",i); for(j=0; j<8; j++) { printf("%#010x ",bounce[i*8 + j]); } printf("\n"); } }
/* Read a block from a named file. Returns 1 for success; 0 for failure. */ int block_read_filename(struct block *b, const char *filename) { FILE *fp; int rc; fp = fopen(filename, "rb"); if (fp == NULL) return 0; rc = block_read(b, fp); if (rc != 1) { fclose(fp); return rc; } rc = fclose(fp); return rc == 0; }
// Reads an inode from disk static void inode_read(unsigned int inode_n, inode * n) { unsigned int locin_block_index = inode_get_block_index(inode_n); unsigned int real_block_index = inode_get_block(inode_n); block b; block_clear(&b); block_read((void *)&b, real_block_index); int i = 0; inode * inodes = (inode *) &b; for (; i < FS_INODE_SIZE / sizeof(int); i++) { ((int*)n)[i] = ((int *)&inodes[locin_block_index])[i]; } }
void load_swapped_page_into_frame(struct page_info* p, void* frame) { lock_acquire(&swap_lock); int index = p->swap_info.swap_index; bitmap_reset(swapmap, index); // Read the 4KB page from disk to the passed-in frame // We're going to need to read out eight sectors, one at a time block_sector_t sector_index = index * SECTORS_PER_PAGE; int i; for (i = 0; i < SECTORS_PER_PAGE; i++) { block_sector_t source_sector = sector_index + i; void* target_buf = (uint8_t *)frame + (i * BLOCK_SECTOR_SIZE); block_read(swap_block, source_sector, target_buf); } lock_release(&swap_lock); }
/* 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"); }
/* * buffer is the start address in memory to be read from * if used in inode_read_at, buffer = 'buffer' + bytes_read * sector_ofs is the start point to actually read from the buffer cache * chunk_size is the actual size to be read to buffer cache */ void read_via_cache(struct inode *inode, uint8_t *buffer, block_sector_t sector_idx, int sector_ofs, int chunk_size) { //printf("sector_idx %d, size %d\n", sector_idx, size); int buffer_arr_indx = lookup_sector(sector_idx); //lookup result indx for a valid sector in cache if (buffer_arr_indx > BUFFER_SIZE) { PANIC("lookup_sector wrong\n"); } // printf("sector_idx %d\n", sector_idx); if (buffer_arr_indx >= 0){ // printf("indx %d, sector_idx %d size %d\n", buffer_arr_indx, sector_idx, size); void *buffer_cache_start_addr = buffer_vaddr + buffer_arr_indx * BLOCK_SECTOR_SIZE + sector_ofs; memcpy((void *)buffer, buffer_cache_start_addr, chunk_size); } else { //the sector_idx is not in buffer cache //printf("new start\n"); int buffer_indx = lookup_empty_buffer(); if (buffer_indx == -1) { //choose a sector to evict //lookup_evict contains 'clock algorithm' //lookup_evict() takes care of case when buffer_evict_indx == -1 int buffer_evict_indx = lookup_evict(); //buffer_evict_indx should be a valid indx buffer_evict_indx = buffer_evict(buffer_evict_indx); buffer_indx = buffer_evict_indx; //printf("evicting!\n"); } //buffer_cache_start_addr is the start addr of buffer cache sector void *buffer_cache_start_addr = buffer_vaddr + buffer_indx * BLOCK_SECTOR_SIZE; //copy the sector from disk to buffer cache block_read (fs_device, sector_idx, buffer_cache_start_addr); //change buffer_cache_start_addr to the offset of buffer cache sector buffer_cache_start_addr += sector_ofs; //copy the sector from buffer cache to buffer_read memcpy ((void *)buffer, buffer_cache_start_addr, chunk_size); //fill the info into buffer_info_array if(sector_idx < -2) buffer_info_array[buffer_indx].sector_num = sector_idx; buffer_info_array[buffer_indx].buffer_inode = inode; buffer_info_array[buffer_indx].dirty = false; buffer_info_array[buffer_indx].recentlyUsed = true; } }
struct cache * add_cache(block_sector_t block) { struct cache * new_cache = find_empty_cache(); if(block > 0x2000) return NULL; lock_acquire(&device_lock); block_read(fs_device,block,new_cache->caddr); lock_release(&device_lock); ASSERT(new_cache != NULL); new_cache->used = true; new_cache->sector = block; //printf("add new sector to cache : %d\n",block); new_cache->dirty = false; //printf("add new sector %d to cache\n",block); return new_cache; }
struct buffer_head * buffer_read(int dev,uint32_t block) { int retval; struct buffer_head *buf = NULL; buf = buffer_get(dev,block); if (!buf) return NULL; if (buf->b_uptodate) return buf; //ide read!!! retval = block_read(buf); if (buf->b_uptodate) return buf; return NULL; }
struct cache_block * cache_evict_block(block_sector_t sect) { lock_acquire(&eviction_lock); struct cache_block * curr_block = cache_find_block(sect); if (curr_block == NULL) { while (true) { if (clock_hand == 64) { clock_hand = 0; } curr_block = &cache[clock_hand]; lock_acquire(&curr_block->modify_variables); if (curr_block->use && curr_block->valid) { curr_block->use = 0; lock_release(&curr_block->modify_variables); clock_hand++; } else { clock_hand++; break; } } // At this point we found an entry to evict and the process owns its modify_variables lock and it has been marked invalid curr_block->evict_penders++; while (curr_block->accessors > 0) { cond_wait(&curr_block->need_to_evict, &curr_block->modify_variables); } curr_block->evict_penders--; if (curr_block->dirty && curr_block->valid) { curr_block->valid = 0; device_writes++; block_write(fs_device, curr_block->sect, curr_block->data); // cache_to_disk(curr_block); ACQUIRING LOCK NOT NECESSARY curr_block->dirty = 0; } // Read directly into the cache without the lock since nothing can modify this entry due to it being invalid // Should not be a sychronization problem block_read(fs_device, sect, curr_block->data); curr_block->sect = sect; curr_block->valid = 1; curr_block->use = 0; } lock_release(&eviction_lock); return curr_block; }
/* adds a block to cache */ static size_t cache_add (block_sector_t bid) { /* lock the cache */ lock_acquire(&cache_globallock); //bool hellYeah = bid == (unsigned) 163; /* lock for a free_cache_block cache block */ size_t free_cache_block = bitmap_scan (cache_table, 0, 1, false); //if(DEBUG || hellYeah) printf("bitscan complete bla\n"); /* if no free cache block is found, evict one and * search again */ if (free_cache_block == BITMAP_ERROR) { //if(DEBUG || hellYeah) printf("evict some\n"); cache_evict(); free_cache_block = bitmap_scan (cache_table, 0, 1, false); } ASSERT(free_cache_block != BITMAP_ERROR); //if(DEBUG || hellYeah) printf("add cache block %d\n",bid); /* copy block to cache */ block_read (fs_device, bid, cache[free_cache_block]->kpage); /* setup cache entry */ cache[free_cache_block]->dirty = false; cache[free_cache_block]->accessed = false; cache[free_cache_block]->bid = bid; /* set used bit of the cache table for this entry */ bitmap_set (cache_table, free_cache_block, true); /* release the lock for the cache table */ lock_release(&cache_globallock); if(CACHE_DEBUG) printf("added cache block %u for sector %u\n", (unsigned int) free_cache_block, (unsigned int) bid); return free_cache_block; }
void fs_copy_file(fs_t *fs, inodeid_t dir2, inodeid_t file1id, char* file2) { inodeid_t file2id; fs_inode_t ifile1 = fs->inode_tab[file1id]; fs_create(fs, dir2, file2, &file2id); fs_inode_t ifile2 = fs->inode_tab[file2id]; for (int i = 0; i < INODE_NUM_BLKS && ifile1.blocks[i] != 0; i++) { char new_block[BLOCK_SIZE]; unsigned blockid = 0; block_read(fs->blocks,ifile1.blocks[i], new_block); fsi_bmap_find_free(fs->blk_bmap, BLOCK_SIZE, &blockid); block_write(fs->blocks, blockid, new_block); ifile2.blocks[i] = blockid; //ifile2.blocks[i]=ifile1.blocks[i]; } }
static int fsi_dir_search(fs_t* fs, inodeid_t dir, char* file, inodeid_t* fileid) { fs_dentry_t page[DIR_PAGE_ENTRIES]; fs_inode_t* idir = &fs->inode_tab[dir]; int num = idir->size / sizeof(fs_dentry_t); int iblock = 0; while (num > 0) { block_read(fs->blocks,idir->blocks[iblock++],(char*)page); for (int i = 0; i < DIR_PAGE_ENTRIES && num > 0; i++, num--) { if (strcmp(page[i].name,file) == 0) { *fileid = page[i].inodeid; return 0; } } } return -1; }
/* Swaps in page P, which must have a locked frame (and be swapped out). */ void swap_in(void *f, size_t index) { if (!swap_device || !swap_bitmap) { PANIC("No swap partition available!"); } lock_acquire(&swap_lock); if (bitmap_test(swap_bitmap, index) == SWAP_FREE) { lock_release(&swap_lock); return; } bitmap_flip(swap_bitmap, index); lock_release(&swap_lock); size_t i; for (i = 0; i < SECTORS_PER_PAGE; i++) { block_read(swap_device, index * SECTORS_PER_PAGE + i, (uint8_t *) f + i * BLOCK_SECTOR_SIZE); } }
bool bc_read(block_sector_t sector_idx, void *buffer, off_t bytes_read, int chunck_size, int sector_ofs) { /* find the buffer cache entry of which block_sector_t is equal to sector_idx */ struct buffer_head *sector_buffer = bc_lookup(sector_idx); /* if can't find the buffer cache entry */ if(sector_buffer == NULL) { sector_buffer = bc_select_victim(); /* update buffer_head and read the data from disk */ sector_buffer->sector = sector_idx; sector_buffer->is_used = true; block_read(fs_device, sector_idx, sector_buffer->data); } /* updata the clock bit */ sector_buffer->clock_bit = true; /* read data from buffer cache */ memcpy(buffer + bytes_read, sector_buffer->data + sector_ofs, chunck_size); return true; }
/* * Fetch block from disk * Haven't do synchronization here, not sure whether ok????????? */ struct cache_block* read_block_from_disk (block_sector_t sector, bool dirty) { // lock_acquire (&cache_lock); cache_size ++; struct cache_block *c = malloc (sizeof (struct cache_block)); if (!c) { PANIC ("Not enought memory for buffer cache"); } c->open_cnt = 1; list_push_back (&cache, &c->elem); c->sector = sector; block_read (fs_device, c->sector, &c->block); c->dirty = dirty; c->accessed = true; // lock_release (&cache_lock); return c; }
/* Remove the swapped in page at SECTOR, and write it to BUFFER. If BUFFER is NULL, remove from swap table and do NOT perform write. */ void swap_remove(block_sector_t sector, void *buffer) { struct hash_elem *e; struct swap_slot ss; block_sector_t i; if (buffer != NULL) { for (i = 0; i < SECTORS_PER_PAGE; i++) { block_read(swap_device, sector + i, buffer + BLOCK_SECTOR_SIZE * i); } } /* Remove the struct swap_slot from the swap table. */ ss.sector_ind = sector; lock_acquire(&swap_lock); e = hash_delete(&swap_table, &ss.hash_elem); if (e == NULL) { PANIC("Attempting to release a free slot in swap."); } lock_release(&swap_lock); free(hash_entry(e, struct swap_slot, hash_elem)); }
/* Read in the node at the current path and depth into the node cache. * You must set INFO->blocks[depth] before. */ static char * read_tree_node( __u32 blockNr, __u16 depth ) { char *cache = CACHE(depth); int num_cached = INFO->cached_slots; errnum = 0; if ( depth < num_cached ) { /* This is the cached part of the path. Check if same block is needed. */ if ( blockNr == INFO->blocks[depth] ) return cache; } else cache = CACHE(num_cached); DEBUG_F( " next read_in: block=%u (depth=%u)\n", blockNr, depth ); if ( !block_read( blockNr, 0, INFO->blocksize, cache ) ) { DEBUG_F( "block_read failed\n" ); return 0; } DEBUG_F( "FOUND: blk_level=%u, blk_nr_item=%u, blk_free_space=%u\n", blkh_level(BLOCKHEAD(cache)), blkh_nr_item(BLOCKHEAD(cache)), le16_to_cpu(BLOCKHEAD(cache)->blk_free_space) ); /* Make sure it has the right node level */ if ( blkh_level(BLOCKHEAD(cache)) != depth ) { DEBUG_F( "depth = %u != %u\n", blkh_level(BLOCKHEAD(cache)), depth ); DEBUG_LEAVE(FILE_ERR_BAD_FSYS); errnum = FILE_ERR_BAD_FSYS; return 0; } INFO->blocks[depth] = blockNr; return cache; }
/* low level file-system operations */ int fat_get_free_cluster() { #ifdef TRACE printf("fat_get_free_cluster\n"); #endif blockno_t i; int j; uint32_t e; for(i=fatfs.active_fat_start;i<fatfs.active_fat_start + fatfs.sectors_per_fat;i++) { if(block_read(i, fatfs.sysbuf)) { return 0xFFFFFFFF; } for(j=0;j<(512/fatfs.fat_entry_len);j++) { e = fatfs.sysbuf[j*fatfs.fat_entry_len]; e += fatfs.sysbuf[j*fatfs.fat_entry_len+1] << 8; if(fatfs.type == PART_TYPE_FAT32) { e += fatfs.sysbuf[j*fatfs.fat_entry_len+2] << 16; e += fatfs.sysbuf[j*fatfs.fat_entry_len+3] << 24; } if(e == 0) { /* this is a free cluster */ /* first, mark it as the end of the chain */ if(fatfs.type == PART_TYPE_FAT16) { fatfs.sysbuf[j*fatfs.fat_entry_len] = 0xF8; fatfs.sysbuf[j*fatfs.fat_entry_len+1] = 0xFF; } else { fatfs.sysbuf[j*fatfs.fat_entry_len] = 0xF8; fatfs.sysbuf[j*fatfs.fat_entry_len+1] = 0xFF; fatfs.sysbuf[j*fatfs.fat_entry_len+2] = 0xFF; fatfs.sysbuf[j*fatfs.fat_entry_len+3] = 0x0F; } if(block_write(i, fatfs.sysbuf)) { return 0xFFFFFFFF; } #ifdef TRACE printf("fat_get_free_cluster returning %d\n", ((i - fatfs.active_fat_start) / (512 / fatfs.fat_entry_len)) + j); #endif return ((i - fatfs.active_fat_start) / (512 / fatfs.fat_entry_len)) + j; } } } return 0; /* no clusters found, should raise ENOSPC */ }
static void cache_read_ahead(void * cur_block) { int lblock = *((int *)cur_block); if(removed) return; if(find_cache(lblock) == NULL) if(lblock <= 0x2000) { struct cache* empty_cache = find_empty_cache(); lock_acquire(&device_lock); block_read(fs_device, lblock, empty_cache->caddr); lock_release(&device_lock); empty_cache->used = true; empty_cache->sector = lblock; } free(cur_block); thread_exit(); }
// swap a page from swap slot into memory void swap_into_memory (size_t used_index, void * upage) { int i; lock_acquire(&swap_lock); struct swap_item * item = get_swap_item_at_index(used_index); if (item == NULL || item->available == true) { lock_release(&swap_lock); return; } item->available = true; for (i = 0; i < SECTORS_PER_PAGE; i++) { block_read (swap_block, used_index * SECTORS_PER_PAGE + i, (uint8_t *) upage + i * BLOCK_SECTOR_SIZE); } lock_release(&swap_lock); }
//Swap into memory from the disk. Swap_in must only be called if swap_out was //previously called, and disk_block must be the same disk_block from swap_out. //dest_addr should point to a page worth of memory to swap data into. void swap_in (uint32_t *dest_addr, block_sector_t *disk_block) { int i = 0; block_sector_t block_offset = *disk_block; //Read in a page worth of memory for(i = 0; i<PGSIZE; i += BLOCK_SECTOR_SIZE) { block_read (st->swap_block, i/BLOCK_SECTOR_SIZE + block_offset, dest_addr + i/sizeof(uint32_t)); } //Update the swap_table that this disk space is free again lock_acquire(&st->swap_table_lock); block_sector_t idx = bitmap_scan_and_flip(st->map, block_offset, PGSIZE/BLOCK_SECTOR_SIZE, true); //Assert that the page read in was previously marked as in use ASSERT(idx == block_offset); lock_release(&st->swap_table_lock); }
//get a page from the swap table and save it to a memory position void get_swap (size_t idx, void * addr) { //check if bitmap is set correctly ASSERT(bitmap_test (swap_table,idx)); int i; //get frame and the memory position and write it to swap for (i = 0; i< SECPP; i++) //read the value from swap to addr block_read (swap, idx * SECPP + i, addr + BLOCK_SECTOR_SIZE * i); //lock the swap table lock_acquire(&swap_lock); //remove the swap entry at position idx bitmap_set (swap_table, idx, false); //release the lock for the swap table lock_release(&swap_lock); }
// Try to get the sector in cache. // If it's in cache, get this cache, otherwise create a new cache. struct cache_block * cache_get(block_sector_t sector, bool dirty) { struct cache_block *cb = in_cache(sector); if (cb) { cb->access = true; cb->dirty |= dirty; } else { cb = cache_new(); cb->sector_no = sector; cb->access = true; cb->dirty = dirty; block_read(fs_device, cb->sector_no, &cb->data); } //cache_read_ahead(sector); //failed to read ahead return cb; }
struct cached_block * get_cached_block (block_sector_t sector, bool dirty) { lock_acquire (&cache_lock); struct cached_block *cb = lookup_cache (sector); if (cb == NULL) { if (entry_count < MAX_CACHE_SIZE) { cb = (struct cached_block *) malloc (sizeof (struct cached_block)); if (cb == NULL) { lock_release (&cache_lock); PANIC ("ERROR : Main and Cache memory full."); } cb->open = 0; entry_count++; } else { cb = evict_cache_block (); list_remove (&cb->elem); } cb->sector = sector; block_read (fs_device, sector, cb->data); cb->accessed = true; cb->open++; cb->dirty = dirty; list_push_back (&cache_list, &cb->elem); } else { cb->accessed = true; cb->open++; cb->dirty |= dirty; } lock_release (&cache_lock); return cb; }
int fs_delete(char *name) { int i = 0; for (; i < MAX_FILE_COUNT; i++) { if (strcmp(name, meta->fcb_list[i].file_name) == 0) break; } // if the filename was not found, return if (i == MAX_FILE_COUNT) return -1; // must open file before deleting if(meta->fcb_list[i].is_opened == 0) return -1; // if the file size is 0, there is nothing to do with blocks if(meta->fcb_list[i].size != 0) { int current_block = meta->fcb_list[i].first_block; char *buffer = (char*)malloc(BLOCK_SIZE); int next_block = current_block; do { current_block = next_block ; block_read(current_block,buffer); next_block = get_block_icon(buffer); memset(buffer,0,BLOCK_SIZE); block_write(current_block,buffer); meta->vcb.free_block_count ++; } while(next_block > 0); } // deleting metadata meta->vcb.free_fcb[i] = 0; memset(meta->fcb_list[i].file_name,0,20); meta->fcb_list[i].first_block = 0; meta->fcb_list[i].last_block = 0; meta->fcb_list[i].last_block_used = 0; meta->fcb_list[i].size = 0; metadata_rewrite(); }
void swap_read_page(block_sector_t swap_idx, void *frame_addr, bool free) { lock_acquire(&swap_lock); uint32_t i; for (i = 0; i < num_swap_pages; i++) { if (swap_pages[i].start_sector == swap_idx) { block_sector_t j; for (j = 0; j < 8; j++) { block_read(swap_block, swap_pages[i].start_sector + j, frame_addr + j * 512); } if (free) { swap_pages[i].available = true; } break; } } lock_release(&swap_lock); }
/* * void search_dir_entry (fs_t* fs, inodei_t dir, inodeid_t fileid, int *num_dir_entry, char*page) * * searches an entry in a file system * * fs - reference to the filesystem * dir - directory to be searched * fileid - file id * *num_dir_entry - number refering to the position of an entry in a block of a certain directory [out] * *page - array of entries [out] */ void search_dir_entry (fs_t* fs, inodeid_t dir, inodeid_t fileid, int *num_dir_entry, int* block_num, char* page){ fs_inode_t* idir = &fs->inode_tab[dir]; int num = idir->size / sizeof(fs_dentry_t); //número de entradas no directório int iblock = 0; fs_dentry_t ipage[DIR_PAGE_ENTRIES]; while (num > 0){ block_read(fs->blocks, idir->blocks[iblock++], (char*)ipage); //guarda um bloco em page for (int i = 0; i < DIR_PAGE_ENTRIES && num > 0; i++, num--) { if (ipage[i].inodeid == fileid){ num_dir_entry = &i; block_num = &iblock; page = (char *) ipage; return; } } } return; }