// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/storage/minfs/directory.h"

#include <fcntl.h>
#include <lib/syslog/cpp/macros.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <zircon/device/vfs.h>
#include <zircon/time.h>

#include <memory>
#include <utility>

#include <fbl/algorithm.h>
#include <fbl/auto_call.h>
#include <fbl/string_piece.h>
#include <fs/debug.h>
#include <fs/vfs_types.h>

#ifdef __Fuchsia__
#include <lib/fidl-utils/bind.h>
#include <zircon/syscalls.h>

#include <utility>

#include <fbl/auto_lock.h>
#endif

#include "src/storage/minfs/minfs_private.h"
#include "src/storage/minfs/unowned_vmo_buffer.h"
#include "src/storage/minfs/vnode.h"

namespace minfs {
namespace {

// Possible non-error return values for DirentCallback:
//
// Immediately stop iterating over the directory.
constexpr zx_status_t kDirIteratorDone = 0;
// Access the next direntry in the directory. Offsets updated.
constexpr zx_status_t kDirIteratorNext = 1;
// Identify that the direntry record was modified. Stop iterating.
constexpr zx_status_t kDirIteratorSaveSync = 2;

zx_status_t ValidateDirent(Dirent* de, size_t bytes_read, size_t off) {
  uint32_t reclen = static_cast<uint32_t>(MinfsReclen(de, off));
  if ((bytes_read < kMinfsDirentSize) || (reclen < kMinfsDirentSize)) {
    FX_LOGS(ERROR) << "vn_dir: Could not read dirent at offset: " << off;
    return ZX_ERR_IO;
  }
  if ((off + reclen > kMinfsMaxDirectorySize) || (reclen & kMinfsDirentAlignmentMask)) {
    FX_LOGS(ERROR) << "vn_dir: bad reclen " << reclen << " > " << kMinfsMaxDirectorySize;
    return ZX_ERR_IO;
  }
  if (de->ino != 0) {
    if ((de->namelen == 0) || (de->namelen > (reclen - kMinfsDirentSize))) {
      FX_LOGS(ERROR) << "vn_dir: bad namelen " << de->namelen << " / " << reclen;
      return ZX_ERR_IO;
    }
  }
  return ZX_OK;
}

// Updates offset information to move to the next direntry in the directory.
zx_status_t NextDirent(Dirent* de, DirectoryOffset* offs) {
  offs->off_prev = offs->off;
  offs->off += MinfsReclen(de, offs->off);
  return kDirIteratorNext;
}

}  // namespace

Directory::Directory(Minfs* fs) : VnodeMinfs(fs) {}

Directory::~Directory() = default;

blk_t Directory::GetBlockCount() const { return GetInode()->block_count; }

uint64_t Directory::GetSize() const { return GetInode()->size; }

void Directory::SetSize(uint32_t new_size) { GetMutableInode()->size = new_size; }

void Directory::AcquireWritableBlock(Transaction* transaction, blk_t local_bno, blk_t old_bno,
                                     blk_t* out_bno) {
  bool using_new_block = (old_bno == 0);
  if (using_new_block) {
    Vfs()->BlockNew(transaction, out_bno);
    GetMutableInode()->block_count++;
  }
}

void Directory::DeleteBlock(PendingWork* transaction, blk_t local_bno, blk_t old_bno,
                            bool indirect) {
  // If we found a block that was previously allocated, delete it.
  if (old_bno != 0) {
    transaction->DeallocateBlock(old_bno);
    GetMutableInode()->block_count--;
  }
}

#ifdef __Fuchsia__
void Directory::IssueWriteback(Transaction* transaction, blk_t vmo_offset, blk_t dev_offset,
                               blk_t count) {
  storage::Operation operation = {
      .type = storage::OperationType::kWrite,
      .vmo_offset = vmo_offset,
      .dev_offset = dev_offset,
      .length = count,
  };
  UnownedVmoBuffer buffer(vmo());
  transaction->EnqueueMetadata(operation, &buffer);
}

bool Directory::HasPendingAllocation(blk_t vmo_offset) { return false; }

void Directory::CancelPendingWriteback() {}

#endif

zx_status_t Directory::DirentCallbackFind(fbl::RefPtr<Directory> vndir, Dirent* de, DirArgs* args) {
  if ((de->ino != 0) && fbl::StringPiece(de->name, de->namelen) == args->name) {
    args->ino = de->ino;
    args->type = de->type;
    return kDirIteratorDone;
  }
  return NextDirent(de, &args->offs);
}

zx_status_t Directory::CanUnlink() const {
  // directories must be empty (dirent_count == 2)
  if (GetInode()->dirent_count != 2) {
    // if we have more than "." and "..", not empty, cannot unlink
    return ZX_ERR_NOT_EMPTY;
#ifdef __Fuchsia__
  } else if (IsRemote()) {
    // we cannot unlink mount points
    return ZX_ERR_UNAVAILABLE;
#endif
  }
  return ZX_OK;
}

zx_status_t Directory::UnlinkChild(Transaction* transaction, fbl::RefPtr<VnodeMinfs> childvn,
                                   Dirent* de, DirectoryOffset* offs) {
  // Coalesce the current dirent with the previous/next dirent, if they
  // (1) exist and (2) are free.
  size_t off_prev = offs->off_prev;
  size_t off = offs->off;
  size_t off_next = off + MinfsReclen(de, off);
  zx_status_t status;

  // Read the direntries we're considering merging with.
  // Verify they are free and small enough to merge.
  size_t coalesced_size = MinfsReclen(de, off);
  // Coalesce with "next" first, so the kMinfsReclenLast bit can easily flow
  // back to "de" and "de_prev".
  if (!(de->reclen & kMinfsReclenLast)) {
    Dirent de_next;
    size_t len = kMinfsDirentSize;
    if ((status = ReadExactInternal(transaction, &de_next, len, off_next)) != ZX_OK) {
      FX_LOGS(ERROR) << "unlink: Failed to read next dirent";
      return status;
    }
    if ((status = ValidateDirent(&de_next, len, off_next)) != ZX_OK) {
      FX_LOGS(ERROR) << "unlink: Read invalid dirent";
      return status;
    }
    if (de_next.ino == 0) {
      coalesced_size += MinfsReclen(&de_next, off_next);
      // If the next entry *was* last, then 'de' is now last.
      de->reclen |= (de_next.reclen & kMinfsReclenLast);
    }
  }
  if (off_prev != off) {
    Dirent de_prev;
    size_t len = kMinfsDirentSize;
    if ((status = ReadExactInternal(transaction, &de_prev, len, off_prev)) != ZX_OK) {
      FX_LOGS(ERROR) << "unlink: Failed to read previous dirent";
      return status;
    }
    if ((status = ValidateDirent(&de_prev, len, off_prev)) != ZX_OK) {
      FX_LOGS(ERROR) << "unlink: Read invalid dirent";
      return status;
    }
    if (de_prev.ino == 0) {
      coalesced_size += MinfsReclen(&de_prev, off_prev);
      off = off_prev;
    }
  }

  if (!(de->reclen & kMinfsReclenLast) && (coalesced_size >= kMinfsReclenMask)) {
    // Should only be possible if the on-disk record format is corrupted
    FX_LOGS(ERROR) << "unlink: Corrupted direntry with impossibly large size";
    return ZX_ERR_IO;
  }
  de->ino = 0;
  de->reclen =
      static_cast<uint32_t>(coalesced_size & kMinfsReclenMask) | (de->reclen & kMinfsReclenLast);
  // Erase dirent (replace with 'empty' dirent)
  if ((status = WriteExactInternal(transaction, de, kMinfsDirentSize, off)) != ZX_OK) {
    return status;
  }

  if (de->reclen & kMinfsReclenLast) {
    // Truncating the directory merely removed unused space; if it fails,
    // the directory contents are still valid.
    TruncateInternal(transaction, off + kMinfsDirentSize);
  }

  GetMutableInode()->dirent_count--;

  if (MinfsMagicType(childvn->GetInode()->magic) == kMinfsTypeDir) {
    // Child directory had '..' which pointed to parent directory
    GetMutableInode()->link_count--;
  }

  status = childvn->RemoveInodeLink(transaction);
  if (status != ZX_OK) {
    return status;
  }
  transaction->PinVnode(fbl::RefPtr(this));
  transaction->PinVnode(childvn);
  return kDirIteratorSaveSync;
}

// caller is expected to prevent unlink of "." or ".."
zx_status_t Directory::DirentCallbackUnlink(fbl::RefPtr<Directory> vndir, Dirent* de,
                                            DirArgs* args) {
  if ((de->ino == 0) || fbl::StringPiece(de->name, de->namelen) != args->name) {
    return NextDirent(de, &args->offs);
  }

  fbl::RefPtr<VnodeMinfs> vn;
  zx_status_t status;
  if ((status = vndir->Vfs()->VnodeGet(&vn, de->ino)) < 0) {
    return status;
  }

  // If a directory was requested, then only try unlinking a directory
  if ((args->type == kMinfsTypeDir) && !vn->IsDirectory()) {
    return ZX_ERR_NOT_DIR;
  }
  if ((status = vn->CanUnlink()) != ZX_OK) {
    return status;
  }
  return vndir->UnlinkChild(args->transaction, std::move(vn), de, &args->offs);
}

// same as unlink, but do not validate vnode
zx_status_t Directory::DirentCallbackForceUnlink(fbl::RefPtr<Directory> vndir, Dirent* de,
                                                 DirArgs* args) {
  if ((de->ino == 0) || fbl::StringPiece(de->name, de->namelen) != args->name) {
    return NextDirent(de, &args->offs);
  }

  fbl::RefPtr<VnodeMinfs> vn;
  zx_status_t status;
  if ((status = vndir->Vfs()->VnodeGet(&vn, de->ino)) < 0) {
    return status;
  }
  return vndir->UnlinkChild(args->transaction, std::move(vn), de, &args->offs);
}

// Given a (name, inode, type) combination:
//   - If no corresponding 'name' is found, ZX_ERR_NOT_FOUND is returned
//   - If the 'name' corresponds to a vnode, check that the target vnode:
//      - Does not have the same inode as the argument inode
//      - Is the same type as the argument 'type'
//      - Is unlinkable
//   - If the previous checks pass, then:
//      - Remove the old vnode (decrement link count by one)
//      - Replace the old vnode's position in the directory with the new inode
zx_status_t Directory::DirentCallbackAttemptRename(fbl::RefPtr<Directory> vndir, Dirent* de,
                                                   DirArgs* args) {
  if ((de->ino == 0) || fbl::StringPiece(de->name, de->namelen) != args->name) {
    return NextDirent(de, &args->offs);
  }

  fbl::RefPtr<VnodeMinfs> vn;
  zx_status_t status;
  if ((status = vndir->Vfs()->VnodeGet(&vn, de->ino)) < 0) {
    return status;
  }
  if (args->ino == vn->GetIno()) {
    // cannot rename node to itself
    return ZX_ERR_BAD_STATE;
  }
  if (args->type != de->type) {
    // cannot rename directory to file (or vice versa)
    return args->type == kMinfsTypeDir ? ZX_ERR_NOT_DIR : ZX_ERR_NOT_FILE;
  }
  if ((status = vn->CanUnlink()) != ZX_OK) {
    // if we cannot unlink the target, we cannot rename the target
    return status;
  }

  // If we are renaming ON TOP of a directory, then we can skip
  // updating the parent link count -- the old directory had a ".." entry to
  // the parent (link count of 1), but the new directory will ALSO have a ".."
  // entry, making the rename operation idempotent w.r.t. the parent link
  // count.

  status = vn->RemoveInodeLink(args->transaction);
  if (status != ZX_OK) {
    return status;
  }

  de->ino = args->ino;
  status =
      vndir->WriteExactInternal(args->transaction, de, DirentSize(de->namelen), args->offs.off);
  if (status != ZX_OK) {
    return status;
  }

  args->transaction->PinVnode(vn);
  args->transaction->PinVnode(vndir);
  return kDirIteratorSaveSync;
}

zx_status_t Directory::DirentCallbackUpdateInode(fbl::RefPtr<Directory> vndir, Dirent* de,
                                                 DirArgs* args) {
  if ((de->ino == 0) || fbl::StringPiece(de->name, de->namelen) != args->name) {
    return NextDirent(de, &args->offs);
  }

  de->ino = args->ino;
  zx_status_t status =
      vndir->WriteExactInternal(args->transaction, de, DirentSize(de->namelen), args->offs.off);
  if (status != ZX_OK) {
    return status;
  }
  args->transaction->PinVnode(vndir);
  return kDirIteratorSaveSync;
}

zx_status_t Directory::DirentCallbackFindSpace(fbl::RefPtr<Directory> vndir, Dirent* de,
                                               DirArgs* args) {
  uint32_t reclen = static_cast<uint32_t>(MinfsReclen(de, args->offs.off));
  if (de->ino == 0) {
    // empty entry, do we fit?
    if (args->reclen > reclen) {
      return NextDirent(de, &args->offs);
    }
    return kDirIteratorDone;
  }

  // filled entry, can we sub-divide?
  uint32_t size = static_cast<uint32_t>(DirentSize(de->namelen));
  if (size > reclen) {
    FX_LOGS(ERROR) << "bad reclen (smaller than dirent) " << reclen << " < " << size;
    return ZX_ERR_IO;
  }
  uint32_t extra = reclen - size;
  if (extra < args->reclen) {
    return NextDirent(de, &args->offs);
  }
  return kDirIteratorDone;
}

zx_status_t Directory::AppendDirent(DirArgs* args) {
  DirentBuffer dirent_buffer;
  Dirent* de = &dirent_buffer.dirent;

  size_t r;
  zx_status_t status = ReadInternal(args->transaction, de, kMinfsMaxDirentSize, args->offs.off, &r);
  if (status != ZX_OK) {
    return status;
  }

  status = ValidateDirent(de, r, args->offs.off);
  if (status != ZX_OK) {
    return status;
  }

  uint32_t reclen = static_cast<uint32_t>(MinfsReclen(de, args->offs.off));
  if (de->ino == 0) {
    // empty entry, do we fit?
    if (args->reclen > reclen) {
      return ZX_ERR_NO_SPACE;
    }
  } else {
    // filled entry, can we sub-divide?
    uint32_t size = static_cast<uint32_t>(DirentSize(de->namelen));
    if (size > reclen) {
      FX_LOGS(ERROR) << "bad reclen (smaller than dirent) " << reclen << " < " << size;
      return ZX_ERR_IO;
    }
    uint32_t extra = reclen - size;
    if (extra < args->reclen) {
      return ZX_ERR_NO_SPACE;
    }
    // shrink existing entry
    bool was_last_record = de->reclen & kMinfsReclenLast;
    de->reclen = size;
    if ((status = WriteExactInternal(args->transaction, de, DirentSize(de->namelen),
                                     args->offs.off)) != ZX_OK) {
      return status;
    }

    args->offs.off += size;
    // Overwrite dirent data to reflect the new dirent.
    de->reclen = extra | (was_last_record ? kMinfsReclenLast : 0);
  }

  de->ino = args->ino;
  de->type = static_cast<uint8_t>(args->type);
  de->namelen = static_cast<uint8_t>(args->name.length());
  memcpy(de->name, args->name.data(), de->namelen);
  if ((status = WriteExactInternal(args->transaction, de, DirentSize(de->namelen),
                                   args->offs.off)) != ZX_OK) {
    return status;
  }

  if (args->type == kMinfsTypeDir) {
    // Child directory has '..' which will point to parent directory
    GetMutableInode()->link_count++;
  }

  GetMutableInode()->dirent_count++;
  GetMutableInode()->seq_num++;
  InodeSync(args->transaction, kMxFsSyncMtime);
  args->transaction->PinVnode(fbl::RefPtr(this));
  return ZX_OK;
}

// Calls a callback 'func' on all direntries in a directory 'vn' with the
// provided arguments, reacting to the return code of the callback.
//
// When 'func' is called, it receives a few arguments:
//  'vndir': The directory on which the callback is operating
//  'de': A pointer the start of a single dirent.
//        Only DirentSize(de->namelen) bytes are guaranteed to exist in
//        memory from this starting pointer.
//  'args': Additional arguments plumbed through ForEachDirent
//  'offs': Offset info about where in the directory this direntry is located.
//          Since 'func' may create / remove surrounding dirents, it is responsible for
//          updating the offset information to access the next dirent.
zx_status_t Directory::ForEachDirent(DirArgs* args, const DirentCallback func) {
  DirentBuffer dirent_buffer;
  Dirent* de = &dirent_buffer.dirent;

  args->offs.off = 0;
  args->offs.off_prev = 0;
  while (args->offs.off + kMinfsDirentSize < kMinfsMaxDirectorySize) {
    FX_LOGS(DEBUG) << "Reading dirent at offset " << args->offs.off;
    size_t r;
    zx_status_t status =
        ReadInternal(args->transaction, de, kMinfsMaxDirentSize, args->offs.off, &r);
    if (status != ZX_OK) {
      return status;
    }
    status = ValidateDirent(de, r, args->offs.off);
    if (status != ZX_OK) {
      return status;
    }

    switch ((status = func(fbl::RefPtr<Directory>(this), de, args))) {
      case kDirIteratorNext:
        break;
      case kDirIteratorSaveSync:
        GetMutableInode()->seq_num++;
        InodeSync(args->transaction, kMxFsSyncMtime);
        args->transaction->PinVnode(fbl::RefPtr(this));
        return ZX_OK;
      case kDirIteratorDone:
        return ZX_OK;
      default:
        // All errors. The callback should not be returning any other non-error (positive) values.
        ZX_DEBUG_ASSERT(status < 0);
        return status;
    }
  }

  return ZX_ERR_NOT_FOUND;
}

fs::VnodeProtocolSet Directory::GetProtocols() const { return fs::VnodeProtocol::kDirectory; }

zx_status_t Directory::Read(void* data, size_t len, size_t off, size_t* out_actual) {
  return ZX_ERR_NOT_FILE;
}

zx_status_t Directory::Write(const void* data, size_t len, size_t offset, size_t* out_actual) {
  return ZX_ERR_NOT_FILE;
}

zx_status_t Directory::Append(const void* data, size_t len, size_t* out_end, size_t* out_actual) {
  return ZX_ERR_NOT_FILE;
}

zx_status_t Directory::Lookup(fbl::StringPiece name, fbl::RefPtr<fs::Vnode>* out) {
  TRACE_DURATION("minfs", "Directory::Lookup", "name", name);
  ZX_DEBUG_ASSERT(fs::vfs_valid_name(name));

  return LookupInternal(out, name);
}

zx_status_t Directory::LookupInternal(fbl::RefPtr<fs::Vnode>* out, fbl::StringPiece name) {
  DirArgs args;
  args.name = name;

  bool success = false;
  fs::Ticker ticker(Vfs()->StartTicker());
  auto get_metrics = fbl::MakeAutoCall(
      [&ticker, &success, this]() { Vfs()->UpdateLookupMetrics(success, ticker.End()); });

  if (zx_status_t status = ForEachDirent(&args, DirentCallbackFind); status != ZX_OK) {
    return status;
  }
  fbl::RefPtr<VnodeMinfs> vn;
  if (zx_status_t status = Vfs()->VnodeGet(&vn, args.ino); status != ZX_OK) {
    return status;
  }
  *out = std::move(vn);
  return ZX_OK;
}

struct DirCookie {
  size_t off;         // Offset into directory
  uint32_t reserved;  // Unused
  uint32_t seqno;     // inode seq no
};

static_assert(sizeof(DirCookie) <= sizeof(fs::VdirCookie),
              "MinFS DirCookie too large to fit in IO state");

zx_status_t Directory::Readdir(fs::VdirCookie* cookie, void* dirents, size_t len,
                               size_t* out_actual) {
  TRACE_DURATION("minfs", "Directory::Readdir");
  FX_LOGS(DEBUG) << "minfs_readdir() vn=" << this << "(#" << GetIno() << ") cookie=" << cookie
                 << " len=" << len;

  if (IsUnlinked()) {
    *out_actual = 0;
    return ZX_OK;
  }

  DirCookie* dc = reinterpret_cast<DirCookie*>(cookie);
  fs::DirentFiller df(dirents, len);

  size_t off = dc->off;
  size_t r;

  DirentBuffer dirent_buffer;
  Dirent* de = &dirent_buffer.dirent;

  if (off != 0 && dc->seqno != GetInode()->seq_num) {
    // The offset *might* be invalid, if we called Readdir after a directory
    // has been modified. In this case, we need to re-read the directory
    // until we get to the direntry at or after the previously identified offset.

    size_t off_recovered = 0;
    while (off_recovered < off) {
      if (off_recovered + kMinfsDirentSize >= kMinfsMaxDirectorySize) {
        FX_LOGS(ERROR) << "Readdir: Corrupt dirent; dirent reclen too large";
        goto fail;
      }
      zx_status_t status = ReadInternal(nullptr, de, kMinfsMaxDirentSize, off_recovered, &r);
      if ((status != ZX_OK) || (ValidateDirent(de, r, off_recovered) != ZX_OK)) {
        FX_LOGS(ERROR) << "Readdir: Corrupt dirent unreadable/failed validation";
        goto fail;
      }
      off_recovered += MinfsReclen(de, off_recovered);
    }
    off = off_recovered;
  }

  while (off + kMinfsDirentSize < kMinfsMaxDirectorySize) {
    zx_status_t status = ReadInternal(nullptr, de, kMinfsMaxDirentSize, off, &r);
    if (status != ZX_OK) {
      FX_LOGS(ERROR) << "Readdir: Unreadable dirent " << status;
      goto fail;
    } else if ((status = ValidateDirent(de, r, off)) != ZX_OK) {
      FX_LOGS(ERROR) << "Readdir: Corrupt dirent failed validation " << status;
      goto fail;
    }

    fbl::StringPiece name(de->name, de->namelen);

    if (de->ino && name != "..") {
      zx_status_t status;
      if ((status = df.Next(name, de->type, de->ino)) != ZX_OK) {
        // no more space
        goto done;
      }
    }

    off += MinfsReclen(de, off);
  }

done:
  // save our place in the DirCookie
  dc->off = off;
  dc->seqno = GetInode()->seq_num;
  *out_actual = df.BytesFilled();
  ZX_DEBUG_ASSERT(*out_actual <= len);  // Otherwise, we're overflowing the input buffer.
  return ZX_OK;

fail:
  dc->off = 0;
  return ZX_ERR_IO;
}

zx_status_t Directory::Create(fbl::StringPiece name, uint32_t mode, fbl::RefPtr<fs::Vnode>* out) {
  TRACE_DURATION("minfs", "Directory::Create", "name", name);

  if (!fs::vfs_valid_name(name)) {
    return ZX_ERR_INVALID_ARGS;
  }

  bool success = false;
  fs::Ticker ticker(Vfs()->StartTicker());
  auto get_metrics = fbl::MakeAutoCall(
      [&ticker, &success, this]() { Vfs()->UpdateCreateMetrics(success, ticker.End()); });

  if (IsUnlinked()) {
    return ZX_ERR_BAD_STATE;
  }

  DirArgs args;
  args.name = name;

  // Ensure file does not exist.
  zx_status_t status;
  if ((status = ForEachDirent(&args, DirentCallbackFind)) != ZX_ERR_NOT_FOUND) {
    return ZX_ERR_ALREADY_EXISTS;
  }

  // Creating a directory?
  uint32_t type = S_ISDIR(mode) ? kMinfsTypeDir : kMinfsTypeFile;

  // Ensure that we have enough space to write the new vnode's direntry
  // before updating any other metadata.
  args.type = type;
  args.reclen = static_cast<uint32_t>(DirentSize(static_cast<uint8_t>(name.length())));
  status = ForEachDirent(&args, DirentCallbackFindSpace);
  if (status == ZX_ERR_NOT_FOUND) {
    return ZX_ERR_NO_SPACE;
  }
  if (status != ZX_OK) {
    return status;
  }

  // Calculate maximum blocks to reserve for the current directory, based on the size and offset
  // of the new direntry (Assuming that the offset is the current size of the directory).
  auto reserve_blocks_or = GetRequiredBlockCount(GetSize(), args.reclen, Vfs()->BlockSize());
  if (reserve_blocks_or.is_error()) {
    return reserve_blocks_or.error_value();
  }

  // Reserve 1 additional block for the new directory's initial . and .. entries.
  blk_t reserve_blocks = reserve_blocks_or.value() + 1;

  ZX_DEBUG_ASSERT(reserve_blocks <= Vfs()->Limits().GetMaximumMetaDataBlocks());

  // In addition to reserve_blocks, reserve 1 inode for the vnode to be created.
  std::unique_ptr<Transaction> transaction;
  if ((status = Vfs()->BeginTransaction(1, reserve_blocks, &transaction)) != ZX_OK) {
    return status;
  }

  // mint a new inode and vnode for it
  fbl::RefPtr<VnodeMinfs> vn;
  if ((status = Vfs()->VnodeNew(transaction.get(), &vn, type)) < 0) {
    return status;
  }

  // If the new node is a directory, fill it with '.' and '..'.
  if (type == kMinfsTypeDir) {
    char bdata[DirentSize(1) + DirentSize(2)];
    InitializeDirectory(bdata, vn->GetIno(), GetIno());
    size_t expected = DirentSize(1) + DirentSize(2);
    if ((status = vn->WriteExactInternal(transaction.get(), bdata, expected, 0)) != ZX_OK) {
      FX_LOGS(ERROR) << "Create: Failed to initialize empty directory: " << status;
      return ZX_ERR_IO;
    }
    vn->InodeSync(transaction.get(), kMxFsSyncDefault);
  }

  // add directory entry for the new child node
  args.ino = vn->GetIno();
  args.transaction = transaction.get();
  if ((status = AppendDirent(&args)) != ZX_OK) {
    return status;
  }

  transaction->PinVnode(fbl::RefPtr(this));
  transaction->PinVnode(vn);
  Vfs()->CommitTransaction(std::move(transaction));

  if ((status = vn->OpenValidating(fs::VnodeConnectionOptions(), nullptr)) != ZX_OK) {
    return status;
  }
  *out = std::move(vn);
  success = true;
  return ZX_OK;
}

zx_status_t Directory::Unlink(fbl::StringPiece name, bool must_be_dir) {
  TRACE_DURATION("minfs", "Directory::Unlink", "name", name);
  ZX_DEBUG_ASSERT(fs::vfs_valid_name(name));
  bool success = false;
  fs::Ticker ticker(Vfs()->StartTicker());
  auto get_metrics = fbl::MakeAutoCall(
      [&ticker, &success, this]() { Vfs()->UpdateUnlinkMetrics(success, ticker.End()); });

  zx_status_t status;
  std::unique_ptr<Transaction> transaction;
  if ((status = Vfs()->BeginTransaction(0, 0, &transaction)) != ZX_OK) {
    return status;
  }

  DirArgs args;
  args.name = name;
  args.type = must_be_dir ? kMinfsTypeDir : 0;
  args.transaction = transaction.get();

  status = ForEachDirent(&args, DirentCallbackUnlink);
  if (status != ZX_OK) {
    return status;
  }
  transaction->PinVnode(fbl::RefPtr(this));
  Vfs()->CommitTransaction(std::move(transaction));
  success = true;
  return ZX_OK;
}

zx_status_t Directory::Truncate(size_t len) { return ZX_ERR_NOT_FILE; }

// Verify that the 'newdir' inode is not a subdirectory of the source.
zx_status_t Directory::CheckNotSubdirectory(fbl::RefPtr<Directory> newdir) {
  fbl::RefPtr<Directory> vn = std::move(newdir);
  zx_status_t status = ZX_OK;
  while (vn->GetIno() != kMinfsRootIno) {
    if (vn->GetIno() == GetIno()) {
      status = ZX_ERR_INVALID_ARGS;
      break;
    }

    fbl::RefPtr<fs::Vnode> out = nullptr;
    if ((status = vn->LookupInternal(&out, "..")) < 0) {
      break;
    }
    vn = fbl::RefPtr<Directory>::Downcast(out);
  }
  return status;
}

zx_status_t Directory::Rename(fbl::RefPtr<fs::Vnode> _newdir, fbl::StringPiece oldname,
                              fbl::StringPiece newname, bool src_must_be_dir,
                              bool dst_must_be_dir) {
  TRACE_DURATION("minfs", "Directory::Rename", "src", oldname, "dst", newname);
  bool success = false;
  fs::Ticker ticker(Vfs()->StartTicker());
  auto get_metrics = fbl::MakeAutoCall(
      [&ticker, &success, this]() { Vfs()->UpdateRenameMetrics(success, ticker.End()); });

  ZX_DEBUG_ASSERT(fs::vfs_valid_name(oldname));
  ZX_DEBUG_ASSERT(fs::vfs_valid_name(newname));

  auto newdir_minfs = fbl::RefPtr<VnodeMinfs>::Downcast(_newdir);

  // Ensure that the vnodes containing oldname and newname are directories.
  if (!(newdir_minfs->IsDirectory())) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  if (newdir_minfs->IsUnlinked()) {
    return ZX_ERR_NOT_FOUND;
  }
  auto newdir = fbl::RefPtr<Directory>::Downcast(newdir_minfs);

  zx_status_t status;
  fbl::RefPtr<VnodeMinfs> oldvn = nullptr;

  // Acquire the 'oldname' node (it must exist).
  DirArgs args;
  args.name = oldname;
  if ((status = ForEachDirent(&args, DirentCallbackFind)) < 0) {
    return status;
  }
  if ((status = Vfs()->VnodeGet(&oldvn, args.ino)) < 0) {
    return status;
  }
  if (oldvn->IsDirectory()) {
    auto olddir = fbl::RefPtr<Directory>::Downcast(oldvn);
    if ((status = olddir->CheckNotSubdirectory(newdir)) < 0) {
      return status;
    }
  }

  // If either the 'src' or 'dst' must be directories, BOTH of them must be directories.
  if (!oldvn->IsDirectory() && (src_must_be_dir || dst_must_be_dir)) {
    return ZX_ERR_NOT_DIR;
  }
  if ((newdir->GetIno() == GetIno()) && (oldname == newname)) {
    // Renaming a file or directory to itself?
    // Shortcut success case.
    success = true;
    return ZX_OK;
  }

  // Ensure that we have enough space to write the vnode's new direntry
  // before updating any other metadata.
  args.type = oldvn->IsDirectory() ? kMinfsTypeDir : kMinfsTypeFile;
  args.reclen = static_cast<uint32_t>(DirentSize(static_cast<uint8_t>(newname.length())));

  status = newdir->ForEachDirent(&args, DirentCallbackFindSpace);
  if (status == ZX_ERR_NOT_FOUND) {
    return ZX_ERR_NO_SPACE;
  }
  if (status != ZX_OK) {
    return status;
  }

  DirectoryOffset append_offs = args.offs;

  // Reserve potential blocks to add a new direntry to newdir.
  auto reserved_blocks_or =
      GetRequiredBlockCount(newdir->GetInode()->size, args.reclen, Vfs()->BlockSize());
  if (reserved_blocks_or.is_error()) {
    return reserved_blocks_or.error_value();
  }

  std::unique_ptr<Transaction> transaction;
  if ((status = Vfs()->BeginTransaction(0, reserved_blocks_or.value(), &transaction)) != ZX_OK) {
    return status;
  }

  // If the entry for 'newname' exists, make sure it can be replaced by
  // the vnode behind 'oldname'.
  args.transaction = transaction.get();
  args.name = newname;
  args.ino = oldvn->GetIno();
  status = newdir->ForEachDirent(&args, DirentCallbackAttemptRename);
  if (status == ZX_ERR_NOT_FOUND) {
    // If 'newname' does not exist, create it.
    args.offs = append_offs;
    if ((status = newdir->AppendDirent(&args)) != ZX_OK) {
      return status;
    }
  } else if (status != ZX_OK) {
    return status;
  }

  // Update the oldvn's entry for '..' if (1) it was a directory, and (2) it moved to a new
  // directory.
  if ((args.type == kMinfsTypeDir) && (GetIno() != newdir->GetIno())) {
    fbl::RefPtr<fs::Vnode> vn_fs;
    if ((status = newdir->Lookup(newname, &vn_fs)) < 0) {
      return status;
    }
    auto vn = fbl::RefPtr<Directory>::Downcast(vn_fs);
    args.name = "..";
    args.ino = newdir->GetIno();
    if ((status = vn->ForEachDirent(&args, DirentCallbackUpdateInode)) < 0) {
      return status;
    }
  }

  // At this point, the oldvn exists with multiple names (or the same name in different
  // directories).
  oldvn->AddLink();

  // finally, remove oldname from its original position
  args.name = oldname;
  if ((status = ForEachDirent(&args, DirentCallbackForceUnlink)) != ZX_OK) {
    return status;
  }
  transaction->PinVnode(oldvn);
  transaction->PinVnode(newdir);
  Vfs()->CommitTransaction(std::move(transaction));
  success = true;
  return ZX_OK;
}

zx_status_t Directory::Link(fbl::StringPiece name, fbl::RefPtr<fs::Vnode> _target) {
  TRACE_DURATION("minfs", "Directory::Link", "name", name);
  ZX_DEBUG_ASSERT(fs::vfs_valid_name(name));

  if (IsUnlinked()) {
    return ZX_ERR_BAD_STATE;
  }

  auto target = fbl::RefPtr<VnodeMinfs>::Downcast(_target);
  if (target->IsDirectory()) {
    // The target must not be a directory
    return ZX_ERR_NOT_FILE;
  }

  // The destination should not exist
  DirArgs args;
  args.name = name;
  zx_status_t status;
  if ((status = ForEachDirent(&args, DirentCallbackFind)) != ZX_ERR_NOT_FOUND) {
    return (status == ZX_OK) ? ZX_ERR_ALREADY_EXISTS : status;
  }

  // Ensure that we have enough space to write the new vnode's direntry
  // before updating any other metadata.
  args.type = kMinfsTypeFile;  // We can't hard link directories
  args.reclen = static_cast<uint32_t>(DirentSize(static_cast<uint8_t>(name.length())));
  status = ForEachDirent(&args, DirentCallbackFindSpace);
  if (status == ZX_ERR_NOT_FOUND) {
    return ZX_ERR_NO_SPACE;
  }
  if (status != ZX_OK) {
    return status;
  }

  // Reserve potential blocks to write a new direntry.
  auto reserved_blocks_or =
      GetRequiredBlockCount(GetInode()->size, args.reclen, Vfs()->BlockSize());
  if (reserved_blocks_or.is_error()) {
    return reserved_blocks_or.error_value();
  }

  std::unique_ptr<Transaction> transaction;
  if ((status = Vfs()->BeginTransaction(0, reserved_blocks_or.value(), &transaction)) != ZX_OK) {
    return status;
  }

  args.ino = target->GetIno();
  args.transaction = transaction.get();
  if ((status = AppendDirent(&args)) != ZX_OK) {
    return status;
  }

  // We have successfully added the vn to a new location. Increment the link count.
  target->AddLink();
  target->InodeSync(transaction.get(), kMxFsSyncDefault);
  transaction->PinVnode(fbl::RefPtr(this));
  transaction->PinVnode(target);
  Vfs()->CommitTransaction(std::move(transaction));
  return ZX_OK;
}

}  // namespace minfs
