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

#include <stdbool.h>
#include <string.h>

// DDK Includes
#include <ddk/device.h>
#include <ddk/protocol/block.h>
#include <ddk/debug.h>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_call.h>
#include <fbl/auto_lock.h>
#include <fbl/limits.h>
#include <fbl/new.h>
#include <fbl/ref_ptr.h>
#include <zircon/compiler.h>
#include <zircon/device/block.h>
#include <zircon/syscalls.h>
#include <lib/zx/fifo.h>

// Tracing Includes
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/async/cpp/time.h>
#include <trace-provider/provider.h>
#include <trace/event.h>

#include "server.h"

namespace {

// This signal is set on the FIFO when the server should be instructed
// to terminate.
constexpr zx_signals_t kSignalFifoTerminate   = ZX_USER_SIGNAL_0;
// This signal is set on the FIFO when, after the thread enqueueing operations
// has encountered a barrier, all prior operations have completed.
constexpr zx_signals_t kSignalFifoOpsComplete = ZX_USER_SIGNAL_1;
// Signalled on the fifo when it has finished terminating.
// (If we need to free up user signals, this could easily be transformed
// into a completion object).
constexpr zx_signals_t kSignalFifoTerminated  = ZX_USER_SIGNAL_2;

void OutOfBandRespond(const fzl::fifo<block_fifo_response_t, block_fifo_request_t>& fifo,
                      zx_status_t status, txnid_t txnid) {
    block_fifo_response_t response;
    response.status = status;
    response.txnid = txnid;
    response.count = 0;

    status = fifo.write_one(response);
    if (status != ZX_OK) {
        fprintf(stderr, "Block Server I/O error: Could not write response\n");
    }
}

void BlockComplete(BlockMsg* msg, zx_status_t status) {
    auto extra = msg->extra();
    // Since iobuf is a RefPtr, it lives at least as long as the txn,
    // and is not discarded underneath the block device driver.
    extra->iobuf = nullptr;
    extra->server->TxnEnd();
    extra->txn->Complete(status);
}

void BlockCompleteCb(block_op_t* bop, zx_status_t status) {
    ZX_DEBUG_ASSERT(bop != nullptr);
    BlockMsg msg(static_cast<block_msg_t*>(bop->cookie));
    BlockComplete(&msg, status);
}

uint32_t OpcodeToCommand(uint32_t opcode) {
    // TODO(ZX-1826): Unify block protocol and block device interface
    static_assert(BLOCK_OP_READ == BLOCKIO_READ, "");
    static_assert(BLOCK_OP_WRITE == BLOCKIO_WRITE, "");
    static_assert(BLOCK_OP_FLUSH == BLOCKIO_FLUSH, "");
    static_assert(BLOCK_FL_BARRIER_BEFORE == BLOCKIO_BARRIER_BEFORE, "");
    static_assert(BLOCK_FL_BARRIER_AFTER == BLOCKIO_BARRIER_AFTER, "");
    const uint32_t shared = BLOCK_OP_READ | BLOCK_OP_WRITE | BLOCK_OP_FLUSH |
            BLOCK_FL_BARRIER_BEFORE | BLOCK_FL_BARRIER_AFTER;
    return opcode & shared;
}

void InQueueAdd(zx_handle_t vmo, uint64_t length, uint64_t vmo_offset,
                uint64_t dev_offset, block_msg_t* msg, BlockMsgQueue* queue) {
    block_op_t* bop = &msg->op;
    bop->rw.length = (uint32_t) length;
    bop->rw.vmo = vmo;
    bop->rw.offset_dev = dev_offset;
    bop->rw.offset_vmo = vmo_offset;
    bop->rw.pages = NULL;
    bop->completion_cb = BlockCompleteCb;
    bop->cookie = msg;
    queue->push_back(msg);
}

}  // namespace


async::Loop loop;
trace::TraceProvider provider(loop.async());

