Пример #1
0
/**
 * @brief Compare two NFSv4 owners in the hash table
 *
 * @param[in] buff1 One key
 * @param[in] buff2 Another owner
 *
 * @retval 0 on equality.
 * @retval 1 on inequality.
 */
int compare_nfs4_owner_key(struct gsh_buffdesc *buff1,
			   struct gsh_buffdesc *buff2)
{
	state_owner_t *pkey1 = buff1->addr;
	state_owner_t *pkey2 = buff2->addr;

	if (isFullDebug(COMPONENT_STATE) && isDebug(COMPONENT_HASHTABLE)) {
		char str1[HASHTABLE_DISPLAY_STRLEN];
		char str2[HASHTABLE_DISPLAY_STRLEN];

		DisplayOwner(pkey1, str1);
		DisplayOwner(pkey2, str2);

		if (isDebug(COMPONENT_HASHTABLE))
			LogFullDebug(COMPONENT_STATE, "{%s} vs {%s}", str1,
				     str2);
	}

	if (pkey1 == NULL || pkey2 == NULL)
		return 1;

	if (pkey1->so_type != pkey2->so_type)
		return 1;

	return compare_nfs4_owner(pkey1, pkey2);
}
Пример #2
0
state_owner_t *create_nfs4_owner(state_nfs4_owner_name_t * pname,
                                 nfs_client_id_t         * pclientid,
                                 state_owner_type_t        type,
                                 state_owner_t           * related_owner,
                                 unsigned int              init_seqid)
{
  state_owner_t           * powner;
  state_nfs4_owner_name_t * powner_name;

  /* This lock owner is not known yet, allocated and set up a new one */
  powner = pool_alloc(state_owner_pool, NULL);

  if(powner == NULL)
    return NULL;

  powner_name = pool_alloc(state_nfs4_owner_name_pool, NULL);

  if(powner_name == NULL)
    {
      pool_free(state_owner_pool, powner);
      return NULL;
    }

  *powner_name = *pname;

  /* set up the content of the open_owner */
  memset(powner, 0, sizeof(*powner));
  powner->so_type                                 = type;
  powner->so_owner.so_nfs4_owner.so_seqid         = init_seqid;
  powner->so_owner.so_nfs4_owner.so_related_owner = related_owner;
  powner->so_owner.so_nfs4_owner.so_clientid      = pname->son_clientid;
  powner->so_owner.so_nfs4_owner.so_pclientid     = pclientid;
  powner->so_owner_len                            = pname->son_owner_len;
  powner->so_owner.so_nfs4_owner.so_resp.resop    = NFS4_OP_ILLEGAL;
  powner->so_owner.so_nfs4_owner.so_args.argop    = NFS4_OP_ILLEGAL;
  powner->so_refcount                             = 1;
#if 0
  /* WAITING FOR COMMUNITY FIX */
  /* setting lock owner confirmed */
  if ( type == STATE_LOCK_OWNER_NFSV4)
    powner->so_owner.so_nfs4_owner.so_confirmed   = 1;
#endif
  init_glist(&powner->so_lock_list);
  init_glist(&powner->so_owner.so_nfs4_owner.so_state_list);

  memcpy(powner->so_owner_val,
         pname->son_owner_val,
         pname->son_owner_len);

  powner->so_owner_val[powner->so_owner_len] = '\0';

  if(pthread_mutex_init(&powner->so_mutex, NULL) == -1)
    {
      pool_free(state_owner_pool, powner);
      pool_free(state_nfs4_owner_name_pool, powner_name);
      return NULL;
    }

  if(!nfs4_owner_Set(powner_name, powner))
    {
      pool_free(state_owner_pool, powner);
      pool_free(state_nfs4_owner_name_pool, powner_name);
      return NULL;
    }

  if(isFullDebug(COMPONENT_STATE))
    {
      char str[HASHTABLE_DISPLAY_STRLEN];

      DisplayOwner(powner, str);
      LogFullDebug(COMPONENT_STATE,
                   "New Owner %s", str);
    }

  /* Increment refcount on related owner */
  if(related_owner != NULL)
    inc_state_owner_ref(related_owner);

  P(pclientid->cid_mutex);

  if (type == STATE_OPEN_OWNER_NFSV4)
    {
      /* If open owner, add to clientid lock owner list */
      powner->so_refcount++;
      glist_add_tail(&pclientid->cid_openowners, &powner->so_owner.so_nfs4_owner.so_perclient);
    }
  else if(type == STATE_LOCK_OWNER_NFSV4)
    {
      /* If lock owner, add to clientid open owner list */
      powner->so_refcount++;
      glist_add_tail(&pclientid->cid_lockowners, &powner->so_owner.so_nfs4_owner.so_perclient);
    }

  /* Increment reference count for clientid record */
  inc_client_id_ref(pclientid);

  V(pclientid->cid_mutex);

  return powner;
}
Пример #3
0
/**
 * @brief Check NFS4 request for valid seqid for replay, next request, or BAD_SEQID.
 *
 * Returns true if the request is the next seqid.  If the request is a
 * replay, copies the saved response and returns false.  Otherwise,
 * sets status to NFS4ERR_BAD_SEQID and returns false.
 *
 * In either case, on a false return, the caller should send the
 * resulting response back to the client.
 *
 * @param[in]  owner Owner to check
 * @param[in]  seqid Seqid to check
 * @param[in]  args  Arguments of operation
 * @param[in]  data  Compound data
 * @param[out] resp  Cached request, if replay
 * @param[in]  tag   Arbitrary string for logging/debugging
 *
 * @retval true if the caller should process the operation.
 * @retval false if the caller should immediately return the provides response.
 */
