int nfs4_op_destroy_session(struct nfs_argop4 *op, compound_data_t *data,
			    struct nfs_resop4 *resp)
{

	DESTROY_SESSION4args * const arg_DESTROY_SESSION4 =
	    &op->nfs_argop4_u.opdestroy_session;
	DESTROY_SESSION4res * const res_DESTROY_SESSION4 =
	    &resp->nfs_resop4_u.opdestroy_session;

	sockaddr_t nw_addr;
	sockaddr_t client_addr;
	nfs41_session_t *session;

	resp->resop = NFS4_OP_DESTROY_SESSION;
	res_DESTROY_SESSION4->dsr_status = NFS4_OK;

	if (data->minorversion == 0) {
		res_DESTROY_SESSION4->dsr_status = NFS4ERR_INVAL;
		return res_DESTROY_SESSION4->dsr_status = NFS4ERR_INVAL;
	}

	if (!nfs41_Session_Get_Pointer(arg_DESTROY_SESSION4->dsa_sessionid,
				       &session)) {
		res_DESTROY_SESSION4->dsr_status = NFS4ERR_BADSESSION;
		return res_DESTROY_SESSION4->dsr_status;
	}

	/* DESTROY_SESSION MUST be invoked on a connection that is associated
	 * with the session being destroyed
	 */

	/* Copy the address coming over the wire. */
	copy_xprt_addr(&nw_addr, data->req->rq_xprt);

	/* Copy the address recorded in the session. */
	copy_xprt_addr(&client_addr, session->xprt);

	/* Compare these fields. */
	if (!cmp_sockaddr(&nw_addr, &client_addr, false)) {
		res_DESTROY_SESSION4->dsr_status =
		    NFS4ERR_CONN_NOT_BOUND_TO_SESSION;
		return res_DESTROY_SESSION4->dsr_status;
	}

	if (!nfs41_Session_Del(arg_DESTROY_SESSION4->dsa_sessionid))
		res_DESTROY_SESSION4->dsr_status = NFS4ERR_BADSESSION;
	else
		res_DESTROY_SESSION4->dsr_status = NFS4_OK;

	/* Release ref taken in get_pointer */

	dec_session_ref(session);

	return res_DESTROY_SESSION4->dsr_status;
}				/* nfs41_op_destroy_session */
示例#2
0
/**
 *
 * nfs41_op_sequence: the NFS4_OP_SEQUENCE operation
 *
 * This functions handles the NFS4_OP_SEQUENCE operation in NFSv4. This function can be called only from nfs4_Compound.
 *
 * @param op    [IN]    pointer to nfs4_op arguments
 * @param data  [INOUT] Pointer to the compound request's data
 * @param resp  [IN]    Pointer to nfs4_op results
 * 
 * @return NFS4_OK if successfull, other values show an error. 
 *
 * @see all the nfs4_op_<*> function
 * @see nfs4_Compound
 *
 */