/*
zx_status_t status;
async_loop_t* loop;
trace_provider_t* trace_provider;
trace_async_id_t async_id;


void register_trace(void) {
    // Create a message loop.
    status = async_loop_create(NULL, &loop);
    if (status != ZX_OK) {
        zxlogf(ERROR, "Failed to create a message loop.\n");
        zxlogf(ERROR, "----------Failed to register the tracing interface.----------\n");
        return;
    }

    // Start a thread for the loop to run on.
    // We could instead use async_loop_run() to run on the current thread.
    status = async_loop_start_thread(loop, "loop", NULL);
    if (status != ZX_OK) {
        zxlogf(ERROR, "Failed to start a thread.\n");
        zxlogf(ERROR, "----------Failed to register the tracing interface.----------\n");
        return;
    } 

    // Create the trace provider.
    async_t* async = async_loop_get_dispatcher(loop);
    trace_provider = trace_provider_create(async);
    if (!trace_provider) {
        zxlogf(ERROR, "Failed to create a trace provider.\n");
        zxlogf(ERROR, "----------Failed to register the tracing interface.----------\n");
    }

    zxlogf(TRACE, "----------Tracing interface is registered successfully!-------\n");
}

void close_trace(void) {
    trace_provider_destroy(trace_provider);
    async_loop_shutdown(loop);
    zxlogf(TRACE, "----------Tracing interface is closed successfully!----------\n");
}
*/
TransactionGroup::TransactionGroup(zx_handle_t fifo, txnid_t txnid) :
    fifo_(fifo), flags_(0), ctr_(0) {
    memset(&response_, 0, sizeof(response_));
    response_.txnid = txnid;
}

TransactionGroup::~TransactionGroup() {}

zx_status_t TransactionGroup::Enqueue(bool do_respond) {
    
    fbl::AutoLock lock(&lock_);
    if (flags_ & kTxnFlagRespond) {
        // Can't get more than one response for a txn
        response_.status = ZX_ERR_IO;
        goto fail;
    } else if (response_.status != ZX_OK) {
        // This operation already failed; don't bother enqueueing it.
        goto fail;
    }
    ctr_++;
    if (do_respond) {
        SetResponseReadyLocked();
    }
    return ZX_OK;
fail:
    if (do_respond) {
        SetResponseReadyLocked();
    }
    return ZX_ERR_IO;
}

void TransactionGroup::CtrAdd(uint32_t n) {
    fbl::AutoLock lock(&lock_);
    ctr_ += n;
}

void TransactionGroup::SetResponse(zx_status_t status, bool ready_to_send) {
    fbl::AutoLock lock(&lock_);

    if (response_.status == ZX_OK) {
        response_.status = status;
    }
    if (ready_to_send) {
        SetResponseReadyLocked();
    }
}

void TransactionGroup::SetResponseReadyLocked() {
    flags_ |= kTxnFlagRespond;
    if (response_.count == ctr_) {
        RespondLocked();
    }
}

void TransactionGroup::RespondLocked() {
    zx_status_t status = zx_fifo_write(fifo_, sizeof(response_), &response_, 1, nullptr);
    if (status != ZX_OK) {
        fprintf(stderr, "Block Server I/O error: Could not write response\n");
    }
    response_.count = 0;
    response_.status = ZX_OK;
    ctr_ = 0;
    flags_ &= ~kTxnFlagRespond;
}

void TransactionGroup::Complete(zx_status_t status) {
    fbl::AutoLock lock(&lock_);
    if ((status != ZX_OK) && (response_.status == ZX_OK)) {
        response_.status = status;
    }

    response_.count++;
    ZX_DEBUG_ASSERT(ctr_ != 0);
    ZX_DEBUG_ASSERT(response_.count <= ctr_);

    if ((flags_ & kTxnFlagRespond) && (response_.count == ctr_)) {
        RespondLocked();
    }
}

IoBuffer::IoBuffer(zx::vmo vmo, vmoid_t id) : io_vmo_(fbl::move(vmo)), vmoid_(id) {}

IoBuffer::~IoBuffer() {}

