Blame uds/pageCache.h

Packit Service 310c69
/*
Packit Service 310c69
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 310c69
 *
Packit Service 310c69
 * This program is free software; you can redistribute it and/or
Packit Service 310c69
 * modify it under the terms of the GNU General Public License
Packit Service 310c69
 * as published by the Free Software Foundation; either version 2
Packit Service 310c69
 * of the License, or (at your option) any later version.
Packit Service 310c69
 * 
Packit Service 310c69
 * This program is distributed in the hope that it will be useful,
Packit Service 310c69
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 310c69
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 310c69
 * GNU General Public License for more details.
Packit Service 310c69
 * 
Packit Service 310c69
 * You should have received a copy of the GNU General Public License
Packit Service 310c69
 * along with this program; if not, write to the Free Software
Packit Service 310c69
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 310c69
 * 02110-1301, USA. 
Packit Service 310c69
 *
Packit Service 310c69
 * $Id: //eng/uds-releases/jasper/src/uds/pageCache.h#5 $
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#ifndef PAGE_CACHE_H
Packit Service 310c69
#define PAGE_CACHE_H
Packit Service 310c69
Packit Service 310c69
#include "atomicDefs.h"
Packit Service 310c69
#include "cacheCounters.h"
Packit Service 310c69
#include "chapterIndex.h"
Packit Service 310c69
#include "common.h"
Packit Service 310c69
#include "compiler.h"
Packit Service 310c69
#include "indexConfig.h"
Packit Service 310c69
#include "opaqueTypes.h"
Packit Service 310c69
#include "permassert.h"
Packit Service 310c69
#include "request.h"
Packit Service 310c69
#include "volumeStore.h"
Packit Service 310c69
Packit Service 310c69
typedef struct requestList {
Packit Service 310c69
  Request *first;
Packit Service 310c69
  Request *last;
Packit Service 310c69
} RequestList;
Packit Service 310c69
Packit Service 310c69
typedef struct cachedPage {
Packit Service 310c69
  /* whether this page is currently being read asynchronously */
Packit Service 310c69
  bool               cp_readPending;
Packit Service 310c69
  /* if equal to numCacheEntries, the page is invalid */
Packit Service 310c69
  unsigned int       cp_physicalPage;
Packit Service 310c69
  /* the value of the volume clock when this page was last used */
Packit Service 310c69
  int64_t            cp_lastUsed;
Packit Service 310c69
  /* the cache page data */
Packit Service 310c69
  struct volume_page cp_pageData;
Packit Service 310c69
  /* the chapter index page. This is here, even for record pages */
Packit Service 310c69
  DeltaIndexPage     cp_indexPage;
Packit Service 310c69
} CachedPage;
Packit Service 310c69
Packit Service 310c69
enum {
Packit Service 310c69
  VOLUME_CACHE_MAX_ENTRIES              = (UINT16_MAX >> 1),
Packit Service 310c69
  VOLUME_CACHE_QUEUED_FLAG              = (1 << 15),
Packit Service 310c69
  VOLUME_CACHE_DEFAULT_MAX_QUEUED_READS = 4096
Packit Service 310c69
};
Packit Service 310c69
Packit Service 310c69
typedef struct queuedRead {
Packit Service 310c69
  /* whether this queue entry is invalid */
Packit Service 310c69
  bool         invalid;
Packit Service 310c69
  /* whether this queue entry has a pending read on it */
Packit Service 310c69
  bool         reserved;
Packit Service 310c69
  /* physical page to read */
Packit Service 310c69
  unsigned int physicalPage;
Packit Service 310c69
  /* list of requests waiting on a queued read */
Packit Service 310c69
  RequestList  requestList;
Packit Service 310c69
} QueuedRead;
Packit Service 310c69
Packit Service 310c69
// Reason for invalidating a cache entry, used for gathering statistics
Packit Service 310c69
typedef enum invalidationReason {
Packit Service 310c69
  INVALIDATION_EVICT,           // cache is full, goodbye
Packit Service 310c69
  INVALIDATION_EXPIRE,          // your chapter is being overwritten
Packit Service 310c69
  INVALIDATION_ERROR,           // error happened; don't try to use data
Packit Service 310c69
  INVALIDATION_INIT_SHUTDOWN
Packit Service 310c69
} InvalidationReason;
Packit Service 310c69
Packit Service 310c69
/*
Packit Service 310c69
 * Value stored atomically in a SearchPendingCounter.  The low order 32 bits is
Packit Service 310c69
 * the physical page number of the cached page being read.  The high order 32
Packit Service 310c69
 * bits is a sequence number.
Packit Service 310c69
 *
Packit Service 310c69
 * An InvalidateCounter is only written by its zone thread by calling the
Packit Service 310c69
 * beginPendingSearch or endPendingSearch methods.
Packit Service 310c69
 *
Packit Service 310c69
 * Any other thread that is accessing an InvalidateCounter is reading the value
Packit Service 310c69
 * in the waitForPendingSearches method.
Packit Service 310c69
 */