int nfs41_op_sequence(struct nfs_argop4 *op,
                      compound_data_t * data, struct nfs_resop4 *resp)
{
#define arg_SEQUENCE4  op->nfs_argop4_u.opsequence
#define res_SEQUENCE4  resp->nfs_resop4_u.opsequence

  nfs41_session_t *psession;

  resp->resop = NFS4_OP_SEQUENCE;
  res_SEQUENCE4.sr_status = NFS4_OK;

  /* OP_SEQUENCE is always the first operation of the request */
  if(data->oppos != 0)
    {
      res_SEQUENCE4.sr_status = NFS4ERR_SEQUENCE_POS;
      return res_SEQUENCE4.sr_status;
    }

  if(!nfs41_Session_Get_Pointer(arg_SEQUENCE4.sa_sessionid, &psession))
    {
      res_SEQUENCE4.sr_status = NFS4ERR_BADSESSION;
      return res_SEQUENCE4.sr_status;
    }

  /* Check is slot is compliant with ca_maxrequests */
  if(arg_SEQUENCE4.sa_slotid >= psession->fore_channel_attrs.ca_maxrequests)
    {
      res_SEQUENCE4.sr_status = NFS4ERR_BADSLOT;
      return res_SEQUENCE4.sr_status;
    }

  /* By default, no DRC replay */
  data->use_drc = FALSE;

  P(psession->slots[arg_SEQUENCE4.sa_slotid].lock);
  if(psession->slots[arg_SEQUENCE4.sa_slotid].sequence + 1 != arg_SEQUENCE4.sa_sequenceid)
    {
      if(psession->slots[arg_SEQUENCE4.sa_slotid].sequence == arg_SEQUENCE4.sa_sequenceid)
        {
          if(psession->slots[arg_SEQUENCE4.sa_slotid].cache_used == TRUE)
            {
              /* Replay operation through the DRC */
              data->use_drc = TRUE;
              data->pcached_res = psession->slots[arg_SEQUENCE4.sa_slotid].cached_result;

              res_SEQUENCE4.sr_status = NFS4_OK;
              return res_SEQUENCE4.sr_status;
            }
          else
            {
              /* Illegal replay */
              res_SEQUENCE4.sr_status = NFS4ERR_RETRY_UNCACHED_REP;
              return res_SEQUENCE4.sr_status;
            }
        }
      V(psession->slots[arg_SEQUENCE4.sa_slotid].lock);
      res_SEQUENCE4.sr_status = NFS4ERR_SEQ_MISORDERED;
      return res_SEQUENCE4.sr_status;
    }

  /* Keep memory of the session in the COMPOUND's data */
  data->psession = psession;

  /* Update the sequence id within the slot */
  psession->slots[arg_SEQUENCE4.sa_slotid].sequence += 1;

  memcpy((char *)res_SEQUENCE4.SEQUENCE4res_u.sr_resok4.sr_sessionid,
         (char *)arg_SEQUENCE4.sa_sessionid, NFS4_SESSIONID_SIZE);
  res_SEQUENCE4.SEQUENCE4res_u.sr_resok4.sr_sequenceid =
      psession->slots[arg_SEQUENCE4.sa_slotid].sequence;
  res_SEQUENCE4.SEQUENCE4res_u.sr_resok4.sr_slotid = arg_SEQUENCE4.sa_slotid;
  res_SEQUENCE4.SEQUENCE4res_u.sr_resok4.sr_highest_slotid = NFS41_NB_SLOTS - 1;
  res_SEQUENCE4.SEQUENCE4res_u.sr_resok4.sr_target_highest_slotid = arg_SEQUENCE4.sa_slotid;    /* Maybe not the best choice */
  res_SEQUENCE4.SEQUENCE4res_u.sr_resok4.sr_status_flags = 0;   /* What is to be set here ? */

  if(arg_SEQUENCE4.sa_cachethis == TRUE)
    {
      data->pcached_res = psession->slots[arg_SEQUENCE4.sa_slotid].cached_result;
      psession->slots[arg_SEQUENCE4.sa_slotid].cache_used = TRUE;
    }
  else
    {
      data->pcached_res = NULL;
      psession->slots[arg_SEQUENCE4.sa_slotid].cache_used = FALSE;
    }
  V(psession->slots[arg_SEQUENCE4.sa_slotid].lock);

  res_SEQUENCE4.sr_status = NFS4_OK;
  return res_SEQUENCE4.sr_status;
}                               /* nfs41_op_sequence */
示例#3
0
/**
 * @brief the NFS4_OP_SEQUENCE operation
 *
 * @param[in]     op   nfs4_op arguments
 * @param[in,out] data Compound request's data
 * @param[out]    resp nfs4_op results
 *
 * @return per RFC5661, p. 374
 *
 * @see nfs4_Compound
 *
 */
int nfs4_op_sequence(struct nfs_argop4 *op, compound_data_t *data,
		     struct nfs_resop4 *resp)
{
	SEQUENCE4args * const arg_SEQUENCE4 = &op->nfs_argop4_u.opsequence;
	SEQUENCE4res * const res_SEQUENCE4 = &resp->nfs_resop4_u.opsequence;

	nfs41_session_t *session;

	resp->resop = NFS4_OP_SEQUENCE;
	res_SEQUENCE4->sr_status = NFS4_OK;

	if (data->minorversion == 0) {
		res_SEQUENCE4->sr_status = NFS4ERR_INVAL;
		return res_SEQUENCE4->sr_status;
	}