zx_status_t IoBuffer::ValidateVmoHack(uint64_t length, uint64_t vmo_offset) {
    uint64_t vmo_size;
    zx_status_t status;
    if ((status = io_vmo_.get_size(&vmo_size)) != ZX_OK) {
        return status;
    } else if ((vmo_offset > vmo_size) || (vmo_size - vmo_offset < length)) {
        return ZX_ERR_OUT_OF_RANGE;
    }
    return ZX_OK;
}

void BlockServer::BarrierComplete() {
    // This is the only location that unsets the OpsComplete
    // signal. We'll never "miss" a signal, because we process
    // the queue AFTER unsetting it.
    barrier_in_progress_.store(false);
    fifo_.signal(kSignalFifoOpsComplete, 0);
    InQueueDrainer();
}

void BlockServer::TerminateQueue() {
    InQueueDrainer();
    while (true) {
        if (pending_count_.load() == 0 && in_queue_.is_empty()) {
            return;
        }
        zx_signals_t signals = kSignalFifoOpsComplete;
        zx_signals_t seen = 0;
        fifo_.wait_one(signals, zx::deadline_after(zx::msec(10)), &seen);
        if (seen & kSignalFifoOpsComplete) {
            BarrierComplete();
        }
    }
}

zx_status_t BlockServer::Read(block_fifo_request_t* requests, size_t* count) {
    auto cleanup = fbl::MakeAutoCall([this]() {
        TerminateQueue();
        ZX_ASSERT(pending_count_.load() == 0);
        ZX_ASSERT(in_queue_.is_empty());
        fifo_.signal(0, kSignalFifoTerminated);
    });

    // Keep trying to read messages from the fifo until we have a reason to
    // terminate
    zx_status_t status;
    while (true) {
        status = fifo_.read(requests, BLOCK_FIFO_MAX_DEPTH, count);
        zx_signals_t signals;
        zx_signals_t seen;
        switch (status) {
        case ZX_ERR_SHOULD_WAIT:
            signals = ZX_FIFO_READABLE | ZX_FIFO_PEER_CLOSED |
                    kSignalFifoTerminate | kSignalFifoOpsComplete;
            if ((status = fifo_.wait_one(signals, zx::time::infinite(), &seen)) != ZX_OK) {
                return status;
            }
            if (seen & kSignalFifoOpsComplete) {
                BarrierComplete();
                continue;
            }
            if ((seen & ZX_FIFO_PEER_CLOSED) || (seen & kSignalFifoTerminate)) {
                return ZX_ERR_PEER_CLOSED;
            }
            // Try reading again...
            break;
        case ZX_OK:
            cleanup.cancel();
            return ZX_OK;
        default:
            return status;
        }
    }
}

zx_status_t BlockServer::FindVmoIDLocked(vmoid_t* out) {
    for (vmoid_t i = last_id_; i < fbl::numeric_limits<vmoid_t>::max(); i++) {
        if (!tree_.find(i).IsValid()) {
            *out = i;
            last_id_ = static_cast<vmoid_t>(i + 1);
            return ZX_OK;
        }
    }
    for (vmoid_t i = VMOID_INVALID + 1; i < last_id_; i++) {
        if (!tree_.find(i).IsValid()) {
            *out = i;
            last_id_ = static_cast<vmoid_t>(i + 1);
            return ZX_OK;
        }
    }
    return ZX_ERR_NO_RESOURCES;
}

zx_status_t BlockServer::AttachVmo(zx::vmo vmo, vmoid_t* out) {
    zx_status_t status;
    vmoid_t id;
    fbl::AutoLock server_lock(&server_lock_);
    if ((status = FindVmoIDLocked(&id)) != ZX_OK) {
        return status;
    }

    fbl::AllocChecker ac;
    fbl::RefPtr<IoBuffer> ibuf = fbl::AdoptRef(new (&ac) IoBuffer(fbl::move(vmo), id));
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }
    tree_.insert(fbl::move(ibuf));
    *out = id;
    return ZX_OK;
}

