Initial commit

This commit is contained in:
2025-11-06 10:49:44 +08:00
commit 2d16528ac4
20 changed files with 4653 additions and 0 deletions

77
tools/fsck.cpp Normal file
View File

@@ -0,0 +1,77 @@
#include "simplefs.h"
#include "disk_io.h"
#include "utils.h"
#include <iostream>
#include <vector>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <cmath>
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cerr << "用法: " << argv[0] << " <设备文件>" << std::endl;
return 1;
}
const char* path = argv[1];
int fd = open(path, O_RDONLY);
if (fd < 0) {
perror("打开设备文件失败");
return 1;
}
std::vector<uint8_t> buf(SIMPLEFS_BLOCK_SIZE);
if (read_block(fd, 1, buf.data()) != 0) {
std::cerr << "读取超级块失败" << std::endl;
close(fd);
return 1;
}
SimpleFS_SuperBlock sb;
std::memcpy(&sb, buf.data(), sizeof(sb));
if (sb.s_magic != SIMPLEFS_MAGIC) {
std::cerr << "魔数不匹配不是SimpleFS镜像" << std::endl;
close(fd);
return 1;
}
uint32_t num_groups = static_cast<uint32_t>(std::ceil((double)sb.s_blocks_count / sb.s_blocks_per_group));
uint32_t gdt_size = num_groups * sizeof(SimpleFS_GroupDesc);
uint32_t gdt_blocks = static_cast<uint32_t>(std::ceil((double)gdt_size / SIMPLEFS_BLOCK_SIZE));
std::vector<uint8_t> gdt_raw(gdt_blocks * SIMPLEFS_BLOCK_SIZE);
for (uint32_t i=0;i<gdt_blocks;++i){
if (read_block(fd, 2 + i, gdt_raw.data()+i*SIMPLEFS_BLOCK_SIZE)!=0){
std::cerr<<"读取组描述符表失败"<<std::endl;
close(fd);
return 1;
}
}
std::vector<SimpleFS_GroupDesc> gdt(num_groups);
std::memcpy(gdt.data(), gdt_raw.data(), gdt_size);
uint64_t calc_free_blocks=0, calc_free_inodes=0;
for(uint32_t grp=0; grp<num_groups; ++grp){
const auto& gd=gdt[grp];
std::vector<uint8_t> bb(SIMPLEFS_BLOCK_SIZE), ib(SIMPLEFS_BLOCK_SIZE);
read_block(fd, gd.bg_block_bitmap, bb.data());
read_block(fd, gd.bg_inode_bitmap, ib.data());
uint32_t freeb=0, freei=0;
for(uint32_t b=0;b<sb.s_blocks_per_group && (grp*sb.s_blocks_per_group+b)<sb.s_blocks_count;++b)
if(!is_bitmap_bit_set(bb,b)) freeb++;
for(uint32_t i=0;i<sb.s_inodes_per_group;++i)
if(!is_bitmap_bit_set(ib,i)) freei++;
if(freeb!=gd.bg_free_blocks_count)
std::cout<<""<<grp<<" 块计数不匹配: 位图="<<freeb<<" 描述符="<<gd.bg_free_blocks_count<<std::endl;
if(freei!=gd.bg_free_inodes_count)
std::cout<<""<<grp<<" inode计数不匹配: 位图="<<freei<<" 描述符="<<gd.bg_free_inodes_count<<std::endl;
calc_free_blocks+=freeb;
calc_free_inodes+=freei;
}
if(calc_free_blocks!=sb.s_free_blocks_count)
std::cout<<"超级块空闲块计数不匹配: "<<calc_free_blocks<<" vs "<<sb.s_free_blocks_count<<std::endl;
if(calc_free_inodes!=sb.s_free_inodes_count)
std::cout<<"超级块空闲inode计数不匹配: "<<calc_free_inodes<<" vs "<<sb.s_free_inodes_count<<std::endl;
std::cout<<"fsck检查完成"<<std::endl;
close(fd);
return 0;
}

577
tools/mkfs.cpp Normal file
View File

