// Copyright 2016 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 <inttypes.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <bitmap/raw-bitmap.h>
#include <fs/block-txn.h>
#include <fs/trace.h>
#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/limits.h>
#include <fbl/unique_ptr.h>

#include "minfs-private.h"

namespace minfs {

fs::Vfs vfs;

void minfs_dump_info(const minfs_info_t* info) {
    FS_TRACE(MINFS, "minfs: data blocks:  %10u (size %u)\n", info->block_count, info->block_size);
    FS_TRACE(MINFS, "minfs: inodes:  %10u (size %u)\n", info->inode_count, info->inode_size);
    FS_TRACE(MINFS, "minfs: allocated blocks  @ %10u\n", info->alloc_block_count);
    FS_TRACE(MINFS, "minfs: allocated inodes  @ %10u\n", info->alloc_inode_count);
    FS_TRACE(MINFS, "minfs: inode bitmap @ %10u\n", info->ibm_block);
    FS_TRACE(MINFS, "minfs: alloc bitmap @ %10u\n", info->abm_block);
    FS_TRACE(MINFS, "minfs: inode table  @ %10u\n", info->ino_block);
    FS_TRACE(MINFS, "minfs: data blocks  @ %10u\n", info->dat_block);
    FS_TRACE(MINFS, "minfs: FVM-aware: %s\n", (info->flags & kMinfsFlagFVM) ? "YES" : "NO");
}

void minfs_dump_inode(const minfs_inode_t* inode, ino_t ino) {
    FS_TRACE(MINFS, "inode[%u]: magic:  %10u\n", ino, inode->magic);
    FS_TRACE(MINFS, "inode[%u]: size:   %10u\n", ino, inode->size);
    FS_TRACE(MINFS, "inode[%u]: blocks: %10u\n", ino, inode->block_count);
    FS_TRACE(MINFS, "inode[%u]: links:  %10u\n", ino, inode->link_count);
}

zx_status_t minfs_check_info(const minfs_info_t* info, uint32_t max) {
    minfs_dump_info(info);

    if ((info->magic0 != kMinfsMagic0) ||
        (info->magic1 != kMinfsMagic1)) {
        FS_TRACE_ERROR("minfs: bad magic\n");
        return ZX_ERR_INVALID_ARGS;
    }
    if (info->version != kMinfsVersion) {
        FS_TRACE_ERROR("minfs: FS Version: %08x. Driver version: %08x\n", info->version,
              kMinfsVersion);
        return ZX_ERR_INVALID_ARGS;
    }
    if ((info->block_size != kMinfsBlockSize) ||
        (info->inode_size != kMinfsInodeSize)) {
        FS_TRACE_ERROR("minfs: bsz/isz %u/%u unsupported\n", info->block_size, info->inode_size);
        return ZX_ERR_INVALID_ARGS;
    }
    if ((info->flags & kMinfsFlagFVM) == 0) {
        if (info->dat_block + info->block_count > max) {
            FS_TRACE_ERROR("minfs: too large for device\n");
            return ZX_ERR_INVALID_ARGS;
        }
    } else {
        // TODO(smklein): Verify slice size, vslice count.

        // Verify that the allocated slices are sufficient to hold
        // the allocated data structures of the filesystem.
        size_t ibm_blocks_needed = (info->inode_count + kMinfsBlockBits - 1) / kMinfsBlockBits;
        const size_t kBlocksPerSlice = info->slice_size / kMinfsBlockSize;
        size_t ibm_blocks_allocated = info->ibm_slices * kBlocksPerSlice;
        if (ibm_blocks_needed > ibm_blocks_allocated) {
            FS_TRACE_ERROR("minfs: Not enough slices for inode bitmap\n");
            return ZX_ERR_INVALID_ARGS;
        } else if (ibm_blocks_allocated + info->ibm_block >= info->abm_block) {
            FS_TRACE_ERROR("minfs: Inode bitmap collides into block bitmap\n");
            return ZX_ERR_INVALID_ARGS;
        }
        size_t abm_blocks_needed = (info->block_count + kMinfsBlockBits - 1) / kMinfsBlockBits;
        size_t abm_blocks_allocated = info->abm_slices * kBlocksPerSlice;
        if (abm_blocks_needed > abm_blocks_allocated) {
            FS_TRACE_ERROR("minfs: Not enough slices for block bitmap\n");
            return ZX_ERR_INVALID_ARGS;
        } else if (abm_blocks_allocated + info->abm_block >= info->ino_block) {
            FS_TRACE_ERROR("minfs: Block bitmap collides with inode table\n");
            return ZX_ERR_INVALID_ARGS;
        }
        size_t ino_blocks_needed = (info->inode_count + kMinfsInodesPerBlock - 1) / kMinfsInodesPerBlock;
        size_t ino_blocks_allocated = info->ino_slices * kBlocksPerSlice;
        if (ino_blocks_needed > ino_blocks_allocated) {
            FS_TRACE_ERROR("minfs: Not enough slices for inode table\n");
            return ZX_ERR_INVALID_ARGS;
        } else if (ino_blocks_allocated + info->ino_block >= info->dat_block) {
            FS_TRACE_ERROR("minfs: Inode table collides with data blocks\n");
            return ZX_ERR_INVALID_ARGS;
        }
        size_t dat_blocks_needed = info->block_count;
        size_t dat_blocks_allocated = info->dat_slices * kBlocksPerSlice;
        if (dat_blocks_needed > dat_blocks_allocated) {
            FS_TRACE_ERROR("minfs: Not enough slices for data blocks\n");
            return ZX_ERR_INVALID_ARGS;
        } else if (dat_blocks_allocated + info->dat_block >
                   fbl::numeric_limits<blk_t>::max()) {
            FS_TRACE_ERROR("minfs: Data blocks overflow blk_t\n");
            return ZX_ERR_INVALID_ARGS;
        }
    }
    //TODO: validate layout
    return 0;
}

zx_status_t Minfs::InodeSync(WriteTxn* txn, ino_t ino, const minfs_inode_t* inode) {
    // Obtain the offset of the inode within its containing block
    const uint32_t off_of_ino = (ino % kMinfsInodesPerBlock) * kMinfsInodeSize;
    const blk_t inoblock_rel = ino / kMinfsInodesPerBlock;
    const blk_t inoblock_abs = inoblock_rel + info_.ino_block;
    assert(inoblock_abs < kFVMBlockDataStart);
#ifdef __Fuchsia__
    void* inodata = (void*)((uintptr_t)(inode_table_->GetData()) +
                            (uintptr_t)(inoblock_rel * kMinfsBlockSize));
    auto itable_id = inode_table_vmoid_;
    memcpy((void*)((uintptr_t)inodata + off_of_ino), inode, kMinfsInodeSize);
    txn->Enqueue(itable_id, inoblock_rel, inoblock_abs, 1);
#else
    // Since host-side tools don't have "mapped vmos", just read / update /
    // write the single absolute indoe block.
    uint8_t inodata[kMinfsBlockSize];
    bc_->Readblk(inoblock_abs, inodata);
    memcpy((void*)((uintptr_t)inodata + off_of_ino), inode, kMinfsInodeSize);
    bc_->Writeblk(inoblock_abs, inodata);
#endif
    return ZX_OK;
}

Minfs::Minfs(fbl::unique_ptr<Bcache> bc, const minfs_info_t* info) : bc_(fbl::move(bc)) {
    memcpy(&info_, info, sizeof(minfs_info_t));
}

Minfs::~Minfs() {
    vnode_hash_.clear();
}

zx_status_t Minfs::InoFree(VnodeMinfs* vn) {
    // We're going to be updating block bitmaps repeatedly.
    WriteTxn txn(bc_.get());
#ifdef __Fuchsia__
    auto ibm_id = inode_map_vmoid_;
#else
    auto ibm_id = inode_map_.StorageUnsafe()->GetData();
#endif

    // Free the inode bit itself
    inode_map_.Clear(vn->ino_, vn->ino_ + 1);
    info_.alloc_inode_count--;

    blk_t bitbno = vn->ino_ / kMinfsBlockBits;
    txn.Enqueue(ibm_id, bitbno, info_.ibm_block + bitbno, 1);
    uint32_t block_count = vn->inode_.block_count;

    // release all direct blocks
    for (unsigned n = 0; n < kMinfsDirect; n++) {
        if (vn->inode_.dnum[n] == 0) {
            continue;
        }
        ValidateBno(vn->inode_.dnum[n]);
        block_count--;
        BlockFree(&txn, vn->inode_.dnum[n]);
    }


    // release all indirect blocks
    for (unsigned n = 0; n < kMinfsIndirect; n++) {
        if (vn->inode_.inum[n] == 0) {
            continue;
        }

#ifdef __Fuchsia__
        zx_status_t status;
        if ((status = vn->InitIndirectVmo()) != ZX_OK) {
            return status;
        }

        uint32_t* entry;
        vn->ReadIndirectVmoBlock(n, &entry);
#else
        uint32_t entry[kMinfsBlockSize];
        vn->ReadIndirectBlock(vn->inode_.inum[n], entry);
#endif

        // release the direct blocks pointed at by the entries in the indirect block
        for (unsigned m = 0; m < kMinfsDirectPerIndirect; m++) {
            if (entry[m] == 0) {
                continue;
            }
            block_count--;
            BlockFree(&txn, entry[m]);
        }
        // release the direct block itself
        block_count--;
        BlockFree(&txn, vn->inode_.inum[n]);

    }

    // release doubly indirect blocks
    for (unsigned n = 0; n < kMinfsDoublyIndirect; n++) {
        if (vn->inode_.dinum[n] == 0) {
            continue;
        }
#ifdef __Fuchsia__
        zx_status_t status;
        if ((status = vn->InitIndirectVmo()) != ZX_OK) {
            return status;
        }

        uint32_t* dentry;
        vn->ReadIndirectVmoBlock(GetVmoOffsetForDoublyIndirect(n), &dentry);
#else
        uint32_t dentry[kMinfsBlockSize];
        vn->ReadIndirectBlock(vn->inode_.dinum[n], dentry);
#endif
        // release indirect blocks
        for (unsigned m = 0; m < kMinfsDirectPerIndirect; m++) {
            if (dentry[m] == 0) {
                continue;
            }

#ifdef __Fuchsia__
            if ((status = vn->LoadIndirectWithinDoublyIndirect(n)) != ZX_OK) {
                return status;
            }

            uint32_t* entry;
            vn->ReadIndirectVmoBlock(GetVmoOffsetForIndirect(n) + m, &entry);

#else
            uint32_t entry[kMinfsBlockSize];
            vn->ReadIndirectBlock(dentry[m], entry);
#endif

            // release direct blocks
            for (unsigned k = 0; k < kMinfsDirectPerIndirect; k++) {
                if (entry[k] == 0) {
                    continue;
                }

                block_count--;
                BlockFree(&txn, entry[k]);
            }

            block_count--;
            BlockFree(&txn, dentry[m]);
        }

        // release the doubly indirect block itself
        block_count--;
        BlockFree(&txn, vn->inode_.dinum[n]);
    }

    CountUpdate(&txn);
    ZX_DEBUG_ASSERT(block_count == 0);
    return ZX_OK;
}

zx_status_t Minfs::AddInodes() {
#ifdef __Fuchsia__
    if ((info_.flags & kMinfsFlagFVM) == 0) {
        return ZX_ERR_NO_SPACE;
    }

    const size_t kBlocksPerSlice = info_.slice_size / kMinfsBlockSize;
    extend_request_t request;
    request.length = 1;
    request.offset = (kFVMBlockInodeStart / kBlocksPerSlice) + info_.ino_slices;

    const uint32_t kInodesPerSlice = static_cast<uint32_t>(info_.slice_size /
                                                           kMinfsInodeSize);
    uint32_t inodes = (info_.ino_slices + static_cast<uint32_t>(request.length))
            * kInodesPerSlice;
    uint32_t ibmblks = (inodes + kMinfsBlockBits - 1) / kMinfsBlockBits;
    uint32_t ibmblks_old = (info_.inode_count + kMinfsBlockBits - 1) / kMinfsBlockBits;
    ZX_DEBUG_ASSERT(ibmblks_old <= ibmblks);
    if (ibmblks > kBlocksPerSlice) {
        // TODO(smklein): Increase the size of the inode bitmap,
        // in addition to the size of the inode table.
        fprintf(stderr, "Minfs::AddInodes needs to increase inode bitmap size");
        return ZX_ERR_NO_SPACE;
    }

    if (bc_->FVMExtend(&request) != ZX_OK) {
        // TODO(smklein): Query FVM on reboot to verify our
        // superblock matches our allocated extents.
        fprintf(stderr, "Minfs::AddInodes FVM Extend failure");
        return ZX_ERR_NO_SPACE;
    }

    WriteTxn txn(bc_.get());

    // Update the inode bitmap, write the new blocks back to disk
    // as "zero".
    if (inode_map_.Grow(fbl::roundup(inodes, kMinfsBlockBits)) != ZX_OK) {
        return ZX_ERR_NO_SPACE;
    }
    // Grow before shrinking to ensure the underlying storage is a multiple
    // of kMinfsBlockSize.
    inode_map_.Shrink(inodes);
    if (ibmblks > ibmblks_old) {
        txn.Enqueue(inode_map_vmoid_, ibmblks_old, info_.ibm_block + ibmblks_old,
                    ibmblks - ibmblks_old);
    }

    // Update the inode table
    uint32_t inoblks = (inodes + kMinfsInodesPerBlock - 1) / kMinfsInodesPerBlock;
    if (inode_table_->Grow(inoblks * kMinfsBlockSize) != ZX_OK) {
        return ZX_ERR_NO_SPACE;
    }

    info_.vslice_count += request.length;
    info_.ino_slices += static_cast<uint32_t>(request.length);
    info_.inode_count = inodes;
    ibmblks_ = ibmblks;
    txn.Enqueue(info_vmoid_, 0, 0, 1);

    return txn.Flush();
#else
    return ZX_ERR_NO_SPACE;
#endif
}

zx_status_t Minfs::AddBlocks() {
#ifdef __Fuchsia__
    if ((info_.flags & kMinfsFlagFVM) == 0) {
        return ZX_ERR_NO_SPACE;
    }

    const size_t kBlocksPerSlice = info_.slice_size / kMinfsBlockSize;
    extend_request_t request;
    request.length = 1;
    request.offset = (kFVMBlockDataStart / kBlocksPerSlice) + info_.dat_slices;
    uint64_t blocks64 = (info_.dat_slices + request.length) * kBlocksPerSlice;
    ZX_DEBUG_ASSERT(blocks64 <= fbl::numeric_limits<uint32_t>::max());
    uint32_t blocks = static_cast<uint32_t>(blocks64);
    uint32_t abmblks = (blocks + kMinfsBlockBits - 1) / kMinfsBlockBits;
    uint32_t abmblks_old = (info_.block_count + kMinfsBlockBits - 1) / kMinfsBlockBits;
    ZX_DEBUG_ASSERT(abmblks_old <= abmblks);

    if (abmblks > kBlocksPerSlice) {
        // TODO(smklein): Increase the size of the block bitmap.
        fprintf(stderr, "Minfs::AddBlocks needs to increase block bitmap size");
        return ZX_ERR_NO_SPACE;
    }

    if (bc_->FVMExtend(&request) != ZX_OK) {
        // TODO(smklein): Query FVM on reboot to verify our
        // superblock matches our allocated extents.
        fprintf(stderr, "Minfs::AddBlocks FVM Extend failure");
        return ZX_ERR_NO_SPACE;
    }

    WriteTxn txn(bc_.get());

    // Update the block bitmap, write the new blocks back to disk
    // as "zero".
    if (block_map_.Grow(fbl::roundup(blocks, kMinfsBlockBits)) != ZX_OK) {
        return ZX_ERR_NO_SPACE;
    }
    // Grow before shrinking to ensure the underlying storage is a multiple
    // of kMinfsBlockSize.
    block_map_.Shrink(blocks);
    if (abmblks > abmblks_old) {
        txn.Enqueue(block_map_vmoid_, abmblks_old, info_.abm_block + abmblks_old,
                    abmblks - abmblks_old);
    }

    info_.vslice_count += request.length;
    info_.dat_slices += static_cast<uint32_t>(request.length);
    info_.block_count = blocks;

    abmblks_ = abmblks;
    txn.Enqueue(info_vmoid_, 0, 0, 1);
    return txn.Flush();
#else
    return ZX_ERR_NO_SPACE;
#endif
}

zx_status_t Minfs::InoNew(WriteTxn* txn, const minfs_inode_t* inode, ino_t* ino_out) {
    size_t bitoff_start;
    zx_status_t status = inode_map_.Find(false, 0, inode_map_.size(), 1, &bitoff_start);
    if (status != ZX_OK) {
        size_t old_size = inode_map_.size();
        if ((status = AddInodes()) != ZX_OK) {
            return status;
        } else if ((status = inode_map_.Find(false, old_size, inode_map_.size(),
                                             1, &bitoff_start)) != ZX_OK) {
            return status;
        }
    }

    status = inode_map_.Set(bitoff_start, bitoff_start + 1);
    assert(status == ZX_OK);
    info_.alloc_inode_count++;
    ino_t ino = static_cast<ino_t>(bitoff_start);

    // locate data and block offset of bitmap
    void* bmdata;
    ZX_DEBUG_ASSERT(ino <= inode_map_.size());
    blk_t ibm_relative_bno = (ino / kMinfsBlockBits);
    if ((bmdata = fs::GetBlock<kMinfsBlockSize>(inode_map_.StorageUnsafe()->GetData(),
        ibm_relative_bno)) == nullptr) {
        panic("inode not in bitmap");
    }

    // TODO(smklein): optional sanity check of both blocks

    // Write the inode back
    if ((status = InodeSync(txn, ino, inode)) != ZX_OK) {
        inode_map_.Clear(ino, ino + 1);
        info_.alloc_inode_count--;
        return status;
    }

// Commit blocks to disk
#ifdef __Fuchsia__
    vmoid_t id = inode_map_vmoid_;
#else
    const void* id = inode_map_.StorageUnsafe()->GetData();
#endif
    txn->Enqueue(id, ibm_relative_bno, info_.ibm_block + ibm_relative_bno, 1);

    CountUpdate(txn);
    *ino_out = ino;
    return ZX_OK;
}

zx_status_t Minfs::VnodeNew(WriteTxn* txn, fbl::RefPtr<VnodeMinfs>* out, uint32_t type) {
    if ((type != kMinfsTypeFile) && (type != kMinfsTypeDir)) {
        return ZX_ERR_INVALID_ARGS;
    }

    fbl::RefPtr<VnodeMinfs> vn;
    zx_status_t status;

    // Allocate the in-memory vnode
    if ((status = VnodeMinfs::Allocate(this, type, &vn)) != ZX_OK) {
        return status;
    }

    // Allocate the on-disk inode
    if ((status = InoNew(txn, &vn->inode_, &vn->ino_)) != ZX_OK) {
        return status;
    }

    vnode_hash_.insert(vn.get());

    *out = fbl::move(vn);
    return 0;
}

void Minfs::VnodeRelease(VnodeMinfs* vn) {
    vnode_hash_.erase(*vn);
}

zx_status_t Minfs::VnodeGet(fbl::RefPtr<VnodeMinfs>* out, ino_t ino) {
    if ((ino < 1) || (ino >= info_.inode_count)) {
        return ZX_ERR_OUT_OF_RANGE;
    }
    fbl::RefPtr<VnodeMinfs> vn = fbl::RefPtr<VnodeMinfs>(vnode_hash_.find(ino).CopyPointer());
    if (vn != nullptr) {
        *out = fbl::move(vn);
        return ZX_OK;
    }
    zx_status_t status;
    if ((status = VnodeMinfs::AllocateHollow(this, &vn)) != ZX_OK) {
        return ZX_ERR_NO_MEMORY;
    }

    // obtain the block of the inode table we need
    uint32_t off_of_ino = (ino % kMinfsInodesPerBlock) * kMinfsInodeSize;
#ifdef __Fuchsia__
    void* inodata = (void*)((uintptr_t)(inode_table_->GetData()) +
                            (uintptr_t)((ino / kMinfsInodesPerBlock) * kMinfsBlockSize));
#else
    uint8_t inodata[kMinfsBlockSize];
    bc_->Readblk(info_.ino_block + (ino / kMinfsInodesPerBlock), inodata);
#endif
    memcpy(&vn->inode_, (void*)((uintptr_t)inodata + off_of_ino), kMinfsInodeSize);
    vn->ino_ = ino;
    vnode_hash_.insert(vn.get());

    *out = fbl::move(vn);
    return ZX_OK;
}

zx_status_t Minfs::BlockFree(WriteTxn* txn, blk_t bno) {
    ValidateBno(bno);

#ifdef __Fuchsia__
    auto bbm_id = block_map_vmoid_;
#else
    auto bbm_id = block_map_.StorageUnsafe()->GetData();
#endif

    block_map_.Clear(bno, bno + 1);
    info_.alloc_block_count--;
    blk_t bitbno = bno / kMinfsBlockBits;
    txn->Enqueue(bbm_id, bitbno, info_.abm_block + bitbno, 1);
    return CountUpdate(txn);
}

// Allocate a new data block from the block bitmap.
//
// If hint is nonzero it indicates which block number to start the search for
// free blocks from.
zx_status_t Minfs::BlockNew(WriteTxn* txn, blk_t hint, blk_t* out_bno) {
    size_t bitoff_start;
    zx_status_t status;
    if ((status = block_map_.Find(false, hint, block_map_.size(), 1, &bitoff_start)) != ZX_OK) {
        if ((status = block_map_.Find(false, 0, hint, 1, &bitoff_start)) != ZX_OK) {
            size_t old_size = block_map_.size();
            if ((status = AddBlocks()) != ZX_OK) {
                return status;
            } else if ((status = block_map_.Find(false, old_size, block_map_.size(),
                                                 1, &bitoff_start)) != ZX_OK) {
                return status;
            }
        }
    }

    status = block_map_.Set(bitoff_start, bitoff_start + 1);
    assert(status == ZX_OK);
    info_.alloc_block_count++;
    blk_t bno = static_cast<blk_t>(bitoff_start);
    ValidateBno(bno);

    // obtain the in-memory bitmap block
    blk_t bmbno_rel = bno / kMinfsBlockBits;       // bmbno relative to bitmap
    blk_t bmbno_abs = info_.abm_block + bmbno_rel; // bmbno relative to block device

// commit the bitmap
#ifdef __Fuchsia__
    txn->Enqueue(block_map_vmoid_, bmbno_rel, bmbno_abs, 1);
#else
    void* bmdata = fs::GetBlock<kMinfsBlockSize>(block_map_.StorageUnsafe()->GetData(), bmbno_rel);
    bc_->Writeblk(bmbno_abs, bmdata);
#endif
    *out_bno = bno;

    CountUpdate(txn);
    return ZX_OK;
}

zx_status_t Minfs::CountUpdate(WriteTxn* txn) {
    zx_status_t status = ZX_OK;

#ifdef __Fuchsia__
    void* infodata = info_vmo_->GetData();
    memcpy(infodata, &info_, sizeof(info_));
    //TODO(planders): look into delaying this transaction.
    txn->Enqueue(info_vmoid_, 0, 0, 1);
#else
    uint8_t blk[kMinfsBlockSize];
    memset(blk, 0, sizeof(blk));
    memcpy(blk, &info_, sizeof(info_));
    status = bc_->Writeblk(0, blk);
#endif

    return status;
}

void minfs_dir_init(void* bdata, ino_t ino_self, ino_t ino_parent) {
#define DE0_SIZE DirentSize(1)

    // directory entry for self
    minfs_dirent_t* de = (minfs_dirent_t*)bdata;
    de->ino = ino_self;
    de->reclen = DE0_SIZE;
    de->namelen = 1;
    de->type = kMinfsTypeDir;
    de->name[0] = '.';

    // directory entry for parent
    de = (minfs_dirent_t*)((uintptr_t)bdata + DE0_SIZE);
    de->ino = ino_parent;
    de->reclen = DirentSize(2) | kMinfsReclenLast;
    de->namelen = 2;
    de->type = kMinfsTypeDir;
    de->name[0] = '.';
    de->name[1] = '.';
}

zx_status_t Minfs::Create(Minfs** out, fbl::unique_ptr<Bcache> bc, const minfs_info_t* info) {
    zx_status_t status = minfs_check_info(info, bc->Maxblk());
    if (status < 0) {
        return status;
    }

    fbl::AllocChecker ac;
    fbl::unique_ptr<Minfs> fs(new (&ac) Minfs(fbl::move(bc), info));
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }
    // determine how many blocks of inodes, allocation bitmaps,
    // and inode bitmaps there are
    uint32_t blocks = info->block_count;
    uint32_t inodes = info->inode_count;
    fs->abmblks_ = (blocks + kMinfsBlockBits - 1) / kMinfsBlockBits;
    fs->ibmblks_ = (inodes + kMinfsBlockBits - 1) / kMinfsBlockBits;

