Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

In a transaction, allocator might need to allocate space from an empty non-evict-able page which isn’t in cache yet, then it could call the umem_cache_map() to map the empty MD page to a free memory page, to avoid NVMe I/O (CPU yield) in umem_cache_map() , we must ensure that there are is at least one free in-memory pages page (not in-use, not dirty) available for mapping, this can be achieved by calling umem_cache_reserve() before starting the local transaction.

Code Block
/**
 * Reserve few free memory pages for the potential non-evictable page growing. It's
 * usually called before starting a transaction, and the transaction might need to
 * alloc space from empty non-evictable pages which are not mapped yet.
 *
 * \param[in] store     UMEM store
 *
 * \return              Zero on success, negative value on error.
 */
int umem_cache_reserve(struct umem_store *store);

To handle the potential umem_cache_map() call within a transaction, umem_cache_reserve() will be called before starting a non-nested transaction (in vos_wal_reserve()), it checks the number of non-evict-able pages in cache, if it haven't reached the maximum value (see umem_cache_alloc()), few free in-memory pages (not in-use, not dirty) will be reserved.

Code Block
/**
 * Load & Map MD pages in specified range to memory pages, then take a
 * reference on the mapped memory pages, so that the pages won't be evicted
 * until unpin is called. It's usually for the cases where we need the pages
 * stay loaded across a yield.
 *
 * \param[in] store     UMEM store
 * \param[in] ranges    Ranges to be pinned
 * \param[in] range_nr  Number of ranges
 * \param[in] is_sys    Internal access from system ULTs (aggregation etc.)
 *
 * \return              Zero on success, negative value on error
 */
 int umem_cache_pin(struct umem_store *store, umem_cache_pin_range *ranges, int range_nr, bool is_sys);
 
/**
 * Unpin the pages pinned by prior umem_cache_pin().
 *
 * \param[in] store     UMEM store
 * \param[in] ranges    Ranges to be pinned
 * \param[in] range_nr  Number of ranges
 *
 * \return              N/A
 */
 void umem_cache_unpin(struct umem_store *store, umem_cache_pin_range *ranges, int range_nr);

...