zx_status_t BlockServer::AllocateTxn(txnid_t* out) {
    fbl::AutoLock server_lock(&server_lock_);
    for (size_t i = 0; i < fbl::count_of(txns_); i++) {
        if (txns_[i] == nullptr) {
            txnid_t txnid = static_cast<txnid_t>(i);
            fbl::AllocChecker ac;
            txns_[i] = fbl::AdoptRef(new (&ac) TransactionGroup(fifo_.get_handle(), txnid));
            if (!ac.check()) {
                return ZX_ERR_NO_MEMORY;
            }
            *out = txnid;
            return ZX_OK;
        }
    }
    return ZX_ERR_NO_RESOURCES;
}

void BlockServer::FreeTxn(txnid_t txnid) {
    fbl::AutoLock server_lock(&server_lock_);
    if (txnid >= fbl::count_of(txns_)) {
        return;
    }
    ZX_DEBUG_ASSERT(txns_[txnid] != nullptr);
    txns_[txnid] = nullptr;
}

void BlockServer::TxnEnd() {
    size_t old_count = pending_count_.fetch_sub(1);
    ZX_ASSERT(old_count > 0);
    if ((old_count == 1) && barrier_in_progress_.load()) {
        // Since we're avoiding locking, and there is a gap between
        // "pending count decremented" and "FIFO signalled", it's possible
        // that we'll receive spurious wakeup requests.
        fifo_.signal(0, kSignalFifoOpsComplete);
    }
}

void BlockServer::InQueueDrainer() {
    while (true) {
        if (in_queue_.is_empty()) {
            return;
        }

        auto msg = in_queue_.begin();
        if (deferred_barrier_before_) {
            msg->op.command |= BLOCK_FL_BARRIER_BEFORE;
            deferred_barrier_before_ = false;
        }

        if (msg->op.command & BLOCK_FL_BARRIER_BEFORE) {
            barrier_in_progress_.store(true);
            if (pending_count_.load() > 0) {
                return;
            }
            // Since we're the only thread that could add to pending
            // count, we reliably know it has terminated.
            barrier_in_progress_.store(false);
        }
        if (msg->op.command & BLOCK_FL_BARRIER_AFTER) {
            deferred_barrier_before_ = true;
        }
        pending_count_.fetch_add(1);
        in_queue_.pop_front();
        // Underlying block device drivers should not see block barriers
        // which are already handled by the block midlayer.
        //
        // This may be altered in the future if block devices
        // are capable of implementing hardware barriers.
        msg->op.command &= ~(BLOCK_FL_BARRIER_BEFORE | BLOCK_FL_BARRIER_AFTER);
        bp_.ops->queue(bp_.ctx, &msg->op);
    }
}

zx_status_t BlockServer::Create(zx_device_t* dev, block_protocol_t* bp,
                                fzl::fifo<block_fifo_request_t, block_fifo_response_t>* fifo_out,
                                BlockServer** out) {
    fbl::AllocChecker ac;
    BlockServer* bs = new (&ac) BlockServer(dev, bp);
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }

    zx_status_t status;
    if ((status = fzl::create_fifo(BLOCK_FIFO_MAX_DEPTH, 0, fifo_out, &bs->fifo_)) != ZX_OK) {
        delete bs;
        return status;
    }

    // Notably, drop ZX_RIGHT_SIGNAL_PEER, since we use bs->fifo for thread
    // signalling internally within the block server.
    zx_rights_t rights = ZX_RIGHT_TRANSFER | ZX_RIGHT_READ | ZX_RIGHT_WRITE |
            ZX_RIGHT_SIGNAL | ZX_RIGHT_WAIT;
    if ((status = fifo_out->replace(rights, fifo_out)) != ZX_OK) {
        delete bs;
        return status;
    }

    if (bp->ops != NULL) {
        bp->ops->query(bp->ctx, &bs->info_, &bs->block_op_size_);
    }

    *out = bs;
    return ZX_OK;
}

