Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
/**
 * 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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
/** 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);
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
0
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));
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
/**
 * 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;
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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;
    }
}
Ejemplo n.º 12
0
/**
 * 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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
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;
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
/**
 * 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;
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 18
0
/**
 * 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);
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
0
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);
}
Ejemplo n.º 21
0
/**
 * 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;
}
Ejemplo n.º 22
0
/**
 * 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;
}
Ejemplo n.º 23
0
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);
}
Ejemplo n.º 24
0
/**
 * 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;
}
Ejemplo n.º 25
0
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.");
	}
    }
}
Ejemplo n.º 26
0
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;
}
Ejemplo n.º 27
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;
}
Ejemplo n.º 28
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;
}
Ejemplo n.º 29
0
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;
}
Ejemplo n.º 30
0
/**
 * 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;
}