コード例 #1
0
ファイル: nlm_owner.c プロジェクト: fmarsch/nfs-ganesha-1
int display_nsm_client(state_nsm_client_t *pkey, char *str)
{
  char *strtmp = str;

  if(pkey == NULL)
    return sprintf(str, "NSM Client <NULL>");

  strtmp += sprintf(strtmp, "NSM Client %p: ", pkey);

  if(nfs_param.core_param.nsm_use_caller_name)
    strtmp += sprintf(strtmp, "caller_name=");
  else
    strtmp += sprintf(strtmp, "addr=");

  memcpy(strtmp, pkey->ssc_nlm_caller_name, pkey->ssc_nlm_caller_name_len);
  strtmp += pkey->ssc_nlm_caller_name_len;

  strtmp += sprintf(strtmp,
                    " %s refcount=%d",
                    atomic_fetch_int32_t(&pkey->ssc_monitored) ?
                      "monitored" : "unmonitored",
                    atomic_fetch_int32_t(&pkey->ssc_refcount));

  return strtmp - str;
}
コード例 #2
0
ファイル: nlm_owner.c プロジェクト: JevonQ/nfs-ganesha
/**
 * @brief Display an NSM client
 *
 * @param[in/out] dspbuf display_buffer describing output string
 * @param[in]     key    The NSM client
 *
 * @return the bytes remaining in the buffer.
 */
int display_nsm_client(struct display_buffer *dspbuf, state_nsm_client_t *key)
{
	int b_left;

	if (key == NULL)
		return display_printf(dspbuf, "NSM Client <NULL>");

	b_left = display_printf(dspbuf, "NSM Client %p: ", key);

	if (b_left <= 0)
		return b_left;

	if (nfs_param.core_param.nsm_use_caller_name)
		b_left = display_printf(dspbuf, "caller_name=");
	else
		b_left = display_printf(dspbuf, "addr=");

	if (b_left <= 0)
		return b_left;

	b_left = display_len_cat(dspbuf,
				 key->ssc_nlm_caller_name,
				 key->ssc_nlm_caller_name_len);

	if (b_left <= 0)
		return b_left;

	return display_printf(dspbuf, " ssc_client=%p %s refcount=%d",
			      key->ssc_client,
			      atomic_fetch_int32_t(&key->ssc_monitored)
					? "monitored" : "unmonitored",
			      atomic_fetch_int32_t(&key->ssc_refcount));
}
コード例 #3
0
ファイル: nlm_owner.c プロジェクト: JevonQ/nfs-ganesha
/**
 * @brief Display an NLM client
 *
 * @param[in/out] dspbuf display_buffer describing output string
 * @param[in]     key    The NLM client
 *
 * @return the bytes remaining in the buffer.
 */
int display_nlm_client(struct display_buffer *dspbuf, state_nlm_client_t *key)
{
	int b_left;

	if (key == NULL)
		return display_printf(dspbuf, "NLM Client <NULL>");

	b_left = display_printf(dspbuf, "NLM Client %p: {", key);

	if (b_left <= 0)
		return b_left;

	b_left = display_nsm_client(dspbuf, key->slc_nsm_client);

	if (b_left <= 0)
		return b_left;

	b_left = display_printf(dspbuf, "} caller_name=");

	if (b_left <= 0)
		return b_left;

	b_left = display_len_cat(dspbuf,
				 key->slc_nlm_caller_name,
				 key->slc_nlm_caller_name_len);

	if (b_left <= 0)
		return b_left;

	return display_printf(dspbuf, " type=%s refcount=%d",
			      xprt_type_to_str(key->slc_client_type),
			      atomic_fetch_int32_t(&key->slc_refcount));
}
コード例 #4
0
ファイル: nlm_owner.c プロジェクト: JevonQ/nfs-ganesha
/**
 * @brief Display an NLM cowner
 *
 * @param[in/out] dspbuf display_buffer describing output string
 * @param[in]     key    The NLM owner
 *
 * @return the bytes remaining in the buffer.
 */
int display_nlm_owner(struct display_buffer *dspbuf, state_owner_t *owner)
{
	int b_left;

	if (owner == NULL)
		return display_printf(dspbuf, "STATE_LOCK_OWNER_NLM <NULL>");

	b_left = display_printf(dspbuf, "STATE_LOCK_OWNER_NLM %p: {", owner);

	if (b_left <= 0)
		return b_left;

	b_left =
	    display_nlm_client(dspbuf, owner->so_owner.so_nlm_owner.so_client);

	if (b_left <= 0)
		return b_left;

	b_left = display_printf(dspbuf, "} oh=");

	if (b_left <= 0)
		return b_left;

	b_left = display_opaque_value(dspbuf,
				      owner->so_owner_val,
				      owner->so_owner_len);

	if (b_left <= 0)
		return b_left;

	return display_printf(dspbuf, " svid=%d refcount=%d",
			      owner->so_owner.so_nlm_owner.so_nlm_svid,
			      atomic_fetch_int32_t(&owner->so_refcount));
}
コード例 #5
0
/**
 * @brief Display NFSv4 owner
 *
 * @param[in]  owner The state owner
 * @param[out] str   Output string
 *
 * @return The length of the output string.
 */
