Files
SimpleFS/tools/mkfs.cpp
2025-11-06 10:49:44 +08:00

578 lines
30 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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;
}