bool Check_nfs4_seqid(state_owner_t *owner, seqid4 seqid, nfs_argop4 *args,
		      cache_entry_t *entry, nfs_resop4 *resp, const char *tag)
{
	seqid4 next;
	char str[HASHTABLE_DISPLAY_STRLEN];

	/* Check if any owner to verify seqid against */
	if (owner == NULL) {
		LogFullDebug(COMPONENT_STATE,
			     "%s: Unknown owner doesn't have saved seqid, req seqid %u",
			     tag, seqid);
		return true;
	}

	if (isDebug(COMPONENT_STATE))
		DisplayOwner(owner, str);

	/* If this is a new state owner, client may start with any seqid */
	if (owner->so_owner.so_nfs4_owner.so_last_entry == NULL) {
		LogFullDebug(COMPONENT_STATE,
			     "%s: New {%s} doesn't have saved seqid, req seqid %u",
			     tag, str, seqid);
		return true;
	}

	/* Check for valid next seqid */
	next = owner->so_owner.so_nfs4_owner.so_seqid + 1;

	LogFullDebug(COMPONENT_STATE, "%s: Check {%s} next %u req seqid %u",
		     tag, str, next, seqid);

	if (seqid == next)
		return true;

	/* All NFS4 responses have the status in the same place, so use any to
	 * set NFS4ERR_BAD_SEQID
	 */
	resp->nfs_resop4_u.oplock.status = NFS4ERR_BAD_SEQID;

	/* Now check for valid replay */
	if (owner->so_owner.so_nfs4_owner.so_seqid != seqid) {
		LogDebug(COMPONENT_STATE,
			 "%s: Invalid seqid %u in request (not replay), expected seqid for {%s}, returning NFS4ERR_BAD_SEQID",
			 tag, seqid, str);
		return false;
	}

	if (args->argop != owner->so_owner.so_nfs4_owner.so_args.argop) {
		LogDebug(COMPONENT_STATE,
			 "%s: Invalid seqid %u in request (not replay - not same op), expected seqid for {%s}, returning NFS4ERR_BAD_SEQID",
			 tag, seqid, str);
		return false;
	}

	if (owner->so_owner.so_nfs4_owner.so_last_entry != entry) {
		LogDebug(COMPONENT_STATE,
			 "%s: Invalid seqid %u in request (not replay - wrong file), expected seqid for {%s}, returning NFS4ERR_BAD_SEQID",
			 tag, seqid, str);
		return false;
	}

	/** @todo FSF: add more checks here... */

	LogDebug(COMPONENT_STATE,
		 "%s: Copying saved response for seqid %u into {%s}", tag,
		 seqid, str);

	/* Copy the saved response and tell caller to use it */
	nfs4_Compound_CopyResOne(resp, &owner->so_owner.so_nfs4_owner.so_resp);

	return false;
}
Пример #4
0
/**
 * @brief Create an NFSv4 state owner
 *
 * @param[in]  name          Owner name
 * @param[in]  clientid      Client record
 * @param[in]  type          Owner type
 * @param[in]  related_owner For lock owners, the related open owner
 * @param[in]  init_seqid    The starting seqid (for NFSv4.0)
 * @param[out] pisnew        Whether the owner actually is new
 * @param[in]  care          Care flag (to unify v3/v4 owners?)
 *
 * @return A new state owner or NULL.
 */
