| File: | hw/block/xen_disk.c |
| Location: | line 569, column 5 |
| Description: | Null pointer passed as an argument to a 'nonnull' parameter |
| 1 | /* | |||
| 2 | * xen paravirt block device backend | |||
| 3 | * | |||
| 4 | * (c) Gerd Hoffmann <kraxel@redhat.com> | |||
| 5 | * | |||
| 6 | * This program is free software; you can redistribute it and/or modify | |||
| 7 | * it under the terms of the GNU General Public License as published by | |||
| 8 | * the Free Software Foundation; under version 2 of the License. | |||
| 9 | * | |||
| 10 | * This program is distributed in the hope that it will be useful, | |||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| 13 | * GNU General Public License for more details. | |||
| 14 | * | |||
| 15 | * You should have received a copy of the GNU General Public License along | |||
| 16 | * with this program; if not, see <http://www.gnu.org/licenses/>. | |||
| 17 | * | |||
| 18 | * Contributions after 2012-01-13 are licensed under the terms of the | |||
| 19 | * GNU GPL, version 2 or (at your option) any later version. | |||
| 20 | */ | |||
| 21 | ||||
| 22 | #include <stdio.h> | |||
| 23 | #include <stdlib.h> | |||
| 24 | #include <stdarg.h> | |||
| 25 | #include <string.h> | |||
| 26 | #include <unistd.h> | |||
| 27 | #include <signal.h> | |||
| 28 | #include <inttypes.h> | |||
| 29 | #include <time.h> | |||
| 30 | #include <fcntl.h> | |||
| 31 | #include <errno(*__errno_location ()).h> | |||
| 32 | #include <sys/ioctl.h> | |||
| 33 | #include <sys/types.h> | |||
| 34 | #include <sys/stat.h> | |||
| 35 | #include <sys/mman.h> | |||
| 36 | #include <sys/uio.h> | |||
| 37 | ||||
| 38 | #include "hw/hw.h" | |||
| 39 | #include "hw/xen/xen_backend.h" | |||
| 40 | #include "xen_blkif.h" | |||
| 41 | #include "sysemu/blockdev.h" | |||
| 42 | ||||
| 43 | /* ------------------------------------------------------------- */ | |||
| 44 | ||||
| 45 | static int batch_maps = 0; | |||
| 46 | ||||
| 47 | static int max_requests = 32; | |||
| 48 | ||||
| 49 | /* ------------------------------------------------------------- */ | |||
| 50 | ||||
| 51 | #define BLOCK_SIZE512 512 | |||
| 52 | #define IOCB_COUNT(11 + 2) (BLKIF_MAX_SEGMENTS_PER_REQUEST11 + 2) | |||
| 53 | ||||
| 54 | struct PersistentGrant { | |||
| 55 | void *page; | |||
| 56 | struct XenBlkDev *blkdev; | |||
| 57 | }; | |||
| 58 | ||||
| 59 | typedef struct PersistentGrant PersistentGrant; | |||
| 60 | ||||
| 61 | struct ioreq { | |||
| 62 | blkif_request_t req; | |||
| 63 | int16_t status; | |||
| 64 | ||||
| 65 | /* parsed request */ | |||
| 66 | off_t start; | |||
| 67 | QEMUIOVector v; | |||
| 68 | int presync; | |||
| 69 | int postsync; | |||
| 70 | uint8_t mapped; | |||
| 71 | ||||
| 72 | /* grant mapping */ | |||
| 73 | uint32_t domids[BLKIF_MAX_SEGMENTS_PER_REQUEST11]; | |||
| 74 | uint32_t refs[BLKIF_MAX_SEGMENTS_PER_REQUEST11]; | |||
| 75 | int prot; | |||
| 76 | void *page[BLKIF_MAX_SEGMENTS_PER_REQUEST11]; | |||
| 77 | void *pages; | |||
| 78 | int num_unmap; | |||
| 79 | ||||
| 80 | /* aio status */ | |||
| 81 | int aio_inflight; | |||
| 82 | int aio_errors; | |||
| 83 | ||||
| 84 | struct XenBlkDev *blkdev; | |||
| 85 | QLIST_ENTRY(ioreq)struct { struct ioreq *le_next; struct ioreq **le_prev; } list; | |||
| 86 | BlockAcctCookie acct; | |||
| 87 | }; | |||
| 88 | ||||
| 89 | struct XenBlkDev { | |||
| 90 | struct XenDevice xendev; /* must be first */ | |||
| 91 | char *params; | |||
| 92 | char *mode; | |||
| 93 | char *type; | |||
| 94 | char *dev; | |||
| 95 | char *devtype; | |||
| 96 | bool_Bool directiosafe; | |||
| 97 | const char *fileproto; | |||
| 98 | const char *filename; | |||
| 99 | int ring_ref; | |||
| 100 | void *sring; | |||
| 101 | int64_t file_blk; | |||
| 102 | int64_t file_size; | |||
| 103 | int protocol; | |||
| 104 | blkif_back_rings_t rings; | |||
| 105 | int more_work; | |||
| 106 | int cnt_map; | |||
| 107 | ||||
| 108 | /* request lists */ | |||
| 109 | QLIST_HEAD(inflight_head, ioreq)struct inflight_head { struct ioreq *lh_first; } inflight; | |||
| 110 | QLIST_HEAD(finished_head, ioreq)struct finished_head { struct ioreq *lh_first; } finished; | |||
| 111 | QLIST_HEAD(freelist_head, ioreq)struct freelist_head { struct ioreq *lh_first; } freelist; | |||
| 112 | int requests_total; | |||
| 113 | int requests_inflight; | |||
| 114 | int requests_finished; | |||
| 115 | ||||
| 116 | /* Persistent grants extension */ | |||
| 117 | gboolean feature_persistent; | |||
| 118 | GTree *persistent_gnts; | |||
| 119 | unsigned int persistent_gnt_count; | |||
| 120 | unsigned int max_grants; | |||
| 121 | ||||
| 122 | /* qemu block driver */ | |||
| 123 | DriveInfo *dinfo; | |||
| 124 | BlockDriverState *bs; | |||
| 125 | QEMUBH *bh; | |||
| 126 | }; | |||
| 127 | ||||
| 128 | /* ------------------------------------------------------------- */ | |||
| 129 | ||||
| 130 | static void ioreq_reset(struct ioreq *ioreq) | |||
| 131 | { | |||
| 132 | memset(&ioreq->req, 0, sizeof(ioreq->req)); | |||
| 133 | ioreq->status = 0; | |||
| 134 | ioreq->start = 0; | |||
| 135 | ioreq->presync = 0; | |||
| 136 | ioreq->postsync = 0; | |||
| 137 | ioreq->mapped = 0; | |||
| 138 | ||||
| 139 | memset(ioreq->domids, 0, sizeof(ioreq->domids)); | |||
| 140 | memset(ioreq->refs, 0, sizeof(ioreq->refs)); | |||
| 141 | ioreq->prot = 0; | |||
| 142 | memset(ioreq->page, 0, sizeof(ioreq->page)); | |||
| 143 | ioreq->pages = NULL((void*)0); | |||
| 144 | ||||
| 145 | ioreq->aio_inflight = 0; | |||
| 146 | ioreq->aio_errors = 0; | |||
| 147 | ||||
| 148 | ioreq->blkdev = NULL((void*)0); | |||
| 149 | memset(&ioreq->list, 0, sizeof(ioreq->list)); | |||
| 150 | memset(&ioreq->acct, 0, sizeof(ioreq->acct)); | |||
| 151 | ||||
| 152 | qemu_iovec_reset(&ioreq->v); | |||
| 153 | } | |||
| 154 | ||||
| 155 | static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data) | |||
| 156 | { | |||
| 157 | uint ua = GPOINTER_TO_UINT(a)((guint) (gulong) (a)); | |||
| 158 | uint ub = GPOINTER_TO_UINT(b)((guint) (gulong) (b)); | |||
| 159 | return (ua > ub) - (ua < ub); | |||
| 160 | } | |||
| 161 | ||||
| 162 | static void destroy_grant(gpointer pgnt) | |||
| 163 | { | |||
| 164 | PersistentGrant *grant = pgnt; | |||
| 165 | XenGnttab gnt = grant->blkdev->xendev.gnttabdev; | |||
| 166 | ||||
| 167 | if (xc_gnttab_munmap(gnt, grant->page, 1) != 0) { | |||
| 168 | xen_be_printf(&grant->blkdev->xendev, 0, | |||
| 169 | "xc_gnttab_munmap failed: %s\n", | |||
| 170 | strerror(errno(*__errno_location ()))); | |||
| 171 | } | |||
| 172 | grant->blkdev->persistent_gnt_count--; | |||
| 173 | xen_be_printf(&grant->blkdev->xendev, 3, | |||
| 174 | "unmapped grant %p\n", grant->page); | |||
| 175 | g_free(grant); | |||
| 176 | } | |||
| 177 | ||||
| 178 | static struct ioreq *ioreq_start(struct XenBlkDev *blkdev) | |||
| 179 | { | |||
| 180 | struct ioreq *ioreq = NULL((void*)0); | |||
| 181 | ||||
| 182 | if (QLIST_EMPTY(&blkdev->freelist)((&blkdev->freelist)->lh_first == ((void*)0))) { | |||
| 183 | if (blkdev->requests_total >= max_requests) { | |||
| 184 | goto out; | |||
| 185 | } | |||
| 186 | /* allocate new struct */ | |||
| 187 | ioreq = g_malloc0(sizeof(*ioreq)); | |||
| 188 | ioreq->blkdev = blkdev; | |||
| 189 | blkdev->requests_total++; | |||
| 190 | qemu_iovec_init(&ioreq->v, BLKIF_MAX_SEGMENTS_PER_REQUEST11); | |||
| 191 | } else { | |||
| 192 | /* get one from freelist */ | |||
| 193 | ioreq = QLIST_FIRST(&blkdev->freelist)((&blkdev->freelist)->lh_first); | |||
| 194 | QLIST_REMOVE(ioreq, list)do { if ((ioreq)->list.le_next != ((void*)0)) (ioreq)-> list.le_next->list.le_prev = (ioreq)->list.le_prev; *(ioreq )->list.le_prev = (ioreq)->list.le_next; } while ( 0); | |||
| 195 | } | |||
| 196 | QLIST_INSERT_HEAD(&blkdev->inflight, ioreq, list)do { if (((ioreq)->list.le_next = (&blkdev->inflight )->lh_first) != ((void*)0)) (&blkdev->inflight)-> lh_first->list.le_prev = &(ioreq)->list.le_next; (& blkdev->inflight)->lh_first = (ioreq); (ioreq)->list .le_prev = &(&blkdev->inflight)->lh_first; } while ( 0); | |||
| 197 | blkdev->requests_inflight++; | |||
| 198 | ||||
| 199 | out: | |||
| 200 | return ioreq; | |||
| 201 | } | |||
| 202 | ||||
| 203 | static void ioreq_finish(struct ioreq *ioreq) | |||
| 204 | { | |||
| 205 | struct XenBlkDev *blkdev = ioreq->blkdev; | |||
| 206 | ||||
| 207 | QLIST_REMOVE(ioreq, list)do { if ((ioreq)->list.le_next != ((void*)0)) (ioreq)-> list.le_next->list.le_prev = (ioreq)->list.le_prev; *(ioreq )->list.le_prev = (ioreq)->list.le_next; } while ( 0); | |||
| 208 | QLIST_INSERT_HEAD(&blkdev->finished, ioreq, list)do { if (((ioreq)->list.le_next = (&blkdev->finished )->lh_first) != ((void*)0)) (&blkdev->finished)-> lh_first->list.le_prev = &(ioreq)->list.le_next; (& blkdev->finished)->lh_first = (ioreq); (ioreq)->list .le_prev = &(&blkdev->finished)->lh_first; } while ( 0); | |||
| 209 | blkdev->requests_inflight--; | |||
| 210 | blkdev->requests_finished++; | |||
| 211 | } | |||
| 212 | ||||
| 213 | static void ioreq_release(struct ioreq *ioreq, bool_Bool finish) | |||
| 214 | { | |||
| 215 | struct XenBlkDev *blkdev = ioreq->blkdev; | |||
| 216 | ||||
| 217 | QLIST_REMOVE(ioreq, list)do { if ((ioreq)->list.le_next != ((void*)0)) (ioreq)-> list.le_next->list.le_prev = (ioreq)->list.le_prev; *(ioreq )->list.le_prev = (ioreq)->list.le_next; } while ( 0); | |||
| 218 | ioreq_reset(ioreq); | |||
| 219 | ioreq->blkdev = blkdev; | |||
| 220 | QLIST_INSERT_HEAD(&blkdev->freelist, ioreq, list)do { if (((ioreq)->list.le_next = (&blkdev->freelist )->lh_first) != ((void*)0)) (&blkdev->freelist)-> lh_first->list.le_prev = &(ioreq)->list.le_next; (& blkdev->freelist)->lh_first = (ioreq); (ioreq)->list .le_prev = &(&blkdev->freelist)->lh_first; } while ( 0); | |||
| 221 | if (finish) { | |||
| 222 | blkdev->requests_finished--; | |||
| 223 | } else { | |||
| 224 | blkdev->requests_inflight--; | |||
| 225 | } | |||
| 226 | } | |||
| 227 | ||||
| 228 | /* | |||
| 229 | * translate request into iovec + start offset | |||
| 230 | * do sanity checks along the way | |||
| 231 | */ | |||
| 232 | static int ioreq_parse(struct ioreq *ioreq) | |||
| 233 | { | |||
| 234 | struct XenBlkDev *blkdev = ioreq->blkdev; | |||
| 235 | uintptr_t mem; | |||
| 236 | size_t len; | |||
| 237 | int i; | |||
| 238 | ||||
| 239 | xen_be_printf(&blkdev->xendev, 3, | |||
| 240 | "op %d, nr %d, handle %d, id %" PRId64"l" "d" ", sector %" PRId64"l" "d" "\n", | |||
| 241 | ioreq->req.operation, ioreq->req.nr_segments, | |||
| 242 | ioreq->req.handle, ioreq->req.id, ioreq->req.sector_number); | |||
| 243 | switch (ioreq->req.operation) { | |||
| 244 | case BLKIF_OP_READ0: | |||
| 245 | ioreq->prot = PROT_WRITE0x2; /* to memory */ | |||
| 246 | break; | |||
| 247 | case BLKIF_OP_FLUSH_DISKCACHE3: | |||
| 248 | ioreq->presync = 1; | |||
| 249 | if (!ioreq->req.nr_segments) { | |||
| 250 | return 0; | |||
| 251 | } | |||
| 252 | /* fall through */ | |||
| 253 | case BLKIF_OP_WRITE1: | |||
| 254 | ioreq->prot = PROT_READ0x1; /* from memory */ | |||
| 255 | break; | |||
| 256 | default: | |||
| 257 | xen_be_printf(&blkdev->xendev, 0, "error: unknown operation (%d)\n", | |||
| 258 | ioreq->req.operation); | |||
| 259 | goto err; | |||
| 260 | }; | |||
| 261 | ||||
| 262 | if (ioreq->req.operation != BLKIF_OP_READ0 && blkdev->mode[0] != 'w') { | |||
| 263 | xen_be_printf(&blkdev->xendev, 0, "error: write req for ro device\n"); | |||
| 264 | goto err; | |||
| 265 | } | |||
| 266 | ||||
| 267 | ioreq->start = ioreq->req.sector_number * blkdev->file_blk; | |||
| 268 | for (i = 0; i < ioreq->req.nr_segments; i++) { | |||
| 269 | if (i == BLKIF_MAX_SEGMENTS_PER_REQUEST11) { | |||
| 270 | xen_be_printf(&blkdev->xendev, 0, "error: nr_segments too big\n"); | |||
| 271 | goto err; | |||
| 272 | } | |||
| 273 | if (ioreq->req.seg[i].first_sect > ioreq->req.seg[i].last_sect) { | |||
| 274 | xen_be_printf(&blkdev->xendev, 0, "error: first > last sector\n"); | |||
| 275 | goto err; | |||
| 276 | } | |||
| 277 | if (ioreq->req.seg[i].last_sect * BLOCK_SIZE512 >= XC_PAGE_SIZE(1UL << 12)) { | |||
| 278 | xen_be_printf(&blkdev->xendev, 0, "error: page crossing\n"); | |||
| 279 | goto err; | |||
| 280 | } | |||
| 281 | ||||
| 282 | ioreq->domids[i] = blkdev->xendev.dom; | |||
| 283 | ioreq->refs[i] = ioreq->req.seg[i].gref; | |||
| 284 | ||||
| 285 | mem = ioreq->req.seg[i].first_sect * blkdev->file_blk; | |||
| 286 | len = (ioreq->req.seg[i].last_sect - ioreq->req.seg[i].first_sect + 1) * blkdev->file_blk; | |||
| 287 | qemu_iovec_add(&ioreq->v, (void*)mem, len); | |||
| 288 | } | |||
| 289 | if (ioreq->start + ioreq->v.size > blkdev->file_size) { | |||
| 290 | xen_be_printf(&blkdev->xendev, 0, "error: access beyond end of file\n"); | |||
| 291 | goto err; | |||
| 292 | } | |||
| 293 | return 0; | |||
| 294 | ||||
| 295 | err: | |||
| 296 | ioreq->status = BLKIF_RSP_ERROR-1; | |||
| 297 | return -1; | |||
| 298 | } | |||
| 299 | ||||
| 300 | static void ioreq_unmap(struct ioreq *ioreq) | |||
| 301 | { | |||
| 302 | XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev; | |||
| 303 | int i; | |||
| 304 | ||||
| 305 | if (ioreq->num_unmap == 0 || ioreq->mapped == 0) { | |||
| 306 | return; | |||
| 307 | } | |||
| 308 | if (batch_maps) { | |||
| 309 | if (!ioreq->pages) { | |||
| 310 | return; | |||
| 311 | } | |||
| 312 | if (xc_gnttab_munmap(gnt, ioreq->pages, ioreq->num_unmap) != 0) { | |||
| 313 | xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n", | |||
| 314 | strerror(errno(*__errno_location ()))); | |||
| 315 | } | |||
| 316 | ioreq->blkdev->cnt_map -= ioreq->num_unmap; | |||
| 317 | ioreq->pages = NULL((void*)0); | |||
| 318 | } else { | |||
| 319 | for (i = 0; i < ioreq->num_unmap; i++) { | |||
| 320 | if (!ioreq->page[i]) { | |||
| 321 | continue; | |||
| 322 | } | |||
| 323 | if (xc_gnttab_munmap(gnt, ioreq->page[i], 1) != 0) { | |||
| 324 | xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n", | |||
| 325 | strerror(errno(*__errno_location ()))); | |||
| 326 | } | |||
| 327 | ioreq->blkdev->cnt_map--; | |||
| 328 | ioreq->page[i] = NULL((void*)0); | |||
| 329 | } | |||
| 330 | } | |||
| 331 | ioreq->mapped = 0; | |||
| 332 | } | |||
| 333 | ||||
| 334 | static int ioreq_map(struct ioreq *ioreq) | |||
| 335 | { | |||
| 336 | XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev; | |||
| 337 | uint32_t domids[BLKIF_MAX_SEGMENTS_PER_REQUEST11]; | |||
| 338 | uint32_t refs[BLKIF_MAX_SEGMENTS_PER_REQUEST11]; | |||
| 339 | void *page[BLKIF_MAX_SEGMENTS_PER_REQUEST11]; | |||
| 340 | int i, j, new_maps = 0; | |||
| 341 | PersistentGrant *grant; | |||
| 342 | /* domids and refs variables will contain the information necessary | |||
| 343 | * to map the grants that are needed to fulfill this request. | |||
| 344 | * | |||
| 345 | * After mapping the needed grants, the page array will contain the | |||
| 346 | * memory address of each granted page in the order specified in ioreq | |||
| 347 | * (disregarding if it's a persistent grant or not). | |||
| 348 | */ | |||
| 349 | ||||
| 350 | if (ioreq->v.niov == 0 || ioreq->mapped == 1) { | |||
| 351 | return 0; | |||
| 352 | } | |||
| 353 | if (ioreq->blkdev->feature_persistent) { | |||
| 354 | for (i = 0; i < ioreq->v.niov; i++) { | |||
| 355 | grant = g_tree_lookup(ioreq->blkdev->persistent_gnts, | |||
| 356 | GUINT_TO_POINTER(ioreq->refs[i])((gpointer) (gulong) (ioreq->refs[i]))); | |||
| 357 | ||||
| 358 | if (grant != NULL((void*)0)) { | |||
| 359 | page[i] = grant->page; | |||
| 360 | xen_be_printf(&ioreq->blkdev->xendev, 3, | |||
| 361 | "using persistent-grant %" PRIu32"u" "\n", | |||
| 362 | ioreq->refs[i]); | |||
| 363 | } else { | |||
| 364 | /* Add the grant to the list of grants that | |||
| 365 | * should be mapped | |||
| 366 | */ | |||
| 367 | domids[new_maps] = ioreq->domids[i]; | |||
| 368 | refs[new_maps] = ioreq->refs[i]; | |||
| 369 | page[i] = NULL((void*)0); | |||
| 370 | new_maps++; | |||
| 371 | } | |||
| 372 | } | |||
| 373 | /* Set the protection to RW, since grants may be reused later | |||
| 374 | * with a different protection than the one needed for this request | |||
| 375 | */ | |||
| 376 | ioreq->prot = PROT_WRITE0x2 | PROT_READ0x1; | |||
| 377 | } else { | |||
| 378 | /* All grants in the request should be mapped */ | |||
| 379 | memcpy(refs, ioreq->refs, sizeof(refs)); | |||
| 380 | memcpy(domids, ioreq->domids, sizeof(domids)); | |||
| 381 | memset(page, 0, sizeof(page)); | |||
| 382 | new_maps = ioreq->v.niov; | |||
| 383 | } | |||
| 384 | ||||
| 385 | if (batch_maps && new_maps) { | |||
| 386 | ioreq->pages = xc_gnttab_map_grant_refs | |||
| 387 | (gnt, new_maps, domids, refs, ioreq->prot); | |||
| 388 | if (ioreq->pages == NULL((void*)0)) { | |||
| 389 | xen_be_printf(&ioreq->blkdev->xendev, 0, | |||
| 390 | "can't map %d grant refs (%s, %d maps)\n", | |||
| 391 | new_maps, strerror(errno(*__errno_location ())), ioreq->blkdev->cnt_map); | |||
| 392 | return -1; | |||
| 393 | } | |||
| 394 | for (i = 0, j = 0; i < ioreq->v.niov; i++) { | |||
| 395 | if (page[i] == NULL((void*)0)) { | |||
| 396 | page[i] = ioreq->pages + (j++) * XC_PAGE_SIZE(1UL << 12); | |||
| 397 | } | |||
| 398 | } | |||
| 399 | ioreq->blkdev->cnt_map += new_maps; | |||
| 400 | } else if (new_maps) { | |||
| 401 | for (i = 0; i < new_maps; i++) { | |||
| 402 | ioreq->page[i] = xc_gnttab_map_grant_ref | |||
| 403 | (gnt, domids[i], refs[i], ioreq->prot); | |||
| 404 | if (ioreq->page[i] == NULL((void*)0)) { | |||
| 405 | xen_be_printf(&ioreq->blkdev->xendev, 0, | |||
| 406 | "can't map grant ref %d (%s, %d maps)\n", | |||
| 407 | refs[i], strerror(errno(*__errno_location ())), ioreq->blkdev->cnt_map); | |||
| 408 | ioreq->mapped = 1; | |||
| 409 | ioreq_unmap(ioreq); | |||
| 410 | return -1; | |||
| 411 | } | |||
| 412 | ioreq->blkdev->cnt_map++; | |||
| 413 | } | |||
| 414 | for (i = 0, j = 0; i < ioreq->v.niov; i++) { | |||
| 415 | if (page[i] == NULL((void*)0)) { | |||
| 416 | page[i] = ioreq->page[j++]; | |||
| 417 | } | |||
| 418 | } | |||
| 419 | } | |||
| 420 | if (ioreq->blkdev->feature_persistent) { | |||
| 421 | while ((ioreq->blkdev->persistent_gnt_count < ioreq->blkdev->max_grants) | |||
| 422 | && new_maps) { | |||
| 423 | /* Go through the list of newly mapped grants and add as many | |||
| 424 | * as possible to the list of persistently mapped grants. | |||
| 425 | * | |||
| 426 | * Since we start at the end of ioreq->page(s), we only need | |||
| 427 | * to decrease new_maps to prevent this granted pages from | |||
| 428 | * being unmapped in ioreq_unmap. | |||
| 429 | */ | |||
| 430 | grant = g_malloc0(sizeof(*grant)); | |||
| 431 | new_maps--; | |||
| 432 | if (batch_maps) { | |||
| 433 | grant->page = ioreq->pages + (new_maps) * XC_PAGE_SIZE(1UL << 12); | |||
| 434 | } else { | |||
| 435 | grant->page = ioreq->page[new_maps]; | |||
| 436 | } | |||
| 437 | grant->blkdev = ioreq->blkdev; | |||
| 438 | xen_be_printf(&ioreq->blkdev->xendev, 3, | |||
| 439 | "adding grant %" PRIu32"u" " page: %p\n", | |||
| 440 | refs[new_maps], grant->page); | |||
| 441 | g_tree_insert(ioreq->blkdev->persistent_gnts, | |||
| 442 | GUINT_TO_POINTER(refs[new_maps])((gpointer) (gulong) (refs[new_maps])), | |||
| 443 | grant); | |||
| 444 | ioreq->blkdev->persistent_gnt_count++; | |||
| 445 | } | |||
| 446 | } | |||
| 447 | for (i = 0; i < ioreq->v.niov; i++) { | |||
| 448 | ioreq->v.iov[i].iov_base += (uintptr_t)page[i]; | |||
| 449 | } | |||
| 450 | ioreq->mapped = 1; | |||
| 451 | ioreq->num_unmap = new_maps; | |||
| 452 | return 0; | |||
| 453 | } | |||
| 454 | ||||
| 455 | static int ioreq_runio_qemu_aio(struct ioreq *ioreq); | |||
| 456 | ||||
| 457 | static void qemu_aio_complete(void *opaque, int ret) | |||
| 458 | { | |||
| 459 | struct ioreq *ioreq = opaque; | |||
| 460 | ||||
| 461 | if (ret != 0) { | |||
| 462 | xen_be_printf(&ioreq->blkdev->xendev, 0, "%s I/O error\n", | |||
| 463 | ioreq->req.operation == BLKIF_OP_READ0 ? "read" : "write"); | |||
| 464 | ioreq->aio_errors++; | |||
| 465 | } | |||
| 466 | ||||
| 467 | ioreq->aio_inflight--; | |||
| 468 | if (ioreq->presync) { | |||
| 469 | ioreq->presync = 0; | |||
| 470 | ioreq_runio_qemu_aio(ioreq); | |||
| 471 | return; | |||
| 472 | } | |||
| 473 | if (ioreq->aio_inflight > 0) { | |||
| 474 | return; | |||
| 475 | } | |||
| 476 | if (ioreq->postsync) { | |||
| 477 | ioreq->postsync = 0; | |||
| 478 | ioreq->aio_inflight++; | |||
| 479 | bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq); | |||
| 480 | return; | |||
| 481 | } | |||
| 482 | ||||
| 483 | ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR-1 : BLKIF_RSP_OKAY0; | |||
| 484 | ioreq_unmap(ioreq); | |||
| 485 | ioreq_finish(ioreq); | |||
| 486 | bdrv_acct_done(ioreq->blkdev->bs, &ioreq->acct); | |||
| 487 | qemu_bh_schedule(ioreq->blkdev->bh); | |||
| 488 | } | |||
| 489 | ||||
| 490 | static int ioreq_runio_qemu_aio(struct ioreq *ioreq) | |||
| 491 | { | |||
| 492 | struct XenBlkDev *blkdev = ioreq->blkdev; | |||
| 493 | ||||
| 494 | if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) { | |||
| 495 | goto err_no_map; | |||
| 496 | } | |||
| 497 | ||||
| 498 | ioreq->aio_inflight++; | |||
| 499 | if (ioreq->presync) { | |||
| 500 | bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq); | |||
| 501 | return 0; | |||
| 502 | } | |||
| 503 | ||||
| 504 | switch (ioreq->req.operation) { | |||
| 505 | case BLKIF_OP_READ0: | |||
| 506 | bdrv_acct_start(blkdev->bs, &ioreq->acct, ioreq->v.size, BDRV_ACCT_READ); | |||
| 507 | ioreq->aio_inflight++; | |||
| 508 | bdrv_aio_readv(blkdev->bs, ioreq->start / BLOCK_SIZE512, | |||
| 509 | &ioreq->v, ioreq->v.size / BLOCK_SIZE512, | |||
| 510 | qemu_aio_complete, ioreq); | |||
| 511 | break; | |||
| 512 | case BLKIF_OP_WRITE1: | |||
| 513 | case BLKIF_OP_FLUSH_DISKCACHE3: | |||
| 514 | if (!ioreq->req.nr_segments) { | |||
| 515 | break; | |||
| 516 | } | |||
| 517 | ||||
| 518 | bdrv_acct_start(blkdev->bs, &ioreq->acct, ioreq->v.size, BDRV_ACCT_WRITE); | |||
| 519 | ioreq->aio_inflight++; | |||
| 520 | bdrv_aio_writev(blkdev->bs, ioreq->start / BLOCK_SIZE512, | |||
| 521 | &ioreq->v, ioreq->v.size / BLOCK_SIZE512, | |||
| 522 | qemu_aio_complete, ioreq); | |||
| 523 | break; | |||
| 524 | default: | |||
| 525 | /* unknown operation (shouldn't happen -- parse catches this) */ | |||
| 526 | goto err; | |||
| 527 | } | |||
| 528 | ||||
| 529 | qemu_aio_complete(ioreq, 0); | |||
| 530 | ||||
| 531 | return 0; | |||
| 532 | ||||
| 533 | err: | |||
| 534 | ioreq_unmap(ioreq); | |||
| 535 | err_no_map: | |||
| 536 | ioreq_finish(ioreq); | |||
| 537 | ioreq->status = BLKIF_RSP_ERROR-1; | |||
| 538 | return -1; | |||
| 539 | } | |||
| 540 | ||||
| 541 | static int blk_send_response_one(struct ioreq *ioreq) | |||
| 542 | { | |||
| 543 | struct XenBlkDev *blkdev = ioreq->blkdev; | |||
| 544 | int send_notify = 0; | |||
| 545 | int have_requests = 0; | |||
| 546 | blkif_response_t resp; | |||
| 547 | void *dst; | |||
| 548 | ||||
| 549 | resp.id = ioreq->req.id; | |||
| 550 | resp.operation = ioreq->req.operation; | |||
| 551 | resp.status = ioreq->status; | |||
| 552 | ||||
| 553 | /* Place on the response ring for the relevant domain. */ | |||
| 554 | switch (blkdev->protocol) { | |||
| 555 | case BLKIF_PROTOCOL_NATIVE: | |||
| 556 | dst = RING_GET_RESPONSE(&blkdev->rings.native, blkdev->rings.native.rsp_prod_pvt)(&((&blkdev->rings.native)->sring->ring[((blkdev ->rings.native.rsp_prod_pvt) & (((&blkdev->rings .native)->nr_ents) - 1))].rsp)); | |||
| 557 | break; | |||
| 558 | case BLKIF_PROTOCOL_X86_32: | |||
| 559 | dst = RING_GET_RESPONSE(&blkdev->rings.x86_32_part,(&((&blkdev->rings.x86_32_part)->sring->ring [((blkdev->rings.x86_32_part.rsp_prod_pvt) & (((&blkdev ->rings.x86_32_part)->nr_ents) - 1))].rsp)) | |||
| 560 | blkdev->rings.x86_32_part.rsp_prod_pvt)(&((&blkdev->rings.x86_32_part)->sring->ring [((blkdev->rings.x86_32_part.rsp_prod_pvt) & (((&blkdev ->rings.x86_32_part)->nr_ents) - 1))].rsp)); | |||
| 561 | break; | |||
| 562 | case BLKIF_PROTOCOL_X86_64: | |||
| 563 | dst = RING_GET_RESPONSE(&blkdev->rings.x86_64_part,(&((&blkdev->rings.x86_64_part)->sring->ring [((blkdev->rings.x86_64_part.rsp_prod_pvt) & (((&blkdev ->rings.x86_64_part)->nr_ents) - 1))].rsp)) | |||
| 564 | blkdev->rings.x86_64_part.rsp_prod_pvt)(&((&blkdev->rings.x86_64_part)->sring->ring [((blkdev->rings.x86_64_part.rsp_prod_pvt) & (((&blkdev ->rings.x86_64_part)->nr_ents) - 1))].rsp)); | |||
| 565 | break; | |||
| 566 | default: | |||
| 567 | dst = NULL((void*)0); | |||
| 568 | } | |||
| 569 | memcpy(dst, &resp, sizeof(resp)); | |||
| ||||
| 570 | blkdev->rings.common.rsp_prod_pvt++; | |||
| 571 | ||||
| 572 | RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blkdev->rings.common, send_notify)do { RING_IDX __old = (&blkdev->rings.common)->sring ->rsp_prod; RING_IDX __new = (&blkdev->rings.common )->rsp_prod_pvt; asm volatile ( "" : : : "memory"); (& blkdev->rings.common)->sring->rsp_prod = __new; asm volatile ( "mfence" : : : "memory"); (send_notify) = ((RING_IDX)(__new - (&blkdev->rings.common)->sring->rsp_event) < (RING_IDX)(__new - __old)); } while (0); | |||
| 573 | if (blkdev->rings.common.rsp_prod_pvt == blkdev->rings.common.req_cons) { | |||
| 574 | /* | |||
| 575 | * Tail check for pending requests. Allows frontend to avoid | |||
| 576 | * notifications if requests are already in flight (lower | |||
| 577 | * overheads and promotes batching). | |||
| 578 | */ | |||
| 579 | RING_FINAL_CHECK_FOR_REQUESTS(&blkdev->rings.common, have_requests)do { (have_requests) = ({ unsigned int req = (&blkdev-> rings.common)->sring->req_prod - (&blkdev->rings .common)->req_cons; unsigned int rsp = ((&blkdev->rings .common)->nr_ents) - ((&blkdev->rings.common)->req_cons - (&blkdev->rings.common)->rsp_prod_pvt); req < rsp ? req : rsp; }); if (have_requests) break; (&blkdev-> rings.common)->sring->req_event = (&blkdev->rings .common)->req_cons + 1; asm volatile ( "mfence" : : : "memory" ); (have_requests) = ({ unsigned int req = (&blkdev->rings .common)->sring->req_prod - (&blkdev->rings.common )->req_cons; unsigned int rsp = ((&blkdev->rings.common )->nr_ents) - ((&blkdev->rings.common)->req_cons - (&blkdev->rings.common)->rsp_prod_pvt); req < rsp ? req : rsp; }); } while (0); | |||
| 580 | } else if (RING_HAS_UNCONSUMED_REQUESTS(&blkdev->rings.common)({ unsigned int req = (&blkdev->rings.common)->sring ->req_prod - (&blkdev->rings.common)->req_cons; unsigned int rsp = ((&blkdev->rings.common)->nr_ents) - ((& blkdev->rings.common)->req_cons - (&blkdev->rings .common)->rsp_prod_pvt); req < rsp ? req : rsp; })) { | |||
| 581 | have_requests = 1; | |||
| 582 | } | |||
| 583 | ||||
| 584 | if (have_requests) { | |||
| 585 | blkdev->more_work++; | |||
| 586 | } | |||
| 587 | return send_notify; | |||
| 588 | } | |||
| 589 | ||||
| 590 | /* walk finished list, send outstanding responses, free requests */ | |||
| 591 | static void blk_send_response_all(struct XenBlkDev *blkdev) | |||
| 592 | { | |||
| 593 | struct ioreq *ioreq; | |||
| 594 | int send_notify = 0; | |||
| 595 | ||||
| 596 | while (!QLIST_EMPTY(&blkdev->finished)((&blkdev->finished)->lh_first == ((void*)0))) { | |||
| 597 | ioreq = QLIST_FIRST(&blkdev->finished)((&blkdev->finished)->lh_first); | |||
| 598 | send_notify += blk_send_response_one(ioreq); | |||
| 599 | ioreq_release(ioreq, true1); | |||
| 600 | } | |||
| 601 | if (send_notify) { | |||
| 602 | xen_be_send_notify(&blkdev->xendev); | |||
| 603 | } | |||
| 604 | } | |||
| 605 | ||||
| 606 | static int blk_get_request(struct XenBlkDev *blkdev, struct ioreq *ioreq, RING_IDX rc) | |||
| 607 | { | |||
| 608 | switch (blkdev->protocol) { | |||
| 609 | case BLKIF_PROTOCOL_NATIVE: | |||
| 610 | memcpy(&ioreq->req, RING_GET_REQUEST(&blkdev->rings.native, rc)(&((&blkdev->rings.native)->sring->ring[((rc ) & (((&blkdev->rings.native)->nr_ents) - 1))]. req)), | |||
| 611 | sizeof(ioreq->req)); | |||
| 612 | break; | |||
| 613 | case BLKIF_PROTOCOL_X86_32: | |||
| 614 | blkif_get_x86_32_req(&ioreq->req, | |||
| 615 | RING_GET_REQUEST(&blkdev->rings.x86_32_part, rc)(&((&blkdev->rings.x86_32_part)->sring->ring [((rc) & (((&blkdev->rings.x86_32_part)->nr_ents ) - 1))].req))); | |||
| 616 | break; | |||
| 617 | case BLKIF_PROTOCOL_X86_64: | |||
| 618 | blkif_get_x86_64_req(&ioreq->req, | |||
| 619 | RING_GET_REQUEST(&blkdev->rings.x86_64_part, rc)(&((&blkdev->rings.x86_64_part)->sring->ring [((rc) & (((&blkdev->rings.x86_64_part)->nr_ents ) - 1))].req))); | |||
| 620 | break; | |||
| 621 | } | |||
| 622 | return 0; | |||
| 623 | } | |||
| 624 | ||||
| 625 | static void blk_handle_requests(struct XenBlkDev *blkdev) | |||
| 626 | { | |||
| 627 | RING_IDX rc, rp; | |||
| 628 | struct ioreq *ioreq; | |||
| 629 | ||||
| 630 | blkdev->more_work = 0; | |||
| 631 | ||||
| 632 | rc = blkdev->rings.common.req_cons; | |||
| 633 | rp = blkdev->rings.common.sring->req_prod; | |||
| 634 | xen_rmb()asm volatile ( "" : : : "memory"); /* Ensure we see queued requests up to 'rp'. */ | |||
| 635 | ||||
| 636 | blk_send_response_all(blkdev); | |||
| 637 | while (rc != rp) { | |||
| 638 | /* pull request from ring */ | |||
| 639 | if (RING_REQUEST_CONS_OVERFLOW(&blkdev->rings.common, rc)(((rc) - (&blkdev->rings.common)->rsp_prod_pvt) >= ((&blkdev->rings.common)->nr_ents))) { | |||
| 640 | break; | |||
| 641 | } | |||
| 642 | ioreq = ioreq_start(blkdev); | |||
| 643 | if (ioreq == NULL((void*)0)) { | |||
| 644 | blkdev->more_work++; | |||
| 645 | break; | |||
| 646 | } | |||
| 647 | blk_get_request(blkdev, ioreq, rc); | |||
| 648 | blkdev->rings.common.req_cons = ++rc; | |||
| 649 | ||||
| 650 | /* parse them */ | |||
| 651 | if (ioreq_parse(ioreq) != 0) { | |||
| 652 | if (blk_send_response_one(ioreq)) { | |||
| 653 | xen_be_send_notify(&blkdev->xendev); | |||
| 654 | } | |||
| 655 | ioreq_release(ioreq, false0); | |||
| 656 | continue; | |||
| 657 | } | |||
| 658 | ||||
| 659 | ioreq_runio_qemu_aio(ioreq); | |||
| 660 | } | |||
| 661 | ||||
| 662 | if (blkdev->more_work && blkdev->requests_inflight < max_requests) { | |||
| 663 | qemu_bh_schedule(blkdev->bh); | |||
| 664 | } | |||
| 665 | } | |||
| 666 | ||||
| 667 | /* ------------------------------------------------------------- */ | |||
| 668 | ||||
| 669 | static void blk_bh(void *opaque) | |||
| 670 | { | |||
| 671 | struct XenBlkDev *blkdev = opaque; | |||
| 672 | blk_handle_requests(blkdev); | |||
| ||||
| 673 | } | |||
| 674 | ||||
| 675 | /* | |||
| 676 | * We need to account for the grant allocations requiring contiguous | |||
| 677 | * chunks; the worst case number would be | |||
| 678 | * max_req * max_seg + (max_req - 1) * (max_seg - 1) + 1, | |||
| 679 | * but in order to keep things simple just use | |||
| 680 | * 2 * max_req * max_seg. | |||
| 681 | */ | |||
| 682 | #define MAX_GRANTS(max_req, max_seg)(2 * (max_req) * (max_seg)) (2 * (max_req) * (max_seg)) | |||
| 683 | ||||
| 684 | static void blk_alloc(struct XenDevice *xendev) | |||
| 685 | { | |||
| 686 | struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev)({ const typeof(((struct XenBlkDev *) 0)->xendev) *__mptr = (xendev); (struct XenBlkDev *) ((char *) __mptr - __builtin_offsetof (struct XenBlkDev, xendev));}); | |||
| 687 | ||||
| 688 | QLIST_INIT(&blkdev->inflight)do { (&blkdev->inflight)->lh_first = ((void*)0); } while ( 0); | |||
| 689 | QLIST_INIT(&blkdev->finished)do { (&blkdev->finished)->lh_first = ((void*)0); } while ( 0); | |||
| 690 | QLIST_INIT(&blkdev->freelist)do { (&blkdev->freelist)->lh_first = ((void*)0); } while ( 0); | |||
| 691 | blkdev->bh = qemu_bh_new(blk_bh, blkdev); | |||
| 692 | if (xen_mode != XEN_EMULATE) { | |||
| 693 | batch_maps = 1; | |||
| 694 | } | |||
| 695 | if (xc_gnttab_set_max_grants(xendev->gnttabdev, | |||
| 696 | MAX_GRANTS(max_requests, BLKIF_MAX_SEGMENTS_PER_REQUEST)(2 * (max_requests) * (11))) < 0) { | |||
| 697 | xen_be_printf(xendev, 0, "xc_gnttab_set_max_grants failed: %s\n", | |||
| 698 | strerror(errno(*__errno_location ()))); | |||
| 699 | } | |||
| 700 | } | |||
| 701 | ||||
| 702 | static int blk_init(struct XenDevice *xendev) | |||
| 703 | { | |||
| 704 | struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev)({ const typeof(((struct XenBlkDev *) 0)->xendev) *__mptr = (xendev); (struct XenBlkDev *) ((char *) __mptr - __builtin_offsetof (struct XenBlkDev, xendev));}); | |||
| 705 | int info = 0; | |||
| 706 | char *directiosafe = NULL((void*)0); | |||
| 707 | ||||
| 708 | /* read xenstore entries */ | |||
| 709 | if (blkdev->params == NULL((void*)0)) { | |||
| 710 | char *h = NULL((void*)0); | |||
| 711 | blkdev->params = xenstore_read_be_str(&blkdev->xendev, "params"); | |||
| 712 | if (blkdev->params != NULL((void*)0)) { | |||
| 713 | h = strchr(blkdev->params, ':'); | |||
| 714 | } | |||
| 715 | if (h != NULL((void*)0)) { | |||
| 716 | blkdev->fileproto = blkdev->params; | |||
| 717 | blkdev->filename = h+1; | |||
| 718 | *h = 0; | |||
| 719 | } else { | |||
| 720 | blkdev->fileproto = "<unset>"; | |||
| 721 | blkdev->filename = blkdev->params; | |||
| 722 | } | |||
| 723 | } | |||
| 724 | if (!strcmp("aio", blkdev->fileproto)) { | |||
| 725 | blkdev->fileproto = "raw"; | |||
| 726 | } | |||
| 727 | if (blkdev->mode == NULL((void*)0)) { | |||
| 728 | blkdev->mode = xenstore_read_be_str(&blkdev->xendev, "mode"); | |||
| 729 | } | |||
| 730 | if (blkdev->type == NULL((void*)0)) { | |||
| 731 | blkdev->type = xenstore_read_be_str(&blkdev->xendev, "type"); | |||
| 732 | } | |||
| 733 | if (blkdev->dev == NULL((void*)0)) { | |||
| 734 | blkdev->dev = xenstore_read_be_str(&blkdev->xendev, "dev"); | |||
| 735 | } | |||
| 736 | if (blkdev->devtype == NULL((void*)0)) { | |||
| 737 | blkdev->devtype = xenstore_read_be_str(&blkdev->xendev, "device-type"); | |||
| 738 | } | |||
| 739 | directiosafe = xenstore_read_be_str(&blkdev->xendev, "direct-io-safe"); | |||
| 740 | blkdev->directiosafe = (directiosafe && atoi(directiosafe)); | |||
| 741 | ||||
| 742 | /* do we have all we need? */ | |||
| 743 | if (blkdev->params == NULL((void*)0) || | |||
| 744 | blkdev->mode == NULL((void*)0) || | |||
| 745 | blkdev->type == NULL((void*)0) || | |||
| 746 | blkdev->dev == NULL((void*)0)) { | |||
| 747 | goto out_error; | |||
| 748 | } | |||
| 749 | ||||
| 750 | /* read-only ? */ | |||
| 751 | if (strcmp(blkdev->mode, "w")) { | |||
| 752 | info |= VDISK_READONLY0x4; | |||
| 753 | } | |||
| 754 | ||||
| 755 | /* cdrom ? */ | |||
| 756 | if (blkdev->devtype && !strcmp(blkdev->devtype, "cdrom")) { | |||
| 757 | info |= VDISK_CDROM0x1; | |||
| 758 | } | |||
| 759 | ||||
| 760 | blkdev->file_blk = BLOCK_SIZE512; | |||
| 761 | ||||
| 762 | /* fill info | |||
| 763 | * blk_connect supplies sector-size and sectors | |||
| 764 | */ | |||
| 765 | xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1); | |||
| 766 | xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1); | |||
| 767 | xenstore_write_be_int(&blkdev->xendev, "info", info); | |||
| 768 | ||||
| 769 | g_free(directiosafe); | |||
| 770 | return 0; | |||
| 771 | ||||
| 772 | out_error: | |||
| 773 | g_free(blkdev->params); | |||
| 774 | blkdev->params = NULL((void*)0); | |||
| 775 | g_free(blkdev->mode); | |||
| 776 | blkdev->mode = NULL((void*)0); | |||
| 777 | g_free(blkdev->type); | |||
| 778 | blkdev->type = NULL((void*)0); | |||
| 779 | g_free(blkdev->dev); | |||
| 780 | blkdev->dev = NULL((void*)0); | |||
| 781 | g_free(blkdev->devtype); | |||
| 782 | blkdev->devtype = NULL((void*)0); | |||
| 783 | g_free(directiosafe); | |||
| 784 | blkdev->directiosafe = false0; | |||
| 785 | return -1; | |||
| 786 | } | |||
| 787 | ||||
| 788 | static int blk_connect(struct XenDevice *xendev) | |||
| 789 | { | |||
| 790 | struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev)({ const typeof(((struct XenBlkDev *) 0)->xendev) *__mptr = (xendev); (struct XenBlkDev *) ((char *) __mptr - __builtin_offsetof (struct XenBlkDev, xendev));}); | |||
| 791 | int pers, index, qflags; | |||
| 792 | bool_Bool readonly = true1; | |||
| 793 | ||||
| 794 | /* read-only ? */ | |||
| 795 | if (blkdev->directiosafe) { | |||
| 796 | qflags = BDRV_O_NOCACHE0x0020 | BDRV_O_NATIVE_AIO0x0080; | |||
| 797 | } else { | |||
| 798 | qflags = BDRV_O_CACHE_WB0x0040; | |||
| 799 | } | |||
| 800 | if (strcmp(blkdev->mode, "w") == 0) { | |||
| 801 | qflags |= BDRV_O_RDWR0x0002; | |||
| 802 | readonly = false0; | |||
| 803 | } | |||
| 804 | ||||
| 805 | /* init qemu block driver */ | |||
| 806 | index = (blkdev->xendev.dev - 202 * 256) / 16; | |||
| 807 | blkdev->dinfo = drive_get(IF_XEN, 0, index); | |||
| 808 | if (!blkdev->dinfo) { | |||
| 809 | /* setup via xenbus -> create new block driver instance */ | |||
| 810 | xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n"); | |||
| 811 | blkdev->bs = bdrv_new(blkdev->dev); | |||
| 812 | if (blkdev->bs) { | |||
| 813 | Error *local_err = NULL((void*)0); | |||
| 814 | BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto, | |||
| 815 | readonly); | |||
| 816 | if (bdrv_open(blkdev->bs, | |||
| 817 | blkdev->filename, NULL((void*)0), qflags, drv, &local_err) != 0) | |||
| 818 | { | |||
| 819 | xen_be_printf(&blkdev->xendev, 0, "error: %s\n", | |||
| 820 | error_get_pretty(local_err)); | |||
| 821 | error_free(local_err); | |||
| 822 | bdrv_unref(blkdev->bs); | |||
| 823 | blkdev->bs = NULL((void*)0); | |||
| 824 | } | |||
| 825 | } | |||
| 826 | if (!blkdev->bs) { | |||
| 827 | return -1; | |||
| 828 | } | |||
| 829 | } else { | |||
| 830 | /* setup via qemu cmdline -> already setup for us */ | |||
| 831 | xen_be_printf(&blkdev->xendev, 2, "get configured bdrv (cmdline setup)\n"); | |||
| 832 | blkdev->bs = blkdev->dinfo->bdrv; | |||
| 833 | if (bdrv_is_read_only(blkdev->bs) && !readonly) { | |||
| 834 | xen_be_printf(&blkdev->xendev, 0, "Unexpected read-only drive"); | |||
| 835 | blkdev->bs = NULL((void*)0); | |||
| 836 | return -1; | |||
| 837 | } | |||
| 838 | /* blkdev->bs is not create by us, we get a reference | |||
| 839 | * so we can bdrv_unref() unconditionally */ | |||
| 840 | bdrv_ref(blkdev->bs); | |||
| 841 | } | |||
| 842 | bdrv_attach_dev_nofail(blkdev->bs, blkdev); | |||
| 843 | blkdev->file_size = bdrv_getlength(blkdev->bs); | |||
| 844 | if (blkdev->file_size < 0) { | |||
| 845 | xen_be_printf(&blkdev->xendev, 1, "bdrv_getlength: %d (%s) | drv %s\n", | |||
| 846 | (int)blkdev->file_size, strerror(-blkdev->file_size), | |||
| 847 | bdrv_get_format_name(blkdev->bs) ?: "-"); | |||
| 848 | blkdev->file_size = 0; | |||
| 849 | } | |||
| 850 | ||||
| 851 | xen_be_printf(xendev, 1, "type \"%s\", fileproto \"%s\", filename \"%s\"," | |||
| 852 | " size %" PRId64"l" "d" " (%" PRId64"l" "d" " MB)\n", | |||
| 853 | blkdev->type, blkdev->fileproto, blkdev->filename, | |||
| 854 | blkdev->file_size, blkdev->file_size >> 20); | |||
| 855 | ||||
| 856 | /* Fill in number of sector size and number of sectors */ | |||
| 857 | xenstore_write_be_int(&blkdev->xendev, "sector-size", blkdev->file_blk); | |||
| 858 | xenstore_write_be_int64(&blkdev->xendev, "sectors", | |||
| 859 | blkdev->file_size / blkdev->file_blk); | |||
| 860 | ||||
| 861 | if (xenstore_read_fe_int(&blkdev->xendev, "ring-ref", &blkdev->ring_ref) == -1) { | |||
| 862 | return -1; | |||
| 863 | } | |||
| 864 | if (xenstore_read_fe_int(&blkdev->xendev, "event-channel", | |||
| 865 | &blkdev->xendev.remote_port) == -1) { | |||
| 866 | return -1; | |||
| 867 | } | |||
| 868 | if (xenstore_read_fe_int(&blkdev->xendev, "feature-persistent", &pers)) { | |||
| 869 | blkdev->feature_persistent = FALSE(0); | |||
| 870 | } else { | |||
| 871 | blkdev->feature_persistent = !!pers; | |||
| 872 | } | |||
| 873 | ||||
| 874 | blkdev->protocol = BLKIF_PROTOCOL_NATIVE; | |||
| 875 | if (blkdev->xendev.protocol) { | |||
| 876 | if (strcmp(blkdev->xendev.protocol, XEN_IO_PROTO_ABI_X86_32"x86_32-abi") == 0) { | |||
| 877 | blkdev->protocol = BLKIF_PROTOCOL_X86_32; | |||
| 878 | } | |||
| 879 | if (strcmp(blkdev->xendev.protocol, XEN_IO_PROTO_ABI_X86_64"x86_64-abi") == 0) { | |||
| 880 | blkdev->protocol = BLKIF_PROTOCOL_X86_64; | |||
| 881 | } | |||
| 882 | } | |||
| 883 | ||||
| 884 | blkdev->sring = xc_gnttab_map_grant_ref(blkdev->xendev.gnttabdev, | |||
| 885 | blkdev->xendev.dom, | |||
| 886 | blkdev->ring_ref, | |||
| 887 | PROT_READ0x1 | PROT_WRITE0x2); | |||
| 888 | if (!blkdev->sring) { | |||
| 889 | return -1; | |||
| 890 | } | |||
| 891 | blkdev->cnt_map++; | |||
| 892 | ||||
| 893 | switch (blkdev->protocol) { | |||
| 894 | case BLKIF_PROTOCOL_NATIVE: | |||
| 895 | { | |||
| 896 | blkif_sring_t *sring_native = blkdev->sring; | |||
| 897 | BACK_RING_INIT(&blkdev->rings.native, sring_native, XC_PAGE_SIZE)do { (&blkdev->rings.native)->rsp_prod_pvt = 0; (& blkdev->rings.native)->req_cons = 0; (&blkdev->rings .native)->nr_ents = (((((((1UL << 12)) - (long)(sring_native )->ring + (long)(sring_native)) / sizeof((sring_native)-> ring[0])) & 0xffff0000) ? (((((((1UL << 12)) - (long )(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native )->ring[0]))>>16) & 0x0000ff00) ? ((((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]))>>16)>>8) & 0x000000f0) ? (((((((((1UL << 12)) - (long)(sring_native )->ring + (long)(sring_native)) / sizeof((sring_native)-> ring[0]))>>16)>>8)>>4) & 0x0000000c) ? ( (((((((((1UL << 12)) - (long)(sring_native)->ring + ( long)(sring_native)) / sizeof((sring_native)->ring[0]))>> 16)>>8)>>4)>>2) & 0x00000002) ? 0x2 : ( ((((((((1UL << 12)) - (long)(sring_native)->ring + ( long)(sring_native)) / sizeof((sring_native)->ring[0]))>> 16)>>8)>>4)>>2) & 0x1))<<2 : (((( (((((1UL << 12)) - (long)(sring_native)->ring + (long )(sring_native)) / sizeof((sring_native)->ring[0]))>> 16)>>8)>>4) & 0x00000002) ? 0x2 : ((((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native )) / sizeof((sring_native)->ring[0]))>>16)>>8) >>4) & 0x1)))<<4 : ((((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof ((sring_native)->ring[0]))>>16)>>8) & 0x0000000c ) ? (((((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]) )>>16)>>8)>>2) & 0x00000002) ? 0x2 : (( ((((((1UL << 12)) - (long)(sring_native)->ring + (long )(sring_native)) / sizeof((sring_native)->ring[0]))>> 16)>>8)>>2) & 0x1))<<2 : ((((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]))>>16)>>8) & 0x00000002) ? 0x2 : (((((((1UL << 12)) - (long)(sring_native )->ring + (long)(sring_native)) / sizeof((sring_native)-> ring[0]))>>16)>>8) & 0x1))))<<8 : ((((( ((1UL << 12)) - (long)(sring_native)->ring + (long)( sring_native)) / sizeof((sring_native)->ring[0]))>>16 ) & 0x000000f0) ? ((((((((1UL << 12)) - (long)(sring_native )->ring + (long)(sring_native)) / sizeof((sring_native)-> ring[0]))>>16)>>4) & 0x0000000c) ? (((((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native )) / sizeof((sring_native)->ring[0]))>>16)>>4) >>2) & 0x00000002) ? 0x2 : ((((((((1UL << 12) ) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof ((sring_native)->ring[0]))>>16)>>4)>>2) & 0x1))<<2 : ((((((((1UL << 12)) - (long)(sring_native )->ring + (long)(sring_native)) / sizeof((sring_native)-> ring[0]))>>16)>>4) & 0x00000002) ? 0x2 : (((( (((1UL << 12)) - (long)(sring_native)->ring + (long) (sring_native)) / sizeof((sring_native)->ring[0]))>> 16)>>4) & 0x1)))<<4 : (((((((1UL << 12) ) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof ((sring_native)->ring[0]))>>16) & 0x0000000c) ? ( (((((((1UL << 12)) - (long)(sring_native)->ring + (long )(sring_native)) / sizeof((sring_native)->ring[0]))>> 16)>>2) & 0x00000002) ? 0x2 : (((((((1UL << 12 )) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof ((sring_native)->ring[0]))>>16)>>2) & 0x1) )<<2 : (((((((1UL << 12)) - (long)(sring_native)-> ring + (long)(sring_native)) / sizeof((sring_native)->ring [0]))>>16) & 0x00000002) ? 0x2 : ((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]))>>16) & 0x1)) )))<<16 : ((((((1UL << 12)) - (long)(sring_native )->ring + (long)(sring_native)) / sizeof((sring_native)-> ring[0])) & 0x0000ff00) ? (((((((1UL << 12)) - (long )(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native )->ring[0]))>>8) & 0x000000f0) ? ((((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]))>>8)>>4) & 0x0000000c) ? (((((((((1UL << 12)) - (long)(sring_native )->ring + (long)(sring_native)) / sizeof((sring_native)-> ring[0]))>>8)>>4)>>2) & 0x00000002) ? 0x2 : ((((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]))>> 8)>>4)>>2) & 0x1))<<2 : ((((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]))>>8)>>4) & 0x00000002) ? 0x2 : (((((((1UL << 12)) - (long)(sring_native )->ring + (long)(sring_native)) / sizeof((sring_native)-> ring[0]))>>8)>>4) & 0x1)))<<4 : ((((((( 1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native )) / sizeof((sring_native)->ring[0]))>>8) & 0x0000000c ) ? ((((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]) )>>8)>>2) & 0x00000002) ? 0x2 : (((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]))>>8)>>2) & 0x1))<<2 : (((((((1UL << 12)) - (long)(sring_native )->ring + (long)(sring_native)) / sizeof((sring_native)-> ring[0]))>>8) & 0x00000002) ? 0x2 : ((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]))>>8) & 0x1))) )<<8 : ((((((1UL << 12)) - (long)(sring_native)-> ring + (long)(sring_native)) / sizeof((sring_native)->ring [0])) & 0x000000f0) ? (((((((1UL << 12)) - (long)(sring_native )->ring + (long)(sring_native)) / sizeof((sring_native)-> ring[0]))>>4) & 0x0000000c) ? ((((((((1UL << 12 )) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof ((sring_native)->ring[0]))>>4)>>2) & 0x00000002 ) ? 0x2 : (((((((1UL << 12)) - (long)(sring_native)-> ring + (long)(sring_native)) / sizeof((sring_native)->ring [0]))>>4)>>2) & 0x1))<<2 : (((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]))>>4) & 0x00000002 ) ? 0x2 : ((((((1UL << 12)) - (long)(sring_native)-> ring + (long)(sring_native)) / sizeof((sring_native)->ring [0]))>>4) & 0x1)))<<4 : ((((((1UL << 12 )) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof ((sring_native)->ring[0])) & 0x0000000c) ? (((((((1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof((sring_native)->ring[0]))>>2) & 0x00000002 ) ? 0x2 : ((((((1UL << 12)) - (long)(sring_native)-> ring + (long)(sring_native)) / sizeof((sring_native)->ring [0]))>>2) & 0x1))<<2 : ((((((1UL << 12) ) - (long)(sring_native)->ring + (long)(sring_native)) / sizeof ((sring_native)->ring[0])) & 0x00000002) ? 0x2 : ((((( 1UL << 12)) - (long)(sring_native)->ring + (long)(sring_native )) / sizeof((sring_native)->ring[0])) & 0x1))))))); (& blkdev->rings.native)->sring = (sring_native); } while ( 0); | |||
| 898 | break; | |||
| 899 | } | |||
| 900 | case BLKIF_PROTOCOL_X86_32: | |||
| 901 | { | |||
| 902 | blkif_x86_32_sring_t *sring_x86_32 = blkdev->sring; | |||
| 903 | ||||
| 904 | BACK_RING_INIT(&blkdev->rings.x86_32_part, sring_x86_32, XC_PAGE_SIZE)do { (&blkdev->rings.x86_32_part)->rsp_prod_pvt = 0 ; (&blkdev->rings.x86_32_part)->req_cons = 0; (& blkdev->rings.x86_32_part)->nr_ents = (((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0])) & 0xffff0000) ? (( (((((1UL << 12)) - (long)(sring_x86_32)->ring + (long )(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>> 16) & 0x0000ff00) ? ((((((((1UL << 12)) - (long)(sring_x86_32 )->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)-> ring[0]))>>16)>>8) & 0x000000f0) ? (((((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32 )) / sizeof((sring_x86_32)->ring[0]))>>16)>>8) >>4) & 0x0000000c) ? ((((((((((1UL << 12)) - ( long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof ((sring_x86_32)->ring[0]))>>16)>>8)>>4)>> 2) & 0x00000002) ? 0x2 : (((((((((1UL << 12)) - (long )(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32 )->ring[0]))>>16)>>8)>>4)>>2) & 0x1))<<2 : (((((((((1UL << 12)) - (long)(sring_x86_32 )->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)-> ring[0]))>>16)>>8)>>4) & 0x00000002) ? 0x2 : ((((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>> 16)>>8)>>4) & 0x1)))<<4 : ((((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>>16)>>8) & 0x0000000c) ? (((((((((1UL << 12)) - (long)(sring_x86_32 )->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)-> ring[0]))>>16)>>8)>>2) & 0x00000002) ? 0x2 : ((((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>> 16)>>8)>>2) & 0x1))<<2 : ((((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>>16)>>8) & 0x00000002) ? 0x2 : (((((((1UL << 12)) - (long)(sring_x86_32 )->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)-> ring[0]))>>16)>>8) & 0x1))))<<8 : ((((( ((1UL << 12)) - (long)(sring_x86_32)->ring + (long)( sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>>16 ) & 0x000000f0) ? ((((((((1UL << 12)) - (long)(sring_x86_32 )->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)-> ring[0]))>>16)>>4) & 0x0000000c) ? (((((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32 )) / sizeof((sring_x86_32)->ring[0]))>>16)>>4) >>2) & 0x00000002) ? 0x2 : ((((((((1UL << 12) ) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof ((sring_x86_32)->ring[0]))>>16)>>4)>>2) & 0x1))<<2 : ((((((((1UL << 12)) - (long)(sring_x86_32 )->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)-> ring[0]))>>16)>>4) & 0x00000002) ? 0x2 : (((( (((1UL << 12)) - (long)(sring_x86_32)->ring + (long) (sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>> 16)>>4) & 0x1)))<<4 : (((((((1UL << 12) ) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof ((sring_x86_32)->ring[0]))>>16) & 0x0000000c) ? ( (((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long )(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>> 16)>>2) & 0x00000002) ? 0x2 : (((((((1UL << 12 )) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof ((sring_x86_32)->ring[0]))>>16)>>2) & 0x1) )<<2 : (((((((1UL << 12)) - (long)(sring_x86_32)-> ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring [0]))>>16) & 0x00000002) ? 0x2 : ((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>>16) & 0x1)) )))<<16 : ((((((1UL << 12)) - (long)(sring_x86_32 )->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)-> ring[0])) & 0x0000ff00) ? (((((((1UL << 12)) - (long )(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32 )->ring[0]))>>8) & 0x000000f0) ? ((((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>>8)>>4) & 0x0000000c) ? (((((((((1UL << 12)) - (long)(sring_x86_32 )->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)-> ring[0]))>>8)>>4)>>2) & 0x00000002) ? 0x2 : ((((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>> 8)>>4)>>2) & 0x1))<<2 : ((((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>>8)>>4) & 0x00000002) ? 0x2 : (((((((1UL << 12)) - (long)(sring_x86_32 )->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)-> ring[0]))>>8)>>4) & 0x1)))<<4 : ((((((( 1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32 )) / sizeof((sring_x86_32)->ring[0]))>>8) & 0x0000000c ) ? ((((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]) )>>8)>>2) & 0x00000002) ? 0x2 : (((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>>8)>>2) & 0x1))<<2 : (((((((1UL << 12)) - (long)(sring_x86_32 )->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)-> ring[0]))>>8) & 0x00000002) ? 0x2 : ((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>>8) & 0x1))) )<<8 : ((((((1UL << 12)) - (long)(sring_x86_32)-> ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring [0])) & 0x000000f0) ? (((((((1UL << 12)) - (long)(sring_x86_32 )->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)-> ring[0]))>>4) & 0x0000000c) ? ((((((((1UL << 12 )) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof ((sring_x86_32)->ring[0]))>>4)>>2) & 0x00000002 ) ? 0x2 : (((((((1UL << 12)) - (long)(sring_x86_32)-> ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring [0]))>>4)>>2) & 0x1))<<2 : (((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>>4) & 0x00000002 ) ? 0x2 : ((((((1UL << 12)) - (long)(sring_x86_32)-> ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring [0]))>>4) & 0x1)))<<4 : ((((((1UL << 12 )) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof ((sring_x86_32)->ring[0])) & 0x0000000c) ? (((((((1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring[0]))>>2) & 0x00000002 ) ? 0x2 : ((((((1UL << 12)) - (long)(sring_x86_32)-> ring + (long)(sring_x86_32)) / sizeof((sring_x86_32)->ring [0]))>>2) & 0x1))<<2 : ((((((1UL << 12) ) - (long)(sring_x86_32)->ring + (long)(sring_x86_32)) / sizeof ((sring_x86_32)->ring[0])) & 0x00000002) ? 0x2 : ((((( 1UL << 12)) - (long)(sring_x86_32)->ring + (long)(sring_x86_32 )) / sizeof((sring_x86_32)->ring[0])) & 0x1))))))); (& blkdev->rings.x86_32_part)->sring = (sring_x86_32); } while (0); | |||
| 905 | break; | |||
| 906 | } | |||
| 907 | case BLKIF_PROTOCOL_X86_64: | |||
| 908 | { | |||
| 909 | blkif_x86_64_sring_t *sring_x86_64 = blkdev->sring; | |||
| 910 | ||||
| 911 | BACK_RING_INIT(&blkdev->rings.x86_64_part, sring_x86_64, XC_PAGE_SIZE)do { (&blkdev->rings.x86_64_part)->rsp_prod_pvt = 0 ; (&blkdev->rings.x86_64_part)->req_cons = 0; (& blkdev->rings.x86_64_part)->nr_ents = (((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0])) & 0xffff0000) ? (( (((((1UL << 12)) - (long)(sring_x86_64)->ring + (long )(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>> 16) & 0x0000ff00) ? ((((((((1UL << 12)) - (long)(sring_x86_64 )->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)-> ring[0]))>>16)>>8) & 0x000000f0) ? (((((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64 )) / sizeof((sring_x86_64)->ring[0]))>>16)>>8) >>4) & 0x0000000c) ? ((((((((((1UL << 12)) - ( long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof ((sring_x86_64)->ring[0]))>>16)>>8)>>4)>> 2) & 0x00000002) ? 0x2 : (((((((((1UL << 12)) - (long )(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64 )->ring[0]))>>16)>>8)>>4)>>2) & 0x1))<<2 : (((((((((1UL << 12)) - (long)(sring_x86_64 )->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)-> ring[0]))>>16)>>8)>>4) & 0x00000002) ? 0x2 : ((((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>> 16)>>8)>>4) & 0x1)))<<4 : ((((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>>16)>>8) & 0x0000000c) ? (((((((((1UL << 12)) - (long)(sring_x86_64 )->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)-> ring[0]))>>16)>>8)>>2) & 0x00000002) ? 0x2 : ((((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>> 16)>>8)>>2) & 0x1))<<2 : ((((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>>16)>>8) & 0x00000002) ? 0x2 : (((((((1UL << 12)) - (long)(sring_x86_64 )->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)-> ring[0]))>>16)>>8) & 0x1))))<<8 : ((((( ((1UL << 12)) - (long)(sring_x86_64)->ring + (long)( sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>>16 ) & 0x000000f0) ? ((((((((1UL << 12)) - (long)(sring_x86_64 )->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)-> ring[0]))>>16)>>4) & 0x0000000c) ? (((((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64 )) / sizeof((sring_x86_64)->ring[0]))>>16)>>4) >>2) & 0x00000002) ? 0x2 : ((((((((1UL << 12) ) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof ((sring_x86_64)->ring[0]))>>16)>>4)>>2) & 0x1))<<2 : ((((((((1UL << 12)) - (long)(sring_x86_64 )->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)-> ring[0]))>>16)>>4) & 0x00000002) ? 0x2 : (((( (((1UL << 12)) - (long)(sring_x86_64)->ring + (long) (sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>> 16)>>4) & 0x1)))<<4 : (((((((1UL << 12) ) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof ((sring_x86_64)->ring[0]))>>16) & 0x0000000c) ? ( (((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long )(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>> 16)>>2) & 0x00000002) ? 0x2 : (((((((1UL << 12 )) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof ((sring_x86_64)->ring[0]))>>16)>>2) & 0x1) )<<2 : (((((((1UL << 12)) - (long)(sring_x86_64)-> ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring [0]))>>16) & 0x00000002) ? 0x2 : ((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>>16) & 0x1)) )))<<16 : ((((((1UL << 12)) - (long)(sring_x86_64 )->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)-> ring[0])) & 0x0000ff00) ? (((((((1UL << 12)) - (long )(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64 )->ring[0]))>>8) & 0x000000f0) ? ((((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>>8)>>4) & 0x0000000c) ? (((((((((1UL << 12)) - (long)(sring_x86_64 )->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)-> ring[0]))>>8)>>4)>>2) & 0x00000002) ? 0x2 : ((((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>> 8)>>4)>>2) & 0x1))<<2 : ((((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>>8)>>4) & 0x00000002) ? 0x2 : (((((((1UL << 12)) - (long)(sring_x86_64 )->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)-> ring[0]))>>8)>>4) & 0x1)))<<4 : ((((((( 1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64 )) / sizeof((sring_x86_64)->ring[0]))>>8) & 0x0000000c ) ? ((((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]) )>>8)>>2) & 0x00000002) ? 0x2 : (((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>>8)>>2) & 0x1))<<2 : (((((((1UL << 12)) - (long)(sring_x86_64 )->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)-> ring[0]))>>8) & 0x00000002) ? 0x2 : ((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>>8) & 0x1))) )<<8 : ((((((1UL << 12)) - (long)(sring_x86_64)-> ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring [0])) & 0x000000f0) ? (((((((1UL << 12)) - (long)(sring_x86_64 )->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)-> ring[0]))>>4) & 0x0000000c) ? ((((((((1UL << 12 )) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof ((sring_x86_64)->ring[0]))>>4)>>2) & 0x00000002 ) ? 0x2 : (((((((1UL << 12)) - (long)(sring_x86_64)-> ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring [0]))>>4)>>2) & 0x1))<<2 : (((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>>4) & 0x00000002 ) ? 0x2 : ((((((1UL << 12)) - (long)(sring_x86_64)-> ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring [0]))>>4) & 0x1)))<<4 : ((((((1UL << 12 )) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof ((sring_x86_64)->ring[0])) & 0x0000000c) ? (((((((1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring[0]))>>2) & 0x00000002 ) ? 0x2 : ((((((1UL << 12)) - (long)(sring_x86_64)-> ring + (long)(sring_x86_64)) / sizeof((sring_x86_64)->ring [0]))>>2) & 0x1))<<2 : ((((((1UL << 12) ) - (long)(sring_x86_64)->ring + (long)(sring_x86_64)) / sizeof ((sring_x86_64)->ring[0])) & 0x00000002) ? 0x2 : ((((( 1UL << 12)) - (long)(sring_x86_64)->ring + (long)(sring_x86_64 )) / sizeof((sring_x86_64)->ring[0])) & 0x1))))))); (& blkdev->rings.x86_64_part)->sring = (sring_x86_64); } while (0); | |||
| 912 | break; | |||
| 913 | } | |||
| 914 | } | |||
| 915 | ||||
| 916 | if (blkdev->feature_persistent) { | |||
| 917 | /* Init persistent grants */ | |||
| 918 | blkdev->max_grants = max_requests * BLKIF_MAX_SEGMENTS_PER_REQUEST11; | |||
| 919 | blkdev->persistent_gnts = g_tree_new_full((GCompareDataFunc)int_cmp, | |||
| 920 | NULL((void*)0), NULL((void*)0), | |||
| 921 | (GDestroyNotify)destroy_grant); | |||
| 922 | blkdev->persistent_gnt_count = 0; | |||
| 923 | } | |||
| 924 | ||||
| 925 | xen_be_bind_evtchn(&blkdev->xendev); | |||
| 926 | ||||
| 927 | xen_be_printf(&blkdev->xendev, 1, "ok: proto %s, ring-ref %d, " | |||
| 928 | "remote port %d, local port %d\n", | |||
| 929 | blkdev->xendev.protocol, blkdev->ring_ref, | |||
| 930 | blkdev->xendev.remote_port, blkdev->xendev.local_port); | |||
| 931 | return 0; | |||
| 932 | } | |||
| 933 | ||||
| 934 | static void blk_disconnect(struct XenDevice *xendev) | |||
| 935 | { | |||
| 936 | struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev)({ const typeof(((struct XenBlkDev *) 0)->xendev) *__mptr = (xendev); (struct XenBlkDev *) ((char *) __mptr - __builtin_offsetof (struct XenBlkDev, xendev));}); | |||
| 937 | ||||
| 938 | if (blkdev->bs) { | |||
| 939 | bdrv_detach_dev(blkdev->bs, blkdev); | |||
| 940 | bdrv_unref(blkdev->bs); | |||
| 941 | blkdev->bs = NULL((void*)0); | |||
| 942 | } | |||
| 943 | xen_be_unbind_evtchn(&blkdev->xendev); | |||
| 944 | ||||
| 945 | if (blkdev->sring) { | |||
| 946 | xc_gnttab_munmap(blkdev->xendev.gnttabdev, blkdev->sring, 1); | |||
| 947 | blkdev->cnt_map--; | |||
| 948 | blkdev->sring = NULL((void*)0); | |||
| 949 | } | |||
| 950 | } | |||
| 951 | ||||
| 952 | static int blk_free(struct XenDevice *xendev) | |||
| 953 | { | |||
| 954 | struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev)({ const typeof(((struct XenBlkDev *) 0)->xendev) *__mptr = (xendev); (struct XenBlkDev *) ((char *) __mptr - __builtin_offsetof (struct XenBlkDev, xendev));}); | |||
| 955 | struct ioreq *ioreq; | |||
| 956 | ||||
| 957 | if (blkdev->bs || blkdev->sring) { | |||
| 958 | blk_disconnect(xendev); | |||
| 959 | } | |||
| 960 | ||||
| 961 | /* Free persistent grants */ | |||
| 962 | if (blkdev->feature_persistent) { | |||
| 963 | g_tree_destroy(blkdev->persistent_gnts); | |||
| 964 | } | |||
| 965 | ||||
| 966 | while (!QLIST_EMPTY(&blkdev->freelist)((&blkdev->freelist)->lh_first == ((void*)0))) { | |||
| 967 | ioreq = QLIST_FIRST(&blkdev->freelist)((&blkdev->freelist)->lh_first); | |||
| 968 | QLIST_REMOVE(ioreq, list)do { if ((ioreq)->list.le_next != ((void*)0)) (ioreq)-> list.le_next->list.le_prev = (ioreq)->list.le_prev; *(ioreq )->list.le_prev = (ioreq)->list.le_next; } while ( 0); | |||
| 969 | qemu_iovec_destroy(&ioreq->v); | |||
| 970 | g_free(ioreq); | |||
| 971 | } | |||
| 972 | ||||
| 973 | g_free(blkdev->params); | |||
| 974 | g_free(blkdev->mode); | |||
| 975 | g_free(blkdev->type); | |||
| 976 | g_free(blkdev->dev); | |||
| 977 | g_free(blkdev->devtype); | |||
| 978 | qemu_bh_delete(blkdev->bh); | |||
| 979 | return 0; | |||
| 980 | } | |||
| 981 | ||||
| 982 | static void blk_event(struct XenDevice *xendev) | |||
| 983 | { | |||
| 984 | struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev)({ const typeof(((struct XenBlkDev *) 0)->xendev) *__mptr = (xendev); (struct XenBlkDev *) ((char *) __mptr - __builtin_offsetof (struct XenBlkDev, xendev));}); | |||
| 985 | ||||
| 986 | qemu_bh_schedule(blkdev->bh); | |||
| 987 | } | |||
| 988 | ||||
| 989 | struct XenDevOps xen_blkdev_ops = { | |||
| 990 | .size = sizeof(struct XenBlkDev), | |||
| 991 | .flags = DEVOPS_FLAG_NEED_GNTDEV1, | |||
| 992 | .alloc = blk_alloc, | |||
| 993 | .init = blk_init, | |||
| 994 | .initialise = blk_connect, | |||
| 995 | .disconnect = blk_disconnect, | |||
| 996 | .event = blk_event, | |||
| 997 | .free = blk_free, | |||
| 998 | }; |