zx_status_t BlockServer::Serve() {
    zx_status_t status;
    block_fifo_request_t requests[BLOCK_FIFO_MAX_DEPTH];
    size_t count;
    while (true) {
        // Attempt to drain as much of the input queue as possible
        // before (potentially) blocking in Read.
        InQueueDrainer();

        if ((status = Read(requests, &count) != ZX_OK)) {
            return status;
        }

        for (size_t i = 0; i < count; i++) {
            bool wants_reply = requests[i].opcode & BLOCKIO_TXN_END;
            txnid_t txnid = requests[i].txnid;
            vmoid_t vmoid = requests[i].vmoid;

            // TODO(ZX-1586): Remove this lock once txns are preallocated.
            fbl::AutoLock server_lock(&server_lock_);

            if (txnid >= MAX_TXN_COUNT || txns_[txnid] == nullptr) {
                // Operation which is not accessing a valid txn
                if (wants_reply) {
                    OutOfBandRespond(fifo_, ZX_ERR_IO, txnid);
                }
                continue;
            }

            auto iobuf = tree_.find(vmoid);
            if (!iobuf.IsValid()) {
                // Operation which is not accessing a valid vmo
                txns_[txnid]->SetResponse(ZX_ERR_IO, wants_reply);
                continue;
            }

            switch (requests[i].opcode & BLOCKIO_OP_MASK) {
            case BLOCKIO_READ:
            case BLOCKIO_WRITE: {
                if ((requests[i].length < 1) ||
                    (requests[i].length > fbl::numeric_limits<uint32_t>::max())) {
                    // Operation which is too small or too large
                    txns_[txnid]->SetResponse(ZX_ERR_INVALID_ARGS, wants_reply);
                    continue;
                }

                // Enqueue the message against the transaction group.
                status = txns_[txnid]->Enqueue(wants_reply);
                if (status != ZX_OK) {
                    break;
                }

                // Hack to ensure that the vmo is valid.
                // In the future, this code will be responsible for pinning VMO pages,
                // and the completion will be responsible for un-pinning those same pages.
                size_t bsz = info_.block_size;
                status = iobuf->ValidateVmoHack(bsz * requests[i].length,
                                                bsz * requests[i].vmo_offset);
                if (status != ZX_OK) {
                    txns_[txnid]->Complete(status);
                    break;
                }

                BlockMsg msg;
                if ((status = BlockMsg::Create(block_op_size_, &msg)) != ZX_OK) {
                    txns_[txnid]->Complete(status);
                    break;
                }
                msg.extra()->txn = txns_[txnid];
                msg.extra()->iobuf = iobuf.CopyPointer();
                msg.extra()->server = this;
                msg.op()->command = OpcodeToCommand(requests[i].opcode);

                const uint64_t max_xfer = info_.max_transfer_size / bsz;
                if (max_xfer != 0 && max_xfer < requests[i].length) {
                    uint64_t len_remaining = requests[i].length;
                    uint64_t vmo_offset = requests[i].vmo_offset;
                    uint64_t dev_offset = requests[i].dev_offset;

                    // If the request is larger than the maximum transfer size,
                    // split it up into a collection of smaller block messages.
                    //
                    // Once all of these smaller messages are created, splice
                    // them into the input queue together.
                    BlockMsgQueue sub_txns_queue;
                    uint32_t sub_txns =
                            static_cast<uint32_t>(fbl::round_up(len_remaining,
                                                                max_xfer) / max_xfer);
                    uint32_t sub_txn_idx = 0;
                    while (sub_txn_idx != sub_txns) {
                        // We'll be using a new BlockMsg for each sub-component.
                        if (!msg.valid()) {
                            if ((status = BlockMsg::Create(block_op_size_,
                                                           &msg)) != ZX_OK) {
                                txns_[txnid]->Complete(status);
                                break;
                            }
                            msg.extra()->txn = txns_[txnid];
                            msg.extra()->iobuf = iobuf.CopyPointer();
                            msg.extra()->server = this;
                            msg.op()->command = OpcodeToCommand(requests[i].opcode);
                        }


                        uint64_t length = fbl::min(len_remaining, max_xfer);
                        len_remaining -= length;

                        // Only set the "AFTER" barrier on the last sub-txn.
                        msg.op()->command &= ~(sub_txn_idx == sub_txns - 1 ? 0 :
                                               BLOCK_FL_BARRIER_AFTER);
                        // Only set the "BEFORE" barrier on the first sub-txn.
                        msg.op()->command &= ~(sub_txn_idx == 0 ? 0 :
                                               BLOCK_FL_BARRIER_BEFORE);
                        InQueueAdd(iobuf->vmo(), length, vmo_offset, dev_offset, msg.release(),
                                   &sub_txns_queue);
                        vmo_offset += length;
                        dev_offset += length;
                        sub_txn_idx++;
                    }
                    txns_[txnid]->CtrAdd(sub_txns - 1);
                    ZX_DEBUG_ASSERT(len_remaining == 0);

                    in_queue_.splice(in_queue_.end(), sub_txns_queue);
                } else {
                    InQueueAdd(iobuf->vmo(), requests[i].length, requests[i].vmo_offset,
                               requests[i].dev_offset, msg.release(), &in_queue_);
                }

                break;
            }
            case BLOCKIO_FLUSH: {
                fprintf(stderr, "Warning: BLOCKIO_FLUSH is currently unimplemented\n");
                break;
            }
            case BLOCKIO_CLOSE_VMO: {
                // TODO(smklein): Ensure that "iobuf" is not being used by
                // any in-flight txns.
                tree_.erase(*iobuf);
                txns_[txnid]->SetResponse(ZX_OK, wants_reply);
                break;
            }
            default: {
                fprintf(stderr, "Unrecognized Block Server operation: %x\n",
                        requests[i].opcode);
            }
            }
        }
    }
}

