// 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 <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <threads.h>

#include <fs/vfs.h>
#include <zircon/thread_annotations.h>
#include <fdio/debug.h>
#include <fdio/remoteio.h>
#include <fdio/vfs.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/ref_ptr.h>
#include <fbl/type_support.h>
#include <fbl/unique_ptr.h>

namespace fs {

// Installs a remote filesystem on vn and adds it to the remote_list_.
zx_status_t Vfs::InstallRemote(fbl::RefPtr<Vnode> vn, MountChannel h) {
    if (vn == nullptr) {
        return ZX_ERR_ACCESS_DENIED;
    }

    // Allocate a node to track the remote handle
    fbl::AllocChecker ac;
    fbl::unique_ptr<MountNode> mount_point(new (&ac) MountNode());
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }
    zx_status_t status = vn->AttachRemote(fbl::move(h));
    if (status != ZX_OK) {
        return status;
    }
    // Save this node in the list of mounted vnodes
    mount_point->SetNode(fbl::move(vn));
    fbl::AutoLock lock(&vfs_lock_);
    remote_list_.push_front(fbl::move(mount_point));
    return ZX_OK;
}

// Installs a remote filesystem on vn and adds it to the remote_list_.
zx_status_t Vfs::InstallRemoteLocked(fbl::RefPtr<Vnode> vn, MountChannel h) {
    if (vn == nullptr) {
        return ZX_ERR_ACCESS_DENIED;
    }

    // Allocate a node to track the remote handle
    fbl::AllocChecker ac;
    fbl::unique_ptr<MountNode> mount_point(new (&ac) MountNode());
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }
    zx_status_t status = vn->AttachRemote(fbl::move(h));
    if (status != ZX_OK) {
        return status;
    }
    // Save this node in the list of mounted vnodes
    mount_point->SetNode(fbl::move(vn));
    remote_list_.push_front(fbl::move(mount_point));
    return ZX_OK;
}

zx_status_t Vfs::MountMkdir(fbl::RefPtr<Vnode> vn, const mount_mkdir_config_t* config) {
    fbl::AutoLock lock(&vfs_lock_);
    const char* name = config->name;
    MountChannel h = MountChannel(config->fs_root);
    zx_status_t r = OpenLocked(vn, &vn, name, &name,
                               O_CREAT | O_RDONLY | O_DIRECTORY | O_NOREMOTE, S_IFDIR);
    ZX_DEBUG_ASSERT(r <= ZX_OK); // Should not be accessing remote nodes
    if (r < 0) {
        return r;
    }
    if (vn->IsRemote()) {
        if (config->flags & MOUNT_MKDIR_FLAG_REPLACE) {
            // There is an old remote handle on this vnode; shut it down and
            // replace it with our own.
            zx::channel old_remote;
            Vfs::UninstallRemoteLocked(vn, &old_remote);
            vfs_unmount_handle(old_remote.release(), 0);
        } else {
            return ZX_ERR_BAD_STATE;
        }
    }
    return Vfs::InstallRemoteLocked(vn, fbl::move(h));
}

zx_status_t Vfs::UninstallRemote(fbl::RefPtr<Vnode> vn, zx::channel* h) {
    fbl::AutoLock lock(&vfs_lock_);
    return UninstallRemoteLocked(fbl::move(vn), h);
}

// Uninstall the remote filesystem mounted on vn. Removes vn from the
// remote_list_, and sends its corresponding filesystem an 'unmount' signal.
zx_status_t Vfs::UninstallRemoteLocked(fbl::RefPtr<Vnode> vn, zx::channel* h) {
    fbl::unique_ptr<MountNode> mount_point;
    {
        mount_point = remote_list_.erase_if([&vn](const MountNode& node) {
            return node.VnodeMatch(vn);
        });
        if (!mount_point) {
            return ZX_ERR_NOT_FOUND;
        }
    }
    *h = mount_point->ReleaseRemote();
    return ZX_OK;
}

// Uninstall all remote filesystems. Acts like 'UninstallRemote' for all
// known remotes.
zx_status_t Vfs::UninstallAll(zx_time_t deadline) {
    fbl::unique_ptr<fs::MountNode> mount_point;
    for (;;) {
        {
            fbl::AutoLock lock(&vfs_lock_);
            mount_point = remote_list_.pop_front();
        }
        if (mount_point) {
            vfs_unmount_handle(mount_point->ReleaseRemote().release(), deadline);
        } else {
            return ZX_OK;
        }
    }
}

} // namespace fs