Packit Service 310c69
typedef int64_t InvalidateCounter;
Packit Service 310c69
// Fields of InvalidateCounter.
Packit Service 310c69
// These must be 64 bit, so an enum cannot be not used.
Packit Service 310c69
#define PAGE_FIELD  ((long)UINT_MAX)   // The page number field
Packit Service 310c69
#define COUNTER_LSB (PAGE_FIELD + 1L)  // The LSB of the counter field
Packit Service 310c69
Packit Service 310c69
typedef struct __attribute__((aligned(CACHE_LINE_BYTES))) {
Packit Service 310c69
  atomic64_t atomicValue;
Packit Service 310c69
} SearchPendingCounter;
Packit Service 310c69
Packit Service 310c69
typedef struct pageCache {
Packit Service 310c69
  // Geometry governing the volume
Packit Service 310c69
  const Geometry *geometry;
Packit Service 310c69
  // The number of zones
Packit Service 310c69
  unsigned int    zoneCount;
Packit Service 310c69
  // The number of index entries
Packit Service 310c69
  unsigned int    numIndexEntries;
Packit Service 310c69
  // The max number of cached entries
Packit Service 310c69
  uint16_t        numCacheEntries;
Packit Service 310c69
  // The index used to quickly access page in cache - top bit is a 'queued'
Packit Service 310c69
  // flag
Packit Service 310c69
  uint16_t       *index;
Packit Service 310c69
  // The cache
Packit Service 310c69
  CachedPage     *cache;
Packit Service 310c69
  // A counter for each zone to keep track of when a search is occurring
Packit Service 310c69
  // within that zone.
Packit Service 310c69
  SearchPendingCounter *searchPendingCounters;
Packit Service 310c69
  // Queued reads, as a circular array, with first and last indexes
Packit Service 310c69
  QueuedRead     *readQueue;
Packit Service 310c69
  // Cache counters for stats.  This is the first field of a PageCache that is
Packit Service 310c69
  // not constant after the struct is initialized.
Packit Service 310c69
  CacheCounters   counters;
Packit Service 310c69
  /**
Packit Service 310c69
   * Entries are enqueued at readQueueLast.
Packit Service 310c69
   * To 'reserve' entries, we get the entry pointed to by readQueueLastRead
Packit Service 310c69
   * and increment last read.  This is done with a lock so if another reader
Packit Service 310c69
   * thread reserves a read, it will grab the next one.  After every read
Packit Service 310c69
   * is completed, the reader thread calls releaseReadQueueEntry which
Packit Service 310c69
   * increments readQueueFirst until it is equal to readQueueLastRead, but only
Packit Service 310c69
   * if the value pointed to by readQueueFirst is no longer pending.
Packit Service 310c69
   * This means that if n reads are outstanding, readQueueFirst may not
Packit Service 310c69
   * be incremented until the last of the reads finishes.
Packit Service 310c69
   *
Packit Service 310c69
   *  First                    Last
Packit Service 310c69
   * ||    |    |    |    |    |    ||
Packit Service 310c69
   *   LR   (1)   (2)
Packit Service 310c69
   *
Packit Service 310c69
   * Read thread 1 increments last read (1), then read thread 2 increments it
Packit Service 310c69
   * (2). When each read completes, it checks to see if it can increment first,
Packit Service 310c69
   * when all concurrent reads have completed, readQueueFirst should equal
Packit Service 310c69
   * readQueueLastRead.
Packit Service 310c69
   **/
Packit Service 310c69
  uint16_t              readQueueFirst;
Packit Service 310c69
  uint16_t              readQueueLastRead;
Packit Service 310c69
  uint16_t              readQueueLast;
Packit Service 310c69
  // The size of the read queue
Packit Service 310c69
  unsigned int          readQueueMaxSize;
Packit Service 310c69
  // Page access counter
Packit Service 310c69
  atomic64_t            clock;
Packit Service 310c69
} PageCache;
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Allocate a cache for a volume.
Packit Service 310c69
 *
