fix bug when unlink a file but ref cnt is not decresed

This commit is contained in:
w-mj
2019-06-23 13:59:18 +08:00
parent 3f32f170aa
commit 4ce4a879e2
8 changed files with 91 additions and 43 deletions
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+6 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
+2 -2
View File
@@ -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 $@)