Blame source/vdo/base/allocatingVIO.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/vdo-releases/aluminum/src/c++/vdo/base/allocatingVIO.h#4 $
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#ifndef ALLOCATING_VIO_H
Packit Service 310c69
#define ALLOCATING_VIO_H
Packit Service 310c69
Packit Service 310c69
#include "atomic.h"
Packit Service 310c69
#include "pbnLock.h"
Packit Service 310c69
#include "physicalZone.h"
Packit Service 310c69
#include "types.h"
Packit Service 310c69
#include "vio.h"
Packit Service 310c69
#include "waitQueue.h"
Packit Service 310c69
Packit Service 310c69
typedef void AllocationCallback(AllocatingVIO *allocationVIO);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * A VIO which can receive an allocation from the block allocator. Currently,
Packit Service 310c69
 * these are used both for servicing external data requests and for compressed
Packit Service 310c69
 * block writes.
Packit Service 310c69
 **/
Packit Service 310c69
struct allocatingVIO {
Packit Service 310c69
  /** The underlying VIO */
Packit Service 310c69
  VIO                 vio;
Packit Service 310c69
Packit Service 310c69
  /** The WaitQueue entry structure */
Packit Service 310c69
  Waiter              waiter;
Packit Service 310c69
Packit Service 310c69
  /** The physical zone in which to allocate a physical block */
Packit Service 310c69
  PhysicalZone       *zone;
Packit Service 310c69
Packit Service 310c69
  /** The block allocated to this VIO */
Packit Service 310c69
  PhysicalBlockNumber allocation;
Packit Service 310c69
Packit Service 310c69
  /**
Packit Service 310c69
   * If non-NULL, the pooled PBN lock held on the allocated block. Must be a
Packit Service 310c69
   * write lock until the block has been written, after which it will become a
Packit Service 310c69
   * read lock.
Packit Service 310c69
   **/
Packit Service 310c69
  PBNLock            *allocationLock;
Packit Service 310c69
Packit Service 310c69
  /** The type of write lock to obtain on the allocated block */
Packit Service 310c69
  PBNLockType         writeLockType;
Packit Service 310c69
Packit Service 310c69
  /** The number of zones in which this VIO has attempted an allocation */
Packit Service 310c69
  ZoneCount           allocationAttempts;
Packit Service 310c69
Packit Service 310c69
  /** Whether this VIO should wait for a clean slab */
Packit Service 310c69
  bool                waitForCleanSlab;
Packit Service 310c69
Packit Service 310c69
  /** The function to call once allocation is complete */
Packit Service 310c69
  AllocationCallback *allocationCallback;
Packit Service 310c69
};
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Convert a VIO to an AllocatingVIO.
Packit Service 310c69
 *
Packit Service 310c69
 * @param vio  The VIO to convert
Packit Service 310c69
 *
Packit Service 310c69
 * @return The VIO as an AllocatingVIO
Packit Service 310c69
 **/
