// Copyright 2017 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.

// This file contains the global Blobfs structure used for constructing a Blobfs filesystem in
// memory.

#pragma once

#ifndef __Fuchsia__
#error Fuchsia-only Header
#endif

#include <string.h>

#include <bitmap/raw-bitmap.h>
#include <bitmap/rle-bitmap.h>
#include <block-client/cpp/client.h>
#include <digest/digest.h>
#include <fbl/algorithm.h>
#include <fbl/macros.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <fbl/unique_fd.h>
#include <fbl/unique_ptr.h>
#include <fbl/vector.h>
#include <fs/block-txn.h>
#include <fs/managed-vfs.h>
#include <fs/metrics.h>
#include <fs/trace.h>
#include <fs/vfs.h>
#include <fs/vnode.h>
#include <fuchsia/blobfs/c/fidl.h>
#include <fuchsia/hardware/block/c/fidl.h>
#include <fuchsia/io/c/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/wait.h>
#include <lib/fzl/fdio.h>
#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/fzl/resizeable-vmo-mapper.h>
#include <lib/zx/channel.h>
#include <lib/zx/event.h>
#include <lib/zx/vmo.h>
#include <trace/event.h>

#include <blobfs/allocator.h>
#include <blobfs/blob-cache.h>
#include <blobfs/blob.h>
#include <blobfs/common.h>
#include <blobfs/directory.h>
#include <blobfs/extent-reserver.h>
#include <blobfs/format.h>
#include <blobfs/iterator/allocated-extent-iterator.h>
#include <blobfs/iterator/extent-iterator.h>
#include <blobfs/journal.h>
#include <blobfs/metrics.h>
#include <blobfs/node-reserver.h>
#include <blobfs/writeback.h>

#include <atomic>
#include <utility>

