Blame source/vdo/base/vdoPageCacheInternals.h

Packit Service 7e342f
/*
Packit Service 7e342f
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 7e342f
 *
Packit Service 7e342f
 * This program is free software; you can redistribute it and/or
Packit Service 7e342f
 * modify it under the terms of the GNU General Public License
Packit Service 7e342f
 * as published by the Free Software Foundation; either version 2
Packit Service 7e342f
 * of the License, or (at your option) any later version.
Packit Service 7e342f
 * 
Packit Service 7e342f
 * This program is distributed in the hope that it will be useful,
Packit Service 7e342f
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 7e342f
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 7e342f
 * GNU General Public License for more details.
Packit Service 7e342f
 * 
Packit Service 7e342f
 * You should have received a copy of the GNU General Public License
Packit Service 7e342f
 * along with this program; if not, write to the Free Software
Packit Service 7e342f
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 7e342f
 * 02110-1301, USA. 
Packit Service 7e342f
 *
Packit Service 7e342f
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/vdoPageCacheInternals.h#8 $
Packit Service 7e342f
 */
Packit Service 7e342f
Packit Service 7e342f
#ifndef VDO_PAGE_CACHE_INTERNALS_H
Packit Service 7e342f
#define VDO_PAGE_CACHE_INTERNALS_H
Packit Service 7e342f
Packit Service 7e342f
#include "vdoPageCache.h"
Packit Service 7e342f
Packit Service 7e342f
#ifndef __KERNEL__
Packit Service 7e342f
# include <stdint.h>
Packit Service 7e342f
#endif
Packit Service 7e342f
Packit Service 7e342f
#include "blockMapInternals.h"
Packit Service 7e342f
#include "completion.h"
Packit Service 7e342f
#include "dirtyLists.h"
Packit Service 7e342f
#include "intMap.h"
Packit Service 7e342f
#include "physicalLayer.h"
Packit Service 7e342f
#include "ringNode.h"
Packit Service 7e342f
Packit Service 7e342f
enum {
Packit Service 7e342f
  MAX_PAGE_CONTEXT_SIZE = 8,
Packit Service 7e342f
};
Packit Service 7e342f
Packit Service 7e342f
static const PhysicalBlockNumber NO_PAGE = 0xFFFFFFFFFFFFFFFF;
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * A PageInfoNode is a ring node.
Packit Service 7e342f
 **/
Packit Service 7e342f
typedef RingNode PageInfoNode;
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * The VDO Page Cache abstraction.
Packit Service 7e342f
 **/
Packit Service 7e342f
struct vdoPageCache {
Packit Service 7e342f
  /** the physical layer to page to */
Packit Service 7e342f
  PhysicalLayer             *layer;
Packit Service 7e342f
  /** number of pages in cache */
Packit Service 7e342f
  PageCount                  pageCount;
Packit Service 7e342f
  /** function to call on page read */
Packit Service 7e342f
  VDOPageReadFunction       *readHook;
Packit Service 7e342f
  /** function to call on page write */
Packit Service 7e342f
  VDOPageWriteFunction      *writeHook;
Packit Service 7e342f
  /** number of pages to write in the current batch */
Packit Service 7e342f
  PageCount                  pagesInBatch;
Packit Service 7e342f
  /** Whether the VDO is doing a read-only rebuild */
Packit Service 7e342f
  bool                       rebuilding;
Packit Service 7e342f
Packit Service 7e342f
  /** array of page information entries */
Packit Service 7e342f
  PageInfo                  *infos;
Packit Service 7e342f
  /** raw memory for pages */
Packit Service 7e342f
  char                      *pages;
Packit Service 7e342f
  /** cache last found page info */
Packit Service 7e342f
  PageInfo                  *lastFound;
Packit Service 7e342f
  /** map of page number to info */
Packit Service 7e342f
  IntMap                    *pageMap;
Packit Service 7e342f
  /** master LRU list (all infos) */
Packit Service 7e342f
  PageInfoNode               lruList;
Packit Service 7e342f
  /** dirty pages by period */
Packit Service 7e342f
  DirtyLists                *dirtyLists;
Packit Service 7e342f
  /** free page list (oldest first) */
Packit Service 7e342f
  PageInfoNode               freeList;
Packit Service 7e342f
  /** outgoing page list */
Packit Service 7e342f
  PageInfoNode               outgoingList;
Packit Service 7e342f
  /** number of read I/O operations pending */
Packit Service 7e342f
  PageCount                  outstandingReads;
Packit Service 7e342f
  /** number of write I/O operations pending */
Packit Service 7e342f
  PageCount                  outstandingWrites;
Packit Service 7e342f
  /** number of pages covered by the current flush */
Packit Service 7e342f
  PageCount                  pagesInFlush;
Packit Service 7e342f
  /** number of pages waiting to be included in the next flush */
Packit Service 7e342f
  PageCount                  pagesToFlush;
Packit Service 7e342f
  /** number of discards in progress */
Packit Service 7e342f
  unsigned int               discardCount;
Packit Service 7e342f
  /** how many VPCs waiting for free page */
Packit Service 7e342f
  unsigned int               waiterCount;
Packit Service 7e342f
  /** queue of waiters who want a free page */
Packit Service 7e342f
  WaitQueue                  freeWaiters;
Packit Service 7e342f
  /** statistics */
Packit Service 7e342f
  AtomicPageCacheStatistics  stats;
Packit Service 7e342f
  /** counter for pressure reports */
Packit Service 7e342f
  uint32_t                   pressureReport;
Packit Service 7e342f
  /** the block map zone to which this cache belongs */
Packit Service 7e342f
  BlockMapZone              *zone;
Packit Service 7e342f
};
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * The state of a page buffer. If the page buffer is free no particular page is
Packit Service 7e342f
 * bound to it, otherwise the page buffer is bound to particular page whose