int display_nfs4_owner(state_owner_t *owner, char *str)
{
  char *strtmp = str;

  strtmp += sprintf(strtmp, "%s %p:",
                    state_owner_type_to_str(owner->so_type),
                    owner);

  strtmp += sprintf(strtmp, " clientid={");
  strtmp += display_client_id_rec(owner->so_owner.so_nfs4_owner.so_clientrec, strtmp);
  strtmp += sprintf(strtmp, "} owner=");

  strtmp += DisplayOpaqueValue(owner->so_owner_val,
                               owner->so_owner_len,
                               strtmp);

  strtmp += sprintf(strtmp, " confirmed=%u seqid=%u",
                    owner->so_owner.so_nfs4_owner.so_confirmed,
                    owner->so_owner.so_nfs4_owner.so_seqid);

  if(owner->so_owner.so_nfs4_owner.so_related_owner != NULL)
    {
      strtmp += sprintf(strtmp, " related_owner={");
      strtmp += display_nfs4_owner(owner->so_owner.so_nfs4_owner.so_related_owner, strtmp);
      strtmp += sprintf(strtmp, "}");
    }

  strtmp += sprintf(strtmp, " refcount=%d",
                    atomic_fetch_int32_t(&owner->so_refcount));

  return strtmp - str;
}
コード例 #6
0
ファイル: 9p_owner.c プロジェクト: srimalik/nfs-ganesha
int display_9p_owner(struct display_buffer *dspbuf, state_owner_t *owner)
{
	int b_left;

	if (owner == NULL)
		return display_printf(dspbuf, "<NULL>");

	b_left = display_printf(dspbuf, "STATE_LOCK_OWNER_9P %p", owner);

	if (b_left <= 0)
		return b_left;

	b_left = display_sockaddr(dspbuf,
				  &owner->so_owner.so_9p_owner.client_addr);

	if (b_left <= 0)
		return b_left;

	b_left = display_printf(dspbuf, " proc_id=%u",
				owner->so_owner.so_9p_owner.proc_id);

	if (b_left <= 0)
		return b_left;

	return display_printf(dspbuf, " refcount=%d",
			      atomic_fetch_int32_t(&owner->so_refcount));
}
コード例 #7
0
ファイル: nlm_owner.c プロジェクト: fmarsch/nfs-ganesha-1
int display_nlm_client(state_nlm_client_t *pkey, char *str)
{
  char *strtmp = str;

  if(pkey == NULL)
    return sprintf(str, "NLM Client <NULL>");

  strtmp += sprintf(strtmp, "NLM Client %p: {", pkey);
  strtmp += display_nsm_client(pkey->slc_nsm_client, strtmp);
  strtmp += sprintf(strtmp, "} caller_name=");
  memcpy(strtmp, pkey->slc_nlm_caller_name, pkey->slc_nlm_caller_name_len);
  strtmp += pkey->slc_nlm_caller_name_len;
  strtmp += sprintf(strtmp, " type=%s",
                    xprt_type_to_str(pkey->slc_client_type));
  strtmp += sprintf(strtmp, " refcount=%d",
                    atomic_fetch_int32_t(&pkey->slc_refcount));

  return strtmp - str;
}
コード例 #8
0
ファイル: 9p_owner.c プロジェクト: fmarsch/nfs-ganesha-1
int display_9p_owner(state_owner_t *pkey, char *str)
{
  char *strtmp = str;

  if(pkey == NULL)
    return sprintf(str, "<NULL>");

  strtmp += sprintf(strtmp, "STATE_LOCK_OWNER_9P %p", pkey);
  strtmp += sprint_sockaddr( (sockaddr_t *)&(pkey->so_owner.so_9p_owner.client_addr),
                             strtmp, 
                             SOCK_NAME_MAX ) ;

  strtmp += sprintf(strtmp, " proc_id=%u",
                    pkey->so_owner.so_9p_owner.proc_id);
 
  strtmp += sprintf(strtmp, " refcount=%d",
                    atomic_fetch_int32_t(&pkey->so_refcount));

  return strtmp - str;
}
コード例 #9
0
ファイル: nlm_owner.c プロジェクト: fmarsch/nfs-ganesha-1
int display_nlm_owner(state_owner_t *pkey, char *str)
{
  char *strtmp = str;

  if(pkey == NULL)
    return sprintf(str, "STATE_LOCK_OWNER_NLM <NULL>");

  strtmp += sprintf(strtmp, "STATE_LOCK_OWNER_NLM %p: {", pkey);

  strtmp += display_nlm_client(pkey->so_owner.so_nlm_owner.so_client, strtmp);

  strtmp += sprintf(strtmp, "} oh=");

  strtmp += DisplayOpaqueValue(pkey->so_owner_val, pkey->so_owner_len, strtmp);

  strtmp += sprintf(strtmp, " svid=%d",
                    pkey->so_owner.so_nlm_owner.so_nlm_svid);
  strtmp += sprintf(strtmp, " refcount=%d",
                    atomic_fetch_int32_t(&pkey->so_refcount));

  return strtmp - str;
}
コード例 #10
0
/**
 * @brief Renames an entry
 *
 * This function calls the FSAL to rename a file, then mirrors the
 * operation in the cache.
 *
 * @param[in] dir_src  The source directory
 * @param[in] oldname  The current name of the file
 * @param[in] dir_dest The destination directory
 * @param[in] newname  The name to be assigned to the object
 *
 * @retval CACHE_INODE_SUCCESS if operation is a success.
 * @retval CACHE_INODE_NOT_FOUND if source object does not exist
 * @retval CACHE_INODE_ENTRY_EXISTS on collision.
 * @retval CACHE_INODE_NOT_A_DIRECTORY if dir_src or dir_dest is not a
 *                              directory.
 * @retval CACHE_INODE_BADNAME if either name is "." or ".."
 */
