fix bug when unlink a file but ref cnt is not decresed
This commit is contained in:
@@ -22,7 +22,7 @@ test_module() {
|
||||
if [ ! $? -eq 0 ]; then
|
||||
exit
|
||||
fi
|
||||
g++ $path obj/*.o -I. -Iinclude -DDEBUG -o 'bin/test_'$1'.out'
|
||||
g++ $path obj/*.o -I. -Iinclude -DDEBUG -g -o 'bin/test_'$1'.out'
|
||||
set +x
|
||||
|
||||
echo -e "Run test case.\n=======\n"
|
||||
|
||||
@@ -259,11 +259,11 @@ void EXT2_DEntry::unlink() {
|
||||
// if (type==VFS::Directory)
|
||||
// ext2_inode->i->size = 1024;
|
||||
ext2_inode->i->links_count = 0;
|
||||
ext2_inode->write_inode();
|
||||
ext2_fs->release_inode(inode_n);
|
||||
ext2_fs->write_gdt();
|
||||
ext2_fs->write_super();
|
||||
}
|
||||
ext2_inode->write_inode();
|
||||
_dbg_log("ulink %d ref cnt: %d type: %d. finish", inode_n, ext2_inode->i->links_count, type);
|
||||
}
|
||||
|
||||
|
||||
+23
-16
@@ -109,25 +109,32 @@ _u32 EXT2_File::write(_u8 *buf, _u32 len) {
|
||||
}
|
||||
|
||||
void EXT2_File::resize(_u32 new_size) {
|
||||
if (size == new_size)
|
||||
EXT2_FS *fs = ext2_fs;
|
||||
_u32 current_block = ext2_inode->blocks;
|
||||
_u32 target_block = new_size / fs->block_size + (new_size % fs->block_size > 0);
|
||||
_dbg_log("resize from %d to %d", current_block, target_block);
|
||||
if (target_block == current_block) {
|
||||
return;
|
||||
if (ext2_inode->i->blocks >= 13)
|
||||
_error_s(ext2_inode->i->blocks, "not support big file yet");
|
||||
_u32 current_blocks = ext2_inode->i->blocks;
|
||||
_u32 target_blocks = new_size / ext2_fs->block_size + ((new_size % ext2_fs->block_size) > 0);
|
||||
if (new_size < size) {
|
||||
while (target_blocks < current_blocks) {
|
||||
current_blocks--;
|
||||
if (ext2_inode->i->block[current_blocks] == 0)
|
||||
continue;
|
||||
ext2_fs->release_block(ext2_inode->i->block[current_blocks]); // 循环释放当前块
|
||||
ext2_inode->i->block[current_blocks] = 0;
|
||||
}
|
||||
auto it = ext2_inode->end();
|
||||
if (target_block > current_block) {
|
||||
// 分配空间
|
||||
while (target_block != current_block) {
|
||||
*it; // 利用解引用自动分配空间
|
||||
it++;
|
||||
current_block++;
|
||||
}
|
||||
} else {
|
||||
while (target_blocks > current_blocks) {
|
||||
ext2_inode->i->block[current_blocks - 1] = ext2_fs->alloc_block();
|
||||
current_blocks++;
|
||||
// 缩小空间
|
||||
while (target_block != current_block) {
|
||||
it--;
|
||||
_u32 to_release = *it;
|
||||
fs->release_block(to_release);
|
||||
current_block--;
|
||||
}
|
||||
}
|
||||
ext2_inode->i->blocks = current_blocks;
|
||||
size = new_size;
|
||||
ext2_inode->blocks = target_block;
|
||||
ext2_fs->write_gdt();
|
||||
ext2_fs->write_super();
|
||||
}
|
||||
+46
-12
@@ -45,12 +45,13 @@ EXT2_Inode::EXT2_Inode(EXT2_FS *fs, _u32 n, EXT2::Inode *i): VFS::Inode(fs) {
|
||||
ctime = i->ctime;
|
||||
blkbits = 0;
|
||||
version = i->generation;
|
||||
blocks = i->blocks;
|
||||
bytes = 0;
|
||||
sock = 1;
|
||||
inode_n = n;
|
||||
ext2_fs = fs;
|
||||
blocks = i->blocks / (ext2_fs->block_size / 512);
|
||||
bytes = size % blocks;
|
||||
for (int t = blocks; t < N_BLOCKS; t++)
|
||||
i->block[t] = 0;
|
||||
}
|
||||
|
||||
_u32 EXT2_Inode::byte_in_block(_u32 b) {
|
||||
@@ -97,6 +98,7 @@ void EXT2_Inode::write_inode() {
|
||||
_dbg_log("inode %d, size %d", inode_n, i->size);
|
||||
_u32 inode_pos = ext2_fs->inode_to_pos(inode_n);
|
||||
MM::Buf buf(sizeof(EXT2::Inode));
|
||||
i->blocks = blocks * (ext2_fs->block_size / 512);
|
||||
memcpy(buf.data, i, sizeof(EXT2::Inode));
|
||||
// _sa(buf.data, sizeof(EXT2::Inode));
|
||||
ext2_fs->dev->write(buf, inode_pos, sizeof(EXT2::Inode));
|
||||
@@ -147,6 +149,7 @@ EXT2_Inode::iterator::iterator(EXT2_Inode* i) {
|
||||
|
||||
EXT2_Inode::iterator EXT2_Inode::iterator::getInstance(EXT2_Inode *i, _u32 blocks) {
|
||||
EXT2_Inode::iterator it(i);
|
||||
_dbg_log("get instance %d", blocks);
|
||||
it.index_cnt = blocks; // 最大值
|
||||
if (blocks == 0) {
|
||||
it.level = 0;
|
||||
@@ -178,6 +181,7 @@ EXT2_Inode::iterator EXT2_Inode::iterator::getInstance(EXT2_Inode *i, _u32 block
|
||||
}
|
||||
|
||||
EXT2_Inode::iterator::~iterator() {
|
||||
write_back();
|
||||
delete block_buf[1];
|
||||
delete block_buf[2];
|
||||
delete block_buf[3];
|
||||
@@ -187,18 +191,47 @@ void EXT2_Inode::iterator::load_buf(int t) {
|
||||
_dbg_log("load buf level:%d indexs[%d,%d,%d,%d]", level, indexs[0], indexs[1], indexs[2], indexs[3]);
|
||||
EXT2_FS *fs = inode->ext2_fs;
|
||||
while (t < level) {
|
||||
write_back(); // 在换页之前尝试将修改写入磁盘
|
||||
_u32 new_block_pos = block_buf[t][indexs[t]];
|
||||
MM::Buf buf(fs->block_size);
|
||||
// TODO: Dirty save
|
||||
block_pos[t + 1] = new_block_pos;
|
||||
fs->dev->read(buf, fs->block_to_pos(new_block_pos), fs->block_size);
|
||||
if (block_buf[t + 1] == nullptr)
|
||||
block_buf[t + 1] = new _u32[sub_blocks_in_block[level]];
|
||||
memcpy(block_buf[t + 1], buf.data, sub_blocks_in_block[t]);
|
||||
if (new_block_pos == 0) {
|
||||
_dbg_log("auto alloc data block");
|
||||
// 如果没有下一个数据块,则分配一个
|
||||
new_block_pos = fs->alloc_block();
|
||||
block_buf[t][indexs[t]] = new_block_pos;
|
||||
dirty[t] = true;
|
||||
block_pos[t + 1] = new_block_pos;
|
||||
memset(block_buf[t + 1], 0, sizeof(block_buf[t + 1])); // 新块数据清零
|
||||
} else {
|
||||
MM::Buf buf(fs->block_size);
|
||||
fs->dev->read(buf, fs->block_to_pos(new_block_pos), fs->block_size);
|
||||
memcpy(block_buf[t + 1], buf.data, sizeof(block_buf[t + 1]));
|
||||
}
|
||||
t++;
|
||||
}
|
||||
}
|
||||
|
||||
void EXT2_Inode::iterator::write_back() {
|
||||
if (dirty[0]) {
|
||||
memcpy(inode->i->block, block_buf[0], sizeof(_u32) * EXT2::N_BLOCKS);
|
||||
dirty[0] = false;
|
||||
}
|
||||
EXT2_FS *fs = inode->ext2_fs;
|
||||
MM::Buf *buf=nullptr;
|
||||
for (int t = 1; t < 4; t++) {
|
||||
if (dirty[t]) {
|
||||
if (buf == nullptr)
|
||||
buf = new MM::Buf(fs->block_size);
|
||||
_u32 pos = fs->block_to_pos(block_pos[t]);
|
||||
memmove(buf->data, block_buf[t], sizeof(block_buf[t]));
|
||||
fs->dev->write(*buf, pos, fs->block_size);
|
||||
dirty[t] = false;
|
||||
}
|
||||
}
|
||||
delete buf;
|
||||
}
|
||||
|
||||
|
||||
const EXT2_Inode::iterator& EXT2_Inode::iterator::operator++(int) {
|
||||
return ++(*this);
|
||||
@@ -269,11 +302,12 @@ int EXT2_Inode::iterator::operator*() {
|
||||
if (block_buf[level] == nullptr)
|
||||
load_buf(0);
|
||||
int ans = block_buf[level][indexs[level]];
|
||||
if (ans == 0) {
|
||||
_dbg_log("auto alloc data block");
|
||||
ans = inode->ext2_fs->alloc_block();
|
||||
block_buf[level][indexs[level]] = ans;
|
||||
dirty[level] = true;
|
||||
}
|
||||
_si(ans);
|
||||
return ans;
|
||||
// _pos();
|
||||
// fflush(stdout);
|
||||
// int ans = inode->nth_block(index);
|
||||
// std::cout <<ans << std::endl;
|
||||
return ans;
|
||||
}
|
||||
@@ -29,11 +29,17 @@ namespace EXT2
|
||||
// 每个间接索引块含的间接索引数
|
||||
// [12, 256, 256, 256]
|
||||
_u32 sub_blocks_in_block[4];
|
||||
// 脏缓存
|
||||
bool dirty[4] = {false, false, false, false};
|
||||
|
||||
|
||||
EXT2_Inode* inode;
|
||||
|
||||
// 从磁盘加载块缓存
|
||||
// from可取0, 1, 2,表示加载从第几级间址开始加载
|
||||
void load_buf(int from=0);
|
||||
|
||||
void write_back(); // 写回磁盘
|
||||
iterator(EXT2_Inode* i);
|
||||
|
||||
public:
|
||||
@@ -54,7 +60,6 @@ namespace EXT2
|
||||
friend class EXT2_Inode;
|
||||
};
|
||||
private:
|
||||
_u32 blocks;
|
||||
public:
|
||||
_u32 inode_n;
|
||||
EXT2::Inode* i;
|
||||
|
||||
+5
-9
@@ -42,15 +42,7 @@ VFS::NameI *parse_path(const std::string path) {
|
||||
continue;
|
||||
if (x == ".")
|
||||
continue;
|
||||
if (x == "..") {
|
||||
if (prev->prev == nullptr) {
|
||||
goto error;
|
||||
}
|
||||
prev = prev->prev;
|
||||
prev->next->prev = nullptr;
|
||||
prev->next->next = nullptr;
|
||||
delete prev->next;
|
||||
} else if (ans == nullptr) {
|
||||
if (ans == nullptr) {
|
||||
ans = new NameI(x);
|
||||
prev = ans;
|
||||
} else {
|
||||
@@ -115,6 +107,10 @@ VFS::DEntry *ls(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
|
||||
|
||||
VFS::DEntry *cd(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
|
||||
using namespace std;
|
||||
if (cmdd[cmdd.size() - 1] == ".")
|
||||
return cwd;
|
||||
if (cmdd[cmdd.size() - 1] == "..")
|
||||
return cwd->parent;
|
||||
VFS::NameI *target = parse_path(cmdd[cmdd.size() - 1]);
|
||||
auto ans = cwd->get_child(target);
|
||||
if (ans == nullptr) {
|
||||
|
||||
+7
-1
@@ -43,7 +43,13 @@ DEntry *DEntry::get_path(const NameI *namei, std::string* fname) {
|
||||
}
|
||||
|
||||
while (namei->next != nullptr && ans != nullptr) {
|
||||
ans = ans->get_child(namei->name);
|
||||
if (namei->name == ".") {
|
||||
;
|
||||
} else if (namei->name == "..") {
|
||||
ans = ans->parent;
|
||||
} else {
|
||||
ans = ans->get_child(namei->name);
|
||||
}
|
||||
namei = namei->next;
|
||||
}
|
||||
if (fname != nullptr) {
|
||||
|
||||
@@ -28,7 +28,7 @@ build: .depend $(OBJ_FILE)
|
||||
# echo $(INC_FLAG)
|
||||
|
||||
$(BIN_FILE): $(OBJ_FILE)# $(MAIN_FILE)
|
||||
g++ $(CC_FLAG) $^ -o $@
|
||||
g++ $(CC_FLAG) $^ -g -o $@
|
||||
|
||||
.depend: $(SRC_FILE)
|
||||
g++ -MM $(CC_FLAG) $^ > $@
|
||||
@@ -37,7 +37,7 @@ $(BIN_FILE): $(OBJ_FILE)# $(MAIN_FILE)
|
||||
include .depend
|
||||
|
||||
$(OBJ_PATH)/%.o:
|
||||
g++ -c $< $(CC_FLAG) -o $@
|
||||
g++ -c $< $(CC_FLAG) -g -o $@
|
||||
|
||||
# $(BIN_PATH)/%.out:
|
||||
# TEST_NAME = $(notdir $@)
|
||||
|
||||
Reference in New Issue
Block a user