Packit Service 7e342f
 * absolute pbn is in the pbn field. If the page is resident or dirty the page
Packit Service 7e342f
 * data is stable and may be accessed. Otherwise the page is in flight
Packit Service 7e342f
 * (incoming or outgoing) and its data should not be accessed.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @note Update the static data in vpcPageStateName() and vpcPageStateFlag()
Packit Service 7e342f
 *       if you change this enumeration.
Packit Service 7e342f
 **/
Packit Service 7e342f
typedef enum __attribute__((packed)) pageState {
Packit Service 7e342f
  /* this page buffer is not being used */
Packit Service 7e342f
  PS_FREE,
Packit Service 7e342f
  /* this page is being read from store */
Packit Service 7e342f
  PS_INCOMING,
Packit Service 7e342f
  /* attempt to load this page failed */
Packit Service 7e342f
  PS_FAILED,
Packit Service 7e342f
  /* this page is valid and un-modified */
Packit Service 7e342f
  PS_RESIDENT,
Packit Service 7e342f
  /* this page is valid and modified */
Packit Service 7e342f
  PS_DIRTY,
Packit Service 7e342f
  /* this page is being written and should not be used */
Packit Service 7e342f
  PS_OUTGOING,
Packit Service 7e342f
  /* not a state */
Packit Service 7e342f
  PAGE_STATE_COUNT,
Packit Service 7e342f
} PageState;
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * The write status of page
Packit Service 7e342f
 **/
Packit Service 7e342f
typedef enum __attribute__((packed)) {
Packit Service 7e342f
  WRITE_STATUS_NORMAL,
Packit Service 7e342f
  WRITE_STATUS_DISCARD,
Packit Service 7e342f
  WRITE_STATUS_DEFERRED,
Packit Service 7e342f
} WriteStatus;
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Per-page-slot information.
Packit Service 7e342f
 **/
