[f2fs] Fixed a bug where the vnode ref_count was not maintained properly during file creation.
Change-Id: Id5f948c1f1f2d490c71dd44744b829059440ddde
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/692643
Commit-Queue: Aaron Drew <ripper@google.com>
Reviewed-by: Aaron Drew <ripper@google.com>
diff --git a/src/storage/f2fs/namei.cc b/src/storage/f2fs/namei.cc
index 9328ed7..3e75331 100644
--- a/src/storage/f2fs/namei.cc
+++ b/src/storage/f2fs/namei.cc
@@ -113,6 +113,7 @@
if (zx_status_t err = AddLink(name, vnode); err != ZX_OK) {
vnode->ClearNlink();
vnode->UnlockNewInode();
+ Vfs()->GetVCache().RemoveDirty(vnode);
Vfs()->GetNodeManager().AllocNidFailed(vnode->Ino());
return err;
}
@@ -290,6 +291,7 @@
vnode->ClearFlag(InodeInfoFlag::kIncLink);
vnode->ClearNlink();
vnode->UnlockNewInode();
+ Vfs()->GetVCache().RemoveDirty(vnode);
Vfs()->GetNodeManager().AllocNidFailed(vnode->Ino());
return err;
}
diff --git a/src/storage/f2fs/test/unit/file.cc b/src/storage/f2fs/test/unit/file.cc
index 1aaa029..ac0854c 100644
--- a/src/storage/f2fs/test/unit/file.cc
+++ b/src/storage/f2fs/test/unit/file.cc
@@ -200,6 +200,44 @@
test_file_vn = nullptr;
}
+TEST(FileTest2, FailedNidReuse) {
+ std::unique_ptr<Bcache> bc;
+ constexpr uint64_t kBlockCount = 409600;
+ FileTester::MkfsOnFakeDevWithOptions(&bc, MkfsOptions(), kBlockCount);
+
+ std::unique_ptr<F2fs> fs;
+ async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
+ FileTester::MountWithOptions(loop.dispatcher(), MountOptions{}, &bc, &fs);
+
+ fbl::RefPtr<VnodeF2fs> root;
+ FileTester::CreateRoot(fs.get(), &root);
+ fbl::RefPtr<Dir> root_dir = fbl::RefPtr<Dir>::Downcast(std::move(root));
+
+ fbl::RefPtr<fs::Vnode> tmp_child;
+ uint32_t iter = 0;
+ while (true) {
+ if (auto err = root_dir->Create(std::to_string(++iter), S_IFREG, &tmp_child); err != ZX_OK) {
+ ASSERT_EQ(err, ZX_ERR_NO_SPACE);
+ break;
+ }
+ ASSERT_EQ(tmp_child->Close(), ZX_OK);
+ tmp_child = nullptr;
+ }
+
+ const uint32_t kIteration = fs->GetNodeManager().GetFreeNidCount() + 1;
+ for (uint32_t i = 0; i < kIteration; ++i) {
+ ASSERT_EQ(root_dir->Create(std::to_string(++iter), S_IFREG, &tmp_child), ZX_ERR_NO_SPACE);
+ }
+
+ for (uint32_t i = 0; i < kIteration; ++i) {
+ ASSERT_EQ(root_dir->Create(std::to_string(++iter), S_IFDIR, &tmp_child), ZX_ERR_NO_SPACE);
+ }
+
+ root_dir->Close();
+ root_dir = nullptr;
+ FileTester::Unmount(std::move(fs), &bc);
+}
+
TEST(DeadLockTest, Truncate) {
std::unique_ptr<Bcache> bc;
FileTester::MkfsOnFakeDev(&bc);