cache_inode_status_t
cache_inode_rename(cache_entry_t *dir_src,
		   const char *oldname,
		   cache_entry_t *dir_dest,
		   const char *newname)
{
	fsal_status_t fsal_status = { 0, 0 };
	cache_entry_t *lookup_src = NULL;
	cache_entry_t *lookup_dst = NULL;
	cache_inode_status_t status = CACHE_INODE_SUCCESS;
	cache_inode_status_t status_ref_dir_src = CACHE_INODE_SUCCESS;
	cache_inode_status_t status_ref_dir_dst = CACHE_INODE_SUCCESS;
	cache_inode_status_t status_ref_dst = CACHE_INODE_SUCCESS;

	if ((dir_src->type != DIRECTORY) || (dir_dest->type != DIRECTORY)) {
		status = CACHE_INODE_NOT_A_DIRECTORY;
		goto out;
	}

	/* Check for . and .. on oldname and newname. */
	if (!strcmp(oldname, ".") || !strcmp(oldname, "..")
	    || !strcmp(newname, ".") || !strcmp(newname, "..")) {
		status = CACHE_INODE_BADNAME;
		goto out;
	}

	/* Check for object existence in source directory */
	status =
	    cache_inode_lookup_impl(dir_src, oldname, &lookup_src);

	if (lookup_src == NULL) {
		/* If FSAL FH is stale, then this was managed in
		 * cache_inode_lookup */
		if (status != CACHE_INODE_FSAL_ESTALE)
			status = CACHE_INODE_NOT_FOUND;

		LogEvent(COMPONENT_CACHE_INODE,
			 "Rename (%p,%s)->(%p,%s) : source doesn't exist",
			 dir_src, oldname, dir_dest, newname);
		goto out;
	}

	/* Do not rename a junction node or an export root. */
	if (lookup_src->type == DIRECTORY) {
		/* Get attr_lock for looking at junction_export */
		PTHREAD_RWLOCK_rdlock(&lookup_src->attr_lock);

		if (lookup_src->object.dir.junction_export != NULL ||
		    atomic_fetch_int32_t(&lookup_src->exp_root_refcount)
		    != 0) {
			/* Trying to rename an export mount point */
			LogCrit(COMPONENT_CACHE_INODE,
				 "Attempt to rename export %s",
				 oldname);

			/* Release attr_lock */
			PTHREAD_RWLOCK_unlock(&lookup_src->attr_lock);

			status = CACHE_INODE_DIR_NOT_EMPTY;
			goto out;
		}

		/* Release attr_lock */
		PTHREAD_RWLOCK_unlock(&lookup_src->attr_lock);
	}


	/* Check if an object with the new name exists in the destination
	   directory */
	status =
	    cache_inode_lookup_impl(dir_dest, newname, &lookup_dst);

	if (status == CACHE_INODE_SUCCESS) {
		LogDebug(COMPONENT_CACHE_INODE,
			 "Rename (%p,%s)->(%p,%s) : destination already exists",
			 dir_src, oldname, dir_dest, newname);
	}
	if (status == CACHE_INODE_NOT_FOUND)
		status = CACHE_INODE_SUCCESS;
	if (status == CACHE_INODE_FSAL_ESTALE) {
		LogDebug(COMPONENT_CACHE_INODE,
			 "Rename (%p,%s)->(%p,%s) : stale destination", dir_src,
			 oldname, dir_dest, newname);
	}

	if (lookup_src == lookup_dst) {
		/* Nothing to do according to POSIX and NFS3/4
		 * If from and to both refer to the same file (they might be
		 * hard links of each other), then RENAME should perform no
		 * action and return success */
		LogDebug(COMPONENT_CACHE_INODE,
			 "Rename (%p,%s)->(%p,%s) : same file so skipping out",
			 dir_src, oldname, dir_dest, newname);
		goto out;
	}

	/* Perform the rename operation in FSAL before doing anything in the
	 * cache. Indeed, if the FSAL_rename fails unexpectly, the cache would
	 * be inconsistent!
	 *
	 * We do almost no checking before making call because we want to return
	 * error based on the files actually present in the directories, not
	 * what we have in our cache.
	 */
	LogFullDebug(COMPONENT_CACHE_INODE, "about to call FSAL rename");

	fsal_status =
	    dir_src->obj_handle->ops->rename(dir_src->obj_handle,
					     oldname, dir_dest->obj_handle,
					     newname);

	LogFullDebug(COMPONENT_CACHE_INODE, "returned from FSAL rename");

	status_ref_dir_src = cache_inode_refresh_attrs_locked(dir_src);

	if (dir_src != dir_dest)
		status_ref_dir_dst =
			cache_inode_refresh_attrs_locked(dir_dest);

	LogFullDebug(COMPONENT_CACHE_INODE, "done refreshing attributes");

	if (FSAL_IS_ERROR(fsal_status)) {
		status = cache_inode_error_convert(fsal_status);

		LogFullDebug(COMPONENT_CACHE_INODE,
			     "FSAL rename failed with %s",
			     cache_inode_err_str(status));

		goto out;
	}

	if (lookup_dst) {
		/* Force a refresh of the overwritten inode */
		status_ref_dst =
		    cache_inode_refresh_attrs_locked(lookup_dst);
		if (status_ref_dst == CACHE_INODE_FSAL_ESTALE)
			status_ref_dst = CACHE_INODE_SUCCESS;
	}

	status = status_ref_dir_src;

	if (status == CACHE_INODE_SUCCESS)
		status = status_ref_dir_dst;

	if (status == CACHE_INODE_SUCCESS)
		status = status_ref_dst;

	if (status != CACHE_INODE_SUCCESS)
		goto out;

	/* Must take locks on directories now,
	 * because if another thread checks source and destination existence
	 * in the same time, it will try to do the same checks...
	 * and it will have the same conclusion !!!
	 */
	src_dest_lock(dir_src, dir_dest);

	if (lookup_dst) {
		/* Remove the entry from parent dir_entries avl */
		status_ref_dir_dst =
		    cache_inode_remove_cached_dirent(dir_dest, newname);

		if (status_ref_dir_dst != CACHE_INODE_SUCCESS) {
			LogDebug(COMPONENT_CACHE_INODE,
				 "remove entry failed with status %s",
				 cache_inode_err_str(status_ref_dir_dst));
			cache_inode_invalidate_all_cached_dirent(dir_dest);
		}
	}

	if (dir_src == dir_dest) {
		/* if the rename operation is made within the same dir, then we
		 * use an optimization: cache_inode_rename_dirent is used
		 * instead of adding/removing dirent. This limits the use of
		 * resource in this case */

		LogDebug(COMPONENT_CACHE_INODE,
			 "Rename (%p,%s)->(%p,%s) : source and target "
			 "directory  the same", dir_src, oldname, dir_dest,
			 newname);

		cache_inode_status_t tmp_status =
		    cache_inode_rename_cached_dirent(dir_dest,
						     oldname, newname);
		if (tmp_status != CACHE_INODE_SUCCESS) {
			/* We're obviously out of date.  Throw out the cached
			   directory */
			cache_inode_invalidate_all_cached_dirent(dir_dest);
		}
	} else {
		cache_inode_status_t tmp_status = CACHE_INODE_SUCCESS;

		LogDebug(COMPONENT_CACHE_INODE,
			 "Rename (%p,%s)->(%p,%s) : moving entry", dir_src,
			 oldname, dir_dest, newname);

		/* We may have a cache entry for the destination
		 * filename.  If we do, we must delete it : it is stale. */
		tmp_status =
		    cache_inode_remove_cached_dirent(dir_dest, newname);

		if (tmp_status != CACHE_INODE_SUCCESS
		    && tmp_status != CACHE_INODE_NOT_FOUND) {
			LogDebug(COMPONENT_CACHE_INODE,
				 "Remove stale dirent returned %s",
				 cache_inode_err_str(tmp_status));
			cache_inode_invalidate_all_cached_dirent(dir_dest);
		}

		tmp_status =
		    cache_inode_add_cached_dirent(dir_dest, newname, lookup_src,
						  NULL);
		if (tmp_status != CACHE_INODE_SUCCESS) {
			/* We're obviously out of date.  Throw out the cached
			   directory */
			LogCrit(COMPONENT_CACHE_INODE, "Add dirent returned %s",
				cache_inode_err_str(tmp_status));
			cache_inode_invalidate_all_cached_dirent(dir_dest);
		}

		/* Remove the old entry */
		tmp_status =
		    cache_inode_remove_cached_dirent(dir_src, oldname);
		if (tmp_status != CACHE_INODE_SUCCESS
		    && tmp_status != CACHE_INODE_NOT_FOUND) {
			LogDebug(COMPONENT_CACHE_INODE,
				 "Remove old dirent returned %s",
				 cache_inode_err_str(tmp_status));
			cache_inode_invalidate_all_cached_dirent(dir_src);
		}
	}

	/* unlock entries */
	src_dest_unlock(dir_src, dir_dest);

out:
	if (lookup_src)
		cache_inode_put(lookup_src);

	if (lookup_dst)
		cache_inode_put(lookup_dst);

	return status;
}
コード例 #11
0
/**
 * @brief Display NFSv4 owner
 *
 * @param[in]  owner The state owner
 * @param[out] str   Output string
 *
 * @return the bytes remaining in the buffer.
 */
