static int vrt_cmd_device_replace(const struct VrtDeviceReplace *cmd) { struct vrt_group *group; struct vrt_realdev *rdev; int ret; group = vrt_get_group_from_uuid(&cmd->group_uuid); if (group == NULL) return -VRT_ERR_UNKNOWN_GROUP_UUID; rdev = storage_get_rdev(group->storage, &cmd->vrt_uuid); if (rdev == NULL) { exalog_error("Cannot find vrt UUID " UUID_FMT " in group '%s'", UUID_VAL(&cmd->vrt_uuid), group->name); vrt_group_unref(group); return -VRT_ERR_NO_SUCH_RDEV_IN_GROUP; } if (!vrt_group_supports_device_replacement(group)) { exalog_error("Group '%s' (layout '%s') does not support disk replacement", group->name, group->layout->name); vrt_group_unref(group); return -VRT_ERR_DISK_REPLACEMENT_NOT_SUPPORTED; } ret = vrt_group_rdev_replace(group, rdev, &cmd->rdev_uuid); vrt_group_unref(group); return ret; }
/** * Create a volume in a given group * * @param[in] params The parsed command array * * The real parameters passed in the array are: * - UUID of the group in which the volume has to be created * - Name of the volume to create * - UUID of the volume to create * - Size of the volume to create (in KB) * * @return 0 on success, a negative error code on failure */ static int vrt_cmd_volume_create(const struct VrtVolumeCreate *cmd) { vrt_group_t *group; vrt_volume_t *volume; int ret; EXA_ASSERT(cmd->volume_size > 0); exalog_debug("create volume '%s': size %" PRIu64 " KB", cmd->volume_name, cmd->volume_size); group = vrt_get_group_from_uuid(&cmd->group_uuid); if (group == NULL) { exalog_debug("Unknown group " UUID_FMT, UUID_VAL(&cmd->group_uuid)); return -VRT_ERR_UNKNOWN_GROUP_UUID; } /* !!! All sizes in 'cmd' are in KB and VRT internal functions want sizes in * sectors. */ ret = vrt_group_create_volume(group, &volume, &cmd->volume_uuid, cmd->volume_name, KBYTES_2_SECTORS(cmd->volume_size)); if (ret != EXA_SUCCESS) { exalog_error("Can't create volume '%s' in group '%s': %s(%d)", cmd->volume_name, group->name, exa_error_msg(ret), ret); vrt_group_unref(group); return ret; } EXA_ASSERT(volume != NULL); /* wipe the newly created volume * * FIXME: This code is called from all the clients while it should be done * only once. To do so we should add a new RPC and trigger the wipping from * admind. */ /* Let only one node (the first one) do the wipe */ if (vrt_node_get_upnode_id() == 0) { ret = vrt_group_wipe_volume(group, volume); if (ret != EXA_SUCCESS) { exalog_error("Can't wipe volume '%s' in group '%s': %s(%d)", volume->name, group->name, exa_error_msg(ret), ret); /* Rollback volume creation */ vrt_group_delete_volume(group, volume); vrt_group_unref(group); return ret; } } vrt_group_unref(group); return EXA_SUCCESS; }
int vrt_rdev_replace(struct vrt_realdev *rdev, const exa_uuid_t *new_rdev_uuid) { blockdevice_t *new_blockdevice; int err; if (rdev_is_ok(rdev)) { exalog_error("Bad rdev status %d", rdev_get_compound_status(rdev)); return -VRT_ERR_CANT_DGDISKRECOVER; } new_blockdevice = client_get_blockdevice(new_rdev_uuid); if (new_blockdevice == NULL) { exalog_error("Could not open device "UUID_FMT, UUID_VAL(new_rdev_uuid)); return -ENODEV; } if (__get_block_aligned_bdev_size(new_blockdevice) < __get_block_aligned_bdev_size(rdev->blockdevice)) return -VRT_ERR_RDEV_TOO_SMALL; rdev->blockdevice = new_blockdevice; /* re-open the superblock stream */ vrt_rdev_close_superblock_streams(rdev); err = vrt_rdev_open_superblock_streams(rdev); if (err != 0) return err; uuid_copy(&rdev->nbd_uuid, new_rdev_uuid); return EXA_SUCCESS; }
/** select a free connection * * \param[in] sock_xml: socket on which it receives commands. */ static void handle_connection(int msg_sock) { int i; static cl_error_desc_t busy = { .code = -EXA_ERR_ADM_BUSY, .msg = "Too many connections."}; /* Search free slot in connection array */ for (i = 0; i < MAX_CONNECTION; i++) { if (connectlist[i].uid == CMD_UID_INVALID && connectlist[i].fd == -1) { exalog_debug("CONNECTION %d: Using sock %d", i, msg_sock); /* uid is set when the command is actually scheduled */ connectlist[i].fd = msg_sock; FD_SET(msg_sock, &setSocks); return; } } /* * No free connection found. We disconnect the caller now because we * are no room in our connectionlist */ exalog_error("All connections are busy sock=%d", msg_sock); cli_command_end_complete(msg_sock, &busy); os_closesocket(msg_sock); } /*-------------------------------------------------------------------------*/ /** \brief Connection thread: wait on xml message to pass the command * to the work thread. * * \param[in] sock_xml_proto: socket xml on which it receives commands. * \return the selected working thread or a negative error code * */ /*-------------------------------------------------------------------------*/ static void accept_new_client(void) { int fd = os_accept(listen_fd, NULL, NULL); exalog_debug("Got an incoming XML Request on socket: %d", fd); if (fd < 0) { exalog_error("Failed during admind xml connection accept: error=%s", exa_error_msg(-fd)); return; } handle_connection(fd); }
int main(int argc, char *argv[]) { exalog_as(EXAMSG_TEST_ID); exalog_configure(EXAMSG_TEST_ID, EXALOG_LEVEL_DEBUG); exalog_debug("You should see this"); exalog_error("You should see this too"); exalog_configure(EXAMSG_TEST_ID, EXALOG_LEVEL_ERROR); exalog_debug("You shouldn't see this"); exalog_error("But you should see this"); return 0; }
static void handle_start_control(md_msg_control_start_t *start) { int ret; if (!md_srv_com_is_agentx_alive()) { char node_id_str[32]; char master_agentx_port_str[EXA_MAXSIZE_LINE + 1]; os_snprintf(node_id_str, sizeof(node_id_str), "%u", start->node_id); os_snprintf(master_agentx_port_str, sizeof(master_agentx_port_str), "%d", start->master_agentx_port); /* XXX No use for a block here */ { char agentx_path[OS_PATH_MAX]; char *const argv[] = { agentx_path, node_id_str, start->node_name, start->master_agentx_host, master_agentx_port_str, NULL }; exa_env_make_path(agentx_path, sizeof(agentx_path), exa_env_sbindir(), "exa_agentx"); ret = exa_system(argv); } if (ret != EXA_SUCCESS) { exalog_error("Error spawning exa_agentx(%d).", ret); md_messaging_ack_control(ret); return; } /* wait a bit to get the first alive message from agentx * TODO : not robust enough, replace with a timeouted lock */ os_sleep(MD_HEARTBEAT_TIMEOUT_SECONDS); if (!md_srv_com_is_agentx_alive()) { exalog_error("Error spawning exa_agentx(%d).", -MD_ERR_AGENTX_NOT_ALIVE); md_messaging_ack_control(-MD_ERR_AGENTX_NOT_ALIVE); return; } } md_messaging_ack_control(EXA_SUCCESS); }
static void write_result(int msg_sock, const char *result) { int skip = 0; if (result == NULL || msg_sock < 0) return; do { int rv; do rv = os_send(msg_sock, result + skip, strlen(result) - skip); while (rv == -EINTR); if (rv < 0 && rv != -EAGAIN) { exalog_error("Error '%s' while sending result '%s'", exa_error_msg(rv), result); break; } if (rv > 0) skip += rv; } while (skip < strlen(result)); }
int vrt_rdev_open(struct vrt_realdev *rdev) { int err; rdev->blockdevice = client_get_blockdevice(&rdev->nbd_uuid); if (rdev->blockdevice == NULL) { exalog_error("Could not open device "UUID_FMT, UUID_VAL(&rdev->uuid)); return -ENODEV; } err = vrt_rdev_open_superblock_streams(rdev); if (err != 0) return err; if (rdev->up) { uint64_t size = __get_block_aligned_bdev_size(rdev->blockdevice); err = vrt_rdev_set_real_size(rdev, size); if (err != 0) return err; } return EXA_SUCCESS; }
/** * Finalize the insertion of a new rdev in a group. * * @param[in] params The parsed command array * * The real parameters passed in the array are: * - UUID of the group to insert the new rdev in * * @return 0 on success, a negative error code on failure */ static int vrt_cmd_group_insert_rdev(const struct VrtGroupInsertRdev *cmd) { int ret; exalog_debug("finish adding rdev in group " UUID_FMT, UUID_VAL(&cmd->group_uuid)); os_thread_mutex_lock(&pending_group_lock); if (!pending_group) { os_thread_mutex_unlock(&pending_group_lock); return -EPERM; } if (!uuid_is_equal(&cmd->group_uuid, &pending_group->uuid)) { exalog_error("You are trying to insert an rdev into a group " "while a dgcreate, dgstart or dgdiskadd is running."); os_thread_mutex_unlock(&pending_group_lock); return -EAGAIN; } ret = vrt_group_insert_rdev(pending_group, &cmd->uuid, &cmd->nbd_uuid, cmd->node_id, cmd->spof_id, cmd->local, cmd->old_sb_version, cmd->new_sb_version); os_free(pending_group); os_thread_mutex_unlock(&pending_group_lock); return ret; }
int vrt_master_volume_delete (int thr_nb, struct adm_volume *volume, bool metadata_recovery) { int ret; int reply_ret; admwrk_request_t handle; struct vldelete_info info; memset(&info, 0, sizeof(info)); EXA_ASSERT(volume != NULL); /* Do not continue if the group is not started */ if (volume->group->goal == ADM_GROUP_GOAL_STOPPED) return -VRT_ERR_GROUP_NOT_STARTED; ret = exa_nodeset_count(&volume->goal_started); if (ret > 0) { exalog_error("Cannot delete the volume '%s:%s' because it is not stopped on %d nodes", volume->group->name, volume->name, ret); return -VRT_ERR_VOLUME_NOT_STOPPED; } strlcpy(info.group_name, volume->group->name, EXA_MAXSIZE_GROUPNAME + 1); strlcpy(info.volume_name, volume->name, EXA_MAXSIZE_VOLUMENAME + 1); info.metadata_recovery = metadata_recovery; admwrk_run_command(thr_nb, &adm_service_admin, &handle, RPC_ADM_VLDELETE, &info, sizeof(info)); /* Examine replies in order to filter return values. * The priority of return values is the following (in descending order): * o ADMIND_ERR_METADATA_CORRUPTION * o ADMIND_ERR_NODE_DOWN * o other errors */ ret = EXA_SUCCESS; while (admwrk_get_ack(&handle, NULL, &reply_ret)) { if (reply_ret == -ADMIND_ERR_METADATA_CORRUPTION) ret = -ADMIND_ERR_METADATA_CORRUPTION; else if (reply_ret == -ADMIND_ERR_NODE_DOWN && ret != -ADMIND_ERR_METADATA_CORRUPTION) ret = -ADMIND_ERR_NODE_DOWN; else if (reply_ret != EXA_SUCCESS && reply_ret != -ADMIND_ERR_NOTHINGTODO && ret != -ADMIND_ERR_METADATA_CORRUPTION && ret != -ADMIND_ERR_NODE_DOWN) ret = reply_ret; } return ret; }
int exa_perf_instance_static_init(void) { const char *perf_config; exaperf_err_t err; eh = exaperf_alloc(); if (eh == NULL) { exalog_error("Failed initializing exaperf"); return -ENOMEM; } perf_config = getenv("EXANODES_PERF_CONFIG"); if (perf_config == NULL) { exalog_debug("No perf config set"); return 0; } /* initialize the component */ err = exaperf_init(eh, perf_config, exa_perf_instance_print); switch (err) { case EXAPERF_SUCCESS: exalog_info("Loaded perf config '%s'", perf_config); return 0; case EXAPERF_CONF_FILE_OPEN_FAILED: exalog_warning("Perf config '%s' not found, ignored", perf_config); exaperf_free(eh); eh = NULL; return 0; default: /* FIXME Use error string instead of error code */ exalog_error("Failed loading perf config '%s' (%d)", perf_config, err); return -EINVAL; } }
/** * Read and process an event from the network mailbox. * * \param[in,out] pi Ping info * * \return 1 if processed an event, 0 if not, and negative error code otherwise */ static int net_mbox_event(ping_info_t *pi) { ExamsgMID mid; static char msg[sizeof(ExamsgNetRqst) + sizeof(Examsg)]; int s; if (network_status() != 0) return 0; s = examsgMboxRecv(EXAMSG_NETMBOX_ID, &mid, sizeof(mid), msg, sizeof(msg)); if (s == 0) /* Nothing to read */ return 0; if (s <= sizeof(ExamsgNetRqst)) { exalog_error("received %d bytes, error %s", s, exa_error_msg(s)); return -EINVAL; } s = network_send(&mid, (ExamsgNetRqst *)msg); if (s < 0) { if (network_manageable(s)) { remember_unsent(&mid, msg, sizeof(msg)); return s; } exalog_error("net mailbox event: error %s", exa_error_msg(s)); return -EIO; } reset_ping(pi); return 1; }
int vrt_rdev_end_superblock_read(vrt_realdev_t *rdev, superblock_read_op_t *op) { uint64_t sb_data_size = stream_tell(op->stream); if (op->header.data_size != sb_data_size) { exalog_error("SB data size (%"PRIu64") mismatch header (%"PRIu64")", sb_data_size, op->header.data_size); return -VRT_ERR_SB_CORRUPTION; } return 0; }
/* --- Ndevs manipulation functions -------------------------------- */ int server_add_client(char *node_name, char *net_id, exa_nodeid_t node_id) { int err; if (strncmp(node_name, nbd_server.node_name, EXA_MAXSIZE_HOSTNAME) == 0) nbd_server.server_id = node_id; err = tcp_add_peer(node_id, net_id, nbd_server.tcp); if (err != EXA_SUCCESS) exalog_error("Tcp server returned an error when adding client %s", node_name); return err; }
static int vrt_cmd_group_reset(const struct VrtGroupReset *cmd) { struct vrt_group *group; int ret; group = vrt_get_group_from_uuid(&cmd->group_uuid); if (group == NULL) return -VRT_ERR_UNKNOWN_GROUP_UUID; ret = vrt_group_reset(group); if (ret != EXA_SUCCESS) exalog_error("Reset failed with %d", ret); vrt_group_unref(group); return ret; }
/** * Sync metadata on disk. * * @param[in] params The parsed command array * * The real parameters passed in the array are: * - UUID of the group * * @return 0 on success, a negative error code on failure */ static int vrt_cmd_group_sync_sb(const struct VrtGroupSyncSb *cmd) { struct vrt_group *group; int ret; group = vrt_get_group_from_uuid(&cmd->group_uuid); if(!group) { exalog_error("Unknown group " UUID_FMT, UUID_VAL(&cmd->group_uuid)); return -VRT_ERR_UNKNOWN_GROUP_UUID; } ret = vrt_group_sync_sb(group, cmd->old_sb_version, cmd->new_sb_version); vrt_group_unref(group); return ret; }
int vrt_rdev_set_real_size(struct vrt_realdev *rdev, uint64_t size) { EXA_ASSERT(rdev->up); EXA_ASSERT(rdev->blockdevice != NULL); if (__usable_size(size) <= 0) { exalog_error("rdev " UUID_FMT " is too small (%" PRIu64 " sectors) to store the superblocks", UUID_VAL(&rdev->uuid), size); return -VRT_ERR_RDEV_TOO_SMALL; } rdev->real_size = size; return EXA_SUCCESS; }
/** * Check a checksummed stream's checksum against an expected value. * * @param[in] checksum_stream The stream to check * @param[in] size The size to read * @param[in] expected_checksum The expected checksum * * @return 0 if checksums match, a negative error code if read failed, * -VRT_ERR_SB_CHECKSUM if the checksums don't match. */ static int __check_sb_checksum(stream_t *checksum_stream, uint64_t size, checksum_t expected_checksum) { int err; uint64_t remaining; checksum_t computed_checksum; err = stream_rewind(checksum_stream); if (err != 0) return err; remaining = size; while (remaining > 0) { int r, n; char buf[512]; /* We don't really mind the size of the buffer, the * underlying blockdevice_stream caches. */ n = MIN(sizeof(buf), remaining); /* We don't care about the read contents, we just read to let the * checksum stream do his job. You'll be informed as soon as possible */ r = stream_read(checksum_stream, buf, n); if (r < 0) return err; else if (r != n) return -EIO; remaining -= r; } computed_checksum = checksum_stream_get_value(checksum_stream); if (computed_checksum != expected_checksum) { exalog_error("Invalid checksum "CHECKSUM_FMT", expected "CHECKSUM_FMT, computed_checksum, expected_checksum); return -VRT_ERR_SB_CHECKSUM; } /* Rewind so that the stream is ready. This also has the effect of resetting the checksum stream's checksum. */ return stream_rewind(checksum_stream); }
static int vrt_cmd_group_resync(const struct vrt_group_resync_request *cmd) { struct vrt_group *group; int err; group = vrt_get_group_from_uuid(&cmd->group_uuid); if (group == NULL) return -VRT_ERR_UNKNOWN_GROUP_UUID; err = vrt_group_resync(group, &cmd->nodes); if (err != EXA_SUCCESS) exalog_error("Resync failed: %s (%d)", exa_error_msg(err), err); vrt_group_unref(group); return err; }
static void handle_stop_control(md_msg_control_stop_t *stop) { int ret; char *const argv[] = { "pkill", "exa_agentx", NULL }; ret = exa_system(argv); if (ret != EXA_SUCCESS) { exalog_error("Error stopping exa_agentx(%d).", ret); md_messaging_ack_control(ret); return; } md_messaging_ack_control(EXA_SUCCESS); }
/** * Tells that a unusable device is now available again. We'll put it * in the EXA_REALDEV_UPDATING state, which doesn't mean we can safely * use it, but that a rebuilding process must take place before * changing the status to EXA_REALDEV_OK. * * @param[in] rdev The real device which is now available again * * @return always EXA_SUCCESS */ int vrt_rdev_up(struct vrt_realdev *rdev) { uint64_t size; uint64_t required_size; int err; /* Admind can send an up message even if the device is not down */ if (rdev_is_ok(rdev)) return EXA_SUCCESS; rdev->up = TRUE; size = __get_block_aligned_bdev_size(rdev->blockdevice); err = vrt_rdev_set_real_size(rdev, size); if (err != EXA_SUCCESS) return err; /* Check that the size of the device correspond to the real size of the * device. * This test is also done at group start (see vrt_group_start) * * FIXME: This kind of verification could be done by the service in * charge of the devices */ required_size = rdev_chunk_based_size(rdev); if (vrt_realdev_get_usable_size(rdev) < required_size) { /* XXX Duplicate: same error in vrt_group_start() */ exalog_error("Real size of device "UUID_FMT" is too small: %"PRIu64" < %"PRIu64, UUID_VAL(&rdev->uuid), vrt_realdev_get_usable_size(rdev), required_size); rdev->corrupted = TRUE; rdev->real_size = 0; return EXA_SUCCESS; } rdev->corrupted = FALSE; return EXA_SUCCESS; }
/** * Command to register a real device in a group. * It must be called after group_begin() and before * group_create() or group_start(). * * @param[in] params The parsed command array * * The real parameters passed in the array are: * - UUID of the group in which the real device has to be added * - UUID of the real device in the VRT * - UUID of the real device in the NBD * - Whether the disk is local or not * - Whether the disk is UP or not * - Whether the device properties must be loaded from disk * * @return EXA_SUCCESS on success, negative error code on failure. */ static int vrt_cmd_group_add_rdev(const struct VrtGroupAddRdev *cmd) { vrt_rdev_info_t *rdev_info; os_thread_mutex_lock(&pending_group_lock); if (!pending_group) { os_thread_mutex_unlock(&pending_group_lock); return -EPERM; } if (!uuid_is_equal(&cmd->group_uuid, &pending_group->uuid)) { exalog_error("Failed to edit group " UUID_FMT ", group " UUID_FMT " is already being edited.", UUID_VAL(&cmd->group_uuid), UUID_VAL(&pending_group->uuid)); os_thread_mutex_unlock(&pending_group_lock); return -EAGAIN; } if (pending_group->nb_rdevs == NBMAX_DISKS_PER_GROUP) { os_thread_mutex_unlock(&pending_group_lock); return -EAGAIN; } rdev_info = &pending_group->rdevs[pending_group->nb_rdevs]; uuid_copy(&rdev_info->uuid, &cmd->uuid); uuid_copy(&rdev_info->nbd_uuid, &cmd->nbd_uuid); rdev_info->node_id = cmd->node_id; rdev_info->spof_id = cmd->spof_id; rdev_info->local = cmd->local; rdev_info->up = cmd->up; pending_group->nb_rdevs++; os_thread_mutex_unlock(&pending_group_lock); return EXA_SUCCESS; }
int vrt_rdev_begin_superblock_write(vrt_realdev_t *rdev, uint64_t old_version, uint64_t new_version, superblock_write_op_t *op) { superblock_header_t headers[2]; int write_position; int i; int err; err = __read_sb_headers(rdev, headers); if (err != 0) return err; write_position = -1; for (i = 0; i < 2; i++) { if (__check_sb_header(&headers[i], i) != 0) continue; /* We want to keep the old version => pick the header whose version is *not* old_version (or a header whose version is zero, ie none) */ if (headers[i].sb_version == 0 || headers[i].sb_version != old_version) { write_position = i; break; } } if (write_position != 0 && write_position != 1) { exalog_error("No superblock available for writing version %"PRIu64, new_version); return -VRT_ERR_SB_CORRUPTION; } op->header = headers[write_position]; op->new_sb_version = new_version; op->stream = rdev->checksum_sb_streams[write_position]; /* Rewind so that the stream is ready for writing. This also has the effect of resetting the checksum stream's checksum. */ return stream_rewind(op->stream); }
/** * Get FS from the XML command. * \param[in] group_name * \param[in] volume_name * \param[out] fs filled with data, not NULL! * \param[out] fs_definition filled with defnition , may be NULL * \param[out] check_ok Check everything is valid * \param[in] type_fs Type of FS awaited * return error code if parameters were invalid */ int fscommands_params_get_fs(const char *group_name, const char *volume_name, fs_data_t* fs, fs_definition_t **fs_definition, bool check_ok) { struct adm_volume* volume; struct adm_group* group; group = adm_group_get_group_by_name(group_name); if (group == NULL) return -ADMIND_ERR_UNKNOWN_GROUPNAME; if (group->goal == ADM_GROUP_GOAL_STOPPED) return -VRT_ERR_GROUP_NOT_STARTED; volume = adm_cluster_get_volume_by_name(group->name, volume_name); if (!volume) return -ADMIND_ERR_UNKNOWN_FSNAME; if (!adm_volume_is_in_fs(volume)) { exalog_error("volume '%s:%s' is not managed by the file system layer", group->name, volume_name); return -ADMIND_ERR_UNKNOWN_FSNAME; } fs_fill_data_from_config(fs, volume->filesystem); if (fs_definition) { *fs_definition = (fs_definition_t *)fs_get_definition(fs->fstype); } if (check_ok) { if (!fs->transaction) { return -FS_ERR_INVALID_FILESYSTEM; } } return EXA_SUCCESS; }
static void md_controller_loop(void) { md_msg_control_t control; if (md_messaging_recv_control(&control)) { switch(control.type) { case MD_MSG_CONTROL_START: handle_start_control(&control.content.start); break; case MD_MSG_CONTROL_STOP: handle_stop_control(&control.content.stop); break; case MD_MSG_CONTROL_STATUS: handle_status_control(&control.content.status); break; default: exalog_error("Unknown event message type."); } } }
static int __check_sb_header(const superblock_header_t *header, int position) { int i; if (header->magic != SUPERBLOCK_HEADER_MAGIC) { exalog_error("Invalid magic in superblock %d", position); return -VRT_ERR_SB_MAGIC; } if (header->format != SUPERBLOCK_HEADER_FORMAT) { exalog_error("Unknown format %d in superblock %d", header->format, position); return -VRT_ERR_SB_FORMAT; } if (header->position != position) { exalog_error("Invalid position %d in superblock %d", header->position, position); return -VRT_ERR_SB_CORRUPTION; } if (header->reserved1 != 0) { exalog_error("Invalid reserved field 0x%08x in superblock %d", header->reserved1, position); return -VRT_ERR_SB_CORRUPTION; } if (header->data_size > header->data_max_size) { exalog_error("Data size (%"PRIu64" bytes) in superblock %d" " larger than alloted area (%"PRIu64" bytes)", header->data_size, position, header->data_max_size); return -VRT_ERR_SB_CORRUPTION; } for (i = 0; i < sizeof(header->reserved2); i++) if (header->reserved2[i] != 0) { exalog_error("Invalid data 0x%0x in reserved field in superblock %d", header->reserved2[i], position); return -VRT_ERR_SB_CORRUPTION; } return 0; }
static int send_command_to_evmgr(cmd_uid_t uid, const AdmCommand *adm_cmd, const exa_uuid_t *cluster_uuid, const void *data, size_t data_size) { Examsg msg; command_t *cmd = (command_t *)msg.payload; size_t payload_size; int s; /* Message to trigger the command execution on thread thr_nb */ msg.any.type = EXAMSG_ADM_CLUSTER_CMD; payload_size = data_size + sizeof(command_t); if (payload_size >= EXAMSG_PAYLOAD_MAX) { exalog_error("Command %s parameter structure is too big to fit in " "a message. %zu > %zu", adm_cmd->msg, payload_size, EXAMSG_PAYLOAD_MAX); return -E2BIG; } cmd->code = adm_cmd->code; cmd->uid = uid; memcpy(cmd->data, data, data_size); cmd->data_size = data_size; uuid_copy(&cmd->cluster_uuid, cluster_uuid); exalog_debug("Scheduling command '%s', uid=%d", adm_cmd->msg, cmd->uid); s = examsgSend(cli_mh, EXAMSG_ADMIND_EVMGR_ID, EXAMSG_LOCALHOST, &msg, sizeof(ExamsgAny) + payload_size); if (s != sizeof(ExamsgAny) + payload_size) return s; return 0; }
/** * Finalize the start of a group. * * @param[in] params The parsed command array * * The real parameters passed in the array are: * - UUID of the group to start * * @return 0 on success, a negative error code on failure */ static int vrt_cmd_group_start(const struct VrtGroupStart *cmd) { vrt_group_t *group; int ret; exalog_debug("start group " UUID_FMT, UUID_VAL(&cmd->group_uuid)); os_thread_mutex_lock(&pending_group_lock); if (!pending_group) { os_thread_mutex_unlock(&pending_group_lock); return -EPERM; } if (!uuid_is_equal(&cmd->group_uuid, &pending_group->uuid)) { exalog_error("You are trying to create or start two groups at the same time."); os_thread_mutex_unlock(&pending_group_lock); return -EAGAIN; } ret = vrt_group_start(pending_group, &group); if (ret == EXA_SUCCESS) { ret = vrt_groups_list_add(group); if (ret != EXA_SUCCESS) vrt_group_stop(group); } os_free(pending_group); os_thread_mutex_unlock(&pending_group_lock); return ret; }
int unexport_device(const exa_uuid_t *uuid) { device_t *dev = find_device_from_uuid(uuid); if (dev == NULL) { exalog_error("can not remove unknown device with UUID = " UUID_FMT, UUID_VAL(uuid)); return -CMD_EXP_ERR_UNKNOWN_DEVICE; } os_thread_mutex_lock(&nbd_server.mutex_edevs); /* ask the thread to terminate */ dev->exit_thread = true; /* prevent any new IO to be put in device IO list */ nbd_server.devices[dev->dev_index] = NULL; os_thread_mutex_unlock(&nbd_server.mutex_edevs); /* now we can join, because with the nbd_close_list() * we can assume was the disk thread will reach a cancelation point */ os_thread_join(nbd_server.td_pid[dev->dev_index]); /* close the list used to disk queue */ nbd_close_list(&dev->disk_queue); /* get back all header in the kernel exa_rdev to the free list and close the device */ if (dev->handle != NULL) exa_rdev_handle_free(dev->handle); /* close the semaphore used by the disk */ os_sem_destroy(&dev->lock_sem_disk); /* free used memory for the device */ os_free(dev); return EXA_SUCCESS; }
/** * Process an event from a local mailbox. * * \param[in,out] pi Ping info * * \return 1 if processed an event 0 if not, negative error code otherwise */ static int local_mbox_event(ping_info_t *pi) { ExamsgMID mid; static Examsg ev; int ev_size; int s; ev_size = examsgRecv(local_mh, &mid, &ev, sizeof(ev)); if (ev_size <= 0) return 0; switch (ev.any.type) { case EXAMSG_EXIT: { exa_nodeset_t dest_nodes; quit = true; exa_nodeset_single(&dest_nodes, mid.netid.node); examsgAckReply(local_mh, &ev, EXA_SUCCESS, mid.id, &dest_nodes); } /* Return 0 because, despite we received a message, we do not want the * main loop to continue to process messages as it is asked to stop now. * So returning 0 juste means here "no need to read anymore messages" */ return 0; case EXAMSG_SUP_PING: if (network_status() == 0) network_special_send(&mid, &ev, ev_size); break; case EXAMSG_ADDNODE: { exa_nodeset_t dest_nodes; examsg_node_info_msg_t *info = (examsg_node_info_msg_t *)&ev; s = network_add_node(info->node_id, info->node_name); exa_nodeset_single(&dest_nodes, mid.netid.node); examsgAckReply(local_mh, &ev, s, mid.id, &dest_nodes); } break; case EXAMSG_DELNODE: { exa_nodeset_t dest_nodes; s = network_del_node(((examsg_node_info_msg_t *)&ev)->node_id); exa_nodeset_single(&dest_nodes, mid.netid.node); examsgAckReply(local_mh, &ev, s, mid.id, &dest_nodes); } break; case EXAMSG_RETRANSMIT_REQ: if (network_status() == 0) { ExamsgRetransmitReq *retreq = (ExamsgRetransmitReq *)&ev; exalog_debug("will send a retransmit request for %d to %u", retreq->count, retreq->node_id); s = network_send_retransmit_req(retreq->node_id, retreq->count); EXA_ASSERT(s == 0); reset_ping(pi); } break; case EXAMSG_RETRANSMIT: if (network_status() == 0) { ExamsgRetransmit *retr = (ExamsgRetransmit *)&ev; exalog_debug("will retransmit messages: %d", retr->count); retransmit(retr->count); reset_ping(pi); } break; case EXAMSG_FENCE: { const examsgd_fencing_req_t *req = &((examsgd_fencing_req_msg_t *)&ev)->request; network_handle_fence_request(req); } break; case EXAMSG_NEW_COMER: reset_ping(pi); break; default: { exa_nodeset_t dest_nodes; exa_nodeset_single(&dest_nodes, mid.netid.node); examsgAckReply(local_mh, &ev, EINVAL, mid.id, &dest_nodes); exalog_error("got unknown message (type %d)", ev.any.type); EXA_ASSERT(false); } break; } return 1; }