namespace blobfs {

using digest::Digest;

enum class Writability {
    // Do not write to persistent storage under any circumstances whatsoever.
    ReadOnlyDisk,
    // Do not allow users of the filesystem to mutate filesystem state. This
    // state allows the journal to replay while initializing writeback.
    ReadOnlyFilesystem,
    // Permit all operations.
    Writable,
};

// Toggles that may be set on blobfs during initialization.
struct MountOptions {
    Writability writability = Writability::Writable;
    bool metrics = false;
    bool journal = false;
    CachePolicy cache_policy = CachePolicy::EvictImmediately;
};

class Blobfs : public fs::ManagedVfs,
               public fbl::RefCounted<Blobfs>,
               public TransactionManager {
public:
    DISALLOW_COPY_ASSIGN_AND_MOVE(Blobfs);

    ////////////////
    // fs::ManagedVfs interface.

    void Shutdown(fs::Vfs::ShutdownCallback closure) final;

    ////////////////
    // TransactionManager's fs::TransactionHandler interface.
    //
    // Allows transmitting read and write transactions directly to the underlying storage.

    uint32_t FsBlockSize() const final { return kBlobfsBlockSize; }

    uint32_t DeviceBlockSize() const final { return block_info_.block_size; }

    groupid_t BlockGroupID() final {
        thread_local groupid_t group_ = next_group_.fetch_add(1);
        ZX_ASSERT_MSG(group_ < MAX_TXN_GROUP_COUNT, "Too many threads accessing block device");
        return group_;
    }

    zx_status_t Transaction(block_fifo_request_t* requests, size_t count) final {
        TRACE_DURATION("blobfs", "Blobfs::Transaction", "count", count);
        return fifo_client_.Transaction(requests, count);
    }

    ////////////////
    // TransactionManager's SpaceManager interface.
    //
    // Allows viewing and controlling the size of the underlying volume.

    const Superblock& Info() const final { return info_; }
    zx_status_t AttachVmo(const zx::vmo& vmo, vmoid_t* out) final;
    zx_status_t DetachVmo(vmoid_t vmoid) final;
    zx_status_t AddInodes(fzl::ResizeableVmoMapper* node_map) final;
    zx_status_t AddBlocks(size_t nblocks, RawBitmap* block_map) final;

    ////////////////
    // TransactionManager interface.
    //
    // Allows attaching VMOs, controlling the underlying volume, and sending transactions to the
    // underlying storage (optionally through the journal).

    BlobfsMetrics& LocalMetrics() final {
        return metrics_;
    }
    size_t WritebackCapacity() const final;
    zx_status_t CreateWork(fbl::unique_ptr<WritebackWork>* out, Blob* vnode) final;
    zx_status_t EnqueueWork(fbl::unique_ptr<WritebackWork> work, EnqueueType type) final;

    ////////////////
    // Other methods.

    uint64_t DataStart() const { return DataStartBlock(info_); }

    bool CheckBlocksAllocated(uint64_t start_block, uint64_t end_block,
                              uint64_t* first_unset = nullptr) const {
        return allocator_->CheckBlocksAllocated(start_block, end_block, first_unset);
    }
    AllocatedExtentIterator GetExtents(uint32_t node_index) {
        return AllocatedExtentIterator(allocator_.get(), node_index);
    }

    Allocator* GetAllocator() { return allocator_.get(); }

    Inode* GetNode(uint32_t node_index) { return allocator_->GetNode(node_index); }
    zx_status_t ReserveBlocks(size_t num_blocks, fbl::Vector<ReservedExtent>* out_extents) {
        return allocator_->ReserveBlocks(num_blocks, out_extents);
    }
    zx_status_t ReserveNodes(size_t num_nodes, fbl::Vector<ReservedNode>* out_node) {
        return allocator_->ReserveNodes(num_nodes, out_node);
    }

    static zx_status_t Create(fbl::unique_fd blockfd, const MountOptions& options,
                              const Superblock* info, fbl::unique_ptr<Blobfs>* out);

    void CollectMetrics() {
        collecting_metrics_ = true;
        cobalt_metrics_.EnableMetrics(true);
    }
    bool CollectingMetrics() const { return cobalt_metrics_.IsEnabled(); }
    void DisableMetrics() {
        cobalt_metrics_.EnableMetrics(false);
        collecting_metrics_ = false;
    }
    void DumpMetrics() const {
        if (collecting_metrics_) {
            metrics_.Dump();
        }
    }

    void SetUnmountCallback(fbl::Closure closure) { on_unmount_ = std::move(closure); }

    // Initializes the WritebackQueue and Journal, replaying any existing journal entries
    // if requested.
    //
    // If the underlying block device is read-only, the journal may not be
    // replayed, and this function returns ZX_ERR_ACCESS_DENIED.
    // If the filesystem is to be mounted read-only or read + write, the journal may be replayed.
    zx_status_t InitializeWriteback(Writability writability, bool journal_enabled);

    virtual ~Blobfs();

    // Invokes "open" on the root directory.
    // Acts as a special-case to bootstrap filesystem mounting.
    zx_status_t OpenRootNode(fbl::RefPtr<Directory>* out);

    BlobCache& Cache() {
        return blob_cache_;
    }

    zx_status_t Readdir(fs::vdircookie_t* cookie, void* dirents, size_t len, size_t* out_actual);

    const zx::unowned_channel BlockDevice() const {
        return zx::unowned_channel(block_device_.borrow_channel());
    }
    const fbl::unique_fd& BlockDeviceFd() const {
        return block_device_.fd();
    }

    // Returns an unique identifier for this instance.
    uint64_t GetFsId() const { return fs_id_; }

    using SyncCallback = fs::Vnode::SyncCallback;
    void Sync(SyncCallback closure);

    // Frees an inode, from both the reserved map and the inode table. If the
    // inode was allocated in the inode table, write the deleted inode out to
    // disk.
    void FreeInode(WritebackWork* wb, uint32_t node_index);

    // Does a single pass of all blobs, creating uninitialized Vnode
    // objects for them all.
    //
    // By executing this function at mount, we can quickly assert
    // either the presence or absence of a blob on the system without
    // further scanning.
    zx_status_t InitializeVnodes();

    // Writes node data to the inode table and updates disk.
    void PersistNode(WritebackWork* wb, uint32_t node_index);

    // Adds reserved blocks to allocated bitmap and writes the bitmap out to disk.
    void PersistBlocks(WritebackWork* wb, const ReservedExtent& extent);

    fs::VnodeMetrics* GetMutableVnodeMetrics() { return cobalt_metrics_.mutable_vnode_metrics(); }

    // Record the location and size of all non-free block regions.
    fbl::Vector<BlockRegion> GetAllocatedRegions() const {
        return allocator_->GetAllocatedRegions();
    }
private:
    friend class BlobfsChecker;

    Blobfs(fbl::unique_fd fd, const Superblock* info);

    // Reloads metadata from disk. Useful when metadata on disk
    // may have changed due to journal playback.
    zx_status_t Reload();

    // Frees blocks from the allocated map (if allocated) and updates disk if necessary.
    void FreeExtent(WritebackWork* wb, const Extent& extent);

    // Free a single node. Doesn't attempt to parse the type / traverse nodes;
    // this function just deletes a single node.
    void FreeNode(WritebackWork* wb, uint32_t node_index);

    // Given a contiguous number of blocks after a starting block,
    // write out the bitmap to disk for the corresponding blocks.
    // Should only be called by PersistBlocks and FreeExtent.
    void WriteBitmap(WritebackWork* wb, uint64_t nblocks, uint64_t start_block);

    // Given a node within the node map at an index, write it to disk.
    // Should only be called by AllocateNode and FreeNode.
    void WriteNode(WritebackWork* wb, uint32_t map_index);

    // Enqueues an update for allocated inode/block counts.
    void WriteInfo(WritebackWork* wb);

    // When will flush the metrics in the calling thread and will schedule itself
    // to flush again in the future.
    void ScheduleMetricFlush();

    // Creates an unique identifier for this instance. This is to be called only during
    // "construction".
    zx_status_t CreateFsId();

    // Verifies that the contents of a blob are valid.
    zx_status_t VerifyBlob(uint32_t node_index);

    fbl::unique_ptr<WritebackQueue> writeback_;
    fbl::unique_ptr<Journal> journal_;
    Superblock info_;

    BlobCache blob_cache_;

    fzl::FdioCaller block_device_;
    fuchsia_hardware_block_BlockInfo block_info_ = {};
    std::atomic<groupid_t> next_group_ = {};
    block_client::Client fifo_client_;

    fbl::unique_ptr<Allocator> allocator_;

    fzl::ResizeableVmoMapper info_mapping_;
    vmoid_t info_vmoid_ = {};

    uint64_t fs_id_ = 0;

    bool collecting_metrics_ = false;
    BlobfsMetrics metrics_ = {};

    fbl::Closure on_unmount_ = {};

    // TODO(gevalentino): clean up old metrics and update this to inspect API.
    fs::Metrics cobalt_metrics_;
    async::Loop flush_loop_ = async::Loop(&kAsyncLoopConfigNoAttachToThread);
};

zx_status_t Initialize(fbl::unique_fd blockfd, const MountOptions& options,
                       fbl::unique_ptr<Blobfs>* out);
zx_status_t Mount(async_dispatcher_t* dispatcher, fbl::unique_fd blockfd,
                  const MountOptions& options, zx::channel root, fbl::Closure on_unmount);

} // namespace blobfs