Packit Service 310c69
 * @param geometry          The geometry governing the volume
Packit Service 310c69
 * @param chaptersInCache   The size (in chapters) of the page cache
Packit Service 310c69
 * @param readQueueMaxSize  The maximum size of the read queue
Packit Service 310c69
 * @param zoneCount         The number of zones in the index
Packit Service 310c69
 * @param cachePtr          A pointer to hold the new page cache
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
int makePageCache(const Geometry  *geometry,
Packit Service 310c69
                  unsigned int     chaptersInCache,
Packit Service 310c69
                  unsigned int     readQueueMaxSize,
Packit Service 310c69
                  unsigned int     zoneCount,
Packit Service 310c69
                  PageCache      **cachePtr)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Clean up a volume's cache
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache the volumecache
Packit Service 310c69
 **/
Packit Service 310c69
void freePageCache(PageCache *cache);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Invalidates a page cache for a particular chapter
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache           the page cache
Packit Service 310c69
 * @param chapter         the chapter
Packit Service 310c69
 * @param pagesPerChapter the number of pages per chapter
Packit Service 310c69
 * @param reason          the reason for invalidation
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
int invalidatePageCacheForChapter(PageCache          *cache,
Packit Service 310c69
                                  unsigned int        chapter,
Packit Service 310c69
                                  unsigned int        pagesPerChapter,
Packit Service 310c69
                                  InvalidationReason  reason)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Find a page, invalidate it, and make its memory the least recent.  This
Packit Service 310c69
 * method is only exposed for the use of unit tests.
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache        The cache containing the page
Packit Service 310c69
 * @param physicalPage The id of the page to invalidate
Packit Service 310c69
 * @param readQueue    The queue of pending reads (may be NULL)
Packit Service 310c69
 * @param reason       The reason for the invalidation, for stats
Packit Service 310c69
 * @param mustFind     If true, it is an error if the page
Packit Service 310c69
 *                     can't be found
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
int findInvalidateAndMakeLeastRecent(PageCache          *cache,
Packit Service 310c69
                                     unsigned int        physicalPage,
Packit Service 310c69
                                     QueuedRead         *readQueue,
Packit Service 310c69
                                     InvalidationReason  reason,
Packit Service 310c69
                                     bool                mustFind);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Make the page the most recent in the cache
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache   the page cache
Packit Service 310c69
 * @param pagePtr the page to make most recent
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
void makePageMostRecent(PageCache *cache, CachedPage *pagePtr);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Verifies that a page is in the cache.  This method is only exposed for the
Packit Service 310c69
 * use of unit tests.
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache the cache to verify
Packit Service 310c69
 * @param page the page to find
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
int assertPageInCache(PageCache *cache, CachedPage *page)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Gets a page from the cache.
Packit Service 310c69
 *
Packit Service 310c69
 * @param [in] cache        the page cache
Packit Service 310c69
 * @param [in] physicalPage the page number