    if ((status = fs->block_map_.Reset(fs->abmblks_ * kMinfsBlockBits)) < 0) {
        return status;
    }
    if ((status = fs->inode_map_.Reset(fs->ibmblks_ * kMinfsBlockBits)) < 0) {
        return status;
    }
    // this keeps the underlying storage a block multiple but ensures we
    // can't allocate beyond the last real block or inode
    if ((status = fs->block_map_.Shrink(fs->info_.block_count)) < 0) {
        return status;
    }
    if ((status = fs->inode_map_.Shrink(fs->info_.inode_count)) < 0) {
        return status;
    }

#ifdef __Fuchsia__
    if ((status = fs->bc_->AttachVmo(fs->block_map_.StorageUnsafe()->GetVmo(),
                                     &fs->block_map_vmoid_)) != ZX_OK) {
        return status;
    }
    if ((status = fs->bc_->AttachVmo(fs->inode_map_.StorageUnsafe()->GetVmo(),
                                     &fs->inode_map_vmoid_)) != ZX_OK) {
        return status;
    }

    // Create the inode table.
    uint32_t inoblks = (inodes + kMinfsInodesPerBlock - 1) / kMinfsInodesPerBlock;
    if ((status = MappedVmo::Create(inoblks * kMinfsBlockSize, "minfs-inode-table",
                                    &fs->inode_table_)) != ZX_OK) {
        return status;
    }