Packit Service 310c69
static inline AllocatingVIO *vioAsAllocatingVIO(VIO *vio)
Packit Service 310c69
{
Packit Service 310c69
  STATIC_ASSERT(offsetof(AllocatingVIO, vio) == 0);
Packit Service 310c69
  ASSERT_LOG_ONLY(((vio->type == VIO_TYPE_DATA)
Packit Service 310c69
                   || (vio->type == VIO_TYPE_COMPRESSED_BLOCK)),
Packit Service 310c69
                  "VIO is an AllocatingVIO");
Packit Service 310c69
  return (AllocatingVIO *) vio;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Convert an AllocatingVIO to a VIO.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The AllocatingVIO to convert
Packit Service 310c69
 *
Packit Service 310c69
 * @return The AllocatingVIO as a VIO
Packit Service 310c69
 **/
Packit Service 310c69
static inline VIO *allocatingVIOAsVIO(AllocatingVIO *allocatingVIO)
Packit Service 310c69
{
Packit Service 310c69
  return &allocatingVIO->vio;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Convert a generic VDOCompletion to an AllocatingVIO.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion to convert
Packit Service 310c69
 *
Packit Service 310c69
 * @return The completion as an AllocatingVIO
Packit Service 310c69
 **/
Packit Service 310c69
static inline AllocatingVIO *asAllocatingVIO(VDOCompletion *completion)
Packit Service 310c69
{
Packit Service 310c69
  return vioAsAllocatingVIO(asVIO(completion));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Convert an AllocatingVIO to a generic completion.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The AllocatingVIO to convert
Packit Service 310c69
 *
Packit Service 310c69
 * @return The AllocatingVIO as a completion
Packit Service 310c69
 **/
Packit Service 310c69
static inline
Packit Service 310c69
VDOCompletion *allocatingVIOAsCompletion(AllocatingVIO *allocatingVIO)
Packit Service 310c69
{
Packit Service 310c69
  return vioAsCompletion(allocatingVIOAsVIO(allocatingVIO));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Convert an AllocatingVIO to a generic wait queue entry.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The AllocatingVIO to convert
Packit Service 310c69
 *
Packit Service 310c69
 * @return The AllocatingVIO as a wait queue entry
Packit Service 310c69
 **/
Packit Service 310c69
static inline Waiter *allocatingVIOAsWaiter(AllocatingVIO *allocatingVIO)
Packit Service 310c69
{
Packit Service 310c69
  return &allocatingVIO->waiter;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Convert an AllocatingVIO's generic wait queue entry back to the
Packit Service 310c69
 * AllocatingVIO.
Packit Service 310c69
 *
Packit Service 310c69
 * @param waiter  The wait queue entry to convert
Packit Service 310c69
 *
Packit Service 310c69
 * @return The wait queue entry as an AllocatingVIO
Packit Service 310c69
 **/
Packit Service 310c69
static inline AllocatingVIO *waiterAsAllocatingVIO(Waiter *waiter)
Packit Service 310c69
{
Packit Service 310c69
  if (waiter == NULL) {
Packit Service 310c69
    return NULL;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return
Packit Service 310c69
    (AllocatingVIO *) ((uintptr_t) waiter - offsetof(AllocatingVIO, waiter));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Check whether an AllocatingVIO is a compressed block write.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The AllocatingVIO to check
Packit Service 310c69
 *
Packit Service 310c69
 * @return true if the AllocatingVIO is a compressed block write
Packit Service 310c69
 **/
Packit Service 310c69
static inline bool isCompressedWriteAllocatingVIO(AllocatingVIO *allocatingVIO)
Packit Service 310c69
{
Packit Service 310c69
  return isCompressedWriteVIO(allocatingVIOAsVIO(allocatingVIO));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Add a trace record for the current source location.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The AllocatingVIO structure to be updated
Packit Service 310c69
 * @param location       The source-location descriptor to be recorded
Packit Service 310c69
 **/
Packit Service 310c69
static inline void allocatingVIOAddTraceRecord(AllocatingVIO *allocatingVIO,
Packit Service 310c69
                                               TraceLocation  location)
Packit Service 310c69
{
Packit Service 310c69
  vioAddTraceRecord(allocatingVIOAsVIO(allocatingVIO), location);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Get the VDO from an AllocatingVIO.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The AllocatingVIO from which to get the VDO
Packit Service 310c69
 *
Packit Service 310c69
 * @return The VDO to which an AllocatingVIO belongs
Packit Service 310c69
 **/
Packit Service 310c69
static inline VDO *getVDOFromAllocatingVIO(AllocatingVIO *allocatingVIO)
Packit Service 310c69
{
Packit Service 310c69
  return allocatingVIOAsVIO(allocatingVIO)->vdo;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Check that an AllocatingVIO is running on the physical zone thread in
Packit Service 310c69
 * which it did its allocation.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The AllocatingVIO in question
Packit Service 310c69
 **/
Packit Service 310c69
static inline void assertInPhysicalZone(AllocatingVIO *allocatingVIO)
Packit Service 310c69
{
Packit Service 310c69
  ThreadID expected = getPhysicalZoneThreadID(allocatingVIO->zone);
Packit Service 310c69
  ThreadID threadID = getCallbackThreadID();
Packit Service 310c69
  ASSERT_LOG_ONLY((expected == threadID),
Packit Service 310c69
                  "AllocatingVIO for allocated physical block %" PRIu64
Packit Service 310c69
                  " on thread %u, should be on thread %u",
Packit Service 310c69
                  allocatingVIO->allocation, threadID, expected);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Set a callback as a physical block operation in an AllocatingVIO's allocated
Packit Service 310c69
 * zone.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The AllocatingVIO
Packit Service 310c69
 * @param callback       The callback to set
Packit Service 310c69
 * @param location       The tracing info for the call site
Packit Service 310c69
 **/
Packit Service 310c69
static inline void setPhysicalZoneCallback(AllocatingVIO *allocatingVIO,
Packit Service 310c69
                                           VDOAction     *callback,
Packit Service 310c69
                                           TraceLocation  location)
Packit Service 310c69
{
Packit Service 310c69
  setCallback(allocatingVIOAsCompletion(allocatingVIO), callback,
Packit Service 310c69
              getPhysicalZoneThreadID(allocatingVIO->zone));
Packit Service 310c69
  allocatingVIOAddTraceRecord(allocatingVIO, location);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Set a callback as a physical block operation in an AllocatingVIO's allocated
Packit Service 310c69
 * zone and invoke it immediately.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The AllocatingVIO
Packit Service 310c69
 * @param callback       The callback to invoke
Packit Service 310c69
 * @param location       The tracing info for the call site
Packit Service 310c69
 **/
Packit Service 310c69
static inline void launchPhysicalZoneCallback(AllocatingVIO *allocatingVIO,
Packit Service 310c69
                                              VDOAction     *callback,
Packit Service 310c69
                                              TraceLocation  location)
Packit Service 310c69
{
Packit Service 310c69
  setPhysicalZoneCallback(allocatingVIO, callback, location);
Packit Service 310c69
  invokeCallback(allocatingVIOAsCompletion(allocatingVIO));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Allocate a data block to an AllocatingVIO.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The AllocatingVIO which needs an allocation
Packit Service 310c69
 * @param selector       The allocation selector for deciding which physical
Packit Service 310c69
 *                       zone to allocate from
Packit Service 310c69
 * @param writeLockType  The type of write lock to obtain on the block
Packit Service 310c69
 * @param callback       The function to call once the allocation is complete
Packit Service 310c69
 **/
Packit Service 310c69
void allocateDataBlock(AllocatingVIO      *allocatingVIO,
Packit Service 310c69
                       AllocationSelector *selector,
Packit Service 310c69
                       PBNLockType         writeLockType,
Packit Service 310c69
                       AllocationCallback *callback);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Release the PBN lock on the allocated block. If the reference to the locked
Packit Service 310c69
 * block is still provisional, it will be released as well.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The lock holder
Packit Service 310c69
 **/
Packit Service 310c69
void releaseAllocationLock(AllocatingVIO *allocatingVIO);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Reset an AllocatingVIO after it has done an allocation.
Packit Service 310c69
 *
Packit Service 310c69
 * @param allocatingVIO  The AllocatingVIO
Packit Service 310c69
 **/
Packit Service 310c69
void resetAllocation(AllocatingVIO *allocatingVIO);
Packit Service 310c69
Packit Service 310c69
#endif // ALLOCATING_VIO_H