	/* OP_SEQUENCE is always the first operation of the request */
	if (data->oppos != 0) {
		res_SEQUENCE4->sr_status = NFS4ERR_SEQUENCE_POS;
		return res_SEQUENCE4->sr_status;
	}

	if (!nfs41_Session_Get_Pointer(arg_SEQUENCE4->sa_sessionid, &session)) {
		if (nfs_in_grace()) {
			memcpy(res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.
			       sr_sessionid, arg_SEQUENCE4->sa_sessionid,
			       NFS4_SESSIONID_SIZE);
			res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.sr_sequenceid =
			    arg_SEQUENCE4->sa_sequenceid;
			res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.sr_slotid =
			    arg_SEQUENCE4->sa_slotid;
			res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.
			    sr_highest_slotid = NFS41_NB_SLOTS - 1;
			res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.
			    sr_target_highest_slotid = arg_SEQUENCE4->sa_slotid;
			res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.
			    sr_status_flags =
			    SEQ4_STATUS_RESTART_RECLAIM_NEEDED;
			LogDebugAlt(COMPONENT_SESSIONS, COMPONENT_CLIENTID,
				    "SEQUENCE returning status %s flags 0x%X",
				    nfsstat4_to_str(res_SEQUENCE4->sr_status),
				    res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.
				    sr_status_flags);
		} else {
			res_SEQUENCE4->sr_status = NFS4ERR_BADSESSION;
			LogDebugAlt(COMPONENT_SESSIONS, COMPONENT_CLIENTID,
				    "SEQUENCE returning status %s",
				    nfsstat4_to_str(res_SEQUENCE4->sr_status));
		}

		return res_SEQUENCE4->sr_status;
	}

	/* session->refcount +1 */

	LogDebug(COMPONENT_SESSIONS, "SEQUENCE session=%p", session);

	/* Check if lease is expired and reserve it */
	pthread_mutex_lock(&session->clientid_record->cid_mutex);

	if (!reserve_lease(session->clientid_record)) {
		pthread_mutex_unlock(&session->clientid_record->cid_mutex);

		dec_session_ref(session);
		res_SEQUENCE4->sr_status = NFS4ERR_EXPIRED;
		LogDebugAlt(COMPONENT_SESSIONS, COMPONENT_CLIENTID,
			    "SEQUENCE returning status %s",
			    nfsstat4_to_str(res_SEQUENCE4->sr_status));
		return res_SEQUENCE4->sr_status;
	}

	data->preserved_clientid = session->clientid_record;

	pthread_mutex_unlock(&session->clientid_record->cid_mutex);

	/* Check is slot is compliant with ca_maxrequests */
	if (arg_SEQUENCE4->sa_slotid >=
	    session->fore_channel_attrs.ca_maxrequests) {
		dec_session_ref(session);
		res_SEQUENCE4->sr_status = NFS4ERR_BADSLOT;
		LogDebugAlt(COMPONENT_SESSIONS, COMPONENT_CLIENTID,
			    "SEQUENCE returning status %s",
			    nfsstat4_to_str(res_SEQUENCE4->sr_status));
		return res_SEQUENCE4->sr_status;
	}

	/* By default, no DRC replay */
	data->use_drc = false;

