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

#include <atomic>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <utility>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>
#include <fbl/ref_ptr.h>
#include <fbl/unique_ptr.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/vfs.h>
#include <fs/vfs.h>
#include <lib/memfs/cpp/vnode.h>
#include <lib/memfs/memfs.h>
#include <lib/sync/completion.h>
#include <zircon/device/vfs.h>

#include "dnode.h"

namespace {

constexpr size_t kPageSize = static_cast<size_t>(PAGE_SIZE);

}

namespace memfs {

zx_status_t Vfs::CreateFromVmo(VnodeDir* parent, fbl::StringPiece name,
                               zx_handle_t vmo, zx_off_t off,
                               zx_off_t len) {
    fbl::AutoLock lock(&vfs_lock_);
    return parent->CreateFromVmo(name, vmo, off, len);
}

void Vfs::MountSubtree(VnodeDir* parent, fbl::RefPtr<VnodeDir> subtree) {
    fbl::AutoLock lock(&vfs_lock_);
    parent->MountSubtree(std::move(subtree));
}

zx_status_t Vfs::FillFsId() {
    if (fs_id_) {
        return ZX_OK;
    }
    zx::event event;
    zx_status_t status = zx::event::create(0, &event);
    if (status != ZX_OK) {
        return status;
    }
    zx_info_handle_basic_t info;
    status = event.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
    if (status != ZX_OK) {
        return status;
    }

    fs_id_ = info.koid;
    return ZX_OK;
}

zx_status_t Vfs::GrowVMO(zx::vmo& vmo, size_t current_size,
                         size_t request_size, size_t* actual_size) {
    if (request_size <= current_size) {
        *actual_size = current_size;
        return ZX_OK;
    }
    size_t aligned_len = fbl::round_up(request_size, kPageSize);
    ZX_DEBUG_ASSERT(current_size % kPageSize == 0);
    size_t num_new_pages = (aligned_len - current_size) / kPageSize;
    if (num_new_pages + num_allocated_pages_ > pages_limit_) {
        *actual_size = current_size;
        return ZX_ERR_NO_SPACE;
    }
    zx_status_t status;
    if (!vmo.is_valid()) {
        if ((status = zx::vmo::create(aligned_len, 0, &vmo)) != ZX_OK) {
            return status;
        }
    } else {
        if ((status = vmo.set_size(aligned_len)) != ZX_OK) {
            return status;
        }
    }
    // vmo operation succeeded
    num_allocated_pages_ += num_new_pages;
    *actual_size = aligned_len;
    return ZX_OK;
}

void Vfs::WillFreeVMO(size_t vmo_size) {
    ZX_DEBUG_ASSERT(vmo_size % kPageSize == 0);
    size_t freed_pages = vmo_size / kPageSize;
    ZX_DEBUG_ASSERT(freed_pages <= num_allocated_pages_);
    num_allocated_pages_ -= freed_pages;
}

std::atomic<uint64_t> VnodeMemfs::ino_ctr_ = 0;
std::atomic<uint64_t> VnodeMemfs::deleted_ino_ctr_ = 0;

VnodeMemfs::VnodeMemfs(Vfs* vfs) : dnode_(nullptr), link_count_(0), vfs_(vfs),
    ino_(ino_ctr_.fetch_add(1, std::memory_order_relaxed)) {
    create_time_ = modify_time_ = zx_clock_get(ZX_CLOCK_UTC);
}

VnodeMemfs::~VnodeMemfs() {
    deleted_ino_ctr_.fetch_add(1, std::memory_order_relaxed);
}

zx_status_t VnodeMemfs::Setattr(const vnattr_t* attr) {
    if ((attr->valid & ~(ATTR_MTIME)) != 0) {
        // only attr currently supported
        return ZX_ERR_INVALID_ARGS;
    }
    if (attr->valid & ATTR_MTIME) {
        modify_time_ = attr->modify_time;
    }
    return ZX_OK;
}

void VnodeMemfs::Sync(SyncCallback closure) {
    // Since this filesystem is in-memory, all data is already up-to-date in
    // the underlying storage
    closure(ZX_OK);
}

zx_status_t VnodeMemfs::AttachRemote(fs::MountChannel h) {
    if (!IsDirectory()) {
        return ZX_ERR_NOT_DIR;
    } else if (IsRemote()) {
        return ZX_ERR_ALREADY_BOUND;
    }
    SetRemote(h.TakeChannel());
    return ZX_OK;
}

zx_status_t CreateFilesystem(const char* name, memfs::Vfs* vfs, fbl::RefPtr<VnodeDir>* out) {
    zx_status_t status;
    if ((status = vfs->FillFsId()) != ZX_OK) {
        return status;
    }
    fbl::AllocChecker ac;
    fbl::RefPtr<VnodeDir> fs = fbl::AdoptRef(new (&ac) VnodeDir(vfs));
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }

    fbl::RefPtr<Dnode> dn = Dnode::Create(name, fs);
    if (dn == nullptr) {
        return ZX_ERR_NO_MEMORY;
    }

    fs->dnode_ = dn; // FS root is directory
    *out = fs;
    return ZX_OK;
}

} // namespace memfs