int display_nfs4_owner(struct display_buffer *dspbuf, state_owner_t *owner)
{
	int b_left;

	if (owner == NULL)
		return display_cat(dspbuf, "<NULL>");

	b_left = display_printf(dspbuf,  "%s %p:",
				state_owner_type_to_str(owner->so_type),
				owner);

	if (b_left <= 0)
		return b_left;

	b_left = display_printf(dspbuf, " clientid={");

	if (b_left <= 0)
		return b_left;

	b_left = display_client_id_rec(dspbuf, owner->so_owner.so_nfs4_owner
						.so_clientrec);

	if (b_left <= 0)
		return b_left;

	b_left = display_printf(dspbuf, "} owner=");

	if (b_left <= 0)
		return b_left;

	b_left = display_opaque_value(dspbuf,
				      owner->so_owner_val,
				      owner->so_owner_len);

	if (b_left <= 0)
		return b_left;

	b_left = display_printf(dspbuf, " confirmed=%u seqid=%u",
		    owner->so_owner.so_nfs4_owner.so_confirmed,
		    owner->so_owner.so_nfs4_owner.so_seqid);

	if (b_left <= 0)
		return b_left;

	if (owner->so_owner.so_nfs4_owner.so_related_owner != NULL) {
		b_left = display_printf(dspbuf, " related_owner={");

		if (b_left <= 0)
			return b_left;

		b_left =
		    display_nfs4_owner(dspbuf, owner->so_owner
					       .so_nfs4_owner.so_related_owner);

		if (b_left <= 0)
			return b_left;

		b_left = display_printf(dspbuf, "}");

		if (b_left <= 0)
			return b_left;
	}

	return display_printf(dspbuf, " refcount=%d",
		    atomic_fetch_int32_t(&owner->so_refcount));
}
コード例 #12
0
ファイル: nlm_owner.c プロジェクト: fmarsch/nfs-ganesha-1
void dec_nlm_client_ref(state_nlm_client_t *pclient)
{
  char              str[HASHTABLE_DISPLAY_STRLEN];
  struct hash_latch latch;
  hash_error_t      rc;
  hash_buffer_t     buffkey;
  hash_buffer_t     old_value;
  hash_buffer_t     old_key;
  int32_t           refcount;

  if(isDebug(COMPONENT_STATE))
    display_nlm_client(pclient, str);

  refcount = atomic_dec_int32_t(&pclient->slc_refcount);

  if(refcount > 0)
    {
      LogFullDebug(COMPONENT_STATE,
                   "Decrement refcount now=%"PRId32" {%s}",
                   refcount, str);

      return;
    }

  LogFullDebug(COMPONENT_STATE,
               "Try to remove {%s}",
               str);

  buffkey.pdata = pclient;
  buffkey.len   = sizeof(*pclient);

  /* Get the hash table entry and hold latch */
  rc = HashTable_GetLatch(ht_nlm_client,
                          &buffkey,
                          &old_value,
                          TRUE,
                          &latch);

  if(rc != HASHTABLE_SUCCESS)
    {
      if(rc == HASHTABLE_ERROR_NO_SUCH_KEY)
        HashTable_ReleaseLatched(ht_nlm_client, &latch);

      display_nlm_client(pclient, str);

      LogCrit(COMPONENT_STATE,
              "Error %s, could not find {%s}",
              hash_table_err_to_str(rc), str);

      return;
    }

  refcount = atomic_fetch_int32_t(&pclient->slc_refcount);

  if(refcount > 0)
    {
      LogDebug(COMPONENT_STATE,
               "Did not release refcount now=%"PRId32" {%s}",
               refcount, str);

      HashTable_ReleaseLatched(ht_nlm_client, &latch);

      return;
    }

  /* use the key to delete the entry */
  rc = HashTable_DeleteLatched(ht_nlm_client,
                               &buffkey,
                               &latch,
                               &old_key,
                               &old_value);

  if(rc != HASHTABLE_SUCCESS)
    {
      if(rc == HASHTABLE_ERROR_NO_SUCH_KEY)
        HashTable_ReleaseLatched(ht_nlm_client, &latch);

      display_nlm_client(pclient, str);

      LogCrit(COMPONENT_STATE,
              "Error %s, could not remove {%s}",
              hash_table_err_to_str(rc), str);

      return;
    }

  LogFullDebug(COMPONENT_STATE,
               "Free {%s}",
               str);

  free_nlm_client(old_value.pdata);
}
コード例 #13
0
ファイル: nlm_owner.c プロジェクト: JevonQ/nfs-ganesha
/**
 * @brief Relinquish a reference on an NSM client
 *
 * @param[in] client The client to release
 */
