/* Run the actual write request */ static void rq_write_run(NFS_WriteRequest *rq) { dprintf(2, "run NFS Write request\n"); NFS_File *nf = (NFS_File *) rq->p.vnode->extra; nfs_write(&(nf->fh), rq->offset, rq->nbyte, rq->buf, write_cb, rq->p.token); }
/** * This function will select a page (based on second chance) * and swap it out to file system. However if the selected page * was not dirty then we just need to mark it swapped again and * can return immediatly. * We stop the initiator thread as long as we're swapping * data out to the file system. The thread is restarted in the * write callback function (above). * * @param initiator ID of the thread who caused the swapping to happen * @return SWAPPING_PENDING in case we need to write the page to the disk * SWAPPING_COMPLETE in case the page was not dirty * OUT_OF_SWAP_SPACE if our swap space is already full * NO_PAGE_AVAILABLE if second_chance_select did not find a page */ int swap_out(L4_ThreadId_t initiator) { page_queue_item* page = second_chance_select(&active_pages_head); if(page == NULL) { return NO_PAGE_AVAILABLE; } assert(!is_referenced(page)); // decide where in the swap file our page will be if(page->swap_offset < 0 && (page->swap_offset = allocate_swap_entry()) < 0) return OUT_OF_SWAP_SPACE; dprintf(1, "swap_out: Second chance selected page: thread:0x%X vaddr:0x%X swap_offset:0x%X\n", page->tid, page->virtual_address, page->swap_offset); if(is_dirty(page)) { dprintf(1, "Selected page is dirty, need to write to swap space\n"); page->to_swap = PAGESIZE; page->initiator = initiator; TAILQ_INSERT_TAIL(&swapping_pages_head, page, entries); file_table_entry* swap_fd = get_process(root_thread_g)->filetable[SWAP_FD]; assert(swap_fd != NULL); data_ptr physical_page = pager_physical_lookup(page->tid, page->virtual_address); assert(physical_page != NULL); // write page in swap file assert(PAGESIZE % BATCH_SIZE == 0); for(int write_offset=0; write_offset < page->to_swap; write_offset += BATCH_SIZE) { nfs_write( &swap_fd->file->nfs_handle, page->swap_offset + write_offset, BATCH_SIZE, physical_page + write_offset, &swap_write_callback, (int)page ); } return SWAPPING_PENDING; } else { assert(page->swap_offset >= 0); page_table_entry* pte = pager_table_lookup(page->tid, page->virtual_address); frame_free(CLEAR_LOWER_BITS(pte->address)); mark_swapped(pte, page->swap_offset); free(page); return SWAPPING_COMPLETE; } }
ssize_t write(int fd, const void *buf, size_t count) { if (nfs_fd_list[fd].is_nfs == 1) { int ret; LD_NFS_DPRINTF(9, "write(fd:%d count:%d)", fd, (int)count); if ((ret = nfs_write(nfs_fd_list[fd].nfs, nfs_fd_list[fd].fh, count, (char *)discard_const(buf))) < 0) { errno = -ret; return -1; } return ret; } return real_write(fd, buf, count); }
/* * Internal function to write a page table location to a swap location and to invoke a read * from swap if necessary which is invoked by the nfs write callback */ static void writeToSwap(int index,int readSwapIndex,L4_ThreadId_t tid,L4_Fpage_t fpage) { if(!swapInitialised) { initialise_swap(); } //Now we need to write the contents of pagetable index to swap file //Get a free location in the swap table int swap_index = head_free_swap; head_free_swap = swap_table[head_free_swap].next_free; if(swap_index >= MAX_SWAP_ENTRIES || swap_index < 0) { printf("Panic !!! Swap table full ! No more swapping possible!\n"); return; } //If a swap location was once used overwrite it to keep a constant swap file size if(swap_table[swap_index].offset == PTE_SENTINEL) { swap_table[swap_index].offset = swap_file_size; swap_file_size += PAGESIZE; } //Now we need to write the file, struct page_token *token_val; page_table[index].being_updated = 1; page_table[index].write_bytes_transferred = 0; page_table[index].error_in_transfer = 0; //Unmap before the first nfs write L4_UnmapFpage(page_table[index].tid,page_table[index].pageNo); for(int i=0;i<PAGESIZE/NFS_WRITE_SIZE;i++) { //Set the token val token_val = (struct page_token *) malloc(sizeof(struct page_token)); //printf("After malloc of page_token for i %d\n",i); token_val -> pageIndex = index; token_val -> swapIndex = swap_index; //Send reply only if there is no read from swap token_val -> send_reply = (readSwapIndex == -1) ? 1 : 0 ; token_val -> chunk_index = i; token_val -> destination_tid = tid; token_val -> destination_page = fpage; token_val -> source_tid = page_table[index].tid; token_val -> source_page = page_table[index].pageNo; token_val -> swapIndexToBeReadIn = readSwapIndex; //All nfs writes for each chunk are issued at once nfs_write(swapcookie,swap_table[swap_index].offset+i*NFS_WRITE_SIZE,NFS_WRITE_SIZE,(void *)(new_low + index*PAGESIZE + i*NFS_WRITE_SIZE),pager_write_callback,(uintptr_t)token_val); } send = 0; }