Packit Service 7e342f
struct pageInfo {
Packit Service 7e342f
  /** Preallocated page VIO */
Packit Service 7e342f
  VIO                 *vio;
Packit Service 7e342f
  /** back-link for references */
Packit Service 7e342f
  VDOPageCache        *cache;
Packit Service 7e342f
  /** the pbn of the page */
Packit Service 7e342f
  PhysicalBlockNumber  pbn;
Packit Service 7e342f
  /** page is busy (temporarily locked) */
Packit Service 7e342f
  uint16_t             busy;
Packit Service 7e342f
  /** the write status the page */
Packit Service 7e342f
  WriteStatus          writeStatus;
Packit Service 7e342f
  /** page state */
Packit Service 7e342f
  PageState            state;
Packit Service 7e342f
  /** queue of completions awaiting this item */
Packit Service 7e342f
  WaitQueue            waiting;
Packit Service 7e342f
  /** state linked list node */
Packit Service 7e342f
  PageInfoNode         listNode;
Packit Service 7e342f
  /** LRU node */
Packit Service 7e342f
  PageInfoNode         lruNode;
Packit Service 7e342f
  /** Space for per-page client data */
Packit Service 7e342f
  byte                 context[MAX_PAGE_CONTEXT_SIZE];
Packit Service 7e342f
};
Packit Service 7e342f
Packit Service 7e342f
// PAGE INFO LIST OPERATIONS
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline PageInfo *pageInfoFromListNode(PageInfoNode *node)
Packit Service 7e342f
{
Packit Service 7e342f
  if (node == NULL) {
Packit Service 7e342f
    return NULL;
Packit Service 7e342f
  }
Packit Service 7e342f
  return (PageInfo *) ((uintptr_t) node - offsetof(PageInfo, listNode));
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline PageInfo *pageInfoFromLRUNode(PageInfoNode *node)
Packit Service 7e342f
{
Packit Service 7e342f
  if (node == NULL) {
Packit Service 7e342f
    return NULL;
Packit Service 7e342f
  }
Packit Service 7e342f
  return (PageInfo *) ((uintptr_t) node - offsetof(PageInfo, lruNode));
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
// PAGE INFO STATE ACCESSOR FUNCTIONS
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline bool isFree(const PageInfo *info)
Packit Service 7e342f
{
Packit Service 7e342f
  return info->state == PS_FREE;
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline bool isAvailable(const PageInfo *info)
Packit Service 7e342f
{
Packit Service 7e342f
  return (info->state == PS_FREE) || (info->state == PS_FAILED);
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline bool isPresent(const PageInfo *info)
Packit Service 7e342f
{
Packit Service 7e342f
  return (info->state == PS_RESIDENT) || (info->state == PS_DIRTY);
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline bool isDirty(const PageInfo *info)
Packit Service 7e342f
{
Packit Service 7e342f
  return info->state == PS_DIRTY;
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline bool isResident(const PageInfo *info)
Packit Service 7e342f
{
Packit Service 7e342f
  return info->state == PS_RESIDENT;
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline bool isInFlight(const PageInfo *info)
Packit Service 7e342f
{
Packit Service 7e342f
  return (info->state == PS_INCOMING) || (info->state == PS_OUTGOING);
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline bool isIncoming(const PageInfo *info)
Packit Service 7e342f
{
Packit Service 7e342f
  return info->state == PS_INCOMING;
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline bool isOutgoing(const PageInfo *info)
Packit Service 7e342f
{
Packit Service 7e342f
  return info->state == PS_OUTGOING;
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline bool isValid(const PageInfo *info)
Packit Service 7e342f
{
Packit Service 7e342f
  return isPresent(info) || isOutgoing(info);
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
// COMPLETION CONVERSIONS
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline VDOPageCompletion *asVDOPageCompletion(VDOCompletion *completion)
Packit Service 7e342f
{
Packit Service 7e342f
  assertCompletionType(completion->type, VDO_PAGE_COMPLETION);
Packit Service 7e342f
  return (VDOPageCompletion *) ((uintptr_t) completion
Packit Service 7e342f
                                - offsetof(VDOPageCompletion, completion));
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**********************************************************************/
Packit Service 7e342f
static inline
Packit Service 7e342f
VDOPageCompletion *pageCompletionFromWaiter(Waiter *waiter)
Packit Service 7e342f
{
Packit Service 7e342f
  if (waiter == NULL) {
Packit Service 7e342f
    return NULL;
Packit Service 7e342f
  }
Packit Service 7e342f
Packit Service 7e342f
  VDOPageCompletion *completion = (VDOPageCompletion *)
Packit Service 7e342f
    ((uintptr_t) waiter - offsetof(VDOPageCompletion, waiter));
Packit Service 7e342f
  assertCompletionType(completion->completion.type, VDO_PAGE_COMPLETION);
Packit Service 7e342f
  return completion;
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
// COMMONLY USED FUNCTIONS
Packit Service 7e342f
Packit Service 7e342f
// All of these functions are prefixed "vpc" in order to prevent namespace
Packit Service 7e342f
// issues (ordinarily they would be static).
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Find the page info (if any) associated with a given pbn.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param cache  the page cache
Packit Service 7e342f
 * @param pbn    the absolute physical block number of the page
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return the page info for the page if available, or NULL if not
Packit Service 7e342f
 **/
Packit Service 7e342f
PageInfo *vpcFindPage(VDOPageCache *cache, PhysicalBlockNumber pbn)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Return the name of a page state.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param state     a page state
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return a pointer to a static page state name
Packit Service 7e342f
 *
Packit Service 7e342f
 * @note If the page state is invalid a static string is returned and the
Packit Service 7e342f
 *       invalid state is logged.
Packit Service 7e342f
 **/
Packit Service 7e342f
const char *vpcPageStateName(PageState state)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
#endif // VDO_PAGE_CACHE_INTERNALS_H