diff --git a/fs/nova/balloc.c b/fs/nova/balloc.c index 98fb8b9170e3..4268d4621da2 100644 --- a/fs/nova/balloc.c +++ b/fs/nova/balloc.c @@ -409,7 +409,7 @@ static int nova_free_blocks(struct super_block *sb, unsigned long blocknr, struct free_list *free_list; int cpuid; int new_node_used = 0; - int ret; + int ret=0; int i; INIT_TIMING(free_time); @@ -440,7 +440,7 @@ static int nova_free_blocks(struct super_block *sb, unsigned long blocknr, /* NOVA DEDUP KHJ */ for(i=t_block_low; i<=t_block_high;i++){ - if(nova_dedup_is_duplicate(sb, i) == 1){ + if(nova_dedup_is_duplicate(sb, i,false) != 0){ block_low = t_block_low; block_high = i; if(i != t_block_high) diff --git a/fs/nova/dedup.c b/fs/nova/dedup.c index 371d963702b3..2bd143c38b2f 100644 --- a/fs/nova/dedup.c +++ b/fs/nova/dedup.c @@ -5,6 +5,7 @@ /******************** DEDUP QUEUE ********************/ +// TODO LOCK IN DEDUP QUEUE struct nova_dedup_queue nova_dedup_queue_head; // Initialize Dedup Queue @@ -132,8 +133,6 @@ int nova_dedup_crosscheck(struct nova_file_write_entry *entry return 0; } } - - int nova_dedup_reassign_file_tree(struct super_block *sb, struct nova_inode_info_header *sih, u64 begin_tail) { @@ -178,8 +177,46 @@ int nova_dedup_reassign_file_tree(struct super_block *sb, } -/******************** FACT ********************/ +int nova_dedup_invalidate_target_entry(struct super_block *sb, + struct nova_inode_info_header *sih, struct nova_file_write_entry *target_entry){ + + unsigned long start_pgoff = target_entry->pgoff; + unsigned int num = target_entry->num_pages; + unsigned int num_free = 0; + unsigned long curr_pgoff; + unsigned long start_blocknr = (target_entry->block)>>PAGE_SHIFT; + unsigned long curr_blocknr; + // Free Data pages that are duplicate + // Invalidate Target Entry + // radix_tree_replace_slot + + int i; + int ret = 0; + INIT_TIMING(assign_time); + + NOVA_START_TIMING(assign_t, assign_time); + for (i = 0; i < num; i++) { + curr_pgoff = start_pgoff + i; + curr_blocknr = start_blocknr + i; + + // duplicate: Free (not inside dedup table) + if(nova_dedup_is_duplicate(sb,curr_blocknr,true) == 2) + nova_free_old_entry(sb, sih,target_entry, + curr_pgoff,1,false,target_entry->epoch_id); + // unique: Don't Free + else + nova_invalidate_write_entry(sb,target_entry,1,1); + } + + nova_invalidate_write_entry(sb, target_entry, 1, 0); +out: + NOVA_END_TIMING(assign_t, assign_time); + return ret; +} + +/******************** FACT ********************/ +// TODO Range Lock in FACT table // Find FACT entry with index(of FACT) int nova_dedup_FACT_update_count(struct super_block *sb, u64 index){ u32 count = 0; @@ -196,7 +233,6 @@ int nova_dedup_FACT_update_count(struct super_block *sb, u64 index){ target_index = NOVA_DEF_BLOCK_SIZE_4K * FACT_TABLE_START + target_index * NOVA_FACT_ENTRY_SIZE; target_entry = (struct fact_entry*) nova_get_block(sb,target_index); count = target_entry->count; - printk("Updating Count : %d\n",count); // IF update Count > 0 if(compare & count){ // decrease update count 1 @@ -248,6 +284,7 @@ int nova_dedup_FACT_insert(struct super_block *sb, struct fingerprint_lookup_dat u64 target_index; int ret=0; + // TODO Key index 24bits --> 27 bits index = lookup->fingerprint[0]; index = index<<8 | lookup->fingerprint[1]; index = index<<8 | lookup->fingerprint[2]; @@ -350,7 +387,7 @@ int nova_dedup_entry_update(struct super_block *sb, struct nova_inode_info_heade // Check if target block has multiple Reference Count // Return 1 if it's okay to delete // Return 0 if it's not okay to delete -int nova_dedup_is_duplicate(struct super_block *sb, unsigned long blocknr){ +int nova_dedup_is_duplicate(struct super_block *sb, unsigned long blocknr, bool check){ unsigned long irq_flags=0; struct fact_entry te; // target entry struct fact_entry* pmem_te; // pmem target entry @@ -372,17 +409,21 @@ int nova_dedup_is_duplicate(struct super_block *sb, unsigned long blocknr){ ret = te.count >> 4; - if(ret <= 0){ // most likely impossible - printk("ERROR: reference count can't be less than 1\n"); - return 1; + // TODO return 1 when there is no entry corresponding to blocknr + // --> Deleted before deduplication + + if(ret <= 0){ // It's not in dedup table + printk("ERROR: Block is not in FACT table\n"); + return 2; } else{ // It's okay to delete, this entry can also be deleted + if(!check){ te.count -= 16; nova_memunlock_range(sb,pmem_te, NOVA_FACT_ENTRY_SIZE, &irq_flags); memcpy_to_pmem_nocache(pmem_te, &te, NOVA_FACT_ENTRY_SIZE - 4); // don't write 'delete' area nova_memlock_range(sb, pmem_te, NOVA_FACT_ENTRY_SIZE, &irq_flags); - + } if(ret == 1) return 1; else @@ -609,7 +650,9 @@ int nova_dedup_test(struct file * filp){ ret = nova_dedup_reassign_file_tree(sb,target_sih,begin_tail); if(ret) goto out; - + ret = nova_dedup_invalidate_target_entry(sb,target_sih,target_entry); + if(ret) + goto out; target_inode->i_blocks = target_sih->i_blocks; out: @@ -624,9 +667,9 @@ int nova_dedup_test(struct file * filp){ kfree(lookup_data); kfree(duplicate_check); iput(target_inode); - printk("----------DEDUP COMPLETE----------\n"); } else printk("no entry!\n"); + printk("----------DEDUP COMPLETE----------\n"); }while(0); kfree(buf); diff --git a/fs/nova/dedup.h b/fs/nova/dedup.h index 2c57d1c8a567..2d2de1e2aa07 100644 --- a/fs/nova/dedup.h +++ b/fs/nova/dedup.h @@ -62,7 +62,7 @@ int nova_dedup_test(struct file *); int nova_dedup_queue_push(u64,u64); int nova_dedup_queue_init(void); -int nova_dedup_is_duplicate(struct super_block *sb, unsigned long blocknr); +int nova_dedup_is_duplicate(struct super_block *sb, unsigned long blocknr, bool check); #endif diff --git a/fs/nova/log.c b/fs/nova/log.c index 3d38c37535bc..a1ac5a8e2e21 100644 --- a/fs/nova/log.c +++ b/fs/nova/log.c @@ -103,7 +103,9 @@ int nova_reassign_logentry(struct super_block *sb, void *entry, return nova_invalidate_reassign_logentry(sb, entry, type, 1, 0); } -static inline int nova_invalidate_write_entry(struct super_block *sb, +/* NOVA DEDUP KHJ */ +//static inline int nova_invalidate_write_entry(struct super_block *sb, +int nova_invalidate_write_entry(struct super_block *sb, struct nova_file_write_entry *entry, int reassign, unsigned int num_free) { diff --git a/fs/nova/log.h b/fs/nova/log.h index a8a95fb2f32e..6c0c73382a64 100644 --- a/fs/nova/log.h +++ b/fs/nova/log.h @@ -321,6 +321,10 @@ int nova_assign_write_entry(struct super_block *sb, struct nova_file_write_entry *entry, struct nova_file_write_entry *entryc, bool free); +/* NOVA DEDUP KHJ */ +int nova_invalidate_write_entry(struct super_block *sb, + struct nova_file_write_entry *entry, int reassign, + unsigned int num_free); void nova_print_curr_log_page(struct super_block *sb, u64 curr); void nova_print_nova_log(struct super_block *sb,