ia64/xen-unstable

view tools/blktap/drivers/tapaio.c @ 15783:c93e2a822d6f

[xen, xencomm] xencomm multiple page support
Current implementation doesn't allow struct xencomm_desc::address
array to be more than single page. On IA64 it causes 64GB+ domain
creation failure. This patch generalizes xencomm to allow multipage

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author kfraser@localhost.localdomain
date Tue Aug 28 15:32:27 2007 +0100 (2007-08-28)
parents eeeb77195ac2
children 003542d9ab77
line source
1 /*
2 * Copyright (c) 2006 Andrew Warfield and Julian Chesterfield
3 * Copyright (c) 2007 Red Hat, Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation; or, when distributed
8 * separately from the Linux kernel or incorporated into other
9 * software packages, subject to the following license:
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this source file (the "Software"), to deal in the Software without
13 * restriction, including without limitation the rights to use, copy, modify,
14 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
15 * and to permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 * IN THE SOFTWARE.
28 */
30 #include "tapaio.h"
31 #include "tapdisk.h"
32 #include <unistd.h>
34 /**
35 * We used a kernel patch to return an fd associated with the AIO context
36 * so that we can concurrently poll on synchronous and async descriptors.
37 * This is signalled by passing 1 as the io context to io_setup.
38 */
39 #define REQUEST_ASYNC_FD 1
41 /*
42 * If we don't have any way to do epoll on aio events in a normal kernel,
43 * wait for aio events in a separate thread and return completion status
44 * that via a pipe that can be waited on normally.
45 *
46 * To keep locking problems between the completion thread and the submit
47 * thread to a minimum, there's a handshake which allows only one thread
48 * to be doing work on the completion queue at a time:
49 *
50 * 1) main thread sends completion thread a command via the command pipe;
51 * 2) completion thread waits for aio events and returns the number
52 * received on the completion pipe
53 * 3) main thread processes the received ctx->aio_events events
54 * 4) loop back to 1) to let the completion thread refill the aio_events
55 * buffer.
56 *
57 * This workaround needs to disappear once the kernel provides a single
58 * mechanism for waiting on both aio and normal fd wakeups.
59 */
60 static void *
61 tap_aio_completion_thread(void *arg)
62 {
63 tap_aio_context_t *ctx = (tap_aio_context_t *) arg;
64 int command;
65 int nr_events;
66 int rc;
68 while (1) {
69 rc = read(ctx->command_fd[0], &command, sizeof(command));
71 do {
72 rc = io_getevents(ctx->aio_ctx, 1,
73 ctx->max_aio_events, ctx->aio_events,
74 NULL);
75 if (rc) {
76 nr_events = rc;
77 rc = write(ctx->completion_fd[1], &nr_events,
78 sizeof(nr_events));
79 }
80 } while (!rc);
81 }
82 }
84 void
85 tap_aio_continue(tap_aio_context_t *ctx)
86 {
87 int cmd = 0;
89 if (!ctx->poll_in_thread)
90 return;
92 if (write(ctx->command_fd[1], &cmd, sizeof(cmd)) < 0)
93 DPRINTF("Cannot write to command pipe\n");
94 }
96 int
97 tap_aio_setup(tap_aio_context_t *ctx,
98 struct io_event *aio_events,
99 int max_aio_events)
100 {
101 int ret;
103 ctx->aio_events = aio_events;
104 ctx->max_aio_events = max_aio_events;
105 ctx->poll_in_thread = 0;
107 ctx->aio_ctx = (io_context_t) REQUEST_ASYNC_FD;
108 ret = io_setup(ctx->max_aio_events, &ctx->aio_ctx);
109 if (ret < 0 && ret != -EINVAL)
110 return ret;
111 else if (ret > 0) {
112 ctx->pollfd = ret;
113 return ctx->pollfd;
114 }
116 ctx->aio_ctx = (io_context_t) 0;
117 ret = io_setup(ctx->max_aio_events, &ctx->aio_ctx);
118 if (ret < 0)
119 return ret;
121 if ((ret = pipe(ctx->command_fd)) < 0) {
122 DPRINTF("Unable to create command pipe\n");
123 return -1;
124 }
125 if ((ret = pipe(ctx->completion_fd)) < 0) {
126 DPRINTF("Unable to create completion pipe\n");
127 return -1;
128 }
130 if ((ret = pthread_create(&ctx->aio_thread, NULL,
131 tap_aio_completion_thread, ctx)) != 0) {
132 DPRINTF("Unable to create completion thread\n");
133 return -1;
134 }
136 ctx->pollfd = ctx->completion_fd[0];
137 ctx->poll_in_thread = 1;
139 tap_aio_continue(ctx);
141 return 0;
142 }
144 int
145 tap_aio_get_events(tap_aio_context_t *ctx)
146 {
147 int nr_events = 0;
149 if (!ctx->poll_in_thread)
150 nr_events = io_getevents(ctx->aio_ctx, 1,
151 ctx->max_aio_events, ctx->aio_events, NULL);
152 else
153 read(ctx->completion_fd[0], &nr_events, sizeof(nr_events));
155 return nr_events;
156 }
158 int tap_aio_more_events(tap_aio_context_t *ctx)
159 {
160 return io_getevents(ctx->aio_ctx, 0,
161 ctx->max_aio_events, ctx->aio_events, NULL);
162 }