Blame source/vdo/base/completion.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/completion.h#11 $
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#ifndef COMPLETION_H
Packit Service 310c69
#define COMPLETION_H
Packit Service 310c69
Packit Service 310c69
#include "permassert.h"
Packit Service 310c69
Packit Service 310c69
#include "physicalLayer.h"
Packit Service 310c69
#include "ringNode.h"
Packit Service 310c69
#include "types.h"
Packit Service 310c69
Packit Service 310c69
typedef enum __attribute__((packed)) {
Packit Service 310c69
  // Keep UNSET_COMPLETION_TYPE at the top.
Packit Service 310c69
  UNSET_COMPLETION_TYPE = 0,
Packit Service 310c69
Packit Service 310c69
  // Keep the rest of these in sorted order. If you add or remove an entry,
Packit Service 310c69
  // be sure to update the corresponding list in completion.c.
Packit Service 310c69
  ACTION_COMPLETION,
Packit Service 310c69
  ADMIN_COMPLETION,
Packit Service 310c69
  ASYNC_ACTION_CONTEXT,
Packit Service 310c69
  BLOCK_ALLOCATOR_COMPLETION,
Packit Service 310c69
  BLOCK_MAP_RECOVERY_COMPLETION,
Packit Service 310c69
  CHECK_IDENTIFIER_COMPLETION,
Packit Service 310c69
  EXTERNAL_COMPLETION,
Packit Service 310c69
  FLUSH_NOTIFICATION_COMPLETION,
Packit Service 310c69
  GENERATION_FLUSHED_COMPLETION,
Packit Service 310c69
  HEARTBEAT_COMPLETION,
Packit Service 310c69
  LOCK_COUNTER_COMPLETION,
Packit Service 310c69
  PARTITION_COPY_COMPLETION,
Packit Service 310c69
  READ_ONLY_MODE_COMPLETION,
Packit Service 310c69
  READ_ONLY_REBUILD_COMPLETION,
Packit Service 310c69
  RECOVERY_COMPLETION,
Packit Service 310c69
  REFERENCE_COUNT_REBUILD_COMPLETION,
Packit Service 310c69
  SLAB_SCRUBBER_COMPLETION,
Packit Service 310c69
  SUB_TASK_COMPLETION,
Packit Service 310c69
  TEST_COMPLETION,                      // each unit test may define its own
Packit Service 310c69
  VDO_COMMAND_COMPLETION,
Packit Service 310c69
  VDO_COMMAND_SUB_COMPLETION,
Packit Service 310c69
  VDO_EXTENT_COMPLETION,
Packit Service 310c69
  VDO_PAGE_COMPLETION,
Packit Service 310c69
  VIO_COMPLETION,
Packit Service 310c69
  WRAPPING_COMPLETION,
Packit Service 310c69
Packit Service 310c69
  // Keep MAX_COMPLETION_TYPE at the bottom.
Packit Service 310c69
  MAX_COMPLETION_TYPE
Packit Service 310c69
} VDOCompletionType;
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * An asynchronous VDO operation.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion    the completion of the operation
Packit Service 310c69
 **/
