/*
* Copyright (c) 2008, XenSource Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of XenSource Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <libaio.h>
#ifdef __linux__
#include <linux/version.h>
#endif
#include "tapdisk.h"
#include "tapdisk-log.h"
#include "tapdisk-queue.h"
#include "tapdisk-filter.h"
#include "tapdisk-server.h"
#include "tapdisk-utils.h"
#include "libaio-compat.h"
#include "atomicio.h"
#define WARN(_f, _a...) tlog_write(TLOG_WARN, _f, ##_a)
#define DBG(_f, _a...) tlog_write(TLOG_DBG, _f, ##_a)
#define ERR(_err, _f, _a...) tlog_error(_err, _f, ##_a)
/*
* We used a kernel patch to return an fd associated with the AIO context
* so that we can concurrently poll on synchronous and async descriptors.
* This is signalled by passing 1 as the io context to io_setup.
*/
#define REQUEST_ASYNC_FD ((io_context_t)1)
static inline void
queue_tiocb(struct tqueue *queue, struct tiocb *tiocb)
{
struct iocb *iocb = &tiocb->iocb;
if (queue->queued) {
struct tiocb *prev = (struct tiocb *)
queue->iocbs[queue->queued - 1]->data;
prev->next = tiocb;
}
queue->iocbs[queue->queued++] = iocb;
}
static inline int
deferred_tiocbs(struct tqueue *queue)
{
return (queue->deferred.head != NULL);
}
static inline void
defer_tiocb(struct tqueue *queue, struct tiocb *tiocb)
{
struct tlist *list = &queue->deferred;
if (!list->head)
list->head = list->tail = tiocb;
else
list->tail = list->tail->next = tiocb;
queue->tiocbs_deferred++;
queue->deferrals++;
}
static inline void
queue_deferred_tiocb(struct tqueue *queue)
{
struct tlist *list = &queue->deferred;
if (list->head) {
struct tiocb *tiocb = list->head;
list->head = tiocb->next;
if (!list->head)
list->tail = NULL;
queue_tiocb(queue, tiocb);
queue->tiocbs_deferred--;
}
}
static inline void
queue_deferred_tiocbs(struct tqueue *queue)
{
while (!tapdisk_queue_full(queue) && deferred_tiocbs(queue))