Beispiel #1
0
static void encode_layoutstats(struct xdr_stream *xdr,
			       struct nfs42_layoutstat_args *args,
			       struct nfs42_layoutstat_devinfo *devinfo,
			       struct compound_hdr *hdr)
{
	__be32 *p;

	encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
	p = reserve_space(xdr, 8 + 8);
	p = xdr_encode_hyper(p, devinfo->offset);
	p = xdr_encode_hyper(p, devinfo->length);
	encode_nfs4_stateid(xdr, &args->stateid);
	p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
	p = xdr_encode_hyper(p, devinfo->read_count);
	p = xdr_encode_hyper(p, devinfo->read_bytes);
	p = xdr_encode_hyper(p, devinfo->write_count);
	p = xdr_encode_hyper(p, devinfo->write_bytes);
	p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
			NFS4_DEVICEID4_SIZE);
	/* Encode layoutupdate4 */
	*p++ = cpu_to_be32(devinfo->layout_type);
	if (devinfo->layoutstats_encode != NULL)
		devinfo->layoutstats_encode(xdr, args, devinfo);
	else
		encode_uint32(xdr, 0);
}
Beispiel #2
0
void
serialize_string( char *str, struct buffer *b )
{
    reserve_space( b, sizeof(char) * strlen(str) );
    memcpy( ((char *) b->data) + b->next, str, sizeof(char) * strlen(str) );
    b->next += (sizeof(char) * strlen(str));
}
Beispiel #3
0
void
serialize_short( short x, struct buffer *b )
{
    //x = htonl(x);

    reserve_space( b, sizeof(short) );
    memcpy( ((char *) b->data) + b->next, &x, sizeof(short) );
    b->next += sizeof(short);
}
Beispiel #4
0
void MemoryStream::Write(PLcdata data, PLuint size)
{
    if (data && (size != 0))
    {
        if (iPos + size > iCapacity)
            reserve_space(size);
        memcpy(&pData[iPos], data, size);
        iPos += size;
        if (iPos > iLen)
            iLen = iPos;
    }
}
Beispiel #5
0
void MemoryStream::Write(MemoryStream& stream)
{
    if (&stream != this)
    {
        PLuint size = stream.Size();
        if (iPos + size > iCapacity)
            reserve_space(size);
        memcpy(&pData[iPos], stream.Data(), size);
        iPos += size;
        if (iPos > iLen)
            iLen = iPos;
    }
}
Beispiel #6
0
static void encode_clone(struct xdr_stream *xdr,
			 struct nfs42_clone_args *args,
			 struct compound_hdr *hdr)
{
	__be32 *p;

	encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
	encode_nfs4_stateid(xdr, &args->src_stateid);
	encode_nfs4_stateid(xdr, &args->dst_stateid);
	p = reserve_space(xdr, 3*8);
	p = xdr_encode_hyper(p, args->src_offset);
	p = xdr_encode_hyper(p, args->dst_offset);
	xdr_encode_hyper(p, args->count);
}
Beispiel #7
0
PLuint MemoryStream::Set(PLuint pos, PLcdata data, PLuint size)
{
    if (data && (size != 0))
    {
        if (pos + size > iCapacity)
            reserve_space(size);
        memcpy(&pData[pos], data, size);
        if (pos == iPos)
        {
            iPos += size;
            if (iPos > iLen)
                iLen = iPos;
        }
        return size;
    }
    return 0;
}
Beispiel #8
0
/**
 * make_reservation - reserve journal space.
 * @c: UBIFS file-system description object
 * @jhead: journal head
 * @len: how many bytes to reserve
 *
 * This function makes space reservation in journal head @jhead. The function
 * takes the commit lock and locks the journal head, and the caller has to
 * unlock the head and finish the reservation with 'finish_reservation()'.
 * Returns zero in case of success and a negative error code in case of
 * failure.
 *
 * Note, the journal head may be unlocked as soon as the data is written, while
 * the commit lock has to be released after the data has been added to the
 * TNC.
 */