Packit Service 310c69
 * @param [in] probeType    the type of cache access being done (CacheProbeType
Packit Service 310c69
 *                          optionally OR'ed with CACHE_PROBE_IGNORE_FAILURE)
Packit Service 310c69
 * @param [out] pagePtr     the found page
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
int getPageFromCache(PageCache     *cache,
Packit Service 310c69
                     unsigned int   physicalPage,
Packit Service 310c69
                     int            probeType,
Packit Service 310c69
                     CachedPage   **pagePtr)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Enqueue a read request
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache        the page cache
Packit Service 310c69
 * @param request      the request that depends on the read
Packit Service 310c69
 * @param physicalPage the physicalPage for the request
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_QUEUED  if the page was queued
Packit Service 310c69
 *         UDS_SUCCESS if the queue was full
Packit Service 310c69
 *         an error code if there was an error
Packit Service 310c69
 **/
Packit Service 310c69
int enqueueRead(PageCache *cache, Request *request, unsigned int physicalPage)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Reserves a queued read for future dequeuing, but does not remove it from
Packit Service 310c69
 * the queue. Must call releaseReadQueueEntry to complete the process
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache          the page cache
Packit Service 310c69
 * @param queuePos       the position in the read queue for this pending read
Packit Service 310c69
 * @param firstRequests  list of requests for the pending read
Packit Service 310c69
 * @param physicalPage   the physicalPage for the requests
Packit Service 310c69
 * @param invalid        whether or not this entry is invalid
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
bool reserveReadQueueEntry(PageCache     *cache,
Packit Service 310c69
                           unsigned int  *queuePos,
Packit Service 310c69
                           Request      **firstRequests,
Packit Service 310c69
                           unsigned int  *physicalPage,
Packit Service 310c69
                           bool          *invalid);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Releases a read from the queue, allowing it to be reused by future
Packit Service 310c69
 * enqueues
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache      the page cache
Packit Service 310c69
 * @param queuePos   queue entry position
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
void releaseReadQueueEntry(PageCache    *cache,
Packit Service 310c69
                           unsigned int  queuePos);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Check for the page cache read queue being empty.
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache  the page cache for which to check the read queue.
Packit Service 310c69
 *
Packit Service 310c69
 * @return  true if the read queue for cache is empty, false otherwise.
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE bool readQueueIsEmpty(PageCache *cache)
Packit Service 310c69
{
Packit Service 310c69
  return (cache->readQueueFirst == cache->readQueueLast);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Check for the page cache read queue being full.
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache  the page cache for which to check the read queue.
Packit Service 310c69
 *
Packit Service 310c69
 * @return  true if the read queue for cache is full, false otherwise.
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE bool readQueueIsFull(PageCache *cache)
Packit Service 310c69
{
Packit Service 310c69
  return (cache->readQueueFirst ==
Packit Service 310c69
    (cache->readQueueLast + 1) % cache->readQueueMaxSize);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Selects a page in the cache to be used for a read.
Packit Service 310c69
 *
Packit Service 310c69
 * This will clear the pointer in the page map and
Packit Service 310c69
 * set readPending to true on the cache page
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache          the page cache
Packit Service 310c69
 * @param pagePtr        the page to add
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
int selectVictimInCache(PageCache     *cache,
Packit Service 310c69
                        CachedPage   **pagePtr)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Completes an async page read in the cache, so that
Packit Service 310c69
 * the page can now be used for incoming requests.
Packit Service 310c69
 *
Packit Service 310c69
 * This will invalidate the old cache entry and point
Packit Service 310c69
 * the page map for the new page to this entry
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache          the page cache
Packit Service 310c69
 * @param physicalPage   the page number
Packit Service 310c69
 * @param page           the page to complete processing on
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
int putPageInCache(PageCache    *cache,
Packit Service 310c69
                   unsigned int  physicalPage,
Packit Service 310c69
                   CachedPage   *page)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Cancels an async page read in the cache, so that
Packit Service 310c69
 * the page can now be used for incoming requests.
Packit Service 310c69
 *
Packit Service 310c69
 * This will invalidate the old cache entry and clear
Packit Service 310c69
 * the read queued flag on the page map entry, if it
Packit Service 310c69
 * was set.
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache          the page cache
Packit Service 310c69
 * @param physicalPage   the page number to clear the queued read flag on
Packit Service 310c69
 * @param page           the page to cancel processing on
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
void cancelPageInCache(PageCache    *cache,
Packit Service 310c69
                       unsigned int  physicalPage,
Packit Service 310c69
                       CachedPage   *page);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Get the page cache size
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache the page cache
Packit Service 310c69
 *
Packit Service 310c69
 * @return the size of the page cache
Packit Service 310c69
 **/
Packit Service 310c69
size_t getPageCacheSize(PageCache *cache)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Read the InvalidateCounter for the given zone.
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache       the page cache
Packit Service 310c69
 * @param zoneNumber  the zone number
Packit Service 310c69
 *
Packit Service 310c69
 * @return the InvalidateCounter value
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE InvalidateCounter getInvalidateCounter(PageCache    *cache,
Packit Service 310c69
                                                     unsigned int  zoneNumber)
Packit Service 310c69
{
Packit Service 310c69
  return atomic64_read(&cache->searchPendingCounters[zoneNumber].atomicValue);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Write the InvalidateCounter for the given zone.
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache              the page cache
Packit Service 310c69
 * @param zoneNumber         the zone number
Packit Service 310c69
 * @param invalidateCounter  the InvalidateCounter value to write
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE void setInvalidateCounter(PageCache         *cache,
Packit Service 310c69
                                        unsigned int       zoneNumber,
Packit Service 310c69
                                        InvalidateCounter  invalidateCounter)
Packit Service 310c69
{
Packit Service 310c69
  atomic64_set(&cache->searchPendingCounters[zoneNumber].atomicValue,
Packit Service 310c69
               invalidateCounter);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Return the physical page number of the page being searched.  The return
Packit Service 310c69
 * value is only valid if searchPending indicates that a search is in progress.
Packit Service 310c69
 *
Packit Service 310c69
 * @param counter  the InvalidateCounter value to check
Packit Service 310c69
 *
Packit Service 310c69
 * @return the page that the zone is searching
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE unsigned int pageBeingSearched(InvalidateCounter counter)
Packit Service 310c69
{
Packit Service 310c69
  return counter & PAGE_FIELD;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Determines whether a given value indicates that a search is occuring.
Packit Service 310c69
 *
Packit Service 310c69
 * @param invalidateCounter  the InvalidateCounter value to check
Packit Service 310c69
 *
Packit Service 310c69
 * @return true if a search is pending, false otherwise
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE bool searchPending(InvalidateCounter invalidateCounter)
Packit Service 310c69
{
Packit Service 310c69
  return (invalidateCounter & COUNTER_LSB) != 0;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Determines whether there is a search occuring for the given zone.
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache       the page cache
Packit Service 310c69
 * @param zoneNumber  the zone number
Packit Service 310c69
 *
Packit Service 310c69
 * @return true if a search is pending, false otherwise
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE bool isSearchPending(PageCache    *cache,
Packit Service 310c69
                                   unsigned int  zoneNumber)
Packit Service 310c69
{
Packit Service 310c69
  return searchPending(getInvalidateCounter(cache, zoneNumber));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Increment the counter for the specified zone to signal that a search has
Packit Service 310c69
 * begun.  Also set which page is being searched.  The searchPendingCounters
Packit Service 310c69
 * are protecting read access to pages indexed by the cache.  This is the
Packit Service 310c69
 * "lock" action.
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache         the page cache
Packit Service 310c69
 * @param physicalPage  the page that the zone is searching
Packit Service 310c69
 * @param zoneNumber    the zone number
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE void beginPendingSearch(PageCache    *cache,
Packit Service 310c69
                                      unsigned int  physicalPage,
Packit Service 310c69
                                      unsigned int  zoneNumber)
Packit Service 310c69
{
Packit Service 310c69
  InvalidateCounter invalidateCounter = getInvalidateCounter(cache,
Packit Service 310c69
                                                             zoneNumber);
Packit Service 310c69
  invalidateCounter &= ~PAGE_FIELD;
Packit Service 310c69
  invalidateCounter |= physicalPage;
Packit Service 310c69
  invalidateCounter += COUNTER_LSB;
Packit Service 310c69
  setInvalidateCounter(cache, zoneNumber, invalidateCounter);
Packit Service 310c69
  ASSERT_LOG_ONLY(searchPending(invalidateCounter),
Packit Service 310c69
                  "Search is pending for zone %u", zoneNumber);
Packit Service 310c69
  /*
Packit Service 310c69
   * This memory barrier ensures that the write to the invalidate counter is
Packit Service 310c69
   * seen by other threads before this threads accesses the cached page.  The
Packit Service 310c69
   * corresponding read memory barrier is in waitForPendingSearches.
Packit Service 310c69
   */
Packit Service 310c69
  smp_mb();
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Increment the counter for the specified zone to signal that a search has
Packit Service 310c69
 * finished.  We do not need to reset the page since we only should ever look
Packit Service 310c69
 * at the page value if the counter indicates a search is ongoing.  The
Packit Service 310c69
 * searchPendingCounters are protecting read access to pages indexed by the
Packit Service 310c69
 * cache.  This is the "unlock" action.
Packit Service 310c69
 *
Packit Service 310c69
 * @param cache       the page cache
Packit Service 310c69
 * @param zoneNumber  the zone number
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE void endPendingSearch(PageCache    *cache,
Packit Service 310c69
                                    unsigned int  zoneNumber)
Packit Service 310c69
{
Packit Service 310c69
  // This memory barrier ensures that this thread completes reads of the
Packit Service 310c69
  // cached page before other threads see the write to the invalidate counter.
Packit Service 310c69
  smp_mb();
Packit Service 310c69
Packit Service 310c69
  InvalidateCounter invalidateCounter = getInvalidateCounter(cache,
Packit Service 310c69
                                                             zoneNumber);
Packit Service 310c69
  ASSERT_LOG_ONLY(searchPending(invalidateCounter),
Packit Service 310c69
                  "Search is pending for zone %u", zoneNumber);
Packit Service 310c69
  invalidateCounter += COUNTER_LSB;
Packit Service 310c69
  setInvalidateCounter(cache, zoneNumber, invalidateCounter);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
#endif /* PAGE_CACHE_H */