void dec_nsm_client_ref(state_nsm_client_t *client)
{
	char str[LOG_BUFF_LEN];
	struct display_buffer dspbuf = {sizeof(str), str, str};
	bool str_valid = false;
	struct hash_latch latch;
	hash_error_t rc;
	struct gsh_buffdesc buffkey;
	struct gsh_buffdesc old_value;
	struct gsh_buffdesc old_key;
	int32_t refcount;

	if (isDebug(COMPONENT_STATE)) {
		display_nsm_client(&dspbuf, client);
		str_valid = true;
	}

	refcount = atomic_dec_int32_t(&client->ssc_refcount);

	if (refcount > 0) {
		if (str_valid)
			LogFullDebug(COMPONENT_STATE,
				     "Decrement refcount now=%" PRId32 " {%s}",
				     refcount, str);

		return;
	}

	if (str_valid)
		LogFullDebug(COMPONENT_STATE, "Try to remove {%s}", str);

	buffkey.addr = client;
	buffkey.len = sizeof(*client);

	/* Get the hash table entry and hold latch */
	rc = hashtable_getlatch(ht_nsm_client, &buffkey, &old_value, true,
				&latch);

	if (rc != HASHTABLE_SUCCESS) {
		if (rc == HASHTABLE_ERROR_NO_SUCH_KEY)
			hashtable_releaselatched(ht_nsm_client, &latch);

		if (!str_valid)
			display_nsm_client(&dspbuf, client);

		LogCrit(COMPONENT_STATE, "Error %s, could not find {%s}",
			hash_table_err_to_str(rc), str);

		return;
	}

	refcount = atomic_fetch_int32_t(&client->ssc_refcount);

	if (refcount > 0) {
		if (str_valid)
			LogDebug(COMPONENT_STATE,
				 "Did not release refcount now=%"PRId32" {%s}",
				 refcount, str);

		hashtable_releaselatched(ht_nsm_client, &latch);

		return;
	}

	/* use the key to delete the entry */
	rc = hashtable_deletelatched(ht_nsm_client, &buffkey, &latch, &old_key,
				     &old_value);

	if (rc != HASHTABLE_SUCCESS) {
		if (rc == HASHTABLE_ERROR_NO_SUCH_KEY)
			hashtable_releaselatched(ht_nsm_client, &latch);

		if (!str_valid)
			display_nsm_client(&dspbuf, client);

		LogCrit(COMPONENT_STATE, "Error %s, could not remove {%s}",
			hash_table_err_to_str(rc), str);

		return;
	}

	LogFullDebug(COMPONENT_STATE, "Free {%s}", str);

	nsm_unmonitor(old_value.addr);
	free_nsm_client(old_value.addr);
}
コード例 #14
0
cache_inode_status_t
cache_inode_remove(cache_entry_t *entry, const char *name)
{
	cache_entry_t *to_remove_entry = NULL;
	fsal_status_t fsal_status = { 0, 0 };
	cache_inode_status_t status = CACHE_INODE_SUCCESS;
	cache_inode_status_t status_ref_entry = CACHE_INODE_SUCCESS;

	if (entry->type != DIRECTORY) {
		status = CACHE_INODE_NOT_A_DIRECTORY;
		goto out;
	}

	/* Factor this somewhat.  In the case where the directory hasn't
	   been populated, the entry may not exist in the cache and we'd
	   be bringing it in just to dispose of it. */

	/* Looks up for the entry to remove */
	status =
	    cache_inode_lookup_impl(entry, name, &to_remove_entry);

	if (to_remove_entry == NULL) {
		LogFullDebug(COMPONENT_CACHE_INODE, "lookup %s failure %s",
			     name, cache_inode_err_str(status));
		goto out;
	}

	/* Do not remove a junction node or an export root. */
	if (to_remove_entry->type == DIRECTORY) {
		/* Get attr_lock for looking at junction_export */
		PTHREAD_RWLOCK_rdlock(&to_remove_entry->attr_lock);

		if (to_remove_entry->object.dir.junction_export != NULL ||
		    atomic_fetch_int32_t(&to_remove_entry->exp_root_refcount)
		    != 0) {
			/* Trying to remove an export mount point */
			LogCrit(COMPONENT_CACHE_INODE,
				 "Attempt to remove export %s",
				 name);

			/* Release attr_lock */
			PTHREAD_RWLOCK_unlock(&to_remove_entry->attr_lock);

			status = CACHE_INODE_DIR_NOT_EMPTY;
			goto out;
		}

		/* Release attr_lock */
		PTHREAD_RWLOCK_unlock(&to_remove_entry->attr_lock);
	}

	LogDebug(COMPONENT_CACHE_INODE, "%s", name);

	if (is_open(to_remove_entry)) {
		/* entry is not locked and seems to be open for fd caching
		 * purpose.
		 * candidate for closing since unlink of an open file results
		 * in 'silly rename' on certain platforms */
		status =
		    cache_inode_close(to_remove_entry,
				      CACHE_INODE_FLAG_REALLYCLOSE);
		if (status != CACHE_INODE_SUCCESS) {
			/* non-fatal error. log the warning and move on */
			LogCrit(COMPONENT_CACHE_INODE,
				"Error closing %s before unlink: %s.", name,
				cache_inode_err_str(status));
		}
	}

	fsal_status =
	    entry->obj_handle->obj_ops.unlink(entry->obj_handle, name);

	if (FSAL_IS_ERROR(fsal_status)) {
		if (fsal_status.major == ERR_FSAL_STALE)
			cache_inode_kill_entry(entry);

		status = cache_inode_error_convert(fsal_status);

		LogFullDebug(COMPONENT_CACHE_INODE, "unlink %s failure %s",
			     name, cache_inode_err_str(status));

		if (to_remove_entry->type == DIRECTORY
		    && status == CACHE_INODE_DIR_NOT_EMPTY) {
			/* its dirent tree is probably stale, flush it
			 * to try and make things right again */
			PTHREAD_RWLOCK_wrlock(&to_remove_entry->content_lock);
			(void)
			    cache_inode_invalidate_all_cached_dirent
			    (to_remove_entry);
			PTHREAD_RWLOCK_unlock(&to_remove_entry->content_lock);
		}
		goto out;
	}

	/* Remove the entry from parent dir_entries avl */
	PTHREAD_RWLOCK_wrlock(&entry->content_lock);
	status_ref_entry = cache_inode_remove_cached_dirent(entry, name);
	LogDebug(COMPONENT_CACHE_INODE,
		 "cache_inode_remove_cached_dirent %s status %s", name,
		 cache_inode_err_str(status_ref_entry));
	PTHREAD_RWLOCK_unlock(&entry->content_lock);

	status_ref_entry = cache_inode_refresh_attrs_locked(entry);

	if (FSAL_IS_ERROR(fsal_status)) {
		status = cache_inode_error_convert(fsal_status);
		LogFullDebug(COMPONENT_CACHE_INODE,
			     "not sure this code makes sense %s failure %s",
			     name, cache_inode_err_str(status));
		goto out;
	}

	/* Update the attributes for the removed entry */
	(void)cache_inode_refresh_attrs_locked(to_remove_entry);

	status = status_ref_entry;
	if (status != CACHE_INODE_SUCCESS) {
		LogDebug(COMPONENT_CACHE_INODE,
			 "cache_inode_refresh_attrs_locked(entry %p %s) "
			 "returned %s", entry, name,
			 cache_inode_err_str(status_ref_entry));
	}

out:
	LogFullDebug(COMPONENT_CACHE_INODE, "remove %s: status=%s", name,
		     cache_inode_err_str(status));

	/* This is for the reference taken by lookup */
	if (to_remove_entry)
		cache_inode_put(to_remove_entry);

	return status;
}
コード例 #15
0
ファイル: nsm.c プロジェクト: JasonZen/nfs-ganesha
bool nsm_monitor(state_nsm_client_t *host)
{
	enum clnt_stat ret;
	struct mon nsm_mon;
	struct sm_stat_res res;
	struct timeval tout = { 25, 0 };

	if (host == NULL)
		return true;

	pthread_mutex_lock(&host->ssc_mutex);

	if (atomic_fetch_int32_t(&host->ssc_monitored)) {
		pthread_mutex_unlock(&host->ssc_mutex);
		return true;
	}

	nsm_mon.mon_id.mon_name = host->ssc_nlm_caller_name;
	nsm_mon.mon_id.my_id.my_prog = NLMPROG;
	nsm_mon.mon_id.my_id.my_vers = NLM4_VERS;
	nsm_mon.mon_id.my_id.my_proc = NLMPROC4_SM_NOTIFY;
	/* nothing to put in the private data */
	LogDebug(COMPONENT_NLM, "Monitor %s", host->ssc_nlm_caller_name);

	pthread_mutex_lock(&nsm_mutex);

	/* create a connection to nsm on the localhost */
	if (!nsm_connect()) {
		LogCrit(COMPONENT_NLM,
			"Can not monitor %s clnt_create returned NULL",
			nsm_mon.mon_id.mon_name);
		pthread_mutex_unlock(&nsm_mutex);
		pthread_mutex_unlock(&host->ssc_mutex);
		return false;
	}

	/* Set this after we call nsm_connect() */
	nsm_mon.mon_id.my_id.my_name = nodename;

	ret = clnt_call(nsm_clnt,
			nsm_auth,
			SM_MON,
			(xdrproc_t) xdr_mon,
			&nsm_mon,
			(xdrproc_t) xdr_sm_stat_res,
			&res,
			tout);

	if (ret != RPC_SUCCESS) {
		LogCrit(COMPONENT_NLM,
			"Can not monitor %s SM_MON ret %d %s",
			nsm_mon.mon_id.mon_name,
			ret,
			clnt_sperror(nsm_clnt, ""));

		nsm_disconnect();
		pthread_mutex_unlock(&nsm_mutex);
		pthread_mutex_unlock(&host->ssc_mutex);
		return false;
	}

	if (res.res_stat != STAT_SUCC) {
		LogCrit(COMPONENT_NLM,
			"Can not monitor %s SM_MON status %d",
			nsm_mon.mon_id.mon_name, res.res_stat);

		nsm_disconnect();
		pthread_mutex_unlock(&nsm_mutex);
		pthread_mutex_unlock(&host->ssc_mutex);
		return false;
	}

	nsm_count++;
	atomic_store_int32_t(&host->ssc_monitored, true);

	LogDebug(COMPONENT_NLM,
		 "Monitored %s for nodename %s",
		 nsm_mon.mon_id.mon_name, nodename);

	pthread_mutex_unlock(&nsm_mutex);
	pthread_mutex_unlock(&host->ssc_mutex);
	return true;
}
コード例 #16
0
ファイル: nfs4_owner.c プロジェクト: dotbugfix/nfs-ganesha
/**
 * @brief Display NFSv4 owner
 *
 * @param[in]  owner The state owner
 * @param[out] str   Output string
 *
 * @return the bytes remaining in the buffer.
 */
