blob: 2233488822f33abe829e130f566ab7fba662ed22 [file] [log] [blame]
// 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.
#ifndef SRC_DEVICES_BLOCK_DRIVERS_CORE_SERVER_H_
#define SRC_DEVICES_BLOCK_DRIVERS_CORE_SERVER_H_
#include <fuchsia/hardware/block/c/banjo.h>
#include <fuchsia/hardware/block/cpp/banjo.h>
#include <lib/fzl/fifo.h>
#include <lib/sync/completion.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <lib/zx/vmo.h>
#include <stdio.h>
#include <stdlib.h>
#include <zircon/types.h>
#include <atomic>
#include <new>
#include <utility>
#include <ddktl/device.h>
#include <fbl/condition_variable.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/intrusive_wavl_tree.h>
#include <fbl/mutex.h>
#include <fbl/ref_ptr.h>
#include "iobuffer.h"
#include "message-group.h"
#include "message.h"
class Server {
public:
// Creates a new Server.
static zx_status_t Create(ddk::BlockProtocolClient* bp,
fzl::fifo<block_fifo_request_t, block_fifo_response_t>* fifo_out,
std::unique_ptr<Server>* out);
// This will block until all outstanding messages have been processed.
~Server();
// Starts the Server using the current thread
zx_status_t Serve() TA_EXCL(server_lock_);
zx_status_t AttachVmo(zx::vmo vmo, vmoid_t* out) TA_EXCL(server_lock_) TA_EXCL(server_lock_);
// Updates the total number of pending requests.
void TxnEnd();
// Wrapper around "SendResponse", as a convenience
// for finishing both one-shot and group-based transactions.
void FinishTransaction(zx_status_t status, reqid_t reqid, groupid_t group);
// Send the given response to the client.
void SendResponse(const block_fifo_response_t& response);
// Initiates a shutdown of the server. When this finishes, the server might still be running, but
// it should terminate shortly.
void Shutdown();
// Returns true if the server is about to terminate.
bool WillTerminate() const;
private:
DISALLOW_COPY_ASSIGN_AND_MOVE(Server);
Server(ddk::BlockProtocolClient* bp);
// Helper for processing a single message read from the FIFO.
void ProcessRequest(block_fifo_request_t* request);
zx_status_t ProcessReadWriteRequest(block_fifo_request_t* request);
zx_status_t ProcessCloseVmoRequest(block_fifo_request_t* request);
zx_status_t ProcessFlushRequest(block_fifo_request_t* request);
zx_status_t ProcessTrimRequest(block_fifo_request_t* request);
zx_status_t Read(block_fifo_request_t* requests, size_t* count);
zx_status_t FindVmoIdLocked(vmoid_t* out) TA_REQ(server_lock_);
// Sends the request embedded in the message down to the lower layers.
void Enqueue(std::unique_ptr<Message> message) TA_EXCL(server_lock_);
fzl::fifo<block_fifo_response_t, block_fifo_request_t> fifo_;
block_info_t info_;
ddk::BlockProtocolClient* bp_;
size_t block_op_size_;
// Used to wait for pending_count_ to drop to zero at shutdown time.
fbl::ConditionVariable condition_;
// The number of outstanding requests that have been sent down the stack.
size_t pending_count_ TA_GUARDED(server_lock_);
std::unique_ptr<MessageGroup> groups_[MAX_TXN_GROUP_COUNT];
fbl::Mutex server_lock_;
fbl::WAVLTree<vmoid_t, fbl::RefPtr<IoBuffer>> tree_ TA_GUARDED(server_lock_);
vmoid_t last_id_ TA_GUARDED(server_lock_);
};
#endif // SRC_DEVICES_BLOCK_DRIVERS_CORE_SERVER_H_