static int make_reservation(struct ubifs_info *c, int jhead, int len)
{
	int err, cmt_retries = 0, nospc_retries = 0;

	ubifs_assert(len <= c->dark_wm);

again:
	down_read(&c->commit_sem);
	err = reserve_space(c, jhead, len);
	if (!err)
		return 0;
	up_read(&c->commit_sem);

	if (err == -ENOSPC) {
		/*
		 * GC could not make any progress. We should try to commit
		 * once because it could make some dirty space and GC would
		 * make progress, so make the error -EAGAIN so that the below
		 * will commit and re-try.
		 */
		if (nospc_retries++ < 2) {
			dbg_jrn("no space, retry");
			err = -EAGAIN;
		}

		/*
		 * This means that the budgeting is incorrect. We always have
		 * to be able to write to the media, because all operations are
		 * budgeted. Deletions are not budgeted, though, but we reserve
		 * an extra LEB for them.
		 */
	}

	if (err != -EAGAIN)
		goto out;

	/*
	 * -EAGAIN means that the journal is full or too large, or the above
	 * code wants to do one commit. Do this and re-try.
	 */
	if (cmt_retries > 128) {
		/*
		 * This should not happen unless the journal size limitations
		 * are too tough.
		 */
		ubifs_err("stuck in space allocation");
		err = -ENOSPC;
		goto out;
	} else if (cmt_retries > 32)
		ubifs_warn("too many space allocation re-tries (%d)",
			   cmt_retries);

	dbg_jrn("-EAGAIN, commit and retry (retried %d times)",
		cmt_retries);
	cmt_retries += 1;

	err = ubifs_run_commit(c);
	if (err)
		return err;
	goto again;

out:
	ubifs_err("cannot reserve %d bytes in jhead %d, error %d",
		  len, jhead, err);
	if (err == -ENOSPC) {
		/* This are some budgeting problems, print useful information */
		down_write(&c->commit_sem);
		spin_lock(&c->space_lock);
		dbg_dump_stack();
		dbg_dump_budg(c);
		spin_unlock(&c->space_lock);
		dbg_dump_lprops(c);
		cmt_retries = dbg_check_lprops(c);
		up_write(&c->commit_sem);
	}

	return err;
}
Beispiel #9
0
static void parse_rx_slots(VCHIQ_STATE_T *state)
{
   VCHIQ_CHANNEL_T *remote = state->remote;
   VCHIQ_CHANNEL_T *local = state->local;

   while (remote->ctrl.process != remote->ctrl.insert) {
      VCHIQ_HEADER_T *header = (VCHIQ_HEADER_T *)(remote->ctrl.data + (remote->ctrl.process & VCHIQ_CHANNEL_MASK));
      VCHIQ_SERVICE_T *service = NULL;
      unsigned int stride = calc_stride(header->size);
      int type = VCHIQ_MSG_TYPE(header->fourcc);

      VCHIQ_TRACE("%d: prs %d (%d,%d)", state->id, type, VCHIQ_MSG_DSTPORT(header->fourcc), VCHIQ_MSG_SRCPORT(header->fourcc));

      switch (type)
      {
      case VCHIQ_MSG_OPEN:
         vcos_assert(VCHIQ_MSG_DSTPORT(header->fourcc) == 0);
         if (vcos_verify(header->size == 4))
         {
            VCHIQ_HEADER_T *reply;
            unsigned short remoteport = VCHIQ_MSG_SRCPORT(header->fourcc);
            int target;
            service = get_listening_service(local, *(int *)header->data);

            local_mutex_acquire(&local->ctrl.mutex);

            target = local->ctrl.insert + sizeof(VCHIQ_HEADER_T);
            reply = reserve_space(local, target);
            if (!reply)
            {
               local_mutex_release(&local->ctrl.mutex);
               return; /* Bail out */
            }

            if (service && (service->srvstate == VCHIQ_SRVSTATE_LISTENING))
            {
               /* A matching, listening service exists - attempt the OPEN */
               VCHIQ_STATUS_T status;
               vchiq_set_service_state(service, VCHIQ_SRVSTATE_OPEN); /* Proceed as if the connection will be accepted */
               status = service->base.callback(VCHIQ_SERVICE_OPENED, NULL, &service->base, NULL);
               if (status == VCHIQ_SUCCESS)
               {
                  /* The open was accepted - acknowledge it */
                  reply->fourcc = VCHIQ_MAKE_MSG(VCHIQ_MSG_OPENACK, service->localport, remoteport);
                  service->remoteport = remoteport;
               }
               else
               {
                  vchiq_set_service_state(service, VCHIQ_SRVSTATE_LISTENING);

                  if (status == VCHIQ_RETRY)
                     return; /* Bail out if not ready */

                  /* The open was rejected - send a close */
                  reply->fourcc = VCHIQ_MAKE_MSG(VCHIQ_MSG_CLOSE, 0, remoteport);
               }
            }
            else
            {
               /* No matching, available service - send a CLOSE */
               reply->fourcc = VCHIQ_MAKE_MSG(VCHIQ_MSG_CLOSE, 0, remoteport);
            }
            reply->size = 0;

            local->ctrl.insert = target;

            local_mutex_release(&local->ctrl.mutex);

            remote_event_signal(&remote->trigger);
         }
         break;
      case VCHIQ_MSG_OPENACK:
         {
            unsigned int localport = VCHIQ_MSG_DSTPORT(header->fourcc);
            unsigned int remoteport = VCHIQ_MSG_SRCPORT(header->fourcc);
            service = &local->services[localport];
            if (vcos_verify((localport < VCHIQ_MAX_SERVICES) &&
                            (service->srvstate == VCHIQ_SRVSTATE_OPENING)))
            {
               service->remoteport = remoteport;
               vchiq_set_service_state(service, VCHIQ_SRVSTATE_OPEN);
               local_event_signal(&service->remove_event);
            }
         }
         break;
      case VCHIQ_MSG_CLOSE:
         {
            unsigned int localport = VCHIQ_MSG_DSTPORT(header->fourcc);
            unsigned int remoteport = VCHIQ_MSG_SRCPORT(header->fourcc);
            service = &local->services[localport];
            vcos_assert(header->size == 0); /* There should be no data */

            if (vcos_verify(localport < VCHIQ_MAX_SERVICES))
            {
               switch (service->srvstate)
               {
               case VCHIQ_SRVSTATE_OPEN:
                  if (service->remoteport != remoteport)
                     break;
                  /* Return the close */
                  if (queue_message(state,
                                    VCHIQ_MAKE_MSG(VCHIQ_MSG_CLOSE, service->localport, service->remoteport),
                                    NULL, 0, 0) == VCHIQ_RETRY)
                     return; /* Bail out if not ready */

                  vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT);
                  /* Drop through... */
               case VCHIQ_SRVSTATE_CLOSESENT:
                  if (service->remoteport != remoteport)
                     break;
                  vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSING);
               /* Drop through... */
               case VCHIQ_SRVSTATE_CLOSING:
                  if (service->remoteport == remoteport)
                  {
                     /* Start the close procedure */
                     if (vchiq_close_service_internal(service) == VCHIQ_RETRY)
                        return; /* Bail out if not ready */
                  }
                  break;
               case VCHIQ_SRVSTATE_OPENING:
                  /* A client is mid-open - this is a rejection, so just fail the open */
                  vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSEWAIT);
                  local_event_signal(&service->remove_event);
                  break;
               default:
                  break;
               }
            }
         }
         break;
      case VCHIQ_MSG_DATA:
         {
            unsigned int localport = VCHIQ_MSG_DSTPORT(header->fourcc);
            unsigned int remoteport = VCHIQ_MSG_SRCPORT(header->fourcc);
            service = &local->services[localport];
            if (vcos_verify((localport < VCHIQ_MAX_SERVICES) &&
                            (service->remoteport == remoteport)) &&
                (service->srvstate == VCHIQ_SRVSTATE_OPEN))
            {
               if (service->base.callback(VCHIQ_MESSAGE_AVAILABLE, header, &service->base, NULL) == VCHIQ_RETRY)
                  return; /* Bail out if not ready */
               header = NULL; /* Don't invalidate this message - defer till vchiq_release */
            }
         }
         break;
      case VCHIQ_MSG_CONNECT:
         vcos_event_signal(&state->connect);
         break;
      case VCHIQ_MSG_INVALID:
      default:
         break;
      }

      remote->ctrl.process += stride;
      if (header != NULL)
      {
         /* Invalidate it */
         header->fourcc = VCHIQ_FOURCC_INVALID;
         /* Notify the other end there is some space */
         remote_event_signal(&remote->ctrl.remove_event);
      }
   }
}
Beispiel #10
0
static VCHIQ_STATUS_T queue_message(VCHIQ_STATE_T *state, int fourcc, const VCHIQ_ELEMENT_T *elements, int count, int size)
{
   VCHIQ_CHANNEL_T *local;
   VCHIQ_HEADER_T *header;

   unsigned int stride;
   unsigned int pos;

   VCHIQ_TRACE("%d: qm %d", state->id, VCHIQ_MSG_TYPE(fourcc));

   local = state->local;

   stride = calc_stride(size);

   vcos_assert(stride < VCHIQ_CHANNEL_SIZE);

   local_mutex_acquire(&local->ctrl.mutex);

   pos = local->ctrl.insert; /* Remember for rewind */
   if ((local->ctrl.insert & VCHIQ_CHANNEL_MASK) + stride > VCHIQ_CHANNEL_SIZE) {
      int target = (local->ctrl.insert + VCHIQ_CHANNEL_SIZE) & ~VCHIQ_CHANNEL_MASK;

      header = (VCHIQ_HEADER_T *)reserve_space(local, target);
      if (!header)
      {
         local_mutex_release(&local->ctrl.mutex);
         return VCHIQ_RETRY;
      }
      header->fourcc = VCHIQ_FOURCC_INVALID;
      header->size = VCHIQ_CHANNEL_SIZE - sizeof(VCHIQ_HEADER_T) -
         (local->ctrl.insert & VCHIQ_CHANNEL_MASK);

      local->ctrl.insert = target;
   }

   /*
      write into slot
   */

   header = (VCHIQ_HEADER_T *)reserve_space(local, local->ctrl.insert + stride);
   if (!header)
   {
      local->ctrl.insert = pos;
      local_mutex_release(&local->ctrl.mutex);
      return VCHIQ_RETRY;
   }

   header->fourcc = fourcc;
   header->size = size;

   VCHIQ_TRACE("%d: qm %d - %x", state->id, VCHIQ_MSG_TYPE(fourcc), header);

   if (VCHIQ_MSG_TYPE(fourcc) == VCHIQ_MSG_DATA)
   {
      int i;
      for (i = 0, pos = 0; i < (unsigned int)count; pos += elements[i++].size)
         if (elements[i].size)
         {
            if (vchiq_copy_from_user(header->data + pos, elements[i].data, (size_t) elements[i].size) != VCHIQ_SUCCESS)
            {
               header->fourcc = VCHIQ_FOURCC_INVALID;
               local_mutex_release(&local->ctrl.mutex);
               return VCHIQ_ERROR;
            }
         }
   }
   else if (size != 0)
   {
      vcos_assert((count == 1) && (size == elements[0].size));
      memcpy(header->data, elements[0].data, elements[0].size);
   }

   local->ctrl.insert += stride;

   local_mutex_release(&local->ctrl.mutex);

   remote_event_signal(&state->remote->trigger);

   return VCHIQ_SUCCESS;
}