/* Append . and .. entries */ int nova_append_dir_init_entries(struct super_block *sb, struct nova_inode *pi, u64 self_ino, u64 parent_ino) { int allocated; u64 new_block; u64 curr_p; struct nova_dentry *de_entry; if (pi->log_head) { nova_dbg("%s: log head exists @ 0x%llx!\n", __func__, pi->log_head); return - EINVAL; } allocated = nova_allocate_inode_log_pages(sb, pi, 1, &new_block); if (allocated != 1) { nova_err(sb, "ERROR: no inode log page available\n"); return - ENOMEM; } pi->log_tail = pi->log_head = new_block; pi->i_blocks = 1; nova_flush_buffer(&pi->log_head, CACHELINE_SIZE, 0); de_entry = (struct nova_dentry *)nova_get_block(sb, new_block); de_entry->entry_type = DIR_LOG; de_entry->ino = cpu_to_le64(self_ino); de_entry->name_len = 1; de_entry->de_len = cpu_to_le16(NOVA_DIR_LOG_REC_LEN(1)); de_entry->mtime = CURRENT_TIME_SEC.tv_sec; de_entry->size = sb->s_blocksize; de_entry->links_count = 1; strncpy(de_entry->name, ".\0", 2); nova_flush_buffer(de_entry, NOVA_DIR_LOG_REC_LEN(1), 0); curr_p = new_block + NOVA_DIR_LOG_REC_LEN(1); de_entry = (struct nova_dentry *)((char *)de_entry + le16_to_cpu(de_entry->de_len)); de_entry->entry_type = DIR_LOG; de_entry->ino = cpu_to_le64(parent_ino); de_entry->name_len = 2; de_entry->de_len = cpu_to_le16(NOVA_DIR_LOG_REC_LEN(2)); de_entry->mtime = CURRENT_TIME_SEC.tv_sec; de_entry->size = sb->s_blocksize; de_entry->links_count = 2; strncpy(de_entry->name, "..\0", 3); nova_flush_buffer(de_entry, NOVA_DIR_LOG_REC_LEN(2), 0); curr_p += NOVA_DIR_LOG_REC_LEN(2); nova_update_tail(pi, curr_p); return 0; }
void nova_save_inode_list_to_log(struct super_block *sb) { struct nova_inode *pi = nova_get_inode_by_ino(sb, NOVA_INODELIST1_INO); struct nova_sb_info *sbi = NOVA_SB(sb); unsigned long num_blocks; unsigned long num_nodes = 0; struct inode_map *inode_map; unsigned long i; u64 temp_tail; u64 new_block; int allocated; for (i = 0; i < sbi->cpus; i++) { inode_map = &sbi->inode_maps[i]; num_nodes += inode_map->num_range_node_inode; } num_blocks = num_nodes / RANGENODE_PER_PAGE; if (num_nodes % RANGENODE_PER_PAGE) num_blocks++; allocated = nova_allocate_inode_log_pages(sb, pi, num_blocks, &new_block); if (allocated != num_blocks) { nova_dbg("Error saving inode list: %d\n", allocated); return; } pi->log_head = new_block; nova_flush_buffer(&pi->log_head, CACHELINE_SIZE, 0); temp_tail = new_block; for (i = 0; i < sbi->cpus; i++) { inode_map = &sbi->inode_maps[i]; temp_tail = nova_save_range_nodes_to_log(sb, &inode_map->inode_inuse_tree, temp_tail, i); } nova_update_tail(pi, temp_tail); nova_dbg("%s: %lu inode nodes, pi head 0x%llx, tail 0x%llx\n", __func__, num_nodes, pi->log_head, pi->log_tail); }
void nova_save_blocknode_mappings_to_log(struct super_block *sb) { struct nova_inode *pi = nova_get_inode_by_ino(sb, NOVA_BLOCKNODE_INO); struct nova_sb_info *sbi = NOVA_SB(sb); struct nova_super_block *super; struct free_list *free_list; unsigned long num_blocknode = 0; unsigned long num_pages; int allocated; u64 new_block = 0; u64 temp_tail; int i; /* Allocate log pages before save blocknode mappings */ for (i = 0; i < sbi->cpus; i++) { free_list = nova_get_free_list(sb, i); num_blocknode += free_list->num_blocknode; nova_dbgv("%s: free list %d: %lu nodes\n", __func__, i, free_list->num_blocknode); } free_list = nova_get_free_list(sb, SHARED_CPU); num_blocknode += free_list->num_blocknode; nova_dbgv("%s: shared list: %lu nodes\n", __func__, free_list->num_blocknode); num_pages = num_blocknode / RANGENODE_PER_PAGE; if (num_blocknode % RANGENODE_PER_PAGE) num_pages++; allocated = nova_allocate_inode_log_pages(sb, pi, num_pages, &new_block); if (allocated != num_pages) { nova_dbg("Error saving blocknode mappings: %d\n", allocated); return; } /* * save the total allocated blocknode mappings * in super block * No transaction is needed as we will recover the fields * via failure recovery */ super = nova_get_super(sb); nova_memunlock_range(sb, &super->s_wtime, NOVA_FAST_MOUNT_FIELD_SIZE); super->s_wtime = cpu_to_le32(get_seconds()); nova_memlock_range(sb, &super->s_wtime, NOVA_FAST_MOUNT_FIELD_SIZE); nova_flush_buffer(super, NOVA_SB_SIZE, 0); /* Finally update log head and tail */ pi->log_head = new_block; nova_flush_buffer(&pi->log_head, CACHELINE_SIZE, 0); temp_tail = new_block; for (i = 0; i < sbi->cpus; i++) { temp_tail = nova_save_free_list_blocknodes(sb, i, temp_tail); } temp_tail = nova_save_free_list_blocknodes(sb, SHARED_CPU, temp_tail); nova_update_tail(pi, temp_tail); nova_dbg("%s: %lu blocknodes, %lu log pages, pi head 0x%llx, " "tail 0x%llx\n", __func__, num_blocknode, num_pages, pi->log_head, pi->log_tail); }