debuggers.hg

view tools/blktap2/drivers/block-aio.c @ 20918:b0ffb4912c46

blktap2: Prefer AIO eventfd support on kernels >= 2.6.22

Mainline kernel support for eventfd(2) in linux aio was added between
2.6.21 and 2.6.22. Libaio after 0.3.107 has the header file, but
presently few systems support it. Neither do we rely on an up-to-date
libc6.

Instead, this patch adds a header which defines custom iocb_common
struct, and works around a potentially missing sys/eventfd.h.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jan 29 08:55:27 2010 +0000 (2010-01-29)
parents b7f73a7f3078
children
line source
1 /*
2 * Copyright (c) 2007, XenSource Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of XenSource Inc. nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
20 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <sys/statvfs.h>
36 #include <sys/stat.h>
37 #include <sys/ioctl.h>
39 #include "blk.h"
40 #include "tapdisk.h"
41 #include "tapdisk-driver.h"
42 #include "tapdisk-interface.h"
44 #define MAX_AIO_REQS TAPDISK_DATA_REQUESTS
46 struct tdaio_state;
48 struct aio_request {
49 td_request_t treq;
50 struct tiocb tiocb;
51 struct tdaio_state *state;
52 };
54 struct tdaio_state {
55 int fd;
56 td_driver_t *driver;
58 int aio_free_count;
59 struct aio_request aio_requests[MAX_AIO_REQS];
60 struct aio_request *aio_free_list[MAX_AIO_REQS];
61 };
63 /*Get Image size, secsize*/
64 static int tdaio_get_image_info(int fd, td_disk_info_t *info)
65 {
66 int ret;
67 long size;
68 unsigned long total_size;
69 struct statvfs statBuf;
70 struct stat stat;
72 ret = fstat(fd, &stat);
73 if (ret != 0) {
74 DPRINTF("ERROR: fstat failed, Couldn't stat image");
75 return -EINVAL;
76 }
78 if (S_ISBLK(stat.st_mode)) {
79 /*Accessing block device directly*/
80 info->size = 0;
81 if (blk_getimagesize(fd, &info->size) != 0)
82 return -EINVAL;
84 DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost "
85 "sector_shift [%llu]\n",
86 (long long unsigned)(info->size << SECTOR_SHIFT),
87 (long long unsigned)info->size);
89 /*Get the sector size*/
90 if (blk_getsectorsize(fd, &info->sector_size) != 0)
91 info->sector_size = DEFAULT_SECTOR_SIZE;
93 } else {
94 /*Local file? try fstat instead*/
95 info->size = (stat.st_size >> SECTOR_SHIFT);
96 info->sector_size = DEFAULT_SECTOR_SIZE;
97 DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost "
98 "sector_shift [%llu]\n",
99 (long long unsigned)(info->size << SECTOR_SHIFT),
100 (long long unsigned)info->size);
101 }
103 if (info->size == 0) {
104 info->size =((uint64_t) 16836057);
105 info->sector_size = DEFAULT_SECTOR_SIZE;
106 }
107 info->info = 0;
109 return 0;
110 }
112 /* Open the disk file and initialize aio state. */
113 int tdaio_open(td_driver_t *driver, const char *name, td_flag_t flags)
114 {
115 int i, fd, ret, o_flags;
116 struct tdaio_state *prv;
118 ret = 0;
119 prv = (struct tdaio_state *)driver->data;
121 DPRINTF("block-aio open('%s')", name);
123 memset(prv, 0, sizeof(struct tdaio_state));
125 prv->aio_free_count = MAX_AIO_REQS;
126 for (i = 0; i < MAX_AIO_REQS; i++)
127 prv->aio_free_list[i] = &prv->aio_requests[i];
129 /* Open the file */
130 o_flags = O_DIRECT | O_LARGEFILE |
131 ((flags & TD_OPEN_RDONLY) ? O_RDONLY : O_RDWR);
132 fd = open(name, o_flags);
134 if ( (fd == -1) && (errno == EINVAL) ) {
136 /* Maybe O_DIRECT isn't supported. */
137 o_flags &= ~O_DIRECT;
138 fd = open(name, o_flags);
139 if (fd != -1) DPRINTF("WARNING: Accessing image without"
140 "O_DIRECT! (%s)\n", name);
142 } else if (fd != -1) DPRINTF("open(%s) with O_DIRECT\n", name);
144 if (fd == -1) {
145 DPRINTF("Unable to open [%s] (%d)!\n", name, 0 - errno);
146 ret = 0 - errno;
147 goto done;
148 }
150 ret = tdaio_get_image_info(fd, &driver->info);
151 if (ret) {
152 close(fd);
153 goto done;
154 }
156 prv->fd = fd;
158 done:
159 return ret;
160 }
162 void tdaio_complete(void *arg, struct tiocb *tiocb, int err)
163 {
164 struct aio_request *aio = (struct aio_request *)arg;
165 struct tdaio_state *prv = aio->state;
167 td_complete_request(aio->treq, err);
168 prv->aio_free_list[prv->aio_free_count++] = aio;
169 }
171 void tdaio_queue_read(td_driver_t *driver, td_request_t treq)
172 {
173 int size;
174 uint64_t offset;
175 struct aio_request *aio;
176 struct tdaio_state *prv;
178 prv = (struct tdaio_state *)driver->data;
179 size = treq.secs * driver->info.sector_size;
180 offset = treq.sec * (uint64_t)driver->info.sector_size;
182 if (prv->aio_free_count == 0)
183 goto fail;
185 aio = prv->aio_free_list[--prv->aio_free_count];
186 aio->treq = treq;
187 aio->state = prv;
189 td_prep_read(&aio->tiocb, prv->fd, treq.buf,
190 size, offset, tdaio_complete, aio);
191 td_queue_tiocb(driver, &aio->tiocb);
193 return;
195 fail:
196 td_complete_request(treq, -EBUSY);
197 }
199 void tdaio_queue_write(td_driver_t *driver, td_request_t treq)
200 {
201 int size;
202 uint64_t offset;
203 struct aio_request *aio;
204 struct tdaio_state *prv;
206 prv = (struct tdaio_state *)driver->data;
207 size = treq.secs * driver->info.sector_size;
208 offset = treq.sec * (uint64_t)driver->info.sector_size;
210 if (prv->aio_free_count == 0)
211 goto fail;
213 aio = prv->aio_free_list[--prv->aio_free_count];
214 aio->treq = treq;
215 aio->state = prv;
217 td_prep_write(&aio->tiocb, prv->fd, treq.buf,
218 size, offset, tdaio_complete, aio);
219 td_queue_tiocb(driver, &aio->tiocb);
221 return;
223 fail:
224 td_complete_request(treq, -EBUSY);
225 }
227 int tdaio_close(td_driver_t *driver)
228 {
229 struct tdaio_state *prv = (struct tdaio_state *)driver->data;
231 close(prv->fd);
233 return 0;
234 }
236 int tdaio_get_parent_id(td_driver_t *driver, td_disk_id_t *id)
237 {
238 return TD_NO_PARENT;
239 }
241 int tdaio_validate_parent(td_driver_t *driver,
242 td_driver_t *pdriver, td_flag_t flags)
243 {
244 return -EINVAL;
245 }
247 struct tap_disk tapdisk_aio = {
248 .disk_type = "tapdisk_aio",
249 .flags = 0,
250 .private_data_size = sizeof(struct tdaio_state),
251 .td_open = tdaio_open,
252 .td_close = tdaio_close,
253 .td_queue_read = tdaio_queue_read,
254 .td_queue_write = tdaio_queue_write,
255 .td_get_parent_id = tdaio_get_parent_id,
256 .td_validate_parent = tdaio_validate_parent,
257 .td_debug = NULL,
258 };