Packit Service 310c69
typedef void VDOAction(VDOCompletion *completion);
Packit Service 310c69
Packit Service 310c69
struct vdoCompletion {
Packit Service 310c69
  /** The type of completion this is */
Packit Service 310c69
  VDOCompletionType  type;
Packit Service 310c69
Packit Service 310c69
  /**
Packit Service 310c69
   * true once the processing of the operation is complete.
Packit Service 310c69
   * This flag should not be used by waiters external to the VDO base as
Packit Service 310c69
   * it is used to gate calling the callback.
Packit Service 310c69
   **/
Packit Service 310c69
  bool               complete;
Packit Service 310c69
Packit Service 310c69
  /**
Packit Service 310c69
   * If true, queue this completion on the next callback invocation, even if
Packit Service 310c69
   * it is already running on the correct thread.
Packit Service 310c69
   **/
Packit Service 310c69
  bool               requeue;
Packit Service 310c69
Packit Service 310c69
  /** The ID of the thread which should run the next callback */
Packit Service 310c69
  ThreadID           callbackThreadID;
Packit Service 310c69
Packit Service 310c69
  /** The result of the operation */
Packit Service 310c69
  int                result;
Packit Service 310c69
Packit Service 310c69
  /** The physical layer on which this completion operates */
Packit Service 310c69
  PhysicalLayer     *layer;
Packit Service 310c69
Packit Service 310c69
  /** The callback which will be called once the operation is complete */
Packit Service 310c69
  VDOAction         *callback;
Packit Service 310c69
Packit Service 310c69
  /** The callback which, if set, will be called if an error result is set */
Packit Service 310c69
  VDOAction         *errorHandler;
Packit Service 310c69
Packit Service 310c69
  /** The parent object, if any, that spawned this completion */
Packit Service 310c69
  void              *parent;
Packit Service 310c69
Packit Service 310c69
  /** The enqueueable for this completion (may be NULL) */
Packit Service 310c69
  Enqueueable       *enqueueable;
Packit Service 310c69
};
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Actually run the callback. This function must be called from the correct
Packit Service 310c69
 * callback thread.
Packit Service 310c69
 **/
