char *base16decode(const char *inBuffer, int *count) { char *outBuffer = (char *) malloc(*count); BYTE *outBufferPtr = (BYTE *) outBuffer; bool big_endian = false; if(*inBuffer == '0' && *(inBuffer+1) == 'x') { inBuffer += *count; big_endian = true; *count -= 2; } while(*count>1){ BYTE c0,c1; if(big_endian) { c1 = decode16(*--inBuffer); c0 = decode16(*--inBuffer); } else { c0 = decode16(*inBuffer++); c1 = decode16(*inBuffer++); } if((c0 | c1) == BERR) { free(outBuffer); *count = 0; return(NULL); } *outBufferPtr++ = (c0<<4) | c1; *count -= 2; } *outBufferPtr = '\0'; *count = (int)(outBufferPtr-(BYTE *)outBuffer); return outBuffer; }
/** * 对数据进行解码 * @param in: 要解码的数据 * @param inLen: 要解码的数据的长度(必须为偶数) * @param out: [out]缓冲区,存放解码后的数据(至少是@inLen的一半大小) * @return: 如果@inLen不为偶数或者输入数据中非法字符,则解码失败,返回false; * 否则解码成功,返回true */ bool Base16::decode(const char *in, size_t inLen, void *out) { assert(inLen % 2 == 0); if (inLen % 2 != 0) return false; unsigned char *dest = reinterpret_cast<unsigned char *>(out); for (size_t i = 0; i < inLen; i += 2) { // 高四位 char ch = decode16(in[i]); if (ch == BAD) return false; // 非法字符 dest[i / 2] = ch << 4; // 低四位 ch = decode16(in[i + 1]); if (ch == BAD) return false; // 非法字符 dest[i / 2] |= ch; } return true; }
static int replay_log_stage2(struct replay *rp, struct buffer_head *logbuf) { if(DEBUG_MODE_K==1) { printk(KERN_INFO"%25s %25s %4d #in\n",__FILE__,__func__,__LINE__); } struct sb *sb = rp->sb; struct logblock *log = bufdata(logbuf); block_t blocknr = rp->blocknrs[bufindex(logbuf)]; unsigned char *data = log->data; int err; /* * Log block address itself works as balloc log, and adjust * bitmap and deunify even if logblocks is before latest * unify, to prevent to be overwritten. (This must be after * LOG_FREEBLOCKS replay if there is it.) */ trace("LOG BLOCK: logblock %Lx", blocknr); err = replay_update_bitmap(rp, blocknr, 1, 1); if (err) return err; /* Mark log block as deunify block */ defer_bfree(&sb->deunify, blocknr, 1); /* If log is before latest unify, those were already applied to FS. */ if (bufindex(logbuf) < rp->unify_index) { // assert(0); /* older logs should already be freed */ return 0; } if (bufindex(logbuf) == rp->unify_index) data = rp->unify_pos; while (data < log->data + be16_to_cpu(log->bytes)) { u8 code = *data++; switch (code) { case LOG_BALLOC: case LOG_BFREE: case LOG_BFREE_ON_UNIFY: case LOG_BFREE_RELOG: { u64 block; u32 count; data = decode32(data, &count); data = decode48(data, &block); trace("%s: count %u, block %Lx", log_name[code], count, block); err = 0; if (code == LOG_BALLOC) err = replay_update_bitmap(rp, block, count, 1); else if (code == LOG_BFREE_ON_UNIFY) defer_bfree(&sb->deunify, block, count); else err = replay_update_bitmap(rp, block, count, 0); if (err) return err; break; } case LOG_LEAF_REDIRECT: case LOG_BNODE_REDIRECT: { u64 oldblock, newblock; data = decode48(data, &oldblock); data = decode48(data, &newblock); trace("%s: oldblock %Lx, newblock %Lx", log_name[code], oldblock, newblock); err = replay_update_bitmap(rp, newblock, 1, 1); if (err) return err; if (code == LOG_LEAF_REDIRECT) { err = replay_update_bitmap(rp, oldblock, 1, 0); if (err) return err; } else { /* newblock is not flushing yet */ defer_bfree(&sb->deunify, oldblock, 1); } break; } case LOG_LEAF_FREE: case LOG_BNODE_FREE: { u64 block; data = decode48(data, &block); trace("%s: block %Lx", log_name[code], block); err = replay_update_bitmap(rp, block, 1, 0); if (err) return err; if (code == LOG_BNODE_FREE) { struct buffer_head *buffer = vol_find_get_block(sb, block); blockput_free_unify(sb, buffer); } break; } case LOG_BNODE_ROOT: { u64 root, left, right, rkey; u8 count; count = *data++; data = decode48(data, &root); data = decode48(data, &left); data = decode48(data, &right); data = decode48(data, &rkey); trace("%s: count %u, root block %Lx, left %Lx, right %Lx, rkey %Lx", log_name[code], count, root, left, right, rkey); err = replay_update_bitmap(rp, root, 1, 1); if (err) return err; break; } case LOG_BNODE_SPLIT: { unsigned pos; u64 src, dst; data = decode16(data, &pos); data = decode48(data, &src); data = decode48(data, &dst); trace("%s: pos %x, src %Lx, dst %Lx", log_name[code], pos, src, dst); err = replay_update_bitmap(rp, dst, 1, 1); if (err) return err; break; } case LOG_BNODE_MERGE: { u64 src, dst; data = decode48(data, &src); data = decode48(data, &dst); trace("%s: src 0x%Lx, dst 0x%Lx", log_name[code], src, dst); err = replay_update_bitmap(rp, src, 1, 0); if (err) return err; blockput_free_unify(sb, vol_find_get_block(sb, src)); break; } case LOG_ORPHAN_ADD: case LOG_ORPHAN_DEL: { unsigned version; u64 inum; data = decode16(data, &version); data = decode48(data, &inum); trace("%s: version 0x%x, inum 0x%Lx", log_name[code], version, inum); if (code == LOG_ORPHAN_ADD) err = replay_orphan_add(rp, version, inum); else err = replay_orphan_del(rp, version, inum); if (err) return err; break; } case LOG_FREEBLOCKS: case LOG_BNODE_ADD: case LOG_BNODE_UPDATE: case LOG_BNODE_DEL: case LOG_BNODE_ADJUST: case LOG_UNIFY: case LOG_DELTA: data += log_size[code] - sizeof(code); break; default: tux3_err(sb, "unrecognized log code 0x%x", code); return -EINVAL; } } return 0; }
static int replay_log_stage1(struct replay *rp, struct buffer_head *logbuf) { if(DEBUG_MODE_K==1) { printk(KERN_INFO"%25s %25s %4d #in\n",__FILE__,__func__,__LINE__); } struct sb *sb = rp->sb; struct logblock *log = bufdata(logbuf); unsigned char *data = log->data; int err; /* Check whether array is uptodate */ BUILD_BUG_ON(ARRAY_SIZE(log_name) != LOG_TYPES); /* If log is before latest unify, those were already applied to FS. */ if (bufindex(logbuf) < rp->unify_index) { // assert(0); /* older logs should already be freed */ return 0; } if (bufindex(logbuf) == rp->unify_index) data = rp->unify_pos; while (data < log->data + be16_to_cpu(log->bytes)) { u8 code = *data++; switch (code) { case LOG_BNODE_REDIRECT: { u64 oldblock, newblock; data = decode48(data, &oldblock); data = decode48(data, &newblock); trace("%s: oldblock %Lx, newblock %Lx", log_name[code], oldblock, newblock); err = replay_bnode_redirect(rp, oldblock, newblock); if (err) return err; break; } case LOG_BNODE_ROOT: { u64 root, left, right, rkey; u8 count; count = *data++; data = decode48(data, &root); data = decode48(data, &left); data = decode48(data, &right); data = decode48(data, &rkey); trace("%s: count %u, root block %Lx, left %Lx, right %Lx, rkey %Lx", log_name[code], count, root, left, right, rkey); err = replay_bnode_root(rp, root, count, left, right, rkey); if (err) return err; break; } case LOG_BNODE_SPLIT: { unsigned pos; u64 src, dst; data = decode16(data, &pos); data = decode48(data, &src); data = decode48(data, &dst); trace("%s: pos %x, src %Lx, dst %Lx", log_name[code], pos, src, dst); err = replay_bnode_split(rp, src, pos, dst); if (err) return err; break; } case LOG_BNODE_ADD: case LOG_BNODE_UPDATE: { u64 child, parent, key; data = decode48(data, &parent); data = decode48(data, &child); data = decode48(data, &key); trace("%s: parent 0x%Lx, child 0x%Lx, key 0x%Lx", log_name[code], parent, child, key); if (code == LOG_BNODE_UPDATE) err = replay_bnode_update(rp, parent, child, key); else err = replay_bnode_add(rp, parent, child, key); if (err) return err; break; } case LOG_BNODE_MERGE: { u64 src, dst; data = decode48(data, &src); data = decode48(data, &dst); trace("%s: src 0x%Lx, dst 0x%Lx", log_name[code], src, dst); err = replay_bnode_merge(rp, src, dst); if (err) return err; break; } case LOG_BNODE_DEL: { unsigned count; u64 bnode, key; data = decode16(data, &count); data = decode48(data, &bnode); data = decode48(data, &key); trace("%s: bnode 0x%Lx, count 0x%x, key 0x%Lx", log_name[code], bnode, count, key); err = replay_bnode_del(rp, bnode, key, count); if (err) return err; break; } case LOG_BNODE_ADJUST: { u64 bnode, from, to; data = decode48(data, &bnode); data = decode48(data, &from); data = decode48(data, &to); trace("%s: bnode 0x%Lx, from 0x%Lx, to 0x%Lx", log_name[code], bnode, from, to); err = replay_bnode_adjust(rp, bnode, from, to); if (err) return err; break; } case LOG_FREEBLOCKS: { u64 freeblocks; data = decode48(data, &freeblocks); trace("%s: freeblocks %llu", log_name[code], freeblocks); sb->freeblocks = freeblocks; break; } case LOG_BALLOC: case LOG_BFREE: case LOG_BFREE_ON_UNIFY: case LOG_BFREE_RELOG: case LOG_LEAF_REDIRECT: case LOG_LEAF_FREE: case LOG_BNODE_FREE: case LOG_ORPHAN_ADD: case LOG_ORPHAN_DEL: case LOG_UNIFY: case LOG_DELTA: data += log_size[code] - sizeof(code); break; default: tux3_err(rp->sb, "unrecognized log code 0x%x", code); return -EINVAL; } } return 0; }