예제 #1
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;
}
예제 #2
0
파일: ndevs.c 프로젝트: OznOg/OpenExanodes
void rebuild_helper_thread(void *p)
{
  ExamsgHandle mh;
  int err;

  exalog_as(EXAMSG_NBD_SERVER_ID);

  /* initialize examsg framework */
  mh = examsgInit(EXAMSG_NBD_LOCKING_ID);
  EXA_ASSERT(mh != NULL);

  err = examsgAddMbox(mh, EXAMSG_NBD_LOCKING_ID, 1, 5 * EXAMSG_MSG_MAX);
  EXA_ASSERT(err == 0);

  os_sem_post(&nbd_server.mailbox_sem);

  while (nbd_server.run)
  {
      device_t *device;
      ExamsgNbdLock nbd_lock_msg;
      ExamsgMID from;
      struct timeval timeout = { .tv_sec = 0, .tv_usec = 100000 };
      exa_nodeset_t dest_nodes;

      err = examsgWaitTimeout(mh, &timeout);
      /* Just in order to check stopping the thread is required*/
      if (err == -ETIME)
	  continue;

      if (err != 0)
      {
          exalog_error("Locking thread encountered error %s (%d) while "
                       "waiting in event loop.", exa_error_msg(err), err);
          continue;
      }

      err = examsgRecv(mh, &from, &nbd_lock_msg, sizeof(nbd_lock_msg));

      /* No message */
      if (err == 0)
	continue;

      if (err < 0)
      {
          exalog_error("Locking thread encountered error %s (%d) while "
                       "receiving a messsage.", exa_error_msg(err), err);
	  continue;
      }

      switch(nbd_lock_msg.any.type)
      {
      case EXAMSG_NBD_LOCK:
	  /* find device from name */
          /* FIXME devices lock is not held... it should */
          device = find_device_from_uuid(&nbd_lock_msg.disk_uuid);
	  if (device == NULL)
          {
              exalog_error("Unknown device with UUID " UUID_FMT, UUID_VAL(&nbd_lock_msg.disk_uuid));
              err = -CMD_EXP_ERR_UNKNOWN_DEVICE;
              break;
          }
          if (nbd_lock_msg.lock)
          {
              err = exa_disk_lock_zone(device, nbd_lock_msg.locked_zone_start,
                                          nbd_lock_msg.locked_zone_size);
              EXA_ASSERT_VERBOSE(err == 0, "Trying to lock too many zone "
                                 "(>%d). Last zone not succesfully locked "
                                 "(start = %" PRId64 ", size = %" PRId64 " ) "
                                 "on device UUID " UUID_FMT, NBMAX_DISK_LOCKED_ZONES,
                                 nbd_lock_msg.locked_zone_start,
                                 nbd_lock_msg.locked_zone_size,
                                 UUID_VAL(&nbd_lock_msg.disk_uuid));
          }
          else
          {
              err = exa_disk_unlock_zone(device, nbd_lock_msg.locked_zone_start,
                                            nbd_lock_msg.locked_zone_size);
              EXA_ASSERT_VERBOSE(err == 0, "Trying to unlock a never locked "
                                 "zone (unlocked zone start =%" PRId64 ", "
                                 "unlocked zone size = %" PRId64 ") on device"
                                 " UUID " UUID_FMT,
                                 nbd_lock_msg.locked_zone_start,
                                 nbd_lock_msg.locked_zone_size,
                                 UUID_VAL(&nbd_lock_msg.disk_uuid));
          }
	  break;

	default:
	  /* error */
	  EXA_ASSERT_VERBOSE(false, "Locking thread got unknown message of"
                             " type %d ", nbd_lock_msg.any.type);
	  break;
	}

      exa_nodeset_single(&dest_nodes, from.netid.node);
      examsgAckReply(mh, (Examsg *)&nbd_lock_msg, err, from.id, &dest_nodes);
    }

  examsgDelMbox(mh, EXAMSG_NBD_LOCKING_ID);
  examsgExit(mh);
}

/** get the number of sector of the device
 * \param device_path the device to get the number of sector
 * \param nb_sectors64 the number of sectors of the device
 * \return nb_sectors the returned number of sector
 */

static int get_nb_sectors(const char *device_path, uint64_t *nb_sectors)
{
  uint64_t device_size; /* in bytes */
  int retval;
  int fd;

  /* We need the read access to get the size. */
  if ((fd = os_disk_open_raw(device_path, OS_DISK_READ)) < 0)
  {
    exalog_error("cannot open device '%s'  error=%s ",
                 device_path, exa_error_msg(-fd));
    return -CMD_EXP_ERR_OPEN_DEVICE;
  }

  retval = os_disk_get_size(fd, &device_size);
  if (retval < 0)
  {
    exalog_error("os_disk_get_size() error=%s", exa_error_msg(retval));
    if (close(fd) != 0)
      exalog_error("can't EVEN close dev '%s'", device_path);
    return -EXA_ERR_IOCTL;
  }

  retval = close(fd);
  if (retval < 0)
  {
    retval = -errno;
    exalog_error("cannot close device '%s' error=%s ",
                 device_path, exa_error_msg(retval));
    return -CMD_EXP_ERR_CLOSE_DEVICE;
  }

  *nb_sectors = device_size / SECTOR_SIZE;

  /* remove the size of the reserved area for storing admind info */
  *nb_sectors -= RDEV_RESERVED_AREA_IN_SECTORS;

  /* Align the size on 1K
   * this is the best we can do to have the same size of devices on 2.4 and 2.6 kernels due to
   * the fact that kernel 2.4 rounds the size of devices with 1 K
   */
  *nb_sectors -= *nb_sectors % (1024 / SECTOR_SIZE);

  return EXA_SUCCESS;
}