    if ((status = fs->bc_->AttachVmo(fs->inode_table_->GetVmo(),
                                     &fs->inode_table_vmoid_)) != ZX_OK) {
        return status;
    }

    // Create the info vmo
    if ((status = MappedVmo::Create(kMinfsBlockSize, "minfs-superblock",
                                    &fs->info_vmo_)) != ZX_OK) {
        return status;
    }

    if ((status = fs->bc_->AttachVmo(fs->info_vmo_->GetVmo(),
                                     &fs->info_vmoid_)) != ZX_OK) {
        return status;
    }

    ReadTxn txn(fs->bc_.get());
    txn.Enqueue(fs->block_map_vmoid_, 0, fs->info_.abm_block, fs->abmblks_);
    txn.Enqueue(fs->inode_map_vmoid_, 0, fs->info_.ibm_block, fs->ibmblks_);
    txn.Enqueue(fs->inode_table_vmoid_, 0, fs->info_.ino_block, inoblks);
    txn.Enqueue(fs->info_vmoid_, 0, 0, 1);
    if ((status = txn.Flush()) != ZX_OK) {
        return status;
    }

#else
    for (uint32_t n = 0; n < fs->abmblks_; n++) {
        void* bmdata = fs::GetBlock<kMinfsBlockSize>(fs->block_map_.StorageUnsafe()->GetData(), n);
        if (fs->bc_->Readblk(fs->info_.abm_block + n, bmdata)) {
            FS_TRACE_ERROR("minfs: failed reading alloc bitmap\n");
        }
    }
    for (uint32_t n = 0; n < fs->ibmblks_; n++) {
        void* bmdata = fs::GetBlock<kMinfsBlockSize>(fs->inode_map_.StorageUnsafe()->GetData(), n);
        if (fs->bc_->Readblk(fs->info_.ibm_block + n, bmdata)) {
            FS_TRACE_ERROR("minfs: failed reading inode bitmap\n");
        }
    }
#endif