	pthread_mutex_lock(&session->slots[arg_SEQUENCE4->sa_slotid].lock);
	if (session->slots[arg_SEQUENCE4->sa_slotid].sequence + 1 !=
	    arg_SEQUENCE4->sa_sequenceid) {
		if (session->slots[arg_SEQUENCE4->sa_slotid].sequence ==
		    arg_SEQUENCE4->sa_sequenceid) {
#if IMPLEMENT_CACHETHIS
			/** @todo
			 *
			 * Ganesha always caches result anyway so ignore
			 * cachethis
			 */
			if (session->slots[arg_SEQUENCE4->sa_slotid]
			    .cache_used) {
#endif
				/* Replay operation through the DRC */
				data->use_drc = true;
				data->cached_res =
				    &session->slots[arg_SEQUENCE4->sa_slotid].
				    cached_result;

				LogFullDebugAlt(COMPONENT_SESSIONS,
						COMPONENT_CLIENTID,
						"Use sesson slot %" PRIu32
						"=%p for DRC",
						arg_SEQUENCE4->sa_slotid,
						data->cached_res);

				pthread_mutex_unlock(&session->
					slots[arg_SEQUENCE4->sa_slotid].lock);
				dec_session_ref(session);
				res_SEQUENCE4->sr_status = NFS4_OK;
				return res_SEQUENCE4->sr_status;
#if IMPLEMENT_CACHETHIS
			} else {
				/* Illegal replay */
				pthread_mutex_unlock(&session->
					slots[arg_SEQUENCE4->sa_slotid].lock);
				dec_session_ref(session);
				res_SEQUENCE4->sr_status =
				    NFS4ERR_RETRY_UNCACHED_REP;
				LogDebugAlt(COMPONENT_SESSIONS,
					    COMPONENT_CLIENTID,
					    "SEQUENCE returning status %s",
					    nfsstat4_to_str(res_SEQUENCE4->
							    sr_status));
				return res_SEQUENCE4->sr_status;
			}
#endif
		}

		pthread_mutex_unlock(&session->
			slots[arg_SEQUENCE4->sa_slotid].lock);
		dec_session_ref(session);
		res_SEQUENCE4->sr_status = NFS4ERR_SEQ_MISORDERED;
		LogDebugAlt(COMPONENT_SESSIONS, COMPONENT_CLIENTID,
			    "SEQUENCE returning status %s",
			    nfsstat4_to_str(res_SEQUENCE4->sr_status));
		return res_SEQUENCE4->sr_status;
	}

	/* Keep memory of the session in the COMPOUND's data */
	data->session = session;

	/* Record the sequenceid and slotid in the COMPOUND's data */
	data->sequence = arg_SEQUENCE4->sa_sequenceid;
	data->slot = arg_SEQUENCE4->sa_slotid;

	/* Update the sequence id within the slot */
	session->slots[arg_SEQUENCE4->sa_slotid].sequence += 1;

	memcpy(res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.sr_sessionid,
	       arg_SEQUENCE4->sa_sessionid, NFS4_SESSIONID_SIZE);
	res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.sr_sequenceid =
	    session->slots[arg_SEQUENCE4->sa_slotid].sequence;
	res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.sr_slotid =
	    arg_SEQUENCE4->sa_slotid;
	res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.sr_highest_slotid =
	    NFS41_NB_SLOTS - 1;
	res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.sr_target_highest_slotid =
	    arg_SEQUENCE4->sa_slotid;	/* Maybe not the best choice */

	res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.sr_status_flags = 0;

	if (nfs_rpc_get_chan(session->clientid_record, 0) == NULL) {
		res_SEQUENCE4->SEQUENCE4res_u.sr_resok4.sr_status_flags |=
		    SEQ4_STATUS_CB_PATH_DOWN;
	}

#if IMPLEMENT_CACHETHIS
/* Ganesha always caches result anyway so ignore cachethis */
	if (arg_SEQUENCE4->sa_cachethis) {
#endif
		data->cached_res =
		    &session->slots[arg_SEQUENCE4->sa_slotid].cached_result;
		session->slots[arg_SEQUENCE4->sa_slotid].cache_used = true;

		LogFullDebugAlt(COMPONENT_SESSIONS, COMPONENT_CLIENTID,
				"Use sesson slot %" PRIu32 "=%p for DRC",
				arg_SEQUENCE4->sa_slotid, data->cached_res);
#if IMPLEMENT_CACHETHIS
	} else {
		data->cached_res = NULL;
		session->slots[arg_SEQUENCE4->sa_slotid].cache_used = false;

		LogFullDebugAlt(COMPONENT_SESSIONS, COMPONENT_CLIENTID,
				"Don't use sesson slot %" PRIu32
				"=NULL for DRC", arg_SEQUENCE4->sa_slotid);
	}
#endif

	pthread_mutex_unlock(&session->slots[arg_SEQUENCE4->sa_slotid].lock);

	/* If we were successful, stash the clientid in the request
	 * context.
	 */
	data->req_ctx->clientid = &data->session->clientid;

	res_SEQUENCE4->sr_status = NFS4_OK;
	return res_SEQUENCE4->sr_status;
}				/* nfs41_op_sequence */