if (i == this->bitmap_block_cnt - 1) { // If current block is the last block of the bitmap.
// TODO: Find the first free bit of current bitmap block // and store it in `res`. // 对于最后一个bitmap block,只搜索last_block_num个bit,这里使用bitmap.h中的相关api res = Bitmap(buffer.data(), bm->block_size()) .find_first_free_w_bound(this->last_block_num);
} else {
// TODO: Find the first free bit of current bitmap block // and store it in `res`. // 而其他bitmap block,搜索全部bit res = Bitmap(buffer.data(), bm->block_size()).find_first_free(); }
// The block id of the allocated block. block_id_t retval = static_cast<block_id_t>(0);
// TODO: // 1. Set the free bit we found to 1 in the bitmap. Bitmap bitmap(buffer.data(), bm->block_size()); bitmap.set(*res); // 2. Flush the changed bitmap block back to the block manager. bm->write_block(i + this->bitmap_block_id, buffer.data()); // 3. Calculate the value of `retval`. retval = i * (bm->block_size() * KBitsPerByte) + *res;
// TODO: // 1. Initialize the inode with the given type. // 使用buffer存储inode数据 std::vector<u8> buffer(bm->block_size()); Inode inode(type, bm->block_size()); inode.flush_to_buffer(buffer.data()); // 将buffer的内容写入到bid指定的block中 auto write_res = bm->write_block(bid, buffer.data()); if (write_res.is_err()) { returnChfsResult<inode_id_t>(write_res.unwrap_error()); } // 2. Setup the inode table. // 先根据free_idx和count计算出inode id inode_id_t raw_id = count * (bm->block_size() * KBitsPerByte) + free_idx.value(); // 根据inode id计算出inode index inode_id_t logic_id = RAW_2_LOGIC(raw_id); // 实现bid和inode index的映射关系 auto set_res = this->set_table(raw_id, bid); if (set_res.is_err()) { returnChfsResult<inode_id_t>(set_res.unwrap_error()); } // 3. Return the id of the allocated inode. returnChfsResult<inode_id_t>(logic_id); // You may have to use the `RAW_2_LOGIC` macro // to get the result inode id.
// TODO: Implement this function. // Get the block id of inode whose id is `id` // from the inode table. You may have to use // the macro `LOGIC_2_RAW` to get the inode // table index. inode_id_t raw_id = LOGIC_2_RAW(id); if (raw_id >= max_inode_supported - 1) { returnChfsResult<block_id_t>(ErrorType::INVALID_ARG); } // 计算在inode table的第几个block的第几个entry auto inode_per_block = bm->block_size() / sizeof(block_id_t); auto block_idx = raw_id / inode_per_block; auto entry_idx = raw_id % inode_per_block; // 使用buffer存储读入的block数据 std::vector<u8> buffer(bm->block_size()); // 注意inode table从1开始,因为0是super block,以1 + n_table_blocks结尾 bm->read_block(1 + block_idx, buffer.data()).unwrap(); // 实现转换,保证数组的最小单位是block_id_t block_id_t *table = reinterpret_cast<block_id_t *>(buffer.data()); res_block_id = table[entry_idx];
// TODO: // 1. Allocate a block for the inode. auto block_res = this->block_allocator_->allocate(); // unwrap用于获取Result的值,即获取bid,提供给allocate_inode使用 block_id_t bid = block_res.unwrap(); // 2. Allocate an inode. inode_res = this->inode_manager_->allocate_inode(type, bid); // 3. Initialize the inode block // and write the block back to block manager.
// Get current block id. block_id_t bid = KInvalidBlockID; if (inode_p->is_direct_block(read_sz / block_size)) { // TODO: Implement the case of direct block. // 直接从inode中获取block id bid = inode_p->blocks[read_sz / block_size]; } else { // TODO: Implement the case of indirect block. // 先进入indirect block,再从indirect block中获取block id block_manager_->read_block(inode_p->get_indirect_block_id(), indirect_block.data()); // 将indirect_block转换为block_id_t数组 auto indirect_block_p = reinterpret_cast<block_id_t *>(indirect_block.data()); // 在indirect block中,从direct block的数量开始找 bid = indirect_block_p[read_sz / block_size - inode_p->get_direct_block_num()]; }
然后是读取文件到content这一步,比较简单,善用内置api即可:
1 2 3 4 5
// TODO: Read from current block and store to `content`. auto read_res = this->block_manager_->read_block(bid, buffer.data()); // content用于存放file读取的内容 content.insert(content.end(), buffer.data(), buffer.data() + sz); read_sz += sz;
// TODO: Implement the case of allocating more blocks. // 1. Allocate a block. auto res = this->block_allocator_->allocate(); block_id_t bid = res.unwrap(); // 2. Fill the allocated block id to the inode. // You should pay attention to the case of indirect block. // You may use function `get_or_insert_indirect_block` // in the case of indirect block. // 分类讨论是否是direct block if (inode_p->is_direct_block(idx)) { // Direct block inode_p->set_block_direct(idx, bid); } else { // Indirect block auto indirect_res = inode_p->get_or_insert_indirect_block(this->block_allocator_); // 读取indirect block内容到indirect_block auto read_res = this->block_manager_->read_block( inode_p->get_indirect_block_id(), indirect_block.data()); // 将indirect_block转换为block_id_t数组 auto indirect_block_p = reinterpret_cast<block_id_t *>(indirect_block.data()); // 在indirect block中,从direct block的数量开始找 indirect_block_p[idx - inode_p->get_direct_block_num()] = bid; // 将修改后的indirect block写回block manager // 而inode本身暂时不用写回磁盘,等最后一起写回 auto write_res = this->block_manager_->write_block( inode_p->get_indirect_block_id(), indirect_block.data());
// TODO: Implement this function. // Remove the directory entry from `src`. // 使用stream来分割字符串,将不等于filename的部分重新拼接起来 std::stringstream ss(src); std::string item; bool first = true; while (std::getline(ss, item, '/')) { auto pos = item.find(':'); if (pos != std::string::npos) { std::string name = item.substr(0, pos); if (name != filename) { if (!first) { res += '/'; } res += item; first = false; } } }
// TODO: // 1. Remove the file, you can use the function `remove_file` // 使用lookup找到对应的inode id auto lookup_res = lookup(parent, name); inode_id_t target_id = lookup_res.unwrap(); auto remove_res = this->remove_file(target_id); // 2. Remove the entry from the directory. // 使用read directory函数得到list auto list = std::list<DirectoryEntry>(); auto read_res = read_directory(this, parent, list); // 在list中删除对应的entry list.remove_if([name](const DirectoryEntry &entry) { return entry.name == name; }); // 将list转换成string std::string data = dir_list_to_string(list); // 将string写回到文件中 std::vector<u8> new_content(data.begin(), data.end()); auto write_res = this->write_file(parent, new_content); return KNullOk; }