int display_nfs4_owner(struct display_buffer *dspbuf, state_owner_t *owner)
{
	int b_left;
	time_t texpire;
	struct state_nfs4_owner_t *nfs4_owner = &owner->so_owner.so_nfs4_owner;

	if (owner == NULL)
		return display_cat(dspbuf, "<NULL>");

	b_left = display_printf(dspbuf,  "%s %p:",
				state_owner_type_to_str(owner->so_type),
				owner);

	if (b_left <= 0)
		return b_left;

	b_left = display_printf(dspbuf, " clientid={");

	if (b_left <= 0)
		return b_left;

	b_left = display_client_id_rec(dspbuf, nfs4_owner->so_clientrec);

	if (b_left <= 0)
		return b_left;

	b_left = display_printf(dspbuf, "} owner=");

	if (b_left <= 0)
		return b_left;

	b_left = display_opaque_value(dspbuf,
				      owner->so_owner_val,
				      owner->so_owner_len);

	if (b_left <= 0)
		return b_left;

	b_left = display_printf(dspbuf, " confirmed=%u seqid=%u",
				nfs4_owner->so_confirmed,
				nfs4_owner->so_seqid);

	if (b_left <= 0)
		return b_left;

	if (nfs4_owner->so_related_owner != NULL) {
		b_left = display_printf(dspbuf, " related_owner={");

		if (b_left <= 0)
			return b_left;

		b_left =
		    display_nfs4_owner(dspbuf, nfs4_owner->so_related_owner);

		if (b_left <= 0)
			return b_left;

		b_left = display_printf(dspbuf, "}");

		if (b_left <= 0)
			return b_left;
	}

	texpire = atomic_fetch_time_t(&nfs4_owner->so_cache_expire);

	if (texpire != 0) {
		b_left = display_printf(dspbuf,
					" cached(expires in %d secs)",
					texpire - time(NULL));

		if (b_left <= 0)
			return b_left;
	}

	return display_printf(dspbuf, " refcount=%d",
		    atomic_fetch_int32_t(&owner->so_refcount));
}