1 /* SPDX-License-Identifier: MIT */ 2 /* 3 * Description: uring_cmd based ublk 4 */ 5 6 #include "kublk.h" 7 8 #define MAX_NR_TGT_ARG 64 9 10 unsigned int ublk_dbg_mask = UBLK_LOG; 11 static const struct ublk_tgt_ops *tgt_ops_list[] = { 12 &null_tgt_ops, 13 &loop_tgt_ops, 14 &stripe_tgt_ops, 15 &fault_inject_tgt_ops, 16 }; 17 18 static const struct ublk_tgt_ops *ublk_find_tgt(const char *name) 19 { 20 int i; 21 22 if (name == NULL) 23 return NULL; 24 25 for (i = 0; i < ARRAY_SIZE(tgt_ops_list); i++) 26 if (strcmp(tgt_ops_list[i]->name, name) == 0) 27 return tgt_ops_list[i]; 28 return NULL; 29 } 30 31 static inline int ublk_setup_ring(struct io_uring *r, int depth, 32 int cq_depth, unsigned flags) 33 { 34 struct io_uring_params p; 35 36 memset(&p, 0, sizeof(p)); 37 p.flags = flags | IORING_SETUP_CQSIZE; 38 p.cq_entries = cq_depth; 39 40 return io_uring_queue_init_params(depth, r, &p); 41 } 42 43 static void ublk_ctrl_init_cmd(struct ublk_dev *dev, 44 struct io_uring_sqe *sqe, 45 struct ublk_ctrl_cmd_data *data) 46 { 47 struct ublksrv_ctrl_dev_info *info = &dev->dev_info; 48 struct ublksrv_ctrl_cmd *cmd = (struct ublksrv_ctrl_cmd *)ublk_get_sqe_cmd(sqe); 49 50 sqe->fd = dev->ctrl_fd; 51 sqe->opcode = IORING_OP_URING_CMD; 52 sqe->ioprio = 0; 53 54 if (data->flags & CTRL_CMD_HAS_BUF) { 55 cmd->addr = data->addr; 56 cmd->len = data->len; 57 } 58 59 if (data->flags & CTRL_CMD_HAS_DATA) 60 cmd->data[0] = data->data[0]; 61 62 cmd->dev_id = info->dev_id; 63 cmd->queue_id = -1; 64 65 ublk_set_sqe_cmd_op(sqe, data->cmd_op); 66 67 io_uring_sqe_set_data(sqe, cmd); 68 } 69 70 static int __ublk_ctrl_cmd(struct ublk_dev *dev, 71 struct ublk_ctrl_cmd_data *data) 72 { 73 struct io_uring_sqe *sqe; 74 struct io_uring_cqe *cqe; 75 int ret = -EINVAL; 76 77 sqe = io_uring_get_sqe(&dev->ring); 78 if (!sqe) { 79 ublk_err("%s: can't get sqe ret %d\n", __func__, ret); 80 return ret; 81 } 82 83 ublk_ctrl_init_cmd(dev, sqe, data); 84 85 ret = io_uring_submit(&dev->ring); 86 if (ret < 0) { 87 ublk_err("uring submit ret %d\n", ret); 88 return ret; 89 } 90 91 ret = io_uring_wait_cqe(&dev->ring, &cqe); 92 if (ret < 0) { 93 ublk_err("wait cqe: %s\n", strerror(-ret)); 94 return ret; 95 } 96 io_uring_cqe_seen(&dev->ring, cqe); 97 98 return cqe->res; 99 } 100 101 static int ublk_ctrl_stop_dev(struct ublk_dev *dev) 102 { 103 struct ublk_ctrl_cmd_data data = { 104 .cmd_op = UBLK_U_CMD_STOP_DEV, 105 }; 106 107 return __ublk_ctrl_cmd(dev, &data); 108 } 109 110 static int ublk_ctrl_start_dev(struct ublk_dev *dev, 111 int daemon_pid) 112 { 113 struct ublk_ctrl_cmd_data data = { 114 .cmd_op = UBLK_U_CMD_START_DEV, 115 .flags = CTRL_CMD_HAS_DATA, 116 }; 117 118 dev->dev_info.ublksrv_pid = data.data[0] = daemon_pid; 119 120 return __ublk_ctrl_cmd(dev, &data); 121 } 122 123 static int ublk_ctrl_start_user_recovery(struct ublk_dev *dev) 124 { 125 struct ublk_ctrl_cmd_data data = { 126 .cmd_op = UBLK_U_CMD_START_USER_RECOVERY, 127 }; 128 129 return __ublk_ctrl_cmd(dev, &data); 130 } 131 132 static int ublk_ctrl_end_user_recovery(struct ublk_dev *dev, int daemon_pid) 133 { 134 struct ublk_ctrl_cmd_data data = { 135 .cmd_op = UBLK_U_CMD_END_USER_RECOVERY, 136 .flags = CTRL_CMD_HAS_DATA, 137 }; 138 139 dev->dev_info.ublksrv_pid = data.data[0] = daemon_pid; 140 141 return __ublk_ctrl_cmd(dev, &data); 142 } 143 144 static int ublk_ctrl_add_dev(struct ublk_dev *dev) 145 { 146 struct ublk_ctrl_cmd_data data = { 147 .cmd_op = UBLK_U_CMD_ADD_DEV, 148 .flags = CTRL_CMD_HAS_BUF, 149 .addr = (__u64) (uintptr_t) &dev->dev_info, 150 .len = sizeof(struct ublksrv_ctrl_dev_info), 151 }; 152 153 return __ublk_ctrl_cmd(dev, &data); 154 } 155 156 static int ublk_ctrl_del_dev(struct ublk_dev *dev) 157 { 158 struct ublk_ctrl_cmd_data data = { 159 .cmd_op = UBLK_U_CMD_DEL_DEV, 160 .flags = 0, 161 }; 162 163 return __ublk_ctrl_cmd(dev, &data); 164 } 165 166 static int ublk_ctrl_get_info(struct ublk_dev *dev) 167 { 168 struct ublk_ctrl_cmd_data data = { 169 .cmd_op = UBLK_U_CMD_GET_DEV_INFO, 170 .flags = CTRL_CMD_HAS_BUF, 171 .addr = (__u64) (uintptr_t) &dev->dev_info, 172 .len = sizeof(struct ublksrv_ctrl_dev_info), 173 }; 174 175 return __ublk_ctrl_cmd(dev, &data); 176 } 177 178 static int ublk_ctrl_set_params(struct ublk_dev *dev, 179 struct ublk_params *params) 180 { 181 struct ublk_ctrl_cmd_data data = { 182 .cmd_op = UBLK_U_CMD_SET_PARAMS, 183 .flags = CTRL_CMD_HAS_BUF, 184 .addr = (__u64) (uintptr_t) params, 185 .len = sizeof(*params), 186 }; 187 params->len = sizeof(*params); 188 return __ublk_ctrl_cmd(dev, &data); 189 } 190 191 static int ublk_ctrl_get_params(struct ublk_dev *dev, 192 struct ublk_params *params) 193 { 194 struct ublk_ctrl_cmd_data data = { 195 .cmd_op = UBLK_U_CMD_GET_PARAMS, 196 .flags = CTRL_CMD_HAS_BUF, 197 .addr = (__u64)params, 198 .len = sizeof(*params), 199 }; 200 201 params->len = sizeof(*params); 202 203 return __ublk_ctrl_cmd(dev, &data); 204 } 205 206 static int ublk_ctrl_get_features(struct ublk_dev *dev, 207 __u64 *features) 208 { 209 struct ublk_ctrl_cmd_data data = { 210 .cmd_op = UBLK_U_CMD_GET_FEATURES, 211 .flags = CTRL_CMD_HAS_BUF, 212 .addr = (__u64) (uintptr_t) features, 213 .len = sizeof(*features), 214 }; 215 216 return __ublk_ctrl_cmd(dev, &data); 217 } 218 219 static const char *ublk_dev_state_desc(struct ublk_dev *dev) 220 { 221 switch (dev->dev_info.state) { 222 case UBLK_S_DEV_DEAD: 223 return "DEAD"; 224 case UBLK_S_DEV_LIVE: 225 return "LIVE"; 226 case UBLK_S_DEV_QUIESCED: 227 return "QUIESCED"; 228 default: 229 return "UNKNOWN"; 230 }; 231 } 232 233 static void ublk_print_cpu_set(const cpu_set_t *set, char *buf, unsigned len) 234 { 235 unsigned done = 0; 236 int i; 237 238 for (i = 0; i < CPU_SETSIZE; i++) { 239 if (CPU_ISSET(i, set)) 240 done += snprintf(&buf[done], len - done, "%d ", i); 241 } 242 } 243 244 static void ublk_adjust_affinity(cpu_set_t *set) 245 { 246 int j, updated = 0; 247 248 /* 249 * Just keep the 1st CPU now. 250 * 251 * In future, auto affinity selection can be tried. 252 */ 253 for (j = 0; j < CPU_SETSIZE; j++) { 254 if (CPU_ISSET(j, set)) { 255 if (!updated) { 256 updated = 1; 257 continue; 258 } 259 CPU_CLR(j, set); 260 } 261 } 262 } 263 264 /* Caller must free the allocated buffer */ 265 static int ublk_ctrl_get_affinity(struct ublk_dev *ctrl_dev, cpu_set_t **ptr_buf) 266 { 267 struct ublk_ctrl_cmd_data data = { 268 .cmd_op = UBLK_U_CMD_GET_QUEUE_AFFINITY, 269 .flags = CTRL_CMD_HAS_DATA | CTRL_CMD_HAS_BUF, 270 }; 271 cpu_set_t *buf; 272 int i, ret; 273 274 buf = malloc(sizeof(cpu_set_t) * ctrl_dev->dev_info.nr_hw_queues); 275 if (!buf) 276 return -ENOMEM; 277 278 for (i = 0; i < ctrl_dev->dev_info.nr_hw_queues; i++) { 279 data.data[0] = i; 280 data.len = sizeof(cpu_set_t); 281 data.addr = (__u64)&buf[i]; 282 283 ret = __ublk_ctrl_cmd(ctrl_dev, &data); 284 if (ret < 0) { 285 free(buf); 286 return ret; 287 } 288 ublk_adjust_affinity(&buf[i]); 289 } 290 291 *ptr_buf = buf; 292 return 0; 293 } 294 295 static void ublk_ctrl_dump(struct ublk_dev *dev) 296 { 297 struct ublksrv_ctrl_dev_info *info = &dev->dev_info; 298 struct ublk_params p; 299 cpu_set_t *affinity; 300 int ret; 301 302 ret = ublk_ctrl_get_params(dev, &p); 303 if (ret < 0) { 304 ublk_err("failed to get params %d %s\n", ret, strerror(-ret)); 305 return; 306 } 307 308 ret = ublk_ctrl_get_affinity(dev, &affinity); 309 if (ret < 0) { 310 ublk_err("failed to get affinity %m\n"); 311 return; 312 } 313 314 ublk_log("dev id %d: nr_hw_queues %d queue_depth %d block size %d dev_capacity %lld\n", 315 info->dev_id, info->nr_hw_queues, info->queue_depth, 316 1 << p.basic.logical_bs_shift, p.basic.dev_sectors); 317 ublk_log("\tmax rq size %d daemon pid %d flags 0x%llx state %s\n", 318 info->max_io_buf_bytes, info->ublksrv_pid, info->flags, 319 ublk_dev_state_desc(dev)); 320 321 if (affinity) { 322 char buf[512]; 323 int i; 324 325 for (i = 0; i < info->nr_hw_queues; i++) { 326 ublk_print_cpu_set(&affinity[i], buf, sizeof(buf)); 327 printf("\tqueue %u: tid %d affinity(%s)\n", 328 i, dev->q[i].tid, buf); 329 } 330 free(affinity); 331 } 332 333 fflush(stdout); 334 } 335 336 static void ublk_ctrl_deinit(struct ublk_dev *dev) 337 { 338 close(dev->ctrl_fd); 339 free(dev); 340 } 341 342 static struct ublk_dev *ublk_ctrl_init(void) 343 { 344 struct ublk_dev *dev = (struct ublk_dev *)calloc(1, sizeof(*dev)); 345 struct ublksrv_ctrl_dev_info *info = &dev->dev_info; 346 int ret; 347 348 dev->ctrl_fd = open(CTRL_DEV, O_RDWR); 349 if (dev->ctrl_fd < 0) { 350 free(dev); 351 return NULL; 352 } 353 354 info->max_io_buf_bytes = UBLK_IO_MAX_BYTES; 355 356 ret = ublk_setup_ring(&dev->ring, UBLK_CTRL_RING_DEPTH, 357 UBLK_CTRL_RING_DEPTH, IORING_SETUP_SQE128); 358 if (ret < 0) { 359 ublk_err("queue_init: %s\n", strerror(-ret)); 360 free(dev); 361 return NULL; 362 } 363 dev->nr_fds = 1; 364 365 return dev; 366 } 367 368 static int __ublk_queue_cmd_buf_sz(unsigned depth) 369 { 370 int size = depth * sizeof(struct ublksrv_io_desc); 371 unsigned int page_sz = getpagesize(); 372 373 return round_up(size, page_sz); 374 } 375 376 static int ublk_queue_max_cmd_buf_sz(void) 377 { 378 return __ublk_queue_cmd_buf_sz(UBLK_MAX_QUEUE_DEPTH); 379 } 380 381 static int ublk_queue_cmd_buf_sz(struct ublk_queue *q) 382 { 383 return __ublk_queue_cmd_buf_sz(q->q_depth); 384 } 385 386 static void ublk_queue_deinit(struct ublk_queue *q) 387 { 388 int i; 389 int nr_ios = q->q_depth; 390 391 io_uring_unregister_buffers(&q->ring); 392 393 io_uring_unregister_ring_fd(&q->ring); 394 395 if (q->ring.ring_fd > 0) { 396 io_uring_unregister_files(&q->ring); 397 close(q->ring.ring_fd); 398 q->ring.ring_fd = -1; 399 } 400 401 if (q->io_cmd_buf) 402 munmap(q->io_cmd_buf, ublk_queue_cmd_buf_sz(q)); 403 404 for (i = 0; i < nr_ios; i++) 405 free(q->ios[i].buf_addr); 406 } 407 408 static int ublk_queue_init(struct ublk_queue *q) 409 { 410 struct ublk_dev *dev = q->dev; 411 int depth = dev->dev_info.queue_depth; 412 int i, ret = -1; 413 int cmd_buf_size, io_buf_size; 414 unsigned long off; 415 int ring_depth = dev->tgt.sq_depth, cq_depth = dev->tgt.cq_depth; 416 417 q->tgt_ops = dev->tgt.ops; 418 q->state = 0; 419 q->q_depth = depth; 420 q->cmd_inflight = 0; 421 q->tid = gettid(); 422 423 if (dev->dev_info.flags & UBLK_F_SUPPORT_ZERO_COPY) { 424 q->state |= UBLKSRV_NO_BUF; 425 q->state |= UBLKSRV_ZC; 426 } 427 428 cmd_buf_size = ublk_queue_cmd_buf_sz(q); 429 off = UBLKSRV_CMD_BUF_OFFSET + q->q_id * ublk_queue_max_cmd_buf_sz(); 430 q->io_cmd_buf = mmap(0, cmd_buf_size, PROT_READ, 431 MAP_SHARED | MAP_POPULATE, dev->fds[0], off); 432 if (q->io_cmd_buf == MAP_FAILED) { 433 ublk_err("ublk dev %d queue %d map io_cmd_buf failed %m\n", 434 q->dev->dev_info.dev_id, q->q_id); 435 goto fail; 436 } 437 438 io_buf_size = dev->dev_info.max_io_buf_bytes; 439 for (i = 0; i < q->q_depth; i++) { 440 q->ios[i].buf_addr = NULL; 441 q->ios[i].flags = UBLKSRV_NEED_FETCH_RQ | UBLKSRV_IO_FREE; 442 443 if (q->state & UBLKSRV_NO_BUF) 444 continue; 445 446 if (posix_memalign((void **)&q->ios[i].buf_addr, 447 getpagesize(), io_buf_size)) { 448 ublk_err("ublk dev %d queue %d io %d posix_memalign failed %m\n", 449 dev->dev_info.dev_id, q->q_id, i); 450 goto fail; 451 } 452 } 453 454 ret = ublk_setup_ring(&q->ring, ring_depth, cq_depth, 455 IORING_SETUP_COOP_TASKRUN | 456 IORING_SETUP_SINGLE_ISSUER | 457 IORING_SETUP_DEFER_TASKRUN); 458 if (ret < 0) { 459 ublk_err("ublk dev %d queue %d setup io_uring failed %d\n", 460 q->dev->dev_info.dev_id, q->q_id, ret); 461 goto fail; 462 } 463 464 if (dev->dev_info.flags & UBLK_F_SUPPORT_ZERO_COPY) { 465 ret = io_uring_register_buffers_sparse(&q->ring, q->q_depth); 466 if (ret) { 467 ublk_err("ublk dev %d queue %d register spare buffers failed %d", 468 dev->dev_info.dev_id, q->q_id, ret); 469 goto fail; 470 } 471 } 472 473 io_uring_register_ring_fd(&q->ring); 474 475 ret = io_uring_register_files(&q->ring, dev->fds, dev->nr_fds); 476 if (ret) { 477 ublk_err("ublk dev %d queue %d register files failed %d\n", 478 q->dev->dev_info.dev_id, q->q_id, ret); 479 goto fail; 480 } 481 482 return 0; 483 fail: 484 ublk_queue_deinit(q); 485 ublk_err("ublk dev %d queue %d failed\n", 486 dev->dev_info.dev_id, q->q_id); 487 return -ENOMEM; 488 } 489 490 #define WAIT_USEC 100000 491 #define MAX_WAIT_USEC (3 * 1000000) 492 static int ublk_dev_prep(const struct dev_ctx *ctx, struct ublk_dev *dev) 493 { 494 int dev_id = dev->dev_info.dev_id; 495 unsigned int wait_usec = 0; 496 int ret = 0, fd = -1; 497 char buf[64]; 498 499 snprintf(buf, 64, "%s%d", UBLKC_DEV, dev_id); 500 501 while (wait_usec < MAX_WAIT_USEC) { 502 fd = open(buf, O_RDWR); 503 if (fd >= 0) 504 break; 505 usleep(WAIT_USEC); 506 wait_usec += WAIT_USEC; 507 } 508 if (fd < 0) { 509 ublk_err("can't open %s %s\n", buf, strerror(errno)); 510 return -1; 511 } 512 513 dev->fds[0] = fd; 514 if (dev->tgt.ops->init_tgt) 515 ret = dev->tgt.ops->init_tgt(ctx, dev); 516 if (ret) 517 close(dev->fds[0]); 518 return ret; 519 } 520 521 static void ublk_dev_unprep(struct ublk_dev *dev) 522 { 523 if (dev->tgt.ops->deinit_tgt) 524 dev->tgt.ops->deinit_tgt(dev); 525 close(dev->fds[0]); 526 } 527 528 int ublk_queue_io_cmd(struct ublk_queue *q, struct ublk_io *io, unsigned tag) 529 { 530 struct ublksrv_io_cmd *cmd; 531 struct io_uring_sqe *sqe[1]; 532 unsigned int cmd_op = 0; 533 __u64 user_data; 534 535 /* only freed io can be issued */ 536 if (!(io->flags & UBLKSRV_IO_FREE)) 537 return 0; 538 539 /* we issue because we need either fetching or committing */ 540 if (!(io->flags & 541 (UBLKSRV_NEED_FETCH_RQ | UBLKSRV_NEED_COMMIT_RQ_COMP))) 542 return 0; 543 544 if (io->flags & UBLKSRV_NEED_COMMIT_RQ_COMP) 545 cmd_op = UBLK_U_IO_COMMIT_AND_FETCH_REQ; 546 else if (io->flags & UBLKSRV_NEED_FETCH_RQ) 547 cmd_op = UBLK_U_IO_FETCH_REQ; 548 549 if (io_uring_sq_space_left(&q->ring) < 1) 550 io_uring_submit(&q->ring); 551 552 ublk_queue_alloc_sqes(q, sqe, 1); 553 if (!sqe[0]) { 554 ublk_err("%s: run out of sqe %d, tag %d\n", 555 __func__, q->q_id, tag); 556 return -1; 557 } 558 559 cmd = (struct ublksrv_io_cmd *)ublk_get_sqe_cmd(sqe[0]); 560 561 if (cmd_op == UBLK_U_IO_COMMIT_AND_FETCH_REQ) 562 cmd->result = io->result; 563 564 /* These fields should be written once, never change */ 565 ublk_set_sqe_cmd_op(sqe[0], cmd_op); 566 sqe[0]->fd = 0; /* dev->fds[0] */ 567 sqe[0]->opcode = IORING_OP_URING_CMD; 568 sqe[0]->flags = IOSQE_FIXED_FILE; 569 sqe[0]->rw_flags = 0; 570 cmd->tag = tag; 571 cmd->q_id = q->q_id; 572 if (!(q->state & UBLKSRV_NO_BUF)) 573 cmd->addr = (__u64) (uintptr_t) io->buf_addr; 574 else 575 cmd->addr = 0; 576 577 user_data = build_user_data(tag, _IOC_NR(cmd_op), 0, 0); 578 io_uring_sqe_set_data64(sqe[0], user_data); 579 580 io->flags = 0; 581 582 q->cmd_inflight += 1; 583 584 ublk_dbg(UBLK_DBG_IO_CMD, "%s: (qid %d tag %u cmd_op %u) iof %x stopping %d\n", 585 __func__, q->q_id, tag, cmd_op, 586 io->flags, !!(q->state & UBLKSRV_QUEUE_STOPPING)); 587 return 1; 588 } 589 590 static void ublk_submit_fetch_commands(struct ublk_queue *q) 591 { 592 int i = 0; 593 594 for (i = 0; i < q->q_depth; i++) 595 ublk_queue_io_cmd(q, &q->ios[i], i); 596 } 597 598 static int ublk_queue_is_idle(struct ublk_queue *q) 599 { 600 return !io_uring_sq_ready(&q->ring) && !q->io_inflight; 601 } 602 603 static int ublk_queue_is_done(struct ublk_queue *q) 604 { 605 return (q->state & UBLKSRV_QUEUE_STOPPING) && ublk_queue_is_idle(q); 606 } 607 608 static inline void ublksrv_handle_tgt_cqe(struct ublk_queue *q, 609 struct io_uring_cqe *cqe) 610 { 611 unsigned tag = user_data_to_tag(cqe->user_data); 612 613 if (cqe->res < 0 && cqe->res != -EAGAIN) 614 ublk_err("%s: failed tgt io: res %d qid %u tag %u, cmd_op %u\n", 615 __func__, cqe->res, q->q_id, 616 user_data_to_tag(cqe->user_data), 617 user_data_to_op(cqe->user_data)); 618 619 if (q->tgt_ops->tgt_io_done) 620 q->tgt_ops->tgt_io_done(q, tag, cqe); 621 } 622 623 static void ublk_handle_cqe(struct io_uring *r, 624 struct io_uring_cqe *cqe, void *data) 625 { 626 struct ublk_queue *q = container_of(r, struct ublk_queue, ring); 627 unsigned tag = user_data_to_tag(cqe->user_data); 628 unsigned cmd_op = user_data_to_op(cqe->user_data); 629 int fetch = (cqe->res != UBLK_IO_RES_ABORT) && 630 !(q->state & UBLKSRV_QUEUE_STOPPING); 631 struct ublk_io *io; 632 633 if (cqe->res < 0 && cqe->res != -ENODEV) 634 ublk_err("%s: res %d userdata %llx queue state %x\n", __func__, 635 cqe->res, cqe->user_data, q->state); 636 637 ublk_dbg(UBLK_DBG_IO_CMD, "%s: res %d (qid %d tag %u cmd_op %u target %d/%d) stopping %d\n", 638 __func__, cqe->res, q->q_id, tag, cmd_op, 639 is_target_io(cqe->user_data), 640 user_data_to_tgt_data(cqe->user_data), 641 (q->state & UBLKSRV_QUEUE_STOPPING)); 642 643 /* Don't retrieve io in case of target io */ 644 if (is_target_io(cqe->user_data)) { 645 ublksrv_handle_tgt_cqe(q, cqe); 646 return; 647 } 648 649 io = &q->ios[tag]; 650 q->cmd_inflight--; 651 652 if (!fetch) { 653 q->state |= UBLKSRV_QUEUE_STOPPING; 654 io->flags &= ~UBLKSRV_NEED_FETCH_RQ; 655 } 656 657 if (cqe->res == UBLK_IO_RES_OK) { 658 assert(tag < q->q_depth); 659 if (q->tgt_ops->queue_io) 660 q->tgt_ops->queue_io(q, tag); 661 } else { 662 /* 663 * COMMIT_REQ will be completed immediately since no fetching 664 * piggyback is required. 665 * 666 * Marking IO_FREE only, then this io won't be issued since 667 * we only issue io with (UBLKSRV_IO_FREE | UBLKSRV_NEED_*) 668 * 669 * */ 670 io->flags = UBLKSRV_IO_FREE; 671 } 672 } 673 674 static int ublk_reap_events_uring(struct io_uring *r) 675 { 676 struct io_uring_cqe *cqe; 677 unsigned head; 678 int count = 0; 679 680 io_uring_for_each_cqe(r, head, cqe) { 681 ublk_handle_cqe(r, cqe, NULL); 682 count += 1; 683 } 684 io_uring_cq_advance(r, count); 685 686 return count; 687 } 688 689 static int ublk_process_io(struct ublk_queue *q) 690 { 691 int ret, reapped; 692 693 ublk_dbg(UBLK_DBG_QUEUE, "dev%d-q%d: to_submit %d inflight cmd %u stopping %d\n", 694 q->dev->dev_info.dev_id, 695 q->q_id, io_uring_sq_ready(&q->ring), 696 q->cmd_inflight, 697 (q->state & UBLKSRV_QUEUE_STOPPING)); 698 699 if (ublk_queue_is_done(q)) 700 return -ENODEV; 701 702 ret = io_uring_submit_and_wait(&q->ring, 1); 703 reapped = ublk_reap_events_uring(&q->ring); 704 705 ublk_dbg(UBLK_DBG_QUEUE, "submit result %d, reapped %d stop %d idle %d\n", 706 ret, reapped, (q->state & UBLKSRV_QUEUE_STOPPING), 707 (q->state & UBLKSRV_QUEUE_IDLE)); 708 709 return reapped; 710 } 711 712 static void ublk_queue_set_sched_affinity(const struct ublk_queue *q, 713 cpu_set_t *cpuset) 714 { 715 if (sched_setaffinity(0, sizeof(*cpuset), cpuset) < 0) 716 ublk_err("ublk dev %u queue %u set affinity failed", 717 q->dev->dev_info.dev_id, q->q_id); 718 } 719 720 struct ublk_queue_info { 721 struct ublk_queue *q; 722 sem_t *queue_sem; 723 cpu_set_t *affinity; 724 }; 725 726 static void *ublk_io_handler_fn(void *data) 727 { 728 struct ublk_queue_info *info = data; 729 struct ublk_queue *q = info->q; 730 int dev_id = q->dev->dev_info.dev_id; 731 int ret; 732 733 ret = ublk_queue_init(q); 734 if (ret) { 735 ublk_err("ublk dev %d queue %d init queue failed\n", 736 dev_id, q->q_id); 737 return NULL; 738 } 739 /* IO perf is sensitive with queue pthread affinity on NUMA machine*/ 740 ublk_queue_set_sched_affinity(q, info->affinity); 741 sem_post(info->queue_sem); 742 743 ublk_dbg(UBLK_DBG_QUEUE, "tid %d: ublk dev %d queue %d started\n", 744 q->tid, dev_id, q->q_id); 745 746 /* submit all io commands to ublk driver */ 747 ublk_submit_fetch_commands(q); 748 do { 749 if (ublk_process_io(q) < 0) 750 break; 751 } while (1); 752 753 ublk_dbg(UBLK_DBG_QUEUE, "ublk dev %d queue %d exited\n", dev_id, q->q_id); 754 ublk_queue_deinit(q); 755 return NULL; 756 } 757 758 static void ublk_set_parameters(struct ublk_dev *dev) 759 { 760 int ret; 761 762 ret = ublk_ctrl_set_params(dev, &dev->tgt.params); 763 if (ret) 764 ublk_err("dev %d set basic parameter failed %d\n", 765 dev->dev_info.dev_id, ret); 766 } 767 768 static int ublk_send_dev_event(const struct dev_ctx *ctx, struct ublk_dev *dev, int dev_id) 769 { 770 uint64_t id; 771 int evtfd = ctx->_evtfd; 772 773 if (evtfd < 0) 774 return -EBADF; 775 776 if (dev_id >= 0) 777 id = dev_id + 1; 778 else 779 id = ERROR_EVTFD_DEVID; 780 781 if (dev && ctx->shadow_dev) 782 memcpy(&ctx->shadow_dev->q, &dev->q, sizeof(dev->q)); 783 784 if (write(evtfd, &id, sizeof(id)) != sizeof(id)) 785 return -EINVAL; 786 787 close(evtfd); 788 shmdt(ctx->shadow_dev); 789 790 return 0; 791 } 792 793 794 static int ublk_start_daemon(const struct dev_ctx *ctx, struct ublk_dev *dev) 795 { 796 const struct ublksrv_ctrl_dev_info *dinfo = &dev->dev_info; 797 struct ublk_queue_info *qinfo; 798 cpu_set_t *affinity_buf; 799 void *thread_ret; 800 sem_t queue_sem; 801 int ret, i; 802 803 ublk_dbg(UBLK_DBG_DEV, "%s enter\n", __func__); 804 805 qinfo = (struct ublk_queue_info *)calloc(sizeof(struct ublk_queue_info), 806 dinfo->nr_hw_queues); 807 if (!qinfo) 808 return -ENOMEM; 809 810 sem_init(&queue_sem, 0, 0); 811 ret = ublk_dev_prep(ctx, dev); 812 if (ret) 813 return ret; 814 815 ret = ublk_ctrl_get_affinity(dev, &affinity_buf); 816 if (ret) 817 return ret; 818 819 for (i = 0; i < dinfo->nr_hw_queues; i++) { 820 dev->q[i].dev = dev; 821 dev->q[i].q_id = i; 822 823 qinfo[i].q = &dev->q[i]; 824 qinfo[i].queue_sem = &queue_sem; 825 qinfo[i].affinity = &affinity_buf[i]; 826 pthread_create(&dev->q[i].thread, NULL, 827 ublk_io_handler_fn, 828 &qinfo[i]); 829 } 830 831 for (i = 0; i < dinfo->nr_hw_queues; i++) 832 sem_wait(&queue_sem); 833 free(qinfo); 834 free(affinity_buf); 835 836 /* everything is fine now, start us */ 837 if (ctx->recovery) 838 ret = ublk_ctrl_end_user_recovery(dev, getpid()); 839 else { 840 ublk_set_parameters(dev); 841 ret = ublk_ctrl_start_dev(dev, getpid()); 842 } 843 if (ret < 0) { 844 ublk_err("%s: ublk_ctrl_start_dev failed: %d\n", __func__, ret); 845 goto fail; 846 } 847 848 ublk_ctrl_get_info(dev); 849 if (ctx->fg) 850 ublk_ctrl_dump(dev); 851 else 852 ublk_send_dev_event(ctx, dev, dev->dev_info.dev_id); 853 854 /* wait until we are terminated */ 855 for (i = 0; i < dinfo->nr_hw_queues; i++) 856 pthread_join(dev->q[i].thread, &thread_ret); 857 fail: 858 ublk_dev_unprep(dev); 859 ublk_dbg(UBLK_DBG_DEV, "%s exit\n", __func__); 860 861 return ret; 862 } 863 864 static int wait_ublk_dev(const char *path, int evt_mask, unsigned timeout) 865 { 866 #define EV_SIZE (sizeof(struct inotify_event)) 867 #define EV_BUF_LEN (128 * (EV_SIZE + 16)) 868 struct pollfd pfd; 869 int fd, wd; 870 int ret = -EINVAL; 871 const char *dev_name = basename(path); 872 873 fd = inotify_init(); 874 if (fd < 0) { 875 ublk_dbg(UBLK_DBG_DEV, "%s: inotify init failed\n", __func__); 876 return fd; 877 } 878 879 wd = inotify_add_watch(fd, "/dev", evt_mask); 880 if (wd == -1) { 881 ublk_dbg(UBLK_DBG_DEV, "%s: add watch for /dev failed\n", __func__); 882 goto fail; 883 } 884 885 pfd.fd = fd; 886 pfd.events = POLL_IN; 887 while (1) { 888 int i = 0; 889 char buffer[EV_BUF_LEN]; 890 ret = poll(&pfd, 1, 1000 * timeout); 891 892 if (ret == -1) { 893 ublk_err("%s: poll inotify failed: %d\n", __func__, ret); 894 goto rm_watch; 895 } else if (ret == 0) { 896 ublk_err("%s: poll inotify timeout\n", __func__); 897 ret = -ETIMEDOUT; 898 goto rm_watch; 899 } 900 901 ret = read(fd, buffer, EV_BUF_LEN); 902 if (ret < 0) { 903 ublk_err("%s: read inotify fd failed\n", __func__); 904 goto rm_watch; 905 } 906 907 while (i < ret) { 908 struct inotify_event *event = (struct inotify_event *)&buffer[i]; 909 910 ublk_dbg(UBLK_DBG_DEV, "%s: inotify event %x %s\n", 911 __func__, event->mask, event->name); 912 if (event->mask & evt_mask) { 913 if (!strcmp(event->name, dev_name)) { 914 ret = 0; 915 goto rm_watch; 916 } 917 } 918 i += EV_SIZE + event->len; 919 } 920 } 921 rm_watch: 922 inotify_rm_watch(fd, wd); 923 fail: 924 close(fd); 925 return ret; 926 } 927 928 static int ublk_stop_io_daemon(const struct ublk_dev *dev) 929 { 930 int daemon_pid = dev->dev_info.ublksrv_pid; 931 int dev_id = dev->dev_info.dev_id; 932 char ublkc[64]; 933 int ret = 0; 934 935 if (daemon_pid < 0) 936 return 0; 937 938 /* daemon may be dead already */ 939 if (kill(daemon_pid, 0) < 0) 940 goto wait; 941 942 snprintf(ublkc, sizeof(ublkc), "/dev/%s%d", "ublkc", dev_id); 943 944 /* ublk char device may be gone already */ 945 if (access(ublkc, F_OK) != 0) 946 goto wait; 947 948 /* Wait until ublk char device is closed, when the daemon is shutdown */ 949 ret = wait_ublk_dev(ublkc, IN_CLOSE, 10); 950 /* double check and since it may be closed before starting inotify */ 951 if (ret == -ETIMEDOUT) 952 ret = kill(daemon_pid, 0) < 0; 953 wait: 954 waitpid(daemon_pid, NULL, 0); 955 ublk_dbg(UBLK_DBG_DEV, "%s: pid %d dev_id %d ret %d\n", 956 __func__, daemon_pid, dev_id, ret); 957 958 return ret; 959 } 960 961 static int __cmd_dev_add(const struct dev_ctx *ctx) 962 { 963 unsigned nr_queues = ctx->nr_hw_queues; 964 const char *tgt_type = ctx->tgt_type; 965 unsigned depth = ctx->queue_depth; 966 __u64 features; 967 const struct ublk_tgt_ops *ops; 968 struct ublksrv_ctrl_dev_info *info; 969 struct ublk_dev *dev; 970 int dev_id = ctx->dev_id; 971 int ret, i; 972 973 ops = ublk_find_tgt(tgt_type); 974 if (!ops) { 975 ublk_err("%s: no such tgt type, type %s\n", 976 __func__, tgt_type); 977 return -ENODEV; 978 } 979 980 if (nr_queues > UBLK_MAX_QUEUES || depth > UBLK_QUEUE_DEPTH) { 981 ublk_err("%s: invalid nr_queues or depth queues %u depth %u\n", 982 __func__, nr_queues, depth); 983 return -EINVAL; 984 } 985 986 dev = ublk_ctrl_init(); 987 if (!dev) { 988 ublk_err("%s: can't alloc dev id %d, type %s\n", 989 __func__, dev_id, tgt_type); 990 return -ENOMEM; 991 } 992 993 /* kernel doesn't support get_features */ 994 ret = ublk_ctrl_get_features(dev, &features); 995 if (ret < 0) 996 return -EINVAL; 997 998 if (!(features & UBLK_F_CMD_IOCTL_ENCODE)) 999 return -ENOTSUP; 1000 1001 info = &dev->dev_info; 1002 info->dev_id = ctx->dev_id; 1003 info->nr_hw_queues = nr_queues; 1004 info->queue_depth = depth; 1005 info->flags = ctx->flags; 1006 dev->tgt.ops = ops; 1007 dev->tgt.sq_depth = depth; 1008 dev->tgt.cq_depth = depth; 1009 1010 for (i = 0; i < MAX_BACK_FILES; i++) { 1011 if (ctx->files[i]) { 1012 strcpy(dev->tgt.backing_file[i], ctx->files[i]); 1013 dev->tgt.nr_backing_files++; 1014 } 1015 } 1016 1017 if (ctx->recovery) 1018 ret = ublk_ctrl_start_user_recovery(dev); 1019 else 1020 ret = ublk_ctrl_add_dev(dev); 1021 if (ret < 0) { 1022 ublk_err("%s: can't add dev id %d, type %s ret %d\n", 1023 __func__, dev_id, tgt_type, ret); 1024 goto fail; 1025 } 1026 1027 ret = ublk_start_daemon(ctx, dev); 1028 ublk_dbg(UBLK_DBG_DEV, "%s: daemon exit %d\b", ret); 1029 if (ret < 0) 1030 ublk_ctrl_del_dev(dev); 1031 1032 fail: 1033 if (ret < 0) 1034 ublk_send_dev_event(ctx, dev, -1); 1035 ublk_ctrl_deinit(dev); 1036 return ret; 1037 } 1038 1039 static int __cmd_dev_list(struct dev_ctx *ctx); 1040 1041 static int cmd_dev_add(struct dev_ctx *ctx) 1042 { 1043 int res; 1044 1045 if (ctx->fg) 1046 goto run; 1047 1048 ctx->_shmid = shmget(IPC_PRIVATE, sizeof(struct ublk_dev), IPC_CREAT | 0666); 1049 if (ctx->_shmid < 0) { 1050 ublk_err("%s: failed to shmget %s\n", __func__, strerror(errno)); 1051 exit(-1); 1052 } 1053 ctx->shadow_dev = (struct ublk_dev *)shmat(ctx->_shmid, NULL, 0); 1054 if (ctx->shadow_dev == (struct ublk_dev *)-1) { 1055 ublk_err("%s: failed to shmat %s\n", __func__, strerror(errno)); 1056 exit(-1); 1057 } 1058 ctx->_evtfd = eventfd(0, 0); 1059 if (ctx->_evtfd < 0) { 1060 ublk_err("%s: failed to create eventfd %s\n", __func__, strerror(errno)); 1061 exit(-1); 1062 } 1063 1064 res = fork(); 1065 if (res == 0) { 1066 int res2; 1067 1068 setsid(); 1069 res2 = fork(); 1070 if (res2 == 0) { 1071 /* prepare for detaching */ 1072 close(STDIN_FILENO); 1073 close(STDOUT_FILENO); 1074 close(STDERR_FILENO); 1075 run: 1076 res = __cmd_dev_add(ctx); 1077 return res; 1078 } else { 1079 /* detached from the foreground task */ 1080 exit(EXIT_SUCCESS); 1081 } 1082 } else if (res > 0) { 1083 uint64_t id; 1084 int exit_code = EXIT_FAILURE; 1085 1086 res = read(ctx->_evtfd, &id, sizeof(id)); 1087 close(ctx->_evtfd); 1088 if (res == sizeof(id) && id != ERROR_EVTFD_DEVID) { 1089 ctx->dev_id = id - 1; 1090 if (__cmd_dev_list(ctx) >= 0) 1091 exit_code = EXIT_SUCCESS; 1092 } 1093 shmdt(ctx->shadow_dev); 1094 shmctl(ctx->_shmid, IPC_RMID, NULL); 1095 /* wait for child and detach from it */ 1096 wait(NULL); 1097 exit(exit_code); 1098 } else { 1099 exit(EXIT_FAILURE); 1100 } 1101 } 1102 1103 static int __cmd_dev_del(struct dev_ctx *ctx) 1104 { 1105 int number = ctx->dev_id; 1106 struct ublk_dev *dev; 1107 int ret; 1108 1109 dev = ublk_ctrl_init(); 1110 dev->dev_info.dev_id = number; 1111 1112 ret = ublk_ctrl_get_info(dev); 1113 if (ret < 0) 1114 goto fail; 1115 1116 ret = ublk_ctrl_stop_dev(dev); 1117 if (ret < 0) 1118 ublk_err("%s: stop dev %d failed ret %d\n", __func__, number, ret); 1119 1120 ret = ublk_stop_io_daemon(dev); 1121 if (ret < 0) 1122 ublk_err("%s: stop daemon id %d dev %d, ret %d\n", 1123 __func__, dev->dev_info.ublksrv_pid, number, ret); 1124 ublk_ctrl_del_dev(dev); 1125 fail: 1126 ublk_ctrl_deinit(dev); 1127 1128 return (ret >= 0) ? 0 : ret; 1129 } 1130 1131 static int cmd_dev_del(struct dev_ctx *ctx) 1132 { 1133 int i; 1134 1135 if (ctx->dev_id >= 0 || !ctx->all) 1136 return __cmd_dev_del(ctx); 1137 1138 for (i = 0; i < 255; i++) { 1139 ctx->dev_id = i; 1140 __cmd_dev_del(ctx); 1141 } 1142 return 0; 1143 } 1144 1145 static int __cmd_dev_list(struct dev_ctx *ctx) 1146 { 1147 struct ublk_dev *dev = ublk_ctrl_init(); 1148 int ret; 1149 1150 if (!dev) 1151 return -ENODEV; 1152 1153 dev->dev_info.dev_id = ctx->dev_id; 1154 1155 ret = ublk_ctrl_get_info(dev); 1156 if (ret < 0) { 1157 if (ctx->logging) 1158 ublk_err("%s: can't get dev info from %d: %d\n", 1159 __func__, ctx->dev_id, ret); 1160 } else { 1161 if (ctx->shadow_dev) 1162 memcpy(&dev->q, ctx->shadow_dev->q, sizeof(dev->q)); 1163 1164 ublk_ctrl_dump(dev); 1165 } 1166 1167 ublk_ctrl_deinit(dev); 1168 1169 return ret; 1170 } 1171 1172 static int cmd_dev_list(struct dev_ctx *ctx) 1173 { 1174 int i; 1175 1176 if (ctx->dev_id >= 0 || !ctx->all) 1177 return __cmd_dev_list(ctx); 1178 1179 ctx->logging = false; 1180 for (i = 0; i < 255; i++) { 1181 ctx->dev_id = i; 1182 __cmd_dev_list(ctx); 1183 } 1184 return 0; 1185 } 1186 1187 static int cmd_dev_get_features(void) 1188 { 1189 #define const_ilog2(x) (63 - __builtin_clzll(x)) 1190 static const char *feat_map[] = { 1191 [const_ilog2(UBLK_F_SUPPORT_ZERO_COPY)] = "ZERO_COPY", 1192 [const_ilog2(UBLK_F_URING_CMD_COMP_IN_TASK)] = "COMP_IN_TASK", 1193 [const_ilog2(UBLK_F_NEED_GET_DATA)] = "GET_DATA", 1194 [const_ilog2(UBLK_F_USER_RECOVERY)] = "USER_RECOVERY", 1195 [const_ilog2(UBLK_F_USER_RECOVERY_REISSUE)] = "RECOVERY_REISSUE", 1196 [const_ilog2(UBLK_F_UNPRIVILEGED_DEV)] = "UNPRIVILEGED_DEV", 1197 [const_ilog2(UBLK_F_CMD_IOCTL_ENCODE)] = "CMD_IOCTL_ENCODE", 1198 [const_ilog2(UBLK_F_USER_COPY)] = "USER_COPY", 1199 [const_ilog2(UBLK_F_ZONED)] = "ZONED", 1200 [const_ilog2(UBLK_F_USER_RECOVERY_FAIL_IO)] = "RECOVERY_FAIL_IO", 1201 }; 1202 struct ublk_dev *dev; 1203 __u64 features = 0; 1204 int ret; 1205 1206 dev = ublk_ctrl_init(); 1207 if (!dev) { 1208 fprintf(stderr, "ublksrv_ctrl_init failed id\n"); 1209 return -EOPNOTSUPP; 1210 } 1211 1212 ret = ublk_ctrl_get_features(dev, &features); 1213 if (!ret) { 1214 int i; 1215 1216 printf("ublk_drv features: 0x%llx\n", features); 1217 1218 for (i = 0; i < sizeof(features) * 8; i++) { 1219 const char *feat; 1220 1221 if (!((1ULL << i) & features)) 1222 continue; 1223 if (i < sizeof(feat_map) / sizeof(feat_map[0])) 1224 feat = feat_map[i]; 1225 else 1226 feat = "unknown"; 1227 printf("\t%-20s: 0x%llx\n", feat, 1ULL << i); 1228 } 1229 } 1230 1231 return ret; 1232 } 1233 1234 static void __cmd_create_help(char *exe, bool recovery) 1235 { 1236 int i; 1237 1238 printf("%s %s -t [null|loop|stripe|fault_inject] [-q nr_queues] [-d depth] [-n dev_id]\n", 1239 exe, recovery ? "recover" : "add"); 1240 printf("\t[--foreground] [--quiet] [-z] [--debug_mask mask] [-r 0|1 ] [-g 0|1]\n"); 1241 printf("\t[-e 0|1 ] [-i 0|1]\n"); 1242 printf("\t[target options] [backfile1] [backfile2] ...\n"); 1243 printf("\tdefault: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n"); 1244 1245 for (i = 0; i < sizeof(tgt_ops_list) / sizeof(tgt_ops_list[0]); i++) { 1246 const struct ublk_tgt_ops *ops = tgt_ops_list[i]; 1247 1248 if (ops->usage) 1249 ops->usage(ops); 1250 } 1251 } 1252 1253 static void cmd_add_help(char *exe) 1254 { 1255 __cmd_create_help(exe, false); 1256 printf("\n"); 1257 } 1258 1259 static void cmd_recover_help(char *exe) 1260 { 1261 __cmd_create_help(exe, true); 1262 printf("\tPlease provide exact command line for creating this device with real dev_id\n"); 1263 printf("\n"); 1264 } 1265 1266 static int cmd_dev_help(char *exe) 1267 { 1268 cmd_add_help(exe); 1269 cmd_recover_help(exe); 1270 1271 printf("%s del [-n dev_id] -a \n", exe); 1272 printf("\t -a delete all devices -n delete specified device\n\n"); 1273 printf("%s list [-n dev_id] -a \n", exe); 1274 printf("\t -a list all devices, -n list specified device, default -a \n\n"); 1275 printf("%s features\n", exe); 1276 return 0; 1277 } 1278 1279 int main(int argc, char *argv[]) 1280 { 1281 static const struct option longopts[] = { 1282 { "all", 0, NULL, 'a' }, 1283 { "type", 1, NULL, 't' }, 1284 { "number", 1, NULL, 'n' }, 1285 { "queues", 1, NULL, 'q' }, 1286 { "depth", 1, NULL, 'd' }, 1287 { "debug_mask", 1, NULL, 0 }, 1288 { "quiet", 0, NULL, 0 }, 1289 { "zero_copy", 0, NULL, 'z' }, 1290 { "foreground", 0, NULL, 0 }, 1291 { "recovery", 1, NULL, 'r' }, 1292 { "recovery_fail_io", 1, NULL, 'e'}, 1293 { "recovery_reissue", 1, NULL, 'i'}, 1294 { "get_data", 1, NULL, 'g'}, 1295 { 0, 0, 0, 0 } 1296 }; 1297 const struct ublk_tgt_ops *ops = NULL; 1298 int option_idx, opt; 1299 const char *cmd = argv[1]; 1300 struct dev_ctx ctx = { 1301 .queue_depth = 128, 1302 .nr_hw_queues = 2, 1303 .dev_id = -1, 1304 .tgt_type = "unknown", 1305 }; 1306 int ret = -EINVAL, i; 1307 int tgt_argc = 1; 1308 char *tgt_argv[MAX_NR_TGT_ARG] = { NULL }; 1309 int value; 1310 1311 if (argc == 1) 1312 return ret; 1313 1314 opterr = 0; 1315 optind = 2; 1316 while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:az", 1317 longopts, &option_idx)) != -1) { 1318 switch (opt) { 1319 case 'a': 1320 ctx.all = 1; 1321 break; 1322 case 'n': 1323 ctx.dev_id = strtol(optarg, NULL, 10); 1324 break; 1325 case 't': 1326 if (strlen(optarg) < sizeof(ctx.tgt_type)) 1327 strcpy(ctx.tgt_type, optarg); 1328 break; 1329 case 'q': 1330 ctx.nr_hw_queues = strtol(optarg, NULL, 10); 1331 break; 1332 case 'd': 1333 ctx.queue_depth = strtol(optarg, NULL, 10); 1334 break; 1335 case 'z': 1336 ctx.flags |= UBLK_F_SUPPORT_ZERO_COPY | UBLK_F_USER_COPY; 1337 break; 1338 case 'r': 1339 value = strtol(optarg, NULL, 10); 1340 if (value) 1341 ctx.flags |= UBLK_F_USER_RECOVERY; 1342 break; 1343 case 'e': 1344 value = strtol(optarg, NULL, 10); 1345 if (value) 1346 ctx.flags |= UBLK_F_USER_RECOVERY | UBLK_F_USER_RECOVERY_FAIL_IO; 1347 break; 1348 case 'i': 1349 value = strtol(optarg, NULL, 10); 1350 if (value) 1351 ctx.flags |= UBLK_F_USER_RECOVERY | UBLK_F_USER_RECOVERY_REISSUE; 1352 break; 1353 case 'g': 1354 value = strtol(optarg, NULL, 10); 1355 if (value) 1356 ctx.flags |= UBLK_F_NEED_GET_DATA; 1357 break; 1358 case 0: 1359 if (!strcmp(longopts[option_idx].name, "debug_mask")) 1360 ublk_dbg_mask = strtol(optarg, NULL, 16); 1361 if (!strcmp(longopts[option_idx].name, "quiet")) 1362 ublk_dbg_mask = 0; 1363 if (!strcmp(longopts[option_idx].name, "foreground")) 1364 ctx.fg = 1; 1365 break; 1366 case '?': 1367 /* 1368 * target requires every option must have argument 1369 */ 1370 if (argv[optind][0] == '-' || argv[optind - 1][0] != '-') { 1371 fprintf(stderr, "every target option requires argument: %s %s\n", 1372 argv[optind - 1], argv[optind]); 1373 exit(EXIT_FAILURE); 1374 } 1375 1376 if (tgt_argc < (MAX_NR_TGT_ARG - 1) / 2) { 1377 tgt_argv[tgt_argc++] = argv[optind - 1]; 1378 tgt_argv[tgt_argc++] = argv[optind]; 1379 } else { 1380 fprintf(stderr, "too many target options\n"); 1381 exit(EXIT_FAILURE); 1382 } 1383 optind += 1; 1384 break; 1385 } 1386 } 1387 1388 i = optind; 1389 while (i < argc && ctx.nr_files < MAX_BACK_FILES) { 1390 ctx.files[ctx.nr_files++] = argv[i++]; 1391 } 1392 1393 ops = ublk_find_tgt(ctx.tgt_type); 1394 if (ops && ops->parse_cmd_line) { 1395 optind = 0; 1396 1397 tgt_argv[0] = ctx.tgt_type; 1398 ops->parse_cmd_line(&ctx, tgt_argc, tgt_argv); 1399 } 1400 1401 if (!strcmp(cmd, "add")) 1402 ret = cmd_dev_add(&ctx); 1403 else if (!strcmp(cmd, "recover")) { 1404 if (ctx.dev_id < 0) { 1405 fprintf(stderr, "device id isn't provided for recovering\n"); 1406 ret = -EINVAL; 1407 } else { 1408 ctx.recovery = 1; 1409 ret = cmd_dev_add(&ctx); 1410 } 1411 } else if (!strcmp(cmd, "del")) 1412 ret = cmd_dev_del(&ctx); 1413 else if (!strcmp(cmd, "list")) { 1414 ctx.all = 1; 1415 ret = cmd_dev_list(&ctx); 1416 } else if (!strcmp(cmd, "help")) 1417 ret = cmd_dev_help(argv[0]); 1418 else if (!strcmp(cmd, "features")) 1419 ret = cmd_dev_get_features(); 1420 else 1421 cmd_dev_help(argv[0]); 1422 1423 return ret; 1424 } 1425