    *out = fs.release();
    return ZX_OK;
}

zx_status_t minfs_mount(fbl::RefPtr<VnodeMinfs>* out, fbl::unique_ptr<Bcache> bc) {
    zx_status_t status;

    char blk[kMinfsBlockSize];
    if ((status = bc->Readblk(0, &blk)) != ZX_OK) {
        FS_TRACE_ERROR("minfs: could not read info block\n");
        return status;
    }
    const minfs_info_t* info = reinterpret_cast<minfs_info_t*>(blk);

    Minfs* fs;
    if ((status = Minfs::Create(&fs, fbl::move(bc), info)) != ZX_OK) {
        FS_TRACE_ERROR("minfs: mount failed\n");
        return status;
    }

    fbl::RefPtr<VnodeMinfs> vn;
    if ((status = fs->VnodeGet(&vn, kMinfsRootIno)) != ZX_OK) {
        FS_TRACE_ERROR("minfs: cannot find root inode\n");
        delete fs;
        return status;
    }

    ZX_DEBUG_ASSERT(vn->IsDirectory());
    *out = fbl::move(vn);
    return ZX_OK;
}

zx_status_t Minfs::Unmount() {
#ifdef __Fuchsia__
    dispatcher_ = nullptr;
#endif
    // Explicitly delete this (rather than just letting the memory release when
    // the process exits) to ensure that the block device's fifo has been
    // closed.
    delete this;
    // TODO(smklein): To not bind filesystem lifecycle to a process, shut
    // down (closing dispatcher) rather than calling exit.
    exit(0);
    return ZX_OK;
}

