/**
 *
 * @brief invalidates an entry in the cache
 *
 * This function invalidates the related cache entry correponding to a
 * FSAL handle. It is designed to be called when an FSAL upcall is
 * triggered.
 *
 * @param[in]  handle FSAL handle for the entry to be invalidated
 * @param[out] status Returned status
 *
 * @retval CACHE_INODE_SUCCESS if operation is a success
 * @retval CACHE_INODE_INVALID_ARGUMENT bad parameter(s) as input
 * @retval CACHE_INODE_NOT_FOUND if entry is not cached
 * @retval CACHE_INODE_STATE_CONFLICT if invalidating this entry would
 *                                    result is state conflict
 * @retval CACHE_INODE_INCONSISTENT_ENTRY if entry is not consistent
 * @retval Other errors shows a FSAL error.
 *
 */
cache_inode_status_t
cache_inode_invalidate(cache_inode_fsal_data_t *fsal_data,
                       cache_inode_status_t *status,
                       uint32_t flags)
{
     hash_buffer_t key, value;
     int rc = 0 ;
     cache_entry_t *entry;
     struct hash_latch latch;

     if (status == NULL || fsal_data == NULL) {
          *status = CACHE_INODE_INVALID_ARGUMENT;
          goto out;
     }

     /* Locate the entry in the cache */
     FSAL_ExpandHandle(NULL,  /* pcontext but not used... */
                       FSAL_DIGEST_SIZEOF,
                       &fsal_data->fh_desc);

     /* Turn the input to a hash key */
     key.pdata = fsal_data->fh_desc.start;
     key.len = fsal_data->fh_desc.len;

     if ((rc = HashTable_GetLatch(fh_to_cache_entry_ht,
                                  &key,
                                  &value,
                                  FALSE,
                                  &latch)) == HASHTABLE_ERROR_NO_SUCH_KEY) {
          /* Entry is not cached */
          HashTable_ReleaseLatched(fh_to_cache_entry_ht, &latch);
          *status = CACHE_INODE_NOT_FOUND;
          return *status;
     } else if (rc != HASHTABLE_SUCCESS) {
          LogCrit(COMPONENT_CACHE_INODE,
                  "Unexpected error %u while calling HashTable_GetLatch", rc) ;
          *status = CACHE_INODE_INVALID_ARGUMENT;
          goto out;
     }

     entry = value.pdata;
     if (cache_inode_lru_ref(entry, 0) != CACHE_INODE_SUCCESS) {
          HashTable_ReleaseLatched(fh_to_cache_entry_ht, &latch);
          *status = CACHE_INODE_NOT_FOUND;
          return *status;
     }
     HashTable_ReleaseLatched(fh_to_cache_entry_ht, &latch);

     PTHREAD_RWLOCK_WRLOCK(&entry->attr_lock);
     PTHREAD_RWLOCK_WRLOCK(&entry->content_lock);

     /* We can invalidate entries with state just fine.  We force
        Cache_inode to contact the FSAL for any use of content or
        attributes, and if the FSAL indicates the entry is stale, it
        can be disposed of then. */

     /* We should have a way to invalidate content and attributes
        separately.  Or at least a way to invalidate attributes
        without invalidating content (since any change in content
        really ought to modify mtime, at least.) */

     if ((flags & CACHE_INODE_INVALIDATE_CLEARBITS) != 0)
       atomic_clear_uint32_t_bits(&entry->flags,
                                  CACHE_INODE_TRUST_ATTRS |
                                  CACHE_INODE_DIR_POPULATED |
                                  CACHE_INODE_TRUST_CONTENT);

     /* The main reason for holding the lock at this point is so we
        don't clear the trust bits while someone is populating the
        directory or refreshing attributes. */

     if (((flags & CACHE_INODE_INVALIDATE_CLOSE) != 0) &&
         (entry->type == REGULAR_FILE)) {
          cache_inode_close(entry,
                            NULL,
                            (CACHE_INODE_FLAG_REALLYCLOSE |
                             CACHE_INODE_FLAG_CONTENT_HAVE |
                             CACHE_INODE_FLAG_CONTENT_HOLD),
                            status);
     }

     PTHREAD_RWLOCK_UNLOCK(&entry->attr_lock);
     PTHREAD_RWLOCK_UNLOCK(&entry->content_lock);

     cache_inode_lru_unref(entry, 0);

out:

     /* Memory copying attributes with every call is expensive.
        Let's not do it.  */

     return (*status);
} /* cache_inode_invalidate */
示例#2
0
cache_entry_t *
cache_inode_create(cache_entry_t *parent,
                   fsal_name_t *name,
                   cache_inode_file_type_t type,
                   fsal_accessmode_t mode,
                   cache_inode_create_arg_t *create_arg,
                   fsal_attrib_list_t *attr,
                   fsal_op_context_t *context,
                   cache_inode_status_t *status)
{
     cache_entry_t *entry = NULL;
     fsal_status_t fsal_status = {0, 0};
     fsal_handle_t object_handle;
     fsal_attrib_list_t object_attributes;
     cache_inode_fsal_data_t fsal_data;
     cache_inode_create_arg_t zero_create_arg;

     memset(&zero_create_arg, 0, sizeof(zero_create_arg));
     memset(&fsal_data, 0, sizeof(fsal_data));
     memset(&object_handle, 0, sizeof(object_handle));

     if (create_arg == NULL) {
          create_arg = &zero_create_arg;
     }

     /* Set the return default to CACHE_INODE_SUCCESS */
     *status = CACHE_INODE_SUCCESS;

     if ((type != REGULAR_FILE) && (type != DIRECTORY) &&
         (type != SYMBOLIC_LINK) && (type != SOCKET_FILE) &&
         (type != FIFO_FILE) && (type != CHARACTER_FILE) &&
         (type != BLOCK_FILE)) {
          *status = CACHE_INODE_BAD_TYPE;

          entry = NULL;
          goto out;
        }

     /* Check if an entry of the same name exists */
     entry = cache_inode_lookup(parent,
                                name,
                                attr,
                                context,
                                status);
     if (entry != NULL) {
          *status = CACHE_INODE_ENTRY_EXISTS;
          if (entry->type != type) {
               /* Incompatible types, returns NULL */
               cache_inode_lru_unref(entry, LRU_FLAG_NONE);
               entry = NULL;
               goto out;
          } else {
               goto out;
          }
     }

     /* The entry doesn't exist, so we can create it. */

     object_attributes.asked_attributes = cache_inode_params.attrmask;
     switch (type) {
     case REGULAR_FILE:
          fsal_status = FSAL_create(&parent->handle,
                                    name, context, mode,
                                    &object_handle, &object_attributes);
          break;

     case DIRECTORY:
          fsal_status = FSAL_mkdir(&parent->handle,
                                   name, context, mode,
                                   &object_handle, &object_attributes);
          break;

     case SYMBOLIC_LINK:
          fsal_status = FSAL_symlink(&parent->handle,
                                     name, &create_arg->link_content,
                                     context, mode, &object_handle,
                                     &object_attributes);
          break;

     case SOCKET_FILE:
          fsal_status = FSAL_mknode(&parent->handle, name, context,
                                    mode, FSAL_TYPE_SOCK, NULL,
                                    &object_handle, &object_attributes);
          break;

     case FIFO_FILE:
          fsal_status = FSAL_mknode(&parent->handle, name, context,
                                    mode, FSAL_TYPE_FIFO, NULL,
                                    &object_handle, &object_attributes);
          break;

     case BLOCK_FILE:
          fsal_status = FSAL_mknode(&parent->handle,
                                    name, context,
                                    mode, FSAL_TYPE_BLK,
                                    &create_arg->dev_spec,
                                    &object_handle, &object_attributes);
             break;

     case CHARACTER_FILE:
          fsal_status = FSAL_mknode(&parent->handle,
                                    name, context,
                                    mode, FSAL_TYPE_CHR,
                                    &create_arg->dev_spec,
                                    &object_handle,
                                    &object_attributes);
          break;

     default:
          /* we should never go there */
          *status = CACHE_INODE_INCONSISTENT_ENTRY;
          entry = NULL;
          goto out;
          break;
        }

     /* Check for the result */
     if (FSAL_IS_ERROR(fsal_status)) {
          if (fsal_status.major == ERR_FSAL_STALE) {
               LogEvent(COMPONENT_CACHE_INODE,
                        "FSAL returned STALE on create type %d",
                        type);
               cache_inode_kill_entry(parent);
          }
          *status = cache_inode_error_convert(fsal_status);
          entry = NULL;
          goto out;
     }
     fsal_data.fh_desc.start = (caddr_t) &object_handle;
     fsal_data.fh_desc.len = 0;
     FSAL_ExpandHandle(context->export_context,
                       FSAL_DIGEST_SIZEOF,
                       &fsal_data.fh_desc);

     entry = cache_inode_new_entry(&fsal_data,
                                   &object_attributes,
                                   type,
                                   create_arg,
                                   status);
     if (entry == NULL) {
          *status = CACHE_INODE_INSERT_ERROR;

          return NULL;
     }

     PTHREAD_RWLOCK_WRLOCK(&parent->content_lock);
     /* Add this entry to the directory (also takes an internal ref) */
     cache_inode_add_cached_dirent(parent,
                                   name, entry,
                                   NULL,
                                   status);
     PTHREAD_RWLOCK_UNLOCK(&parent->content_lock);
     if (*status != CACHE_INODE_SUCCESS) {
          cache_inode_lru_unref(entry, LRU_FLAG_NONE);
          entry = NULL;
          goto out;
     }

     PTHREAD_RWLOCK_WRLOCK(&parent->attr_lock);
     /* Update the parent cached attributes */
     cache_inode_set_time_current(&parent->attributes.mtime);
     parent->attributes.ctime = parent->attributes.mtime;
     /* if the created object is a directory, it contains a link
        to its parent : '..'. Thus the numlink attr must be increased. */
     if (type == DIRECTORY) {
          ++(parent->attributes.numlinks);
     }
     PTHREAD_RWLOCK_UNLOCK(&parent->attr_lock);

     /* Copy up the child attributes */
     *attr = object_attributes;

     *status = CACHE_INODE_SUCCESS;

out:

     return entry;
}
示例#3
0
cache_inode_status_t
cache_inode_operate_cached_dirent(cache_entry_t *directory,
				  const char *name,
				  const char *newname,
				  cache_inode_dirent_op_t dirent_op)
{
	cache_inode_dir_entry_t *dirent, *dirent2, *dirent3;
	cache_inode_status_t status = CACHE_INODE_SUCCESS;
	int code = 0;

	assert((dirent_op == CACHE_INODE_DIRENT_OP_LOOKUP)
	       || (dirent_op == CACHE_INODE_DIRENT_OP_REMOVE)
	       || (dirent_op == CACHE_INODE_DIRENT_OP_RENAME));

	/* Sanity check */
	if (directory->type != DIRECTORY) {
		status = CACHE_INODE_NOT_A_DIRECTORY;
		goto out;
	}

	LogFullDebug(COMPONENT_CACHE_INODE, "%s %p name=%s newname=%s",
		     dirent_op ==
		     CACHE_INODE_DIRENT_OP_REMOVE ? "REMOVE" : "RENAME",
		     directory, name, newname);

	/* If no active entry, do nothing */
	if (directory->object.dir.nbactive == 0) {
		if (!
		    ((directory->flags & CACHE_INODE_TRUST_CONTENT)
		     && (directory->flags & CACHE_INODE_DIR_POPULATED))) {
			/* We cannot serve negative lookups. */
			/* status == CACHE_INODE_SUCCESS; */
		} else {
			status = CACHE_INODE_NOT_FOUND;
		}
		goto out;
	}

	dirent = cache_inode_avl_qp_lookup_s(directory, name, 1);
	if ((!dirent) || (dirent->flags & DIR_ENTRY_FLAG_DELETED)) {
		if (!
		    ((directory->flags & CACHE_INODE_TRUST_CONTENT)
		     && (directory->flags & CACHE_INODE_DIR_POPULATED))
		    || (dirent_op == CACHE_INODE_DIRENT_OP_REMOVE)) {
			/* We cannot serve negative lookups. */
			/* status == CACHE_INODE_SUCCESS; */
		} else {
			status = CACHE_INODE_NOT_FOUND;
		}
		LogFullDebug(COMPONENT_CACHE_INODE,
			     "dirent=%p%s directory flags%s%s", dirent,
			     dirent ? ((dirent->flags & DIR_ENTRY_FLAG_DELETED)
				       ? " DELETED" : "")
			     : "",
			     (directory->flags & CACHE_INODE_TRUST_CONTENT)
			     ? " TRUST" : "",
			     (directory->flags & CACHE_INODE_DIR_POPULATED)
			     ? " POPULATED" : "");
		goto out;
	}

	/* We perform operations anyway even if CACHE_INODE_TRUST_CONTENT
	   is clear.  That way future upcalls can call in to this
	   function to update the content to be correct.  We just don't
	   ever return a not found or exists error. */

	switch (dirent_op) {
	case CACHE_INODE_DIRENT_OP_REMOVE:
		/* mark deleted */
		avl_dirent_set_deleted(directory, dirent);
		directory->object.dir.nbactive--;
		break;

	case CACHE_INODE_DIRENT_OP_RENAME:
		dirent2 = cache_inode_avl_qp_lookup_s(directory, newname, 1);
		if (dirent2) {
			/* rename would cause a collision */
			if (directory->flags & CACHE_INODE_TRUST_CONTENT) {
				/* overwrite, replace entry and expire the
				 * old */
				cache_entry_t *oldentry;
				avl_dirent_set_deleted(directory, dirent);
				cache_inode_key_dup(&dirent2->ckey,
						    &dirent->ckey);
				oldentry =
				    cache_inode_get_keyed(
					    &dirent2->ckey,
					    CIG_KEYED_FLAG_CACHED_ONLY,
					    &status);
				if (oldentry) {
					/* if it is still around, mark it
					 * gone/stale */
					status =
					    cache_inode_invalidate(
						    oldentry,
						    CIV_FLAGS);
					cache_inode_lru_unref(oldentry,
							      LRU_FLAG_NONE);
				}
			} else
				status = CACHE_INODE_ENTRY_EXISTS;
		} else {
			/* Size (including terminating NUL) of the filename */
			size_t newnamesize = strlen(newname) + 1;
			/* try to rename--no longer in-place */
			dirent3 = gsh_malloc(sizeof(cache_inode_dir_entry_t)
					     + newnamesize);
			memcpy(dirent3->name, newname, newnamesize);
			dirent3->flags = DIR_ENTRY_FLAG_NONE;
			cache_inode_key_dup(&dirent3->ckey, &dirent->ckey);
			avl_dirent_set_deleted(directory, dirent);
			code = cache_inode_avl_qp_insert(directory, dirent3);
			if (code < 0) {
				/* collision, tree state unchanged (unlikely) */
				status = CACHE_INODE_ENTRY_EXISTS;
				/* dirent is on persist tree, undelete it */
				avl_dirent_clear_deleted(directory, dirent);
				/* dirent3 was never inserted */
				gsh_free(dirent3);
			}
		}		/* !found */
		break;

	case CACHE_INODE_DIRENT_OP_LOOKUP:
		/* Lookup was performed before switch statement */
		break;
	}

out:
	return status;
}				/* cache_inode_operate_cached_dirent */
示例#4
0
cache_inode_status_t
cache_inode_readdir(cache_entry_t *directory,
		    uint64_t cookie, unsigned int *nbfound,
		    bool *eod_met,
		    attrmask_t attrmask,
		    cache_inode_getattr_cb_t cb,
		    void *opaque)
{
	/* The entry being examined */
	cache_inode_dir_entry_t *dirent = NULL;
	/* The node in the tree being traversed */
	struct avltree_node *dirent_node;
	/* The access mask corresponding to permission to list directory
	   entries */
	fsal_accessflags_t access_mask =
	    (FSAL_MODE_MASK_SET(FSAL_R_OK) |
	     FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_LIST_DIR));
	fsal_accessflags_t access_mask_attr =
	    (FSAL_MODE_MASK_SET(FSAL_R_OK) | FSAL_MODE_MASK_SET(FSAL_X_OK) |
	     FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_LIST_DIR) |
	     FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_EXECUTE));
	cache_inode_status_t status = CACHE_INODE_SUCCESS;
	cache_inode_status_t attr_status;
	struct cache_inode_readdir_cb_parms cb_parms = { opaque, NULL,
							 true, 0, true };
	bool retry_stale = true;

	LogFullDebug(COMPONENT_NFS_READDIR,
		     "Enter....");

	/* readdir can be done only with a directory */
	if (directory->type != DIRECTORY) {
		status = CACHE_INODE_NOT_A_DIRECTORY;
		/* no lock acquired so far, just return status */
		LogFullDebug(COMPONENT_NFS_READDIR,
			     "Not a directory");
		return status;
	}

	/* cache_inode_lock_trust_attrs can return an error, and no lock will
	 * be acquired */
	status = cache_inode_lock_trust_attrs(directory, false);
	if (status != CACHE_INODE_SUCCESS) {
		LogDebug(COMPONENT_NFS_READDIR,
			 "cache_inode_lock_trust_attrs status=%s",
			 cache_inode_err_str(status));
		return status;
	}

	/* Adjust access mask if ACL is asked for.
	 * NOTE: We intentionally do NOT check ACE4_READ_ATTR.
	 */
	if ((attrmask & ATTR_ACL) != 0) {
		access_mask |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_READ_ACL);
		access_mask_attr |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_READ_ACL);
	}

	/* Check if user (as specified by the credentials) is authorized to read
	 * the directory or not */
	status = cache_inode_access_no_mutex(directory, access_mask);
	if (status != CACHE_INODE_SUCCESS) {
		LogFullDebug(COMPONENT_NFS_READDIR,
			     "permission check for directory status=%s",
			     cache_inode_err_str(status));
		PTHREAD_RWLOCK_unlock(&directory->attr_lock);
		return status;
	}

	if (attrmask != 0) {
		/* Check for access permission to get attributes */
		attr_status = cache_inode_access_no_mutex(directory,
							  access_mask_attr);
		if (attr_status != CACHE_INODE_SUCCESS) {
			LogFullDebug(COMPONENT_NFS_READDIR,
				     "permission check for attributes "
				     "status=%s",
				     cache_inode_err_str(attr_status));
		}
	} else
		/* No attributes requested, we don't need permission */
		attr_status = CACHE_INODE_SUCCESS;

	PTHREAD_RWLOCK_rdlock(&directory->content_lock);
	PTHREAD_RWLOCK_unlock(&directory->attr_lock);
	if (!
	    ((directory->flags & CACHE_INODE_TRUST_CONTENT)
	     && (directory->flags & CACHE_INODE_DIR_POPULATED))) {
		PTHREAD_RWLOCK_unlock(&directory->content_lock);
		PTHREAD_RWLOCK_wrlock(&directory->content_lock);
		status = cache_inode_readdir_populate(directory);
		if (status != CACHE_INODE_SUCCESS) {
			LogFullDebug(COMPONENT_NFS_READDIR,
				     "cache_inode_readdir_populate status=%s",
				     cache_inode_err_str(status));
			goto unlock_dir;
		}
	}

	/* deal with initial cookie value:
	 * 1. cookie is invalid (-should- be checked by caller)
	 * 2. cookie is 0 (first cookie) -- ok
	 * 3. cookie is > than highest dirent position (error)
	 * 4. cookie <= highest dirent position but > highest cached cookie
	 *    (currently equivalent to #2, because we pre-populate the cookie
	 *    avl)
	 * 5. cookie is in cached range -- ok */

	if (cookie > 0) {
		/* N.B., cache_inode_avl_qp_insert_s ensures k > 2 */
		if (cookie < 3) {
			status = CACHE_INODE_BAD_COOKIE;
			LogFullDebug(COMPONENT_NFS_READDIR,
				     "Bad cookie");
			goto unlock_dir;
		}

		/* we assert this can now succeed */
		dirent =
		    cache_inode_avl_lookup_k(directory, cookie,
					     CACHE_INODE_FLAG_NEXT_ACTIVE);
		if (!dirent) {
			/* Linux (3.4, etc) has been observed to send readdir
			 * at the offset of the last entry's cookie, and
			 * returns no dirents to userland if that readdir
			 * notfound or badcookie. */
			if (cache_inode_avl_lookup_k
			    (directory, cookie, CACHE_INODE_FLAG_NONE)) {
				/* yup, it was the last entry */
				LogFullDebug(COMPONENT_NFS_READDIR,
					     "EOD because empty result");
				*eod_met = true;
				goto unlock_dir;
			}
			LogFullDebug(COMPONENT_NFS_READDIR,
				     "seek to cookie=%" PRIu64 " fail",
				     cookie);
			status = CACHE_INODE_BAD_COOKIE;
			goto unlock_dir;
		}

		/* dirent is the NEXT entry to return, since we sent
		 * CACHE_INODE_FLAG_NEXT_ACTIVE */
		dirent_node = &dirent->node_hk;

	} else {
		/* initial readdir */
		dirent_node = avltree_first(&directory->object.dir.avl.t);
	}

	LogFullDebug(COMPONENT_NFS_READDIR,
		     "About to readdir in cache_inode_readdir: directory=%p "
		     "cookie=%" PRIu64 " collisions %d", directory, cookie,
		     directory->object.dir.avl.collisions);

	/* Now satisfy the request from the cached readdir--stop when either
	 * the requested sequence or dirent sequence is exhausted */
	*nbfound = 0;
	*eod_met = false;

	for (; cb_parms.in_result && dirent_node;
	     dirent_node = avltree_next(dirent_node)) {

		cache_entry_t *entry = NULL;
		cache_inode_status_t tmp_status = 0;

		dirent =
		    avltree_container_of(dirent_node, cache_inode_dir_entry_t,
					 node_hk);

 estale_retry:
		LogFullDebug(COMPONENT_NFS_READDIR,
			     "Lookup direct %s",
			     dirent->name);

		entry =
		    cache_inode_get_keyed(&dirent->ckey,
					  CIG_KEYED_FLAG_NONE, &tmp_status);
		if (!entry) {
			LogFullDebug(COMPONENT_NFS_READDIR,
				     "Lookup returned %s",
				     cache_inode_err_str(tmp_status));

			if (retry_stale
			    && tmp_status == CACHE_INODE_ESTALE) {
				LogDebug(COMPONENT_NFS_READDIR,
					 "cache_inode_get_keyed returned %s "
					 "for %s - retrying entry",
					 cache_inode_err_str(tmp_status),
					 dirent->name);
				retry_stale = false; /* only one retry per
						      * dirent */
				goto estale_retry;
			}

			if (tmp_status == CACHE_INODE_NOT_FOUND
			    || tmp_status == CACHE_INODE_ESTALE) {
				/* Directory changed out from under us.
				   Invalidate it, skip the name, and keep
				   going. */
				atomic_clear_uint32_t_bits(
					&directory->flags,
					CACHE_INODE_TRUST_CONTENT);
				LogDebug(COMPONENT_NFS_READDIR,
					 "cache_inode_get_keyed returned %s "
					 "for %s - skipping entry",
					 cache_inode_err_str(tmp_status),
					 dirent->name);
				continue;
			} else {
				/* Something is more seriously wrong,
				   probably an inconsistency. */
				status = tmp_status;
				LogCrit(COMPONENT_NFS_READDIR,
					"cache_inode_get_keyed returned %s "
					"for %s - bailing out",
					cache_inode_err_str(status),
					dirent->name);
				goto unlock_dir;
			}
		}

		LogFullDebug(COMPONENT_NFS_READDIR,
			     "cache_inode_readdir: dirent=%p name=%s "
			     "cookie=%" PRIu64 " (probes %d)", dirent,
			     dirent->name, dirent->hk.k, dirent->hk.p);

		cb_parms.name = dirent->name;
		cb_parms.attr_allowed = attr_status == CACHE_INODE_SUCCESS;
		cb_parms.cookie = dirent->hk.k;

		tmp_status =
		    cache_inode_getattr(entry, &cb_parms, cb, CB_ORIGINAL);

		if (tmp_status != CACHE_INODE_SUCCESS) {
			cache_inode_lru_unref(entry, LRU_FLAG_NONE);
			if (tmp_status == CACHE_INODE_ESTALE) {
				if (retry_stale) {
					LogDebug(COMPONENT_NFS_READDIR,
						 "cache_inode_getattr returned "
						 "%s for %s - retrying entry",
						 cache_inode_err_str
						 (tmp_status), dirent->name);
					retry_stale = false; /* only one retry
							      * per dirent */
					goto estale_retry;
				}

				/* Directory changed out from under us.
				   Invalidate it, skip the name, and keep
				   going. */
				atomic_clear_uint32_t_bits(
					&directory->flags,
					CACHE_INODE_TRUST_CONTENT);

				LogDebug(COMPONENT_NFS_READDIR,
					 "cache_inode_lock_trust_attrs "
					 "returned %s for %s - skipping entry",
					 cache_inode_err_str(tmp_status),
					 dirent->name);
				continue;
			}

			status = tmp_status;

			LogCrit(COMPONENT_NFS_READDIR,
				"cache_inode_lock_trust_attrs returned %s for "
				"%s - bailing out",
				cache_inode_err_str(status), dirent->name);

			goto unlock_dir;
		}

		(*nbfound)++;

		cache_inode_lru_unref(entry, LRU_FLAG_NONE);

		if (!cb_parms.in_result) {
			LogDebug(COMPONENT_NFS_READDIR,
				 "bailing out due to entry not in result");
			break;
		}
	}

	/* We have reached the last node and every node traversed was
	   added to the result */

	LogDebug(COMPONENT_NFS_READDIR,
		 "dirent_node = %p, nbfound = %u, in_result = %s", dirent_node,
		 *nbfound, cb_parms.in_result ? "TRUE" : "FALSE");

	if (!dirent_node && cb_parms.in_result)
		*eod_met = true;
	else
		*eod_met = false;

unlock_dir:
	PTHREAD_RWLOCK_unlock(&directory->content_lock);
	return status;

}				/* cache_inode_readdir */
示例#5
0
/**
 *
 * cache_inode_put:  release logical reference to a cache entry conferred by
 * a previous call to cache_inode_get (cache_inode_get_located).
 *
 * The result is typically to decrement the reference count on entry, but
 * additional side effects include LRU adjustment, movement to/from the
 * protected LRU partition, or recyling if the caller has raced an operation
 * which made entry unreachable (and this current caller has the last
 * reference).  Caller MUST NOT make further accesses to the memory pointed
 * to by entry.
 *
 * @param[in] entry Cache entry being returned
 *
 * @return CACHE_INDOE_STATUS or error codes
 *
 */
void cache_inode_put(cache_entry_t *entry)
{
    cache_inode_lru_unref(entry, LRU_FLAG_NONE);
}