state_owner_t *create_nfs4_owner(state_nfs4_owner_name_t *name,
				 nfs_client_id_t *clientid,
				 state_owner_type_t type,
				 state_owner_t *related_owner,
				 unsigned int init_seqid, bool_t *pisnew,
				 care_t care)
{
	state_owner_t key;
	state_owner_t *owner;
	bool_t isnew;

	/* set up the content of the open_owner */
	memset(&key, 0, sizeof(key));

	key.so_type = type;
	key.so_owner.so_nfs4_owner.so_seqid = init_seqid;
	key.so_owner.so_nfs4_owner.so_related_owner = related_owner;
	key.so_owner.so_nfs4_owner.so_clientid = clientid->cid_clientid;
	key.so_owner.so_nfs4_owner.so_clientrec = clientid;
	key.so_owner_len = name->son_owner_len;
	key.so_owner_val = name->son_owner_val;
	key.so_owner.so_nfs4_owner.so_resp.resop = NFS4_OP_ILLEGAL;
	key.so_owner.so_nfs4_owner.so_args.argop = NFS4_OP_ILLEGAL;
	key.so_refcount = 1;
#if 0
	/* WAITING FOR COMMUNITY FIX */
	/* setting lock owner confirmed */
	if (type == STATE_LOCK_OWNER_NFSV4)
		key.so_owner.so_nfs4_owner.so_confirmed = 1;
#endif

	owner = get_state_owner(care, &key, init_nfs4_owner, &isnew);

	if (owner != NULL && related_owner != NULL) {
		pthread_mutex_lock(&owner->so_mutex);
		/* Related owner already exists. */
		if (owner->so_owner.so_nfs4_owner.so_related_owner == NULL) {
			/* Attach related owner to owner now that we know it. */
			inc_state_owner_ref(related_owner);
			owner->so_owner.so_nfs4_owner.so_related_owner =
			    related_owner;
		} else if (owner->so_owner.so_nfs4_owner.so_related_owner !=
			   related_owner) {
			char str1[HASHTABLE_DISPLAY_STRLEN];
			char str2[HASHTABLE_DISPLAY_STRLEN];

			DisplayOwner(related_owner, str1);
			DisplayOwner(owner, str1);

			LogCrit(COMPONENT_NFS_V4_LOCK,
				"Related {%s} doesn't match for {%s}", str1,
				str2);
			pthread_mutex_unlock(&owner->so_mutex);

			/* Release the reference to the owner. */
			dec_state_owner_ref(owner);

			return NULL;
		}
		pthread_mutex_unlock(&owner->so_mutex);
	}

	if (!isnew && owner != NULL && pisnew != NULL) {
		if (isDebug(COMPONENT_STATE)) {
			char str[HASHTABLE_DISPLAY_STRLEN];
			DisplayOwner(owner, str);
			LogDebug(COMPONENT_STATE,
				 "Previously known owner {%s} is being reused",
				 str);
		}
	}

	if (pisnew != NULL)
		*pisnew = isnew;

	return owner;
}
Пример #5
0
state_owner_t *create_nfs4_owner(cache_inode_client_t    * pclient,
                                 state_nfs4_owner_name_t * pname,
                                 state_owner_type_t        type,
                                 state_owner_t           * related_owner,
                                 unsigned int              init_seqid)
{
  state_owner_t           * powner;
  state_nfs4_owner_name_t * powner_name;

  /* This lock owner is not known yet, allocated and set up a new one */
  GetFromPool(powner, &pclient->pool_state_owner, state_owner_t);

  if(powner == NULL)
    return NULL;

  GetFromPool(powner_name, &pclient->pool_nfs4_owner_name, state_nfs4_owner_name_t);

  if(powner_name == NULL)
    {
      ReleaseToPool(powner, &pclient->pool_state_owner);
      return NULL;
    }

  *powner_name = *pname;

  /* set up the content of the open_owner */
  memset(powner, 0, sizeof(*powner));
  powner->so_type                                 = type;
  powner->so_owner.so_nfs4_owner.so_seqid         = init_seqid;
  powner->so_owner.so_nfs4_owner.so_related_owner = related_owner;
  powner->so_owner.so_nfs4_owner.so_clientid      = pname->son_clientid;
  powner->so_owner_len                            = pname->son_owner_len;
  powner->so_owner.so_nfs4_owner.so_resp.resop    = NFS4_OP_ILLEGAL;
  powner->so_owner.so_nfs4_owner.so_args.argop    = NFS4_OP_ILLEGAL;
  powner->so_refcount                             = 1;

  init_glist(&powner->so_lock_list);

  memcpy(powner->so_owner_val,
         pname->son_owner_val,
         pname->son_owner_len);

  powner->so_owner_val[powner->so_owner_len] = '\0';

  if(pthread_mutex_init(&powner->so_mutex, NULL) == -1)
    {
      ReleaseToPool(powner, &pclient->pool_state_owner);
      ReleaseToPool(powner_name, &pclient->pool_nfs4_owner_name);
      return NULL;
    }

  if(!nfs4_owner_Set(powner_name, powner))
    {
      ReleaseToPool(powner, &pclient->pool_state_owner);
      ReleaseToPool(powner_name, &pclient->pool_nfs4_owner_name);
      return NULL;
    }

  if(isFullDebug(COMPONENT_STATE))
    {
      char str[HASHTABLE_DISPLAY_STRLEN];

      DisplayOwner(powner, str);
      LogFullDebug(COMPONENT_STATE,
                   "New Open Owner %s", str);
    }

  return powner;
}