struct mem_node* __get_node(struct mem_node* node, uint32_t loc){ switch(node->state){ case LOCKED: case SPLIT: if(loc < node->loc+(1<<(node->size-1))){ if(node->left != 0){ return __get_node(node->left,loc); }else{ return 0;//FIXME } }else{ if(node->right != 0){ return __get_node(node->right,loc); }else{ return 0;//FIXME } } case FREE: case FULL: return node; default: return 0; } }
static void recovery_xdata_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { struct gc_move_arg arg; struct hmfs_node *last = NULL, *this = NULL; struct hmfs_cm_info *cm_i = CM_I(sbi); block_t addr_in_par; bool modify_vb = false; int x_tag; prepare_move_argument(&arg, sbi, src_segno, src_off, src_sum, TYPE_DATA); while (1) { this = __get_node(sbi, arg.cp_i, arg.nid); if (IS_ERR(this)) break; if (this == last) goto next; x_tag = le64_to_cpu(XATTR_HDR(arg.src)->h_magic); addr_in_par = XBLOCK_ADDR(this, x_tag); if (addr_in_par != arg.src_addr && is_valid_address(sbi, addr_in_par)) { break; } if (addr_in_par != arg.src_addr) { hmfs_memcpy_atomic(JUMP(this, x_tag), &arg.src_addr, 8); if (!modify_vb) { arg.dest_sum = get_summary_by_addr(sbi, addr_in_par); clear_summary_valid_bit(arg.dest_sum); modify_vb = true; } } last = this; next: if (arg.cp_i == cm_i->last_cp_i) break; arg.cp_i = get_next_checkpoint_info(sbi, arg.cp_i); } }
struct mem_node* _get_node(uint32_t loc){ return __get_node(root,loc); }
static void recovery_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { struct gc_move_arg args; struct hmfs_node *last = NULL, *this = NULL; struct hmfs_summary *par_sum; struct hmfs_cm_info *cm_i = CM_I(sbi); bool modify_vb = false; block_t addr_in_par; int par_type; prepare_move_argument(&args, sbi, src_segno, src_off, src_sum, TYPE_DATA); while (1) { this = __get_node(sbi, args.cp_i, args.nid); par_sum = get_summary_by_addr(sbi, L_ADDR(sbi, this)); if (IS_ERR(this)) { /* the node(args.nid) has been deleted */ break; } if (this == last) goto next; par_type = get_summary_type(par_sum); if (par_type == SUM_TYPE_INODE) { addr_in_par = le64_to_cpu(this->i.i_addr[args.ofs_in_node]); } else { addr_in_par = le64_to_cpu(this->dn.addr[args.ofs_in_node]); } /* * In recovery, the address stored in parent node would be * arg.src_addr or an invalid address. Because GC might terminate * in the loop change this address. * Condition addr_in_par != args.src_addr is not sufficient * to terminate recovery. For example, we delete a node in a * checkpoint and reuse it later. And address in reused node * is not equal to args.src_addr but we could not modify it. * Luckly, the child block in that node is valid and we could * judge this case by the value of address. */ if (addr_in_par != args.src_addr && is_valid_address(sbi, addr_in_par)) break; if (addr_in_par != args.src_addr) { /* Recover address in parent node */ if (par_type == SUM_TYPE_INODE) { hmfs_memcpy_atomic(&this->i.i_addr[args.ofs_in_node], &args.src_addr, 8); } else { hmfs_memcpy_atomic(&this->dn.addr[args.ofs_in_node], &args.src_addr, 8); } if (!modify_vb) { args.dest_sum = get_summary_by_addr(sbi, addr_in_par); clear_summary_valid_bit(args.dest_sum); modify_vb = true; } } last = this; next: if (args.cp_i == cm_i->last_cp_i) break; args.cp_i = get_next_checkpoint_info(sbi, args.cp_i); } }