Packit Service 310c69
static inline void runCallback(VDOCompletion *completion)
Packit Service 310c69
{
Packit Service 310c69
  if ((completion->result != VDO_SUCCESS)
Packit Service 310c69
      && (completion->errorHandler != NULL)) {
Packit Service 310c69
    completion->errorHandler(completion);
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  completion->callback(completion);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Set the result of a completion. Older errors will not be masked.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion The completion whose result is to be set
Packit Service 310c69
 * @param result     The result to set
Packit Service 310c69
 **/
Packit Service 310c69
void setCompletionResult(VDOCompletion *completion, int result);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Initialize a completion to a clean state, for reused completions.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion The completion to initialize
Packit Service 310c69
 * @param type       The type of the completion
Packit Service 310c69
 * @param layer      The physical layer of the completion
Packit Service 310c69
 **/
Packit Service 310c69
void initializeCompletion(VDOCompletion      *completion,
Packit Service 310c69
                          VDOCompletionType   type,
Packit Service 310c69
                          PhysicalLayer      *layer);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Initialize a completion to a clean state and make an enqueueable for it.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion The completion to initialize
Packit Service 310c69
 * @param type       The type of the completion
Packit Service 310c69
 * @param layer      The physical layer of the completion
Packit Service 310c69
 *
Packit Service 310c69
 * @return VDO_SUCCESS or an error
Packit Service 310c69
 **/
Packit Service 310c69
int initializeEnqueueableCompletion(VDOCompletion      *completion,
Packit Service 310c69
                                    VDOCompletionType   type,
Packit Service 310c69
                                    PhysicalLayer      *layer)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Reset a completion to a clean state, while keeping
Packit Service 310c69
 * the type, layer and parent information.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion the completion to reset
Packit Service 310c69
 **/
Packit Service 310c69
void resetCompletion(VDOCompletion *completion);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Invoke the callback of a completion. If called on the correct thread (i.e.
Packit Service 310c69
 * the one specified in the completion's callbackThreadID field), the
Packit Service 310c69
 * completion will be run immediately. Otherwise, the completion will be
Packit Service 310c69
 * enqueued on the correct callback thread.
Packit Service 310c69
 **/
Packit Service 310c69
void invokeCallback(VDOCompletion *completion);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Continue processing a completion by setting the current result and calling
Packit Service 310c69
 * invokeCallback().
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion to continue
Packit Service 310c69
 * @param result      The current result (will not mask older errors)
Packit Service 310c69
 **/
Packit Service 310c69
void continueCompletion(VDOCompletion *completion, int result);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Complete a completion.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion to complete
Packit Service 310c69
 **/
Packit Service 310c69
void completeCompletion(VDOCompletion *completion);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Finish a completion.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion The completion to finish
Packit Service 310c69
 * @param result     The result of the completion (will not mask older errors)
Packit Service 310c69
 **/
Packit Service 310c69
static inline void finishCompletion(VDOCompletion *completion, int result)
Packit Service 310c69
{
Packit Service 310c69
  setCompletionResult(completion, result);
Packit Service 310c69
  completeCompletion(completion);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Complete a completion and NULL out the reference to it.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completionPtr  A pointer to the completion to release
Packit Service 310c69
 **/
Packit Service 310c69
void releaseCompletion(VDOCompletion **completionPtr);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Finish a completion and NULL out the reference to it.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completionPtr  A pointer to the completion to release
Packit Service 310c69
 * @param result         The result of the completion
Packit Service 310c69
 **/
Packit Service 310c69
void releaseCompletionWithResult(VDOCompletion **completionPtr, int result);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * A callback to finish the parent of a completion.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion which has finished and whose parent should
Packit Service 310c69
 *                    be finished
Packit Service 310c69
 **/
Packit Service 310c69
void finishParentCallback(VDOCompletion *completion);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Error handler which preserves an error in the parent (if there is one),
Packit Service 310c69
 * and then resets the failing completion and calls its non-error callback.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion which failed
Packit Service 310c69
 **/
Packit Service 310c69
void preserveErrorAndContinue(VDOCompletion *completion);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * A callback which does nothing. This callback is intended to be set as an
Packit Service 310c69
 * error handler in the case where an error should do nothing.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion being called back
Packit Service 310c69
 **/
Packit Service 310c69
static inline
Packit Service 310c69
void noopCallback(VDOCompletion *completion __attribute__((unused)))
Packit Service 310c69
{
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Destroy the enqueueable associated with this completion.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion
Packit Service 310c69
 **/
Packit Service 310c69
void destroyEnqueueable(VDOCompletion *completion);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Assert that a completion is of the correct type
Packit Service 310c69
 *
Packit Service 310c69
 * @param actual    The actual completion type
Packit Service 310c69
 * @param expected  The expected completion type
Packit Service 310c69
 *
Packit Service 310c69
 * @return          VDO_SUCCESS or VDO_PARAMETER_MISMATCH
Packit Service 310c69
 **/
Packit Service 310c69
int assertCompletionType(VDOCompletionType actual,
Packit Service 310c69
                         VDOCompletionType expected);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Return the name of a completion type.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completionType        the completion type
Packit Service 310c69
 *
Packit Service 310c69
 * @return a pointer to a static string; if the completionType is unknown
Packit Service 310c69
 *         this is to a static buffer that may be overwritten.
Packit Service 310c69
 **/
Packit Service 310c69
const char *getCompletionTypeName(VDOCompletionType completionType);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Set the callback for a completion.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion
Packit Service 310c69
 * @param callback    The callback to register
Packit Service 310c69
 * @param threadID    The ID of the thread on which the callback should run
Packit Service 310c69
 **/
Packit Service 310c69
static inline void setCallback(VDOCompletion *completion,
Packit Service 310c69
                               VDOAction     *callback,
Packit Service 310c69
                               ThreadID       threadID)
Packit Service 310c69
{
Packit Service 310c69
  completion->callback         = callback;
Packit Service 310c69
  completion->callbackThreadID = threadID;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Set the callback for a completion and invoke it immediately.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion
Packit Service 310c69
 * @param callback    The callback to register
Packit Service 310c69
 * @param threadID    The ID of the thread on which the callback should run
Packit Service 310c69
 **/
Packit Service 310c69
static inline void launchCallback(VDOCompletion *completion,
Packit Service 310c69
                                  VDOAction     *callback,
Packit Service 310c69
                                  ThreadID       threadID)
Packit Service 310c69
{
Packit Service 310c69
  setCallback(completion, callback, threadID);
Packit Service 310c69
  invokeCallback(completion);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Set the callback and parent for a completion.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion
Packit Service 310c69
 * @param callback    The callback to register
Packit Service 310c69
 * @param threadID    The ID of the thread on which the callback should run
Packit Service 310c69
 * @param parent      The new parent of the completion
Packit Service 310c69
 **/
Packit Service 310c69
static inline void setCallbackWithParent(VDOCompletion *completion,
Packit Service 310c69
                                         VDOAction     *callback,
Packit Service 310c69
                                         ThreadID       threadID,
Packit Service 310c69
                                         void          *parent)
Packit Service 310c69
{
Packit Service 310c69
  setCallback(completion, callback, threadID);
Packit Service 310c69
  completion->parent = parent;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Set the callback and parent for a completion and invoke the callback
Packit Service 310c69
 * immediately.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion
Packit Service 310c69
 * @param callback    The callback to register
Packit Service 310c69
 * @param threadID    The ID of the thread on which the callback should run
Packit Service 310c69
 * @param parent      The new parent of the completion
Packit Service 310c69
 **/
Packit Service 310c69
static inline void launchCallbackWithParent(VDOCompletion *completion,
Packit Service 310c69
                                            VDOAction     *callback,
Packit Service 310c69
                                            ThreadID       threadID,
Packit Service 310c69
                                            void          *parent)
Packit Service 310c69
{
Packit Service 310c69
  setCallbackWithParent(completion, callback, threadID, parent);
Packit Service 310c69
  invokeCallback(completion);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Prepare a completion for launch. Reset it, and then set its callback, error
Packit Service 310c69
 * handler, callback thread, and parent.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion    The completion
Packit Service 310c69
 * @param callback      The callback to register
Packit Service 310c69
 * @param errorHandler  The error handler to register
Packit Service 310c69
 * @param threadID      The ID of the thread on which the callback should run
Packit Service 310c69
 * @param parent        The new parent of the completion
Packit Service 310c69
 **/
Packit Service 310c69
static inline void prepareCompletion(VDOCompletion *completion,
Packit Service 310c69
                                     VDOAction     *callback,
Packit Service 310c69
                                     VDOAction     *errorHandler,
Packit Service 310c69
                                     ThreadID       threadID,
Packit Service 310c69
                                     void          *parent)
Packit Service 310c69
{
Packit Service 310c69
  resetCompletion(completion);
Packit Service 310c69
  setCallbackWithParent(completion, callback, threadID, parent);
Packit Service 310c69
  completion->errorHandler = errorHandler;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Prepare a completion for launch ensuring that it will always be requeued.
Packit Service 310c69
 * Reset it, and then set its callback, error handler, callback thread, and
Packit Service 310c69
 * parent.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion    The completion
Packit Service 310c69
 * @param callback      The callback to register
Packit Service 310c69
 * @param errorHandler  The error handler to register
Packit Service 310c69
 * @param threadID      The ID of the thread on which the callback should run
Packit Service 310c69
 * @param parent        The new parent of the completion
Packit Service 310c69
 **/
Packit Service 310c69
static inline void prepareForRequeue(VDOCompletion *completion,
Packit Service 310c69
                                     VDOAction     *callback,
Packit Service 310c69
                                     VDOAction     *errorHandler,
Packit Service 310c69
                                     ThreadID       threadID,
Packit Service 310c69
                                     void          *parent)
Packit Service 310c69
{
Packit Service 310c69
  prepareCompletion(completion, callback, errorHandler, threadID, parent);
Packit Service 310c69
  completion->requeue = true;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Prepare a completion for launch which will complete its parent when
Packit Service 310c69
 * finished.
Packit Service 310c69
 *
Packit Service 310c69
 * @param completion  The completion
Packit Service 310c69
 * @param parent      The parent to complete
Packit Service 310c69
 **/
Packit Service 310c69
static inline void prepareToFinishParent(VDOCompletion *completion,
Packit Service 310c69
                                         VDOCompletion *parent)
Packit Service 310c69
{
Packit Service 310c69
  prepareCompletion(completion, finishParentCallback, finishParentCallback,
Packit Service 310c69
                    parent->callbackThreadID, parent);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
#endif // COMPLETION_H