void minfs_free_slices(Bcache* bc, const minfs_info_t* info) {
    if ((info->flags & kMinfsFlagFVM) == 0) {
        return;
    }
#ifdef __Fuchsia__
    extend_request_t request;
    const size_t kBlocksPerSlice = info->slice_size / kMinfsBlockSize;
    if (info->ibm_slices) {
        request.length = info->ibm_slices;
        request.offset = kFVMBlockInodeBmStart / kBlocksPerSlice;
        bc->FVMShrink(&request);
    }
    if (info->abm_slices) {
        request.length = info->abm_slices;
        request.offset = kFVMBlockDataBmStart / kBlocksPerSlice;
        bc->FVMShrink(&request);
    }
    if (info->ino_slices) {
        request.length = info->ino_slices;
        request.offset = kFVMBlockInodeStart / kBlocksPerSlice;
        bc->FVMShrink(&request);
    }
    if (info->dat_slices) {
        request.length = info->dat_slices;
        request.offset = kFVMBlockDataStart / kBlocksPerSlice;
        bc->FVMShrink(&request);
    }
#endif
}

int minfs_mkfs(fbl::unique_ptr<Bcache> bc) {
    minfs_info_t info;
    memset(&info, 0x00, sizeof(info));
    info.magic0 = kMinfsMagic0;
    info.magic1 = kMinfsMagic1;
    info.version = kMinfsVersion;
    info.flags = kMinfsFlagClean;
    info.block_size = kMinfsBlockSize;
    info.inode_size = kMinfsInodeSize;

    uint32_t blocks = 0;
    uint32_t inodes = 0;

#ifdef __Fuchsia__
    fvm_info_t fvm_info;
    if (bc->FVMQuery(&fvm_info) == ZX_OK) {
        info.slice_size = fvm_info.slice_size;
        info.flags |= kMinfsFlagFVM;


        if (info.slice_size % kMinfsBlockSize) {
            fprintf(stderr, "minfs mkfs: Slice size not multiple of minfs block\n");
            return -1;
        }

        const size_t kBlocksPerSlice = info.slice_size / kMinfsBlockSize;
        extend_request_t request;
        request.length = 1;
        request.offset = kFVMBlockInodeBmStart / kBlocksPerSlice;
        if (bc->FVMExtend(&request) != ZX_OK) {
            fprintf(stderr, "minfs mkfs: Failed to allocate inode bitmap\n");
            return -1;
        }
        info.ibm_slices = 1;
        request.offset = kFVMBlockDataBmStart / kBlocksPerSlice;
        if (bc->FVMExtend(&request) != ZX_OK) {
            fprintf(stderr, "minfs mkfs: Failed to allocate data bitmap\n");
            minfs_free_slices(bc.get(), &info);
            return -1;
        }
        info.abm_slices = 1;
        request.offset = kFVMBlockInodeStart / kBlocksPerSlice;
        if (bc->FVMExtend(&request) != ZX_OK) {
            fprintf(stderr, "minfs mkfs: Failed to allocate inode table\n");
            minfs_free_slices(bc.get(), &info);
            return -1;
        }
        info.ino_slices = 1;
        request.offset = kFVMBlockDataStart / kBlocksPerSlice;
        if (bc->FVMExtend(&request) != ZX_OK) {
            fprintf(stderr, "minfs mkfs: Failed to allocate data blocks\n");
            minfs_free_slices(bc.get(), &info);
            return -1;
        }
        info.dat_slices = 1;

        info.vslice_count = 1 + info.ibm_slices + info.abm_slices +
                            info.ino_slices + info.dat_slices;

        inodes = static_cast<uint32_t>(info.ino_slices * info.slice_size / kMinfsInodeSize);
        blocks = static_cast<uint32_t>(info.dat_slices * info.slice_size / kMinfsBlockSize);
    }
#endif
    if ((info.flags & kMinfsFlagFVM) == 0) {
        inodes = 32768;
        blocks = bc->Maxblk();
    }

    // determine how many blocks of inodes, allocation bitmaps,
    // and inode bitmaps there are
    uint32_t inoblks = (inodes + kMinfsInodesPerBlock - 1) / kMinfsInodesPerBlock;
    uint32_t ibmblks = (inodes + kMinfsBlockBits - 1) / kMinfsBlockBits;
    uint32_t abmblks;

    info.inode_count = inodes;
    info.alloc_block_count = 0;
    info.alloc_inode_count = 0;
    if ((info.flags & kMinfsFlagFVM) == 0) {
        // Aligning distinct data areas to 8 block groups.
        uint32_t non_dat_blocks = (8 + fbl::roundup(ibmblks, 8u) + inoblks);
        if (non_dat_blocks >= blocks) {
            fprintf(stderr, "mkfs: Partition size (%" PRIu64 " bytes) is too small\n",
                    static_cast<uint64_t>(blocks) * kMinfsBlockSize);
            return ZX_ERR_INVALID_ARGS;
        }

        uint32_t dat_block_count = blocks - non_dat_blocks;
        abmblks = (dat_block_count + kMinfsBlockBits - 1) / kMinfsBlockBits;
        info.block_count = dat_block_count - fbl::roundup(abmblks, 8u);
        info.ibm_block = 8;
        info.abm_block = info.ibm_block + fbl::roundup(ibmblks, 8u);
        info.ino_block = info.abm_block + fbl::roundup(abmblks, 8u);
        info.dat_block = info.ino_block + inoblks;
    } else {
        info.block_count = blocks;
        abmblks = (info.block_count + kMinfsBlockBits - 1) / kMinfsBlockBits;
        info.ibm_block = kFVMBlockInodeBmStart;
        info.abm_block = kFVMBlockDataBmStart;
        info.ino_block = kFVMBlockInodeStart;
        info.dat_block = kFVMBlockDataStart;
    }

    minfs_dump_info(&info);

    RawBitmap abm;
    RawBitmap ibm;

    // By allocating the bitmap and then shrinking it, we keep the underlying
    // storage a block multiple but ensure we can't allocate beyond the last
    // real block or inode.
    zx_status_t status;
    if ((status = abm.Reset(fbl::roundup(info.block_count, kMinfsBlockBits))) < 0) {
        FS_TRACE_ERROR("mkfs: Failed to allocate block bitmap\n");
        minfs_free_slices(bc.get(), &info);
        return status;
    }
    if ((status = ibm.Reset(fbl::roundup(info.inode_count, kMinfsBlockBits))) < 0) {
        FS_TRACE_ERROR("mkfs: Failed to allocate inode bitmap\n");
        minfs_free_slices(bc.get(), &info);
        return status;
    }
    if ((status = abm.Shrink(info.block_count)) < 0) {
        FS_TRACE_ERROR("mkfs: Failed to shrink block bitmap\n");
        minfs_free_slices(bc.get(), &info);
        return status;
    }
    if ((status = ibm.Shrink(info.inode_count)) < 0) {
        FS_TRACE_ERROR("mkfs: Failed to shrink inode bitmap\n");
        minfs_free_slices(bc.get(), &info);
        return status;
    }

    // write rootdir
    uint8_t blk[kMinfsBlockSize];
    memset(blk, 0, sizeof(blk));
    minfs_dir_init(blk, kMinfsRootIno, kMinfsRootIno);
    bc->Writeblk(info.dat_block + 1, blk);

    // update inode bitmap
    ibm.Set(0, 1);
    ibm.Set(kMinfsRootIno, kMinfsRootIno + 1);
    info.alloc_inode_count++;

    // update block bitmap:
    // Reserve the 0th data block (as a 'null' value)
    // Reserve the 1st data block (for root directory)
    abm.Set(0, 2);
    info.alloc_block_count++;

    // write allocation bitmap
    for (uint32_t n = 0; n < abmblks; n++) {
        void* bmdata = fs::GetBlock<kMinfsBlockSize>(abm.StorageUnsafe()->GetData(), n);
        memcpy(blk, bmdata, kMinfsBlockSize);
        bc->Writeblk(info.abm_block + n, blk);
    }

    // write inode bitmap
    for (uint32_t n = 0; n < ibmblks; n++) {
        void* bmdata = fs::GetBlock<kMinfsBlockSize>(ibm.StorageUnsafe()->GetData(), n);
        memcpy(blk, bmdata, kMinfsBlockSize);
        bc->Writeblk(info.ibm_block + n, blk);
    }

    // write inodes
    memset(blk, 0, sizeof(blk));
    for (uint32_t n = 0; n < inoblks; n++) {
        bc->Writeblk(info.ino_block + n, blk);
    }

    // setup root inode
    minfs_inode_t* ino = reinterpret_cast<minfs_inode_t*>(&blk[0]);
    ino[kMinfsRootIno].magic = kMinfsMagicDir;
    ino[kMinfsRootIno].size = kMinfsBlockSize;
    ino[kMinfsRootIno].block_count = 1;
    ino[kMinfsRootIno].link_count = 2;
    ino[kMinfsRootIno].dirent_count = 2;
    ino[kMinfsRootIno].dnum[0] = 1;
    bc->Writeblk(info.ino_block, blk);

    memset(blk, 0, sizeof(blk));
    memcpy(blk, &info, sizeof(info));
    bc->Writeblk(0, blk);
    return 0;
}

} // namespace minfs
