static int deactivate_device(char *path) { exa_rdev_handle_t *dev_req; int ret; dev_req = exa_rdev_handle_alloc(path); if (dev_req == NULL) { fprintf(stderr, "exa_rdev_request_init() failed, disk path = %s\n", path); return -1; } ret = exa_rdev_deactivate(dev_req, NULL); if (ret != 0) fprintf(stderr, "Failed to deactivate device %s: error %d\n", path, ret); exa_rdev_handle_free(dev_req); fprintf(stderr, "Deactivated device %s\n", path); return ret; }
static int do_io(const char *disk_path, bool async, bool write, uint64_t offset, uint64_t size_in_bytes) { int exa_rdev_fd; int disk_fd; exa_rdev_handle_t *dev_req; uint64_t disk_size; int ret; /* Get disk size */ disk_fd = os_disk_open_raw(disk_path, OS_DISK_READ); if (disk_fd < 0) { fprintf(stderr, "Can not open disk %s\n", disk_path); return -1; } ret = os_disk_get_size(disk_fd, &disk_size); if (ret < 0) { fprintf(stderr, "Can not get the size of disk %s\n", disk_path); return -1; } fprintf(stderr, "Disk %s has a size of %"PRIu64" bytes\n", disk_path, disk_size); /* Initialise exa_rdev */ exa_rdev_fd = exa_rdev_init(); if (exa_rdev_fd <= 0) { fprintf(stderr, "exa_rdev_init() failed\n"); return -1; } dev_req = exa_rdev_handle_alloc(disk_path); if (dev_req == NULL) { fprintf(stderr, "exa_rdev_request_init() failed, disk_path = %s\n", disk_path); close(exa_rdev_fd); return -1; } /* Carry on requests to exa_rdev */ if (async) { fprintf(stderr, "Asynchronous mode\n"); if (write) async_op(RDEV_OP_WRITE, offset, size_in_bytes, dev_req); else async_op(RDEV_OP_READ, offset, size_in_bytes, dev_req); } else { fprintf(stderr, "Synchronous mode\n"); if (write) sync_op(RDEV_OP_WRITE, offset, size_in_bytes, dev_req); else sync_op(RDEV_OP_READ, offset, size_in_bytes, dev_req); } fprintf(stderr, "Finished %s %"PRIu64 " bytes on disk %s at offset %"PRIu64 "\n", (write == true) ? "writing" : "reading", size_in_bytes, disk_path, offset); close(exa_rdev_fd); return 0; }
/* A new device is handled by the server, do the init operations in order to make the device usable */ int export_device(const exa_uuid_t *uuid, char *device_path) { device_t *dev; int i, err; /* If device was already exported, do nothing */ if (find_device_from_uuid(uuid) != NULL) return EXA_SUCCESS; dev = os_malloc(sizeof(struct device)); if (dev == NULL) { err = -NBD_ERR_MALLOC_FAILED; goto error; } dev->handle = NULL; err = -CMD_EXP_ERR_OPEN_DEVICE; dev->handle = exa_rdev_handle_alloc(device_path); if (dev->handle == NULL) goto error; err = get_nb_sectors(device_path, &dev->size_in_sectors); if (err != EXA_SUCCESS) goto error; uuid_copy(&dev->uuid, uuid); strlcpy(dev->path, device_path, sizeof(dev->path)); for (i = 0; i < NBMAX_DISKS_PER_NODE; i++) if (nbd_server.devices[i] == NULL) break; if (i >= NBMAX_DISKS_PER_NODE) { exalog_error("maximum number of exportable devices exceeded"); err = -NBD_ERR_NB_RDEVS_CREATED; } dev->dev_index = i; dev->exit_thread = false; nbd_init_list(&nbd_server.list_root, &dev->disk_queue); /* resource needed to lock/unlock a zone */ os_sem_init (&dev->lock_sem_disk, 0); /* launch disk thread (TD) */ if (!exathread_create_named(&nbd_server.td_pid[dev->dev_index], NBD_THREAD_STACK_SIZE + MIN_THREAD_STACK_SIZE, exa_td_main, dev, "TD_thread")) { os_sem_destroy(&dev->lock_sem_disk); err = -NBD_ERR_THREAD_CREATION; goto error; } nbd_server.devices[dev->dev_index] = dev; return EXA_SUCCESS; error: if (dev != NULL) { if (dev->handle != NULL) exa_rdev_handle_free(dev->handle); os_free(dev); } return err; }