Commit 221f715d90ec5fec569a19119887445c037bca86
1 parent
64a7fde8
new scsi-generic abstraction, use SG_IO (Christoph Hellwig)
Okay, I started looking into how to handle scsi-generic I/O in the new world order. I think the best is to use the SG_IO ioctl instead of the read/write interface as that allows us to support scsi passthrough on disk/cdrom devices, too. See Hannes patch on the kvm list from August for an example. Now that we always do ioctls we don't need another abstraction than bdrv_ioctl for the synchronous requests for now, and for asynchronous requests I've added a aio_ioctl abstraction keeping it simple. Long-term we might want to move the ops to a higher-level abstraction and let the low-level code fill out the request header, but I'm lazy enough to leave that to the people trying to support scsi-passthrough on a non-Linux OS. Tested lightly by issuing various sg_ commands from sg3-utils in a guest to a host CDROM device. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6895 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
115 additions
and
137 deletions
block-raw-posix.c
@@ -1209,6 +1209,26 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) | @@ -1209,6 +1209,26 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) | ||
1209 | 1209 | ||
1210 | return ioctl(s->fd, req, buf); | 1210 | return ioctl(s->fd, req, buf); |
1211 | } | 1211 | } |
1212 | + | ||
1213 | +static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, | ||
1214 | + unsigned long int req, void *buf, | ||
1215 | + BlockDriverCompletionFunc *cb, void *opaque) | ||
1216 | +{ | ||
1217 | + RawAIOCB *acb; | ||
1218 | + | ||
1219 | + acb = raw_aio_setup(bs, 0, buf, 0, cb, opaque); | ||
1220 | + if (!acb) | ||
1221 | + return NULL; | ||
1222 | + | ||
1223 | + acb->aiocb.aio_ioctl_cmd = req; | ||
1224 | + if (qemu_paio_ioctl(&acb->aiocb) < 0) { | ||
1225 | + raw_aio_remove(acb); | ||
1226 | + return NULL; | ||
1227 | + } | ||
1228 | + | ||
1229 | + return &acb->common; | ||
1230 | +} | ||
1231 | + | ||
1212 | #elif defined(__FreeBSD__) | 1232 | #elif defined(__FreeBSD__) |
1213 | 1233 | ||
1214 | static int fd_open(BlockDriverState *bs) | 1234 | static int fd_open(BlockDriverState *bs) |
@@ -1349,33 +1369,14 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) | @@ -1349,33 +1369,14 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) | ||
1349 | { | 1369 | { |
1350 | return -ENOTSUP; | 1370 | return -ENOTSUP; |
1351 | } | 1371 | } |
1352 | -#endif /* !linux && !FreeBSD */ | ||
1353 | - | ||
1354 | -static int raw_sg_send_command(BlockDriverState *bs, void *buf, int count) | ||
1355 | -{ | ||
1356 | - return raw_pwrite(bs, -1, buf, count); | ||
1357 | -} | ||
1358 | - | ||
1359 | -static int raw_sg_recv_response(BlockDriverState *bs, void *buf, int count) | ||
1360 | -{ | ||
1361 | - return raw_pread(bs, -1, buf, count); | ||
1362 | -} | ||
1363 | - | ||
1364 | -static BlockDriverAIOCB *raw_sg_aio_read(BlockDriverState *bs, | ||
1365 | - void *buf, int count, | ||
1366 | - BlockDriverCompletionFunc *cb, | ||
1367 | - void *opaque) | ||
1368 | -{ | ||
1369 | - return raw_aio_read(bs, 0, buf, -(int64_t)count, cb, opaque); | ||
1370 | -} | ||
1371 | 1372 | ||
1372 | -static BlockDriverAIOCB *raw_sg_aio_write(BlockDriverState *bs, | ||
1373 | - void *buf, int count, | ||
1374 | - BlockDriverCompletionFunc *cb, | ||
1375 | - void *opaque) | 1373 | +static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, |
1374 | + unsigned long int req, void *buf, | ||
1375 | + BlockDriverCompletionFunc *cb, void *opaque) | ||
1376 | { | 1376 | { |
1377 | - return raw_aio_write(bs, 0, buf, -(int64_t)count, cb, opaque); | 1377 | + return -ENOTSUP; |
1378 | } | 1378 | } |
1379 | +#endif /* !linux && !FreeBSD */ | ||
1379 | 1380 | ||
1380 | BlockDriver bdrv_host_device = { | 1381 | BlockDriver bdrv_host_device = { |
1381 | .format_name = "host_device", | 1382 | .format_name = "host_device", |
@@ -1402,8 +1403,5 @@ BlockDriver bdrv_host_device = { | @@ -1402,8 +1403,5 @@ BlockDriver bdrv_host_device = { | ||
1402 | .bdrv_set_locked = raw_set_locked, | 1403 | .bdrv_set_locked = raw_set_locked, |
1403 | /* generic scsi device */ | 1404 | /* generic scsi device */ |
1404 | .bdrv_ioctl = raw_ioctl, | 1405 | .bdrv_ioctl = raw_ioctl, |
1405 | - .bdrv_sg_send_command = raw_sg_send_command, | ||
1406 | - .bdrv_sg_recv_response = raw_sg_recv_response, | ||
1407 | - .bdrv_sg_aio_read = raw_sg_aio_read, | ||
1408 | - .bdrv_sg_aio_write = raw_sg_aio_write, | 1406 | + .bdrv_aio_ioctl = raw_aio_ioctl, |
1409 | }; | 1407 | }; |
block.c
@@ -1633,24 +1633,13 @@ int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) | @@ -1633,24 +1633,13 @@ int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) | ||
1633 | return -ENOTSUP; | 1633 | return -ENOTSUP; |
1634 | } | 1634 | } |
1635 | 1635 | ||
1636 | -int bdrv_sg_send_command(BlockDriverState *bs, void *buf, int count) | ||
1637 | -{ | ||
1638 | - return bs->drv->bdrv_sg_send_command(bs, buf, count); | ||
1639 | -} | ||
1640 | - | ||
1641 | -int bdrv_sg_recv_response(BlockDriverState *bs, void *buf, int count) | ||
1642 | -{ | ||
1643 | - return bs->drv->bdrv_sg_recv_response(bs, buf, count); | ||
1644 | -} | ||
1645 | - | ||
1646 | -BlockDriverAIOCB *bdrv_sg_aio_read(BlockDriverState *bs, void *buf, int count, | ||
1647 | - BlockDriverCompletionFunc *cb, void *opaque) | 1636 | +BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, |
1637 | + unsigned long int req, void *buf, | ||
1638 | + BlockDriverCompletionFunc *cb, void *opaque) | ||
1648 | { | 1639 | { |
1649 | - return bs->drv->bdrv_sg_aio_read(bs, buf, count, cb, opaque); | ||
1650 | -} | 1640 | + BlockDriver *drv = bs->drv; |
1651 | 1641 | ||
1652 | -BlockDriverAIOCB *bdrv_sg_aio_write(BlockDriverState *bs, void *buf, int count, | ||
1653 | - BlockDriverCompletionFunc *cb, void *opaque) | ||
1654 | -{ | ||
1655 | - return bs->drv->bdrv_sg_aio_write(bs, buf, count, cb, opaque); | 1642 | + if (drv && drv->bdrv_aio_ioctl) |
1643 | + return drv->bdrv_aio_ioctl(bs, req, buf, cb, opaque); | ||
1644 | + return NULL; | ||
1656 | } | 1645 | } |
block.h
@@ -102,12 +102,10 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num, | @@ -102,12 +102,10 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num, | ||
102 | void bdrv_aio_cancel(BlockDriverAIOCB *acb); | 102 | void bdrv_aio_cancel(BlockDriverAIOCB *acb); |
103 | 103 | ||
104 | /* sg packet commands */ | 104 | /* sg packet commands */ |
105 | -int bdrv_sg_send_command(BlockDriverState *bs, void *buf, int count); | ||
106 | -int bdrv_sg_recv_response(BlockDriverState *bs, void *buf, int count); | ||
107 | -BlockDriverAIOCB *bdrv_sg_aio_read(BlockDriverState *bs, void *buf, int count, | ||
108 | - BlockDriverCompletionFunc *cb, void *opaque); | ||
109 | -BlockDriverAIOCB *bdrv_sg_aio_write(BlockDriverState *bs, void *buf, int count, | ||
110 | - BlockDriverCompletionFunc *cb, void *opaque); | 105 | +int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf); |
106 | +BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, | ||
107 | + unsigned long int req, void *buf, | ||
108 | + BlockDriverCompletionFunc *cb, void *opaque); | ||
111 | 109 | ||
112 | /* Ensure contents are flushed to disk. */ | 110 | /* Ensure contents are flushed to disk. */ |
113 | void bdrv_flush(BlockDriverState *bs); | 111 | void bdrv_flush(BlockDriverState *bs); |
@@ -169,7 +167,6 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); | @@ -169,7 +167,6 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); | ||
169 | int bdrv_snapshot_list(BlockDriverState *bs, | 167 | int bdrv_snapshot_list(BlockDriverState *bs, |
170 | QEMUSnapshotInfo **psn_info); | 168 | QEMUSnapshotInfo **psn_info); |
171 | char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn); | 169 | char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn); |
172 | -int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf); | ||
173 | 170 | ||
174 | char *get_human_readable_size(char *buf, int buf_size, int64_t size); | 171 | char *get_human_readable_size(char *buf, int buf_size, int64_t size); |
175 | int path_is_absolute(const char *path); | 172 | int path_is_absolute(const char *path); |
block_int.h
@@ -86,16 +86,9 @@ struct BlockDriver { | @@ -86,16 +86,9 @@ struct BlockDriver { | ||
86 | 86 | ||
87 | /* to control generic scsi devices */ | 87 | /* to control generic scsi devices */ |
88 | int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf); | 88 | int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf); |
89 | - int (*bdrv_sg_send_command)(BlockDriverState *bs, void *buf, int count); | ||
90 | - int (*bdrv_sg_recv_response)(BlockDriverState *bs, void *buf, int count); | ||
91 | - BlockDriverAIOCB *(*bdrv_sg_aio_read)(BlockDriverState *bs, | ||
92 | - void *buf, int count, | ||
93 | - BlockDriverCompletionFunc *cb, | ||
94 | - void *opaque); | ||
95 | - BlockDriverAIOCB *(*bdrv_sg_aio_write)(BlockDriverState *bs, | ||
96 | - void *buf, int count, | ||
97 | - BlockDriverCompletionFunc *cb, | ||
98 | - void *opaque); | 89 | + BlockDriverAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs, |
90 | + unsigned long int req, void *buf, | ||
91 | + BlockDriverCompletionFunc *cb, void *opaque); | ||
99 | 92 | ||
100 | AIOPool aio_pool; | 93 | AIOPool aio_pool; |
101 | struct BlockDriver *next; | 94 | struct BlockDriver *next; |
hw/scsi-generic.c
@@ -201,8 +201,6 @@ static int execute_command(BlockDriverState *bdrv, | @@ -201,8 +201,6 @@ static int execute_command(BlockDriverState *bdrv, | ||
201 | SCSIRequest *r, int direction, | 201 | SCSIRequest *r, int direction, |
202 | BlockDriverCompletionFunc *complete) | 202 | BlockDriverCompletionFunc *complete) |
203 | { | 203 | { |
204 | - int ret; | ||
205 | - | ||
206 | r->io_header.interface_id = 'S'; | 204 | r->io_header.interface_id = 'S'; |
207 | r->io_header.dxfer_direction = direction; | 205 | r->io_header.dxfer_direction = direction; |
208 | r->io_header.dxferp = r->buf; | 206 | r->io_header.dxferp = r->buf; |
@@ -215,27 +213,7 @@ static int execute_command(BlockDriverState *bdrv, | @@ -215,27 +213,7 @@ static int execute_command(BlockDriverState *bdrv, | ||
215 | r->io_header.usr_ptr = r; | 213 | r->io_header.usr_ptr = r; |
216 | r->io_header.flags |= SG_FLAG_DIRECT_IO; | 214 | r->io_header.flags |= SG_FLAG_DIRECT_IO; |
217 | 215 | ||
218 | - ret = bdrv_sg_send_command(bdrv, &r->io_header, sizeof(r->io_header)); | ||
219 | - if (ret < 0) { | ||
220 | - BADF("execute_command: write failed ! (%d)\n", errno); | ||
221 | - return -1; | ||
222 | - } | ||
223 | - if (complete == NULL) { | ||
224 | - int ret; | ||
225 | - r->aiocb = NULL; | ||
226 | - while ((ret = bdrv_sg_recv_response(bdrv, &r->io_header, | ||
227 | - sizeof(r->io_header))) < 0 && | ||
228 | - ret == -EINTR) | ||
229 | - ; | ||
230 | - if (ret < 0) { | ||
231 | - BADF("execute_command: read failed !\n"); | ||
232 | - return -1; | ||
233 | - } | ||
234 | - return 0; | ||
235 | - } | ||
236 | - | ||
237 | - r->aiocb = bdrv_sg_aio_read(bdrv, (uint8_t*)&r->io_header, | ||
238 | - sizeof(r->io_header), complete, r); | 216 | + r->aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r); |
239 | if (r->aiocb == NULL) { | 217 | if (r->aiocb == NULL) { |
240 | BADF("execute_command: read failed !\n"); | 218 | BADF("execute_command: read failed !\n"); |
241 | return -1; | 219 | return -1; |
@@ -637,14 +615,7 @@ static int get_blocksize(BlockDriverState *bdrv) | @@ -637,14 +615,7 @@ static int get_blocksize(BlockDriverState *bdrv) | ||
637 | io_header.sbp = sensebuf; | 615 | io_header.sbp = sensebuf; |
638 | io_header.timeout = 6000; /* XXX */ | 616 | io_header.timeout = 6000; /* XXX */ |
639 | 617 | ||
640 | - ret = bdrv_sg_send_command(bdrv, &io_header, sizeof(io_header)); | ||
641 | - if (ret < 0) | ||
642 | - return -1; | ||
643 | - | ||
644 | - while ((ret = bdrv_sg_recv_response(bdrv, &io_header, sizeof(io_header))) < 0 && | ||
645 | - ret == -EINTR) | ||
646 | - ; | ||
647 | - | 618 | + ret = bdrv_ioctl(bdrv, SG_IO, &io_header); |
648 | if (ret < 0) | 619 | if (ret < 0) |
649 | return -1; | 620 | return -1; |
650 | 621 | ||
@@ -675,14 +646,7 @@ static int get_stream_blocksize(BlockDriverState *bdrv) | @@ -675,14 +646,7 @@ static int get_stream_blocksize(BlockDriverState *bdrv) | ||
675 | io_header.sbp = sensebuf; | 646 | io_header.sbp = sensebuf; |
676 | io_header.timeout = 6000; /* XXX */ | 647 | io_header.timeout = 6000; /* XXX */ |
677 | 648 | ||
678 | - ret = bdrv_sg_send_command(bdrv, &io_header, sizeof(io_header)); | ||
679 | - if (ret < 0) | ||
680 | - return -1; | ||
681 | - | ||
682 | - while ((ret = bdrv_sg_recv_response(bdrv, &io_header, sizeof(io_header))) < 0 && | ||
683 | - ret == -EINTR) | ||
684 | - ; | ||
685 | - | 649 | + ret = bdrv_ioctl(bdrv, SG_IO, &io_header); |
686 | if (ret < 0) | 650 | if (ret < 0) |
687 | return -1; | 651 | return -1; |
688 | 652 |
posix-aio-compat.c
@@ -11,6 +11,7 @@ | @@ -11,6 +11,7 @@ | ||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | +#include <sys/ioctl.h> | ||
14 | #include <pthread.h> | 15 | #include <pthread.h> |
15 | #include <unistd.h> | 16 | #include <unistd.h> |
16 | #include <errno.h> | 17 | #include <errno.h> |
@@ -75,6 +76,47 @@ static void thread_create(pthread_t *thread, pthread_attr_t *attr, | @@ -75,6 +76,47 @@ static void thread_create(pthread_t *thread, pthread_attr_t *attr, | ||
75 | if (ret) die2(ret, "pthread_create"); | 76 | if (ret) die2(ret, "pthread_create"); |
76 | } | 77 | } |
77 | 78 | ||
79 | +static size_t handle_aiocb_readwrite(struct qemu_paiocb *aiocb) | ||
80 | +{ | ||
81 | + size_t offset = 0; | ||
82 | + ssize_t len; | ||
83 | + | ||
84 | + while (offset < aiocb->aio_nbytes) { | ||
85 | + if (aiocb->aio_type == QEMU_PAIO_WRITE) | ||
86 | + len = pwrite(aiocb->aio_fildes, | ||
87 | + (const char *)aiocb->aio_buf + offset, | ||
88 | + aiocb->aio_nbytes - offset, | ||
89 | + aiocb->aio_offset + offset); | ||
90 | + else | ||
91 | + len = pread(aiocb->aio_fildes, | ||
92 | + (char *)aiocb->aio_buf + offset, | ||
93 | + aiocb->aio_nbytes - offset, | ||
94 | + aiocb->aio_offset + offset); | ||
95 | + | ||
96 | + if (len == -1 && errno == EINTR) | ||
97 | + continue; | ||
98 | + else if (len == -1) { | ||
99 | + offset = -errno; | ||
100 | + break; | ||
101 | + } else if (len == 0) | ||
102 | + break; | ||
103 | + | ||
104 | + offset += len; | ||
105 | + } | ||
106 | + | ||
107 | + return offset; | ||
108 | +} | ||
109 | + | ||
110 | +static size_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb) | ||
111 | +{ | ||
112 | + int ret; | ||
113 | + | ||
114 | + ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_buf); | ||
115 | + if (ret == -1) | ||
116 | + return -errno; | ||
117 | + return ret; | ||
118 | +} | ||
119 | + | ||
78 | static void *aio_thread(void *unused) | 120 | static void *aio_thread(void *unused) |
79 | { | 121 | { |
80 | pid_t pid; | 122 | pid_t pid; |
@@ -88,8 +130,7 @@ static void *aio_thread(void *unused) | @@ -88,8 +130,7 @@ static void *aio_thread(void *unused) | ||
88 | 130 | ||
89 | while (1) { | 131 | while (1) { |
90 | struct qemu_paiocb *aiocb; | 132 | struct qemu_paiocb *aiocb; |
91 | - size_t offset; | ||
92 | - int ret = 0; | 133 | + size_t ret = 0; |
93 | qemu_timeval tv; | 134 | qemu_timeval tv; |
94 | struct timespec ts; | 135 | struct timespec ts; |
95 | 136 | ||
@@ -109,40 +150,26 @@ static void *aio_thread(void *unused) | @@ -109,40 +150,26 @@ static void *aio_thread(void *unused) | ||
109 | 150 | ||
110 | aiocb = TAILQ_FIRST(&request_list); | 151 | aiocb = TAILQ_FIRST(&request_list); |
111 | TAILQ_REMOVE(&request_list, aiocb, node); | 152 | TAILQ_REMOVE(&request_list, aiocb, node); |
112 | - | ||
113 | - offset = 0; | ||
114 | aiocb->active = 1; | 153 | aiocb->active = 1; |
115 | - | ||
116 | idle_threads--; | 154 | idle_threads--; |
117 | mutex_unlock(&lock); | 155 | mutex_unlock(&lock); |
118 | 156 | ||
119 | - while (offset < aiocb->aio_nbytes) { | ||
120 | - ssize_t len; | ||
121 | - | ||
122 | - if (aiocb->is_write) | ||
123 | - len = pwrite(aiocb->aio_fildes, | ||
124 | - (const char *)aiocb->aio_buf + offset, | ||
125 | - aiocb->aio_nbytes - offset, | ||
126 | - aiocb->aio_offset + offset); | ||
127 | - else | ||
128 | - len = pread(aiocb->aio_fildes, | ||
129 | - (char *)aiocb->aio_buf + offset, | ||
130 | - aiocb->aio_nbytes - offset, | ||
131 | - aiocb->aio_offset + offset); | ||
132 | - | ||
133 | - if (len == -1 && errno == EINTR) | ||
134 | - continue; | ||
135 | - else if (len == -1) { | ||
136 | - offset = -errno; | ||
137 | - break; | ||
138 | - } else if (len == 0) | ||
139 | - break; | ||
140 | - | ||
141 | - offset += len; | ||
142 | - } | 157 | + switch (aiocb->aio_type) { |
158 | + case QEMU_PAIO_READ: | ||
159 | + case QEMU_PAIO_WRITE: | ||
160 | + ret = handle_aiocb_readwrite(aiocb); | ||
161 | + break; | ||
162 | + case QEMU_PAIO_IOCTL: | ||
163 | + ret = handle_aiocb_ioctl(aiocb); | ||
164 | + break; | ||
165 | + default: | ||
166 | + fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type); | ||
167 | + ret = -EINVAL; | ||
168 | + break; | ||
169 | + } | ||
143 | 170 | ||
144 | mutex_lock(&lock); | 171 | mutex_lock(&lock); |
145 | - aiocb->ret = offset; | 172 | + aiocb->ret = ret; |
146 | idle_threads++; | 173 | idle_threads++; |
147 | mutex_unlock(&lock); | 174 | mutex_unlock(&lock); |
148 | 175 | ||
@@ -178,9 +205,9 @@ int qemu_paio_init(struct qemu_paioinit *aioinit) | @@ -178,9 +205,9 @@ int qemu_paio_init(struct qemu_paioinit *aioinit) | ||
178 | return 0; | 205 | return 0; |
179 | } | 206 | } |
180 | 207 | ||
181 | -static int qemu_paio_submit(struct qemu_paiocb *aiocb, int is_write) | 208 | +static int qemu_paio_submit(struct qemu_paiocb *aiocb, int type) |
182 | { | 209 | { |
183 | - aiocb->is_write = is_write; | 210 | + aiocb->aio_type = type; |
184 | aiocb->ret = -EINPROGRESS; | 211 | aiocb->ret = -EINPROGRESS; |
185 | aiocb->active = 0; | 212 | aiocb->active = 0; |
186 | mutex_lock(&lock); | 213 | mutex_lock(&lock); |
@@ -195,12 +222,17 @@ static int qemu_paio_submit(struct qemu_paiocb *aiocb, int is_write) | @@ -195,12 +222,17 @@ static int qemu_paio_submit(struct qemu_paiocb *aiocb, int is_write) | ||
195 | 222 | ||
196 | int qemu_paio_read(struct qemu_paiocb *aiocb) | 223 | int qemu_paio_read(struct qemu_paiocb *aiocb) |
197 | { | 224 | { |
198 | - return qemu_paio_submit(aiocb, 0); | 225 | + return qemu_paio_submit(aiocb, QEMU_PAIO_READ); |
199 | } | 226 | } |
200 | 227 | ||
201 | int qemu_paio_write(struct qemu_paiocb *aiocb) | 228 | int qemu_paio_write(struct qemu_paiocb *aiocb) |
202 | { | 229 | { |
203 | - return qemu_paio_submit(aiocb, 1); | 230 | + return qemu_paio_submit(aiocb, QEMU_PAIO_WRITE); |
231 | +} | ||
232 | + | ||
233 | +int qemu_paio_ioctl(struct qemu_paiocb *aiocb) | ||
234 | +{ | ||
235 | + return qemu_paio_submit(aiocb, QEMU_PAIO_IOCTL); | ||
204 | } | 236 | } |
205 | 237 | ||
206 | ssize_t qemu_paio_return(struct qemu_paiocb *aiocb) | 238 | ssize_t qemu_paio_return(struct qemu_paiocb *aiocb) |
posix-aio-compat.h
@@ -29,12 +29,16 @@ struct qemu_paiocb | @@ -29,12 +29,16 @@ struct qemu_paiocb | ||
29 | int aio_fildes; | 29 | int aio_fildes; |
30 | void *aio_buf; | 30 | void *aio_buf; |
31 | size_t aio_nbytes; | 31 | size_t aio_nbytes; |
32 | +#define aio_ioctl_cmd aio_nbytes /* for QEMU_PAIO_IOCTL */ | ||
32 | int ev_signo; | 33 | int ev_signo; |
33 | off_t aio_offset; | 34 | off_t aio_offset; |
34 | 35 | ||
35 | /* private */ | 36 | /* private */ |
36 | TAILQ_ENTRY(qemu_paiocb) node; | 37 | TAILQ_ENTRY(qemu_paiocb) node; |
37 | - int is_write; | 38 | + int aio_type; |
39 | +#define QEMU_PAIO_READ 0x01 | ||
40 | +#define QEMU_PAIO_WRITE 0x02 | ||
41 | +#define QEMU_PAIO_IOCTL 0x03 | ||
38 | ssize_t ret; | 42 | ssize_t ret; |
39 | int active; | 43 | int active; |
40 | }; | 44 | }; |
@@ -49,6 +53,7 @@ struct qemu_paioinit | @@ -49,6 +53,7 @@ struct qemu_paioinit | ||
49 | int qemu_paio_init(struct qemu_paioinit *aioinit); | 53 | int qemu_paio_init(struct qemu_paioinit *aioinit); |
50 | int qemu_paio_read(struct qemu_paiocb *aiocb); | 54 | int qemu_paio_read(struct qemu_paiocb *aiocb); |
51 | int qemu_paio_write(struct qemu_paiocb *aiocb); | 55 | int qemu_paio_write(struct qemu_paiocb *aiocb); |
56 | +int qemu_paio_ioctl(struct qemu_paiocb *aiocb); | ||
52 | int qemu_paio_error(struct qemu_paiocb *aiocb); | 57 | int qemu_paio_error(struct qemu_paiocb *aiocb); |
53 | ssize_t qemu_paio_return(struct qemu_paiocb *aiocb); | 58 | ssize_t qemu_paio_return(struct qemu_paiocb *aiocb); |
54 | int qemu_paio_cancel(int fd, struct qemu_paiocb *aiocb); | 59 | int qemu_paio_cancel(int fd, struct qemu_paiocb *aiocb); |