[f2fs] Add error handling for hard link

This change corrects error handling in Link(), and
it adds the HardLinkTest support for f2fs.

Test: fx test fs-tests large-fs-tests

Prerequisite:
FUCHSIA_DIR$ patch -p1 < \
third_party/f2fs/patches/0005-f2fs-Enable-hardlink-for-f2fs-fs_test.patch

Change-Id: Ibe50da42f086e61a91cf78fef7e490f8ef8e0814
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/f2fs/+/539563
Reviewed-by: Brett Wilson <brettw@google.com>
diff --git a/namei.cc b/namei.cc
index 8d5e0dd..ea7a8a4 100644
--- a/namei.cc
+++ b/namei.cc
@@ -128,7 +128,19 @@
 zx_status_t Dir::Link(std::string_view name, fbl::RefPtr<fs::Vnode> _target) {
   VnodeF2fs *target = static_cast<VnodeF2fs *>(_target.get());
 
+  if (S_ISDIR(target->i_mode_))
+    return ZX_ERR_NOT_FILE;
+
   fbl::AutoLock lock(&i_mutex_);
+
+  Page *old_entry_page;
+  DirEntry *old_entry = FindEntry(name, &old_entry_page);
+  if (old_entry != nullptr) {
+    nid_t old_ino = LeToCpu(old_entry->ino);
+    if (old_ino == target->Ino())
+      return ZX_ERR_ALREADY_EXISTS;
+  }
+
   fbl::AutoLock tlock(&target->i_mutex_);
 
   clock_gettime(CLOCK_REALTIME, &target->i_ctime_);
@@ -215,8 +227,6 @@
 
   DeleteEntry(de, page, vnode);
 
-  vnode->ClearNlink();
-
   /* In order to evict this inode,  we set it dirty */
   MarkInodeDirty(vnode);
   Vfs()->Segmgr().BalanceFs();
diff --git a/patches/0005-f2fs-Enable-hardlink-for-f2fs-fs_test.patch b/patches/0005-f2fs-Enable-hardlink-for-f2fs-fs_test.patch
new file mode 100644
index 0000000..6599f7a
--- /dev/null
+++ b/patches/0005-f2fs-Enable-hardlink-for-f2fs-fs_test.patch
@@ -0,0 +1,26 @@
+From 410069e00090710757277fc35f19bce7182f5c93 Mon Sep 17 00:00:00 2001
+From: Dongjin Kim <dongjin_.kim@samsung.com>
+Date: Mon, 7 Jun 2021 18:45:07 +0900
+Subject: [PATCH] [f2fs] Enable hardlink for f2fs fs_test
+
+Change-Id: I209ae6dff8b4035afe825402ddbc43bde7269a59
+---
+ src/storage/fs_test/fs_test.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/storage/fs_test/fs_test.h b/src/storage/fs_test/fs_test.h
+index 76ffc4e67c4..44ab4df7cb7 100644
+--- a/src/storage/fs_test/fs_test.h
++++ b/src/storage/fs_test/fs_test.h
+@@ -220,7 +220,7 @@ class F2fsFilesystem : public FilesystemImplWithDefaultMake<F2fsFilesystem> {
+         .name = "f2fs",
+         .can_unmount = true,
+         .timestamp_granularity = zx::nsec(1),
+-        .supports_hard_links = false,
++        .supports_hard_links = true,
+         .supports_mmap = false,
+         .supports_resize = false,
+         // TODO(unknown): Get value from f2fs header
+-- 
+2.25.1
+