@@ -0,0 +1,577 @@
#include "simplefs.h"
#include "disk_io.h"
#include "utils.h" // 位图操作工具函数
// 如果位图工具在utils.h中mkfs.cpp就不再直接需要metadata.h了
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstring> // 字符串操作
#include <sys/stat.h> // stat, fstat
#include <fcntl.h> // open
#include <unistd.h> // close, ftruncate
#include <cmath> // ceil
#include <numeric> // std::fill
#include <algorithm> // std::fill
#include <sys/ioctl.h> // ioctl
#include <linux/fs.h> // BLKGETSIZE64
// 默认参数(可通过选项覆盖)
const uint32_t DEFAULT_BLOCKS_PER_GROUP = SIMPLEFS_BLOCK_SIZE * 8; // 位图中每位对应一个块
const uint32_t DEFAULT_INODES_PER_GROUP = 1024; // 选定的默认值
// 静态位图辅助函数已移至metadata.cpp
void print_usage(const char* prog_name) {
std::cerr << "用法: " << prog_name << " <设备文件> [块数量]" << std::endl;
std::cerr << " <设备文件>: 磁盘镜像文件或块设备路径" << std::endl;
std::cerr << " [块数量]: 可选,新镜像文件的总块数" << std::endl;
}
// 获取文件大小的函数
off_t get_file_size(int fd) {
struct stat st;
if (fstat(fd, &st) == -1) {
perror("获取文件大小失败");
return -1;
}
return st.st_size;
}
int main(int argc, char* argv[]) {
if (argc < 2 || argc > 3) {
print_usage(argv[0]);
return 1;
}
std::string device_path = argv[1];
uint64_t total_blocks_on_device = 0;
uint64_t device_size_bytes = 0;
bool create_new_image = false;
DeviceFd fd = open(device_path.c_str(), O_RDWR);
if (fd == -1) {
if (errno == ENOENT && argc == 3) { // 文件不存在,且提供了大小
std::cout << "正在创建新镜像文件: " << device_path << std::endl;
fd = open(device_path.c_str(), O_RDWR | O_CREAT | O_EXCL, 0666);
if (fd == -1) {
perror("创建镜像文件失败");
return 1;
}
create_new_image = true;
try {
total_blocks_on_device = std::stoull(argv[2]);
if (total_blocks_on_device == 0) {
std::cerr << "块数量必须为正数" << std::endl;
close(fd);
unlink(device_path.c_str()); // 清理已创建的文件
return 1;
}
device_size_bytes = total_blocks_on_device * SIMPLEFS_BLOCK_SIZE;
if (ftruncate(fd, device_size_bytes) == -1) {
perror("设置镜像大小失败");
close(fd);
unlink(device_path.c_str()); // 清理
return 1;
}
std::cout << "已创建新镜像文件 " << device_path << " (大小: "
<< total_blocks_on_device << " 块, " << device_size_bytes << " 字节)" << std::endl;
} catch (const std::exception& e) {
std::cerr << "块数量参数无效: " << e.what() << std::endl;
close(fd);
unlink(device_path.c_str()); // 清理
return 1;
}
} else if (errno == ENOENT) {
std::cerr << "错误: 镜像文件 '" << device_path << "' 未找到,请提供块数量来创建" << std::endl;
perror("打开设备/镜像失败");
return 1;
}
else {
perror("打开设备/镜像失败");
return 1;
}
} else {
bool is_blk_dev = is_block_device(fd);
if (is_blk_dev) {
std::cout << "检测到块设备" << std::endl;
uint64_t size_from_ioctl = 0;
if (ioctl(fd, BLKGETSIZE64, &size_from_ioctl) == 0) {
std::cout << "通过ioctl获取块设备大小: " << size_from_ioctl << " 字节" << std::endl;
if (size_from_ioctl % SIMPLEFS_BLOCK_SIZE != 0) {
std::cerr << "警告: 块设备大小不是文件系统块大小的整数倍" << std::endl;
}
device_size_bytes = size_from_ioctl;
total_blocks_on_device = device_size_bytes / SIMPLEFS_BLOCK_SIZE;
if (argc == 3) {
std::cout << "注意: 忽略[num_blocks]参数,已自动检测设备大小" << std::endl;
}
} else {
perror("ioctl获取设备大小失败");
std::cerr << "无法自动检测块设备大小" << std::endl;
if (argc != 3) {
std::cerr << "错误: 请手动提供[num_blocks]参数" << std::endl;
close(fd);
return 1;
}
try {
total_blocks_on_device = std::stoull(argv[2]);
if (total_blocks_on_device == 0) {
std::cerr << "块数量必须为正数" << std::endl;
close(fd);
return 1;
}
device_size_bytes = total_blocks_on_device * SIMPLEFS_BLOCK_SIZE;
} catch (const std::exception& e) {
std::cerr << "块数量参数无效: " << e.what() << std::endl;
close(fd);
return 1;
}
}
std::cout << "格式化块设备 " << device_path << ",块数: " << total_blocks_on_device
<< " (" << device_size_bytes << " 字节)" << std::endl;
} else {
// 这是常规文件,获取其大小
off_t existing_size = get_file_size(fd);
if (existing_size == -1) {
close(fd);
return 1;
}
if (existing_size == 0) {
if (argc == 3) { // 这是空文件但用户要用指定大小格式化
std::cout << "现有文件为空,按新镜像创建处理" << std::endl;
create_new_image = true;
try {
total_blocks_on_device = std::stoull(argv[2]);
if (total_blocks_on_device == 0) {
std::cerr << "块数量必须为正数" << std::endl;
close(fd);
return 1;
}
device_size_bytes = total_blocks_on_device * SIMPLEFS_BLOCK_SIZE;
if (ftruncate(fd, device_size_bytes) == -1) {
perror("设置镜像大小失败");
close(fd);
return 1;
}
std::cout << "设置镜像 " << device_path << " 大小为 " << total_blocks_on_device
<< " 块 (" << device_size_bytes << " 字节)" << std::endl;
} catch (const std::exception& e) {
std::cerr << "块数量参数无效: " << e.what() << std::endl;
close(fd);
return 1;
}
} else {
std::cerr << "错误: 镜像文件为空" << std::endl;
std::cerr << "如需格式化请提供num_blocks参数" << std::endl;
close(fd);
return 1;
}
} else {
if (existing_size % SIMPLEFS_BLOCK_SIZE != 0) {
std::cerr << "警告: 设备/镜像大小 (" << existing_size
<< " 字节) 不是块大小 (" << SIMPLEFS_BLOCK_SIZE << " 字节) 的整数倍" << std::endl;
}
device_size_bytes = existing_size;
total_blocks_on_device = device_size_bytes / SIMPLEFS_BLOCK_SIZE;
std::cout << "Opened existing image " << device_path << ". Total blocks: " << total_blocks_on_device
<< " (" << device_size_bytes << " bytes)." << std::endl;
if (argc == 3 && !create_new_image) {
std::cout << "Note: [num_blocks] argument is ignored when using an existing, non-empty image file." << std::endl;
}
}
}
}
if (total_blocks_on_device < 64) {
std::cerr << "错误: 设备/镜像太小至少需要64个块" << std::endl;
close(fd);
if (create_new_image) unlink(device_path.c_str());
return 1;
}
std::cout << "正在格式化 " << device_path << " 为 SimpleFS..." << std::endl;
uint32_t inodes_per_block = SIMPLEFS_BLOCK_SIZE / SIMPLEFS_INODE_SIZE;
uint32_t sb_blocks_per_group = DEFAULT_BLOCKS_PER_GROUP;
uint32_t sb_inodes_per_group = DEFAULT_INODES_PER_GROUP;
if (sb_inodes_per_group > SIMPLEFS_BLOCK_SIZE * 8) {
sb_inodes_per_group = SIMPLEFS_BLOCK_SIZE * 8;
std::cout << "警告: 请求的每组inode数超过inode位图最大容量调整为 "
<< sb_inodes_per_group << std::endl;
}
uint32_t num_block_groups = static_cast<uint32_t>(std::ceil(static_cast<double>(total_blocks_on_device) / sb_blocks_per_group));
if (num_block_groups == 0) num_block_groups = 1;
uint64_t total_inodes_fs = static_cast<uint64_t>(num_block_groups) * sb_inodes_per_group;
if (total_inodes_fs > UINT32_MAX) {
total_inodes_fs = UINT32_MAX;
}
std::cout << "文件系统布局:" << std::endl;
std::cout << " 总块数: " << total_blocks_on_device << std::endl;
std::cout << " 每组inode数: " << sb_inodes_per_group << std::endl;
std::cout << " 块组数: " << num_block_groups << std::endl;
std::cout << " 总inode数: " << total_inodes_fs << std::endl;
SimpleFS_SuperBlock sb;
std::memset(&sb, 0, sizeof(SimpleFS_SuperBlock));
sb.s_magic = SIMPLEFS_MAGIC;
sb.s_blocks_count = total_blocks_on_device;
sb.s_inodes_count = static_cast<uint32_t>(total_inodes_fs);
sb.s_log_block_size = static_cast<uint32_t>(std::log2(SIMPLEFS_BLOCK_SIZE)) - 10;
sb.s_blocks_per_group = sb_blocks_per_group;
sb.s_inodes_per_group = sb_inodes_per_group;
sb.s_inode_size = SIMPLEFS_INODE_SIZE;
sb.s_root_inode = SIMPLEFS_ROOT_INODE_NUM;
sb.s_first_ino = 11;
sb.s_state = 1;
sb.s_errors = 1;
sb.s_max_mnt_count = 20;
sb.s_mnt_count = 0;
sb.s_wtime = time(nullptr);
sb.s_block_group_nr = 0;
uint32_t gdt_size_bytes = num_block_groups * sizeof(SimpleFS_GroupDesc);
uint32_t gdt_blocks = static_cast<uint32_t>(std::ceil(static_cast<double>(gdt_size_bytes) / SIMPLEFS_BLOCK_SIZE));
std::cout << " GDT size: " << gdt_size_bytes << " bytes, requiring " << gdt_blocks << " blocks." << std::endl;
uint32_t superblock_location_block = 1;
uint32_t gdt_start_block = superblock_location_block + 1;
std::vector<SimpleFS_GroupDesc> gdt(num_block_groups);
std::memset(gdt.data(), 0, gdt_size_bytes);
uint32_t running_total_free_blocks = total_blocks_on_device;
uint32_t running_total_free_inodes = sb.s_inodes_count;
if (superblock_location_block < total_blocks_on_device) running_total_free_blocks--; else { std::cerr << "No space for SB!" << std::endl; return 1; }
for(uint32_t i = 0; i < gdt_blocks; ++i) {
if ((gdt_start_block + i) < total_blocks_on_device) running_total_free_blocks--; else { std::cerr << "No space for GDT!" << std::endl; return 1; }
}
uint32_t current_group_meta_start_block = gdt_start_block + gdt_blocks;
for (uint32_t i = 0; i < num_block_groups; ++i) {
SimpleFS_GroupDesc& current_gd = gdt[i];
uint32_t group_abs_start_block_for_data = i * sb.s_blocks_per_group;
uint32_t inode_table_size_blocks = static_cast<uint32_t>(std::ceil(static_cast<double>(sb.s_inodes_per_group) * SIMPLEFS_INODE_SIZE / SIMPLEFS_BLOCK_SIZE));
bool backup_here = is_backup_group(i);
if (i == 0) {
current_gd.bg_block_bitmap = current_group_meta_start_block;
current_gd.bg_inode_bitmap = current_gd.bg_block_bitmap + 1;
current_gd.bg_inode_table = current_gd.bg_inode_bitmap + 1;
sb.s_first_data_block = current_gd.bg_inode_table + inode_table_size_blocks;
} else if (backup_here) {
current_gd.bg_block_bitmap = group_abs_start_block_for_data + 1 + gdt_blocks;
current_gd.bg_inode_bitmap = current_gd.bg_block_bitmap + 1;
current_gd.bg_inode_table = current_gd.bg_inode_bitmap + 1;
} else {
current_gd.bg_block_bitmap = group_abs_start_block_for_data;
current_gd.bg_inode_bitmap = current_gd.bg_block_bitmap + 1;
current_gd.bg_inode_table = current_gd.bg_inode_bitmap + 1;
}
uint32_t last_meta_block_for_group = current_gd.bg_inode_table + inode_table_size_blocks -1;
if (last_meta_block_for_group >= total_blocks_on_device || current_gd.bg_block_bitmap >= total_blocks_on_device) {
std::cerr << "错误: 组 " << i << " 的元数据超出设备限制" << std::endl; close(fd); if(create_new_image) unlink(device_path.c_str()); return 1;
}
running_total_free_blocks--; // 块位图
running_total_free_blocks--; // inode位图
running_total_free_blocks -= inode_table_size_blocks; // inode表
// 注意主组组0的超级块和GDT已在前面减去这里不重复减去
if (backup_here && i != 0) { // 只有备份组且不是组0才减去
running_total_free_blocks--; // 备份超级块
running_total_free_blocks -= gdt_blocks; // 备份GDT
}
uint32_t blocks_in_this_group_range = (i == num_block_groups - 1) ?
(total_blocks_on_device - group_abs_start_block_for_data) :
sb.s_blocks_per_group;
current_gd.bg_free_blocks_count = blocks_in_this_group_range;
current_gd.bg_free_blocks_count -= 1; // 块位图
current_gd.bg_free_blocks_count -= 1; // inode位图
current_gd.bg_free_blocks_count -= inode_table_size_blocks; // inode表
if (i == 0) {
current_gd.bg_free_blocks_count--; // 超级块
current_gd.bg_free_blocks_count -= gdt_blocks; // GDT
} else if (backup_here) {
current_gd.bg_free_blocks_count--; // 备份超级块
current_gd.bg_free_blocks_count -= gdt_blocks; // 备份GDT
}
// 主要SB/GDT的额外空闲块调整已在前面完成
current_gd.bg_free_inodes_count = sb.s_inodes_per_group;
current_gd.bg_used_dirs_count = 0;
}
sb.s_free_blocks_count = running_total_free_blocks;
sb.s_free_inodes_count = running_total_free_inodes;
if (gdt_start_block + gdt_blocks > gdt[0].bg_block_bitmap) {
std::cerr << "严重错误: GDT与组0块位图重叠设备太小或计算错误" << std::endl;
close(fd); if(create_new_image) unlink(device_path.c_str()); return 1;
}
std::cout << "超级块(根目录前的最终估计值):" << std::endl;
std::cout << " 空闲块数: " << sb.s_free_blocks_count << std::endl;
std::cout << " 空闲inode数: " << sb.s_free_inodes_count << std::endl;
std::cout << " 首个数据块(全局): " << sb.s_first_data_block << std::endl;
std::vector<uint8_t> fs_block_buffer(SIMPLEFS_BLOCK_SIZE, 0);
std::memcpy(fs_block_buffer.data(), &sb, sizeof(sb));
if (write_block(fd, superblock_location_block, fs_block_buffer.data()) != 0) {
std::cerr << "超级块写入失败" << std::endl; close(fd); if (create_new_image) unlink(device_path.c_str()); return 1;
}
std::cout << "超级块已写入块 " << superblock_location_block << std::endl;
uint8_t* gdt_write_ptr = reinterpret_cast<uint8_t*>(gdt.data());
for (uint32_t i = 0; i < gdt_blocks; ++i) {
std::fill(fs_block_buffer.begin(), fs_block_buffer.end(), 0);
uint32_t bytes_to_copy_this_block = (gdt_size_bytes - (i * SIMPLEFS_BLOCK_SIZE) < SIMPLEFS_BLOCK_SIZE) ?
(gdt_size_bytes % SIMPLEFS_BLOCK_SIZE == 0 && gdt_size_bytes > 0 ? SIMPLEFS_BLOCK_SIZE : gdt_size_bytes % SIMPLEFS_BLOCK_SIZE)
: SIMPLEFS_BLOCK_SIZE;
if (gdt_size_bytes == 0 && i==0) bytes_to_copy_this_block = 0;
std::memcpy(fs_block_buffer.data(), gdt_write_ptr + (i * SIMPLEFS_BLOCK_SIZE), bytes_to_copy_this_block);
if (write_block(fd, gdt_start_block + i, fs_block_buffer.data()) != 0) {
std::cerr << "GDT块 " << (gdt_start_block + i) << " 写入失败" << std::endl; close(fd); if (create_new_image) unlink(device_path.c_str()); return 1;
}
}
std::cout << "GDT已写入块 " << gdt_start_block << "" << (gdt_start_block + gdt_blocks - 1) << std::endl;
std::vector<uint8_t> group_block_bitmap_buffer(SIMPLEFS_BLOCK_SIZE, 0);
std::vector<uint8_t> group_inode_bitmap_buffer(SIMPLEFS_BLOCK_SIZE, 0);
for (uint32_t i = 0; i < num_block_groups; ++i) {
SimpleFS_GroupDesc& current_gd_ref = gdt[i];
uint32_t group_abs_data_start_block = i * sb.s_blocks_per_group; // 这是该组位图中位0的块号
uint32_t inode_table_size_blocks = static_cast<uint32_t>(std::ceil(static_cast<double>(sb.s_inodes_per_group) * SIMPLEFS_INODE_SIZE / SIMPLEFS_BLOCK_SIZE));
std::cout << "Processing Group " << i << ":" << std::endl;
std::cout << " BB@" << current_gd_ref.bg_block_bitmap << ", IB@" << current_gd_ref.bg_inode_bitmap << ", IT@" << current_gd_ref.bg_inode_table << " (" << inode_table_size_blocks << " blocks)" << std::endl;
std::fill(group_block_bitmap_buffer.begin(), group_block_bitmap_buffer.end(), 0);
std::fill(group_inode_bitmap_buffer.begin(), group_inode_bitmap_buffer.end(), 0);
// 在其块位图中将组自己的元数据块标记为已使用
// 组位图中的位索引相对于该组管理的块起始位置
set_bitmap_bit(group_block_bitmap_buffer, current_gd_ref.bg_block_bitmap - group_abs_data_start_block);
set_bitmap_bit(group_block_bitmap_buffer, current_gd_ref.bg_inode_bitmap - group_abs_data_start_block);
for (uint32_t j = 0; j < inode_table_size_blocks; ++j) {
set_bitmap_bit(group_block_bitmap_buffer, (current_gd_ref.bg_inode_table + j) - group_abs_data_start_block);
}
bool backup_here = is_backup_group(i);
if (backup_here) {
uint32_t sb_blk = (i == 0) ? superblock_location_block : group_abs_data_start_block;
set_bitmap_bit(group_block_bitmap_buffer, sb_blk - group_abs_data_start_block);
for (uint32_t gdt_idx = 0; gdt_idx < gdt_blocks; ++gdt_idx) {
uint32_t abs_gdt_block = (i == 0) ? (gdt_start_block + gdt_idx)
: (group_abs_data_start_block + 1 + gdt_idx);
set_bitmap_bit(group_block_bitmap_buffer, abs_gdt_block - group_abs_data_start_block);
}
}
if (i == 0) {
if (!is_bitmap_bit_set(group_block_bitmap_buffer, 0)) {
set_bitmap_bit(group_block_bitmap_buffer, 0);
bool block0_was_sb = (superblock_location_block == 0);
bool block0_was_gdt = false;
for(uint32_t gdt_idx=0; gdt_idx < gdt_blocks; ++gdt_idx) if((gdt_start_block + gdt_idx) == 0) block0_was_gdt = true;
bool block0_was_group0_bb = (current_gd_ref.bg_block_bitmap == 0);
bool block0_was_group0_ib = (current_gd_ref.bg_inode_bitmap == 0);
bool block0_was_group0_it = (current_gd_ref.bg_inode_table == 0);
if (!block0_was_sb && !block0_was_gdt && !block0_was_group0_bb && !block0_was_group0_ib && !block0_was_group0_it) {
if (current_gd_ref.bg_free_blocks_count > 0) current_gd_ref.bg_free_blocks_count--;
if (sb.s_free_blocks_count > 0) sb.s_free_blocks_count--;
}
}
set_bitmap_bit(group_inode_bitmap_buffer, 0);
set_bitmap_bit(group_inode_bitmap_buffer, 1);
if (current_gd_ref.bg_free_inodes_count >= 2) current_gd_ref.bg_free_inodes_count -= 2; else current_gd_ref.bg_free_inodes_count = 0;
if (sb.s_free_inodes_count >= 2) sb.s_free_inodes_count -= 2; else sb.s_free_inodes_count = 0;
}
if (write_block(fd, current_gd_ref.bg_block_bitmap, group_block_bitmap_buffer.data()) != 0) { /* error */ return 1; }
std::cout << " Written Block Bitmap. Group free blocks: " << current_gd_ref.bg_free_blocks_count << std::endl;
if (write_block(fd, current_gd_ref.bg_inode_bitmap, group_inode_bitmap_buffer.data()) != 0) { /* error */ return 1; }
std::cout << " Written Inode Bitmap. Group free inodes: " << current_gd_ref.bg_free_inodes_count << std::endl;
if (write_zero_blocks(fd, current_gd_ref.bg_inode_table, inode_table_size_blocks) != 0) { /* error */ return 1; }
std::cout << " Zeroed Inode Table." << std::endl;
}
std::cout << "Re-writing Superblock and GDT (final pre-root dir)..." << std::endl;
std::memcpy(fs_block_buffer.data(), &sb, sizeof(sb));
if (write_block(fd, superblock_location_block, fs_block_buffer.data()) != 0) { /* error */ return 1;}
gdt_write_ptr = reinterpret_cast<uint8_t*>(gdt.data());
for (uint32_t i = 0; i < gdt_blocks; ++i) {
std::fill(fs_block_buffer.begin(), fs_block_buffer.end(), 0);
uint32_t bytes_to_copy_this_block = (gdt_size_bytes - (i * SIMPLEFS_BLOCK_SIZE) < SIMPLEFS_BLOCK_SIZE) ?
(gdt_size_bytes % SIMPLEFS_BLOCK_SIZE == 0 && gdt_size_bytes > 0 ? SIMPLEFS_BLOCK_SIZE : gdt_size_bytes % SIMPLEFS_BLOCK_SIZE)
: SIMPLEFS_BLOCK_SIZE;
if (gdt_size_bytes == 0 && i==0) bytes_to_copy_this_block = 0;
std::memcpy(fs_block_buffer.data(), gdt_write_ptr + (i * SIMPLEFS_BLOCK_SIZE), bytes_to_copy_this_block);
if (write_block(fd, gdt_start_block + i, fs_block_buffer.data()) != 0) { /* error */ return 1; }
}
// 将超级块和GDT的备份副本写入指定组
for (uint32_t grp = 1; grp < num_block_groups; ++grp) {
if (!is_backup_group(grp)) continue;
uint32_t grp_start = grp * sb.s_blocks_per_group;
std::memcpy(fs_block_buffer.data(), &sb, sizeof(sb));
if (write_block(fd, grp_start, fs_block_buffer.data()) != 0) { /* error */ return 1; }
for (uint32_t i = 0; i < gdt_blocks; ++i) {
std::fill(fs_block_buffer.begin(), fs_block_buffer.end(), 0);
uint32_t bytes_to_copy_this_block = (gdt_size_bytes - (i * SIMPLEFS_BLOCK_SIZE) < SIMPLEFS_BLOCK_SIZE) ?
(gdt_size_bytes % SIMPLEFS_BLOCK_SIZE == 0 && gdt_size_bytes > 0 ? SIMPLEFS_BLOCK_SIZE : gdt_size_bytes % SIMPLEFS_BLOCK_SIZE)
: SIMPLEFS_BLOCK_SIZE;
if (gdt_size_bytes == 0 && i==0) bytes_to_copy_this_block = 0;
std::memcpy(fs_block_buffer.data(), gdt_write_ptr + (i * SIMPLEFS_BLOCK_SIZE), bytes_to_copy_this_block);
if (write_block(fd, grp_start + 1 + i, fs_block_buffer.data()) != 0) { /* error */ return 1; }
}
}
std::cout << "Creating root directory..." << std::endl;
SimpleFS_GroupDesc& group0_gd = gdt[0];
// 根inodeSIMPLEFS_ROOT_INODE_NUM通常为2和inode 1位0
// 已在inode位图中标记以及超级块/组描述符
// 在组0的初始设置循环中已减少了空闲inode计数
// 因此此处不需要再次调用set_bitmap_bit或减少计数
// 只需为组0增加used_dirs_count
group0_gd.bg_used_dirs_count++;
std::cout << " Root inode " << SIMPLEFS_ROOT_INODE_NUM << " allocation accounted for (marked in bitmap and counts updated earlier)." << std::endl;
std::cout << " Incremented used_dirs_count for group 0." << std::endl;
// 如果后续决策依赖于最新状态重新读取inode位图是好习惯
// 但此处不对根inode号本身做分配决策只分配其数据块故继续进行
// 如有疑问,可重新读取:
// if (read_block(fd, group0_gd.bg_inode_bitmap, group_inode_bitmap_buffer.data()) != 0) {
// std::cerr << "根目录数据分配前重新读取组0 inode位图失败" << std::endl; return 1;
// }
uint32_t root_dir_data_block_num = 0;
if (read_block(fd, group0_gd.bg_block_bitmap, group_block_bitmap_buffer.data()) != 0) {
std::cerr << "组0块位图读取失败无法分配根目录数据块" << std::endl; return 1;
}
uint32_t group0_abs_start_block = 0 * sb.s_blocks_per_group;
uint32_t search_start_offset_in_group0 = 0;
if (sb.s_first_data_block >= group0_abs_start_block && sb.s_first_data_block < (group0_abs_start_block + sb.s_blocks_per_group) ) {
search_start_offset_in_group0 = sb.s_first_data_block - group0_abs_start_block;
} else if (sb.s_first_data_block < group0_abs_start_block) {
search_start_offset_in_group0 = (gdt[0].bg_inode_table + static_cast<uint32_t>(std::ceil(static_cast<double>(sb.s_inodes_per_group) * SIMPLEFS_INODE_SIZE / SIMPLEFS_BLOCK_SIZE))) - group0_abs_start_block;
}
for (uint32_t block_offset_in_group = search_start_offset_in_group0;
block_offset_in_group < sb.s_blocks_per_group; ++block_offset_in_group) {
if (!is_bitmap_bit_set(group_block_bitmap_buffer, block_offset_in_group)) {
root_dir_data_block_num = group0_abs_start_block + block_offset_in_group;
set_bitmap_bit(group_block_bitmap_buffer, block_offset_in_group);
group0_gd.bg_free_blocks_count--;
sb.s_free_blocks_count--;
break;
}
}
if (root_dir_data_block_num == 0) {
std::cerr << "错误: 组0中找不到根目录的空闲数据块" << std::endl; return 1;
}
if (write_block(fd, group0_gd.bg_block_bitmap, group_block_bitmap_buffer.data()) != 0) {
std::cerr << "组0块位图更新失败" << std::endl; return 1;
}
std::cout << " 已为根目录分配数据块 " << root_dir_data_block_num << std::endl;
std::vector<uint8_t> root_dir_data_buffer(SIMPLEFS_BLOCK_SIZE, 0);
uint16_t current_offset = 0;
SimpleFS_DirEntry dot_entry;
dot_entry.inode = SIMPLEFS_ROOT_INODE_NUM;
dot_entry.name_len = 1;
dot_entry.file_type = S_IFDIR >> 12;
std::strncpy(dot_entry.name, ".", 1);
dot_entry.rec_len = calculate_dir_entry_len(dot_entry.name_len);
std::memcpy(root_dir_data_buffer.data() + current_offset, &dot_entry, (size_t)8 + dot_entry.name_len);
current_offset += dot_entry.rec_len;
SimpleFS_DirEntry dotdot_entry;
dotdot_entry.inode = SIMPLEFS_ROOT_INODE_NUM;
dotdot_entry.name_len = 2;
dotdot_entry.file_type = S_IFDIR >> 12;
std::strncpy(dotdot_entry.name, "..", 2);
dotdot_entry.rec_len = SIMPLEFS_BLOCK_SIZE - current_offset;
std::memcpy(root_dir_data_buffer.data() + current_offset, &dotdot_entry, (size_t)8 + dotdot_entry.name_len);
if (write_block(fd, root_dir_data_block_num, root_dir_data_buffer.data()) != 0) {
std::cerr << "根目录数据块写入失败" << std::endl; return 1;
}
std::cout << " 已向根目录数据块写入'.'和'..'项" << std::endl;
SimpleFS_Inode root_inode;
std::memset(&root_inode, 0, sizeof(SimpleFS_Inode));
root_inode.i_mode = S_IFDIR | 0777; // 从0755改为0777便于测试
root_inode.i_uid = 0;
root_inode.i_gid = 0;
root_inode.i_size = SIMPLEFS_BLOCK_SIZE;
root_inode.i_links_count = 2;
root_inode.i_blocks = SIMPLEFS_BLOCK_SIZE / 512;
root_inode.i_atime = root_inode.i_ctime = root_inode.i_mtime = time(nullptr);
root_inode.i_block[0] = root_dir_data_block_num;
// 基于1的inode编号的修正计算
uint32_t root_inode_idx_in_group = SIMPLEFS_ROOT_INODE_NUM - 1;
uint32_t root_inode_block_in_table = group0_gd.bg_inode_table + (root_inode_idx_in_group / inodes_per_block);
uint32_t root_inode_offset_in_block = (root_inode_idx_in_group % inodes_per_block) * SIMPLEFS_INODE_SIZE;
std::vector<uint8_t> inode_table_block_buffer(SIMPLEFS_BLOCK_SIZE);
if (read_block(fd, root_inode_block_in_table, inode_table_block_buffer.data()) != 0) {
std::cerr << "根inode的inode表块读取失败" << std::endl; return 1;
}
std::memcpy(inode_table_block_buffer.data() + root_inode_offset_in_block, &root_inode, sizeof(SimpleFS_Inode));
if (write_block(fd, root_inode_block_in_table, inode_table_block_buffer.data()) != 0) {
std::cerr << "根inode写入inode表失败" << std::endl; return 1;
}
std::cout << " Initialized and written root inode (inode " << SIMPLEFS_ROOT_INODE_NUM << ")." << std::endl;
std::cout << "Finalizing Superblock and GDT..." << std::endl;
std::memcpy(fs_block_buffer.data(), &sb, sizeof(sb));
if (write_block(fd, superblock_location_block, fs_block_buffer.data()) != 0) { /* error */ return 1;}
gdt_write_ptr = reinterpret_cast<uint8_t*>(gdt.data());
for (uint32_t i = 0; i < gdt_blocks; ++i) {
std::fill(fs_block_buffer.begin(), fs_block_buffer.end(), 0);
uint32_t bytes_to_copy_this_block = (gdt_size_bytes - (i * SIMPLEFS_BLOCK_SIZE) < SIMPLEFS_BLOCK_SIZE) ?
(gdt_size_bytes % SIMPLEFS_BLOCK_SIZE == 0 && gdt_size_bytes > 0 ? SIMPLEFS_BLOCK_SIZE : gdt_size_bytes % SIMPLEFS_BLOCK_SIZE)
: SIMPLEFS_BLOCK_SIZE;
if (gdt_size_bytes == 0 && i==0) bytes_to_copy_this_block = 0;
std::memcpy(fs_block_buffer.data(), gdt_write_ptr + (i * SIMPLEFS_BLOCK_SIZE), bytes_to_copy_this_block);
if (write_block(fd, gdt_start_block + i, fs_block_buffer.data()) != 0) { /* error */ return 1; }
}
std::cout << "超级块和GDT已完成" << std::endl;
std::cout << "文件系统格式化成功" << std::endl;
if (close(fd) == -1) {
perror("关闭设备/镜像失败");
}
std::cout << "SimpleFS格式化工具完成" << std::endl;
return 0;
}