BlockServer::BlockServer(zx_device_t* dev, block_protocol_t* bp) :
    dev_(dev), bp_(*bp), block_op_size_(0), pending_count_(0),
    barrier_in_progress_(false), last_id_(VMOID_INVALID + 1) {
    size_t actual;
    device_ioctl(dev_, IOCTL_BLOCK_GET_INFO, nullptr, 0, &info_, sizeof(info_), &actual);
}

BlockServer::~BlockServer() {
    ZX_ASSERT(pending_count_.load() == 0);
    ZX_ASSERT(in_queue_.is_empty());
}

void BlockServer::ShutDown() {
    // Identify that the server should stop reading and return,
    // implicitly closing the fifo.
    fifo_.signal(0, kSignalFifoTerminate);
    zx_signals_t signals = kSignalFifoTerminated;
    zx_signals_t seen;
    fifo_.wait_one(signals, zx::time::infinite(), &seen);
}

// C declarations
zx_status_t blockserver_create(zx_device_t* dev, block_protocol_t* bp,
                               zx_handle_t* fifo_out, BlockServer** out) {
    fzl::fifo<block_fifo_request_t, block_fifo_response_t> fifo;
    zx_status_t status = BlockServer::Create(dev, bp, &fifo, out);
    *fifo_out = fifo.release();
    return status;
}
void blockserver_shutdown(BlockServer* bs) {
    bs->ShutDown();
}
void blockserver_free(BlockServer* bs) {
    delete bs;
}
zx_status_t blockserver_serve(BlockServer* bs) {
    return bs->Serve();
}
zx_status_t blockserver_attach_vmo(BlockServer* bs, zx_handle_t raw_vmo, vmoid_t* out) {
    zx::vmo vmo(raw_vmo);
    return bs->AttachVmo(fbl::move(vmo), out);
}
zx_status_t blockserver_allocate_txn(BlockServer* bs, txnid_t* out) {
    return bs->AllocateTxn(out);
}
void blockserver_free_txn(BlockServer* bs, txnid_t txnid) {
    return bs->FreeTxn(txnid);
}
