Blame vdo/kernel/workQueue.h

Packit Service 693862
/*
Packit Service 693862
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 693862
 *
Packit Service 693862
 * This program is free software; you can redistribute it and/or
Packit Service 693862
 * modify it under the terms of the GNU General Public License
Packit Service 693862
 * as published by the Free Software Foundation; either version 2
Packit Service 693862
 * of the License, or (at your option) any later version.
Packit Service 693862
 * 
Packit Service 693862
 * This program is distributed in the hope that it will be useful,
Packit Service 693862
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 693862
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 693862
 * GNU General Public License for more details.
Packit Service 693862
 * 
Packit Service 693862
 * You should have received a copy of the GNU General Public License
Packit Service 693862
 * along with this program; if not, write to the Free Software
Packit Service 693862
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 693862
 * 02110-1301, USA. 
Packit Service 693862
 *
Packit Service 693862
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/kernel/workQueue.h#2 $
Packit Service 693862
 */
Packit Service 693862
Packit Service 693862
#ifndef ALBIREO_WORK_QUEUE_H
Packit Service 693862
#define ALBIREO_WORK_QUEUE_H
Packit Service 693862
Packit Service 693862
#include <linux/kobject.h>
Packit Service 693862
#include <linux/sched.h>        /* for TASK_COMM_LEN */
Packit Service 693862
Packit Service 693862
#include "kernelTypes.h"
Packit Service 693862
#include "util/funnelQueue.h"
Packit Service 693862
Packit Service 693862
enum {
Packit Service 693862
  MAX_QUEUE_NAME_LEN        = TASK_COMM_LEN,
Packit Service 693862
  /** Maximum number of action definitions per work queue type */
Packit Service 693862
  WORK_QUEUE_ACTION_COUNT   = 8,
Packit Service 693862
  /** Number of priority values available */
Packit Service 693862
  WORK_QUEUE_PRIORITY_COUNT = 4,
Packit Service 693862
};
Packit Service 693862
Packit Service 693862
struct kvdoWorkItem {
Packit Service 693862
  /** Entry link for lock-free work queue */
Packit Service 693862
  FunnelQueueEntry  workQueueEntryLink;
Packit Service 693862
  /** Function to be called */
Packit Service 693862
  KvdoWorkFunction  work;
Packit Service 693862
  /** Optional alternate function for display in queue stats */
Packit Service 693862
  void             *statsFunction;
Packit Service 693862
  /** An index into the statistics table; filled in by workQueueStats code */
Packit Service 693862
  unsigned int      statTableIndex;
Packit Service 693862
  /**
Packit Service 693862
   * The action code given to setupWorkItem, from which a priority will be
Packit Service 693862
   * determined.
Packit Service 693862
   **/
Packit Service 693862
  unsigned int      action;
Packit Service 693862
  /** The work queue in which the item is enqueued, or NULL if not enqueued. */
Packit Service 693862
  KvdoWorkQueue    *myQueue;
Packit Service 693862
  /**
Packit Service 693862
   * Time at which to execute in jiffies for a delayed work item, or zero to
Packit Service 693862
   * queue for execution ASAP.
Packit Service 693862
   **/
Packit Service 693862
  Jiffies           executionTime;
Packit Service 693862
  /** List management for delayed or expired work items */
Packit Service 693862
  KvdoWorkItem     *next;
Packit Service 693862
  /** Time of enqueueing, in ns, for recording queue (waiting) time stats */
Packit Service 693862
  uint64_t          enqueueTime;
Packit Service 693862
};
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Table entries defining an action.
Packit Service 693862
 *
Packit Service 693862
 * Actions are intended to distinguish general classes of activity for
Packit Service 693862
 * prioritization purposes, but not necessarily to indicate specific work
Packit Service 693862
 * functions. They are indicated to setupWorkItem numerically, using an
Packit Service 693862
 * enumerator defined per kind of work queue -- bio submission work queue
Packit Service 693862
 * actions use BioQAction, cpu actions use CPUQAction, etc. For example, for
Packit Service 693862
 * the CPU work queues, data compression can be prioritized separately from
Packit Service 693862
 * final cleanup processing of a KVIO or from dedupe verification; base code
Packit Service 693862
 * threads prioritize all VIO callback invocation the same, but separate from
Packit Service 693862
 * sync or heartbeat operations. The bio acknowledgement work queue, on the
Packit Service 693862
 * other hand, only does one thing, so it only defines one action code.
Packit Service 693862
 *
Packit Service 693862
 * Action codes values must be small integers, 0 through
Packit Service 693862
 * WORK_QUEUE_ACTION_COUNT-1, and should not be duplicated for a queue type.
Packit Service 693862
 *
Packit Service 693862
 * A table of KvdoWorkQueueAction entries embedded in KvdoWorkQueueType
Packit Service 693862
 * specifies the name, code, and priority for each type of action in the work
Packit Service 693862
 * queue. The table can have at most WORK_QUEUE_ACTION_COUNT entries, but a
Packit Service 693862
 * NULL name indicates an earlier end to the table.
Packit Service 693862
 *
Packit Service 693862
 * Priorities may be specified as values from 0 through
Packit Service 693862
 * WORK_QUEUE_PRIORITY_COUNT-1, higher values indicating higher priority.
Packit Service 693862
 * Priorities are just strong suggestions; it's possible for a lower-priority
Packit Service 693862
 * work item scheduled right after a high-priority one to be run first, if the
Packit Service 693862
 * worker thread happens to be scanning its queues at just the wrong moment,
Packit Service 693862
 * but the high-priority item will be picked up next.
Packit Service 693862
 *
Packit Service 693862
 * Internally, the priorities in this table are used to initialize another
Packit Service 693862
 * table in the constructed work queue object, and in internal builds,
Packit Service 693862
 * device-mapper messages can be sent to change the priority for an action,
Packit Service 693862
 * identified by name, in a running VDO device. Doing so does not affect the
Packit Service 693862
 * priorities for other devices, or for future VDO device creation.
Packit Service 693862
 **/
Packit Service 693862
typedef struct kvdoWorkQueueAction {
Packit Service 693862
  /** Name of the action */
Packit Service 693862
  char         *name;
Packit Service 693862
Packit Service 693862
  /** The action code (per-type enum) */
Packit Service 693862
  unsigned int  code;
Packit Service 693862
Packit Service 693862
  /** The initial priority for this action */
Packit Service 693862
  unsigned int  priority;
Packit Service 693862
} KvdoWorkQueueAction;
Packit Service 693862
Packit Service 693862
typedef void (*KvdoWorkQueueFunction)(void *);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Static attributes of a work queue that are fixed at compile time
Packit Service 693862
 * for a given call site. (Attributes that may be computed at run time
Packit Service 693862
 * are passed as separate arguments.)
Packit Service 693862
 **/
Packit Service 693862
typedef struct kvdoWorkQueueType {
Packit Service 693862
  /** A function to call in the new thread before servicing requests */
Packit Service 693862
  KvdoWorkQueueFunction start;
Packit Service 693862
Packit Service 693862
  /** A function to call in the new thread when shutting down */
Packit Service 693862
  KvdoWorkQueueFunction finish;
Packit Service 693862
Packit Service 693862
  /** A function to call in the new thread after running out of work */
Packit Service 693862
  KvdoWorkQueueFunction suspend;
Packit Service 693862
Packit Service 693862
  /** Table of actions for this work queue */
Packit Service 693862
  KvdoWorkQueueAction   actionTable[WORK_QUEUE_ACTION_COUNT];
Packit Service 693862
} KvdoWorkQueueType;
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Create a work queue.
Packit Service 693862
 *
Packit Service 693862
 * If multiple threads are requested, work items will be distributed to them in
Packit Service 693862
 * round-robin fashion.
Packit Service 693862
 *
Packit Service 693862
 * @param [in]  threadNamePrefix The per-device prefix to use in thread names
Packit Service 693862
 * @param [in]  name             The queue name
Packit Service 693862
 * @param [in]  parentKobject    The parent sysfs node
Packit Service 693862
 * @param [in]  owner            The kernel layer owning the work queue
Packit Service 693862
 * @param [in]  private          Private data of the queue for use by work
Packit Service 693862
 *                               items or other queue-specific functions
Packit Service 693862
 * @param [in]  type             The work queue type defining the lifecycle
Packit Service 693862
 *                               functions, queue actions, priorities, and
Packit Service 693862
 *                               timeout behavior
Packit Service 693862
 * @param [in]  threadCount      Number of service threads to set up
Packit Service 693862
 * @param [out] queuePtr         Where to store the queue handle
Packit Service 693862
 *
Packit Service 693862
 * @return VDO_SUCCESS or an error code
Packit Service 693862
 **/
Packit Service 693862
int makeWorkQueue(const char               *threadNamePrefix,
Packit Service 693862
                  const char               *name,
Packit Service 693862
                  struct kobject           *parentKobject,
Packit Service 693862
                  KernelLayer              *owner,
Packit Service 693862
                  void                     *private,
Packit Service 693862
                  const KvdoWorkQueueType  *type,
Packit Service 693862
                  unsigned int              threadCount,
Packit Service 693862
                  KvdoWorkQueue           **queuePtr);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Set up the fields of a work queue item.
Packit Service 693862
 *
Packit Service 693862
 * Before the first setup call (setupWorkItem or setupWorkItemWithTimeout), the
Packit Service 693862
 * work item must have been initialized to all-zero. Resetting a
Packit Service 693862
 * previously-used work item does not require another memset.
Packit Service 693862
 *
Packit Service 693862
 * The action code is typically defined in a work-queue-type-specific
Packit Service 693862
 * enumeration; see the description of KvdoWorkQueueAction.
Packit Service 693862
 *
Packit Service 693862
 * @param item           The work item to initialize
Packit Service 693862
 * @param work           The function pointer to execute
Packit Service 693862
 * @param statsFunction  A function pointer to record for stats, or NULL
Packit Service 693862
 * @param action         Action code, for determination of priority
Packit Service 693862
 **/
Packit Service 693862
void setupWorkItem(KvdoWorkItem     *item,
Packit Service 693862
                   KvdoWorkFunction  work,
Packit Service 693862
                   void             *statsFunction,
Packit Service 693862
                   unsigned int      action);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Add a work item to a work queue.
Packit Service 693862
 *
Packit Service 693862
 * If the work item has a timeout that has already passed, the timeout
Packit Service 693862
 * handler function may be invoked at this time.
Packit Service 693862
 *
Packit Service 693862
 * @param queue      The queue handle
Packit Service 693862
 * @param item       The work item to be processed
Packit Service 693862
 **/
Packit Service 693862
void enqueueWorkQueue(KvdoWorkQueue *queue, KvdoWorkItem *item);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Add a work item to a work queue, to be run at a later point in time.
Packit Service 693862
 *
Packit Service 693862
 * Currently delayed work items are used only in a very limited fashion -- at
Packit Service 693862
 * most one at a time for any of the work queue types that use them -- and some
Packit Service 693862
 * shortcuts have been taken that assume that that's the case. Multiple delayed
Packit Service 693862
 * work items should work, but they will execute in the order they were
Packit Service 693862
 * enqueued.
Packit Service 693862
 *
Packit Service 693862
 * @param queue           The queue handle
Packit Service 693862
 * @param item            The work item to be processed
Packit Service 693862
 * @param executionTime   When to run the work item (jiffies)
Packit Service 693862
 **/
Packit Service 693862
void enqueueWorkQueueDelayed(KvdoWorkQueue *queue,
Packit Service 693862
                             KvdoWorkItem  *item,
Packit Service 693862
                             Jiffies        executionTime);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Shut down a work queue's worker thread.
Packit Service 693862
 *
Packit Service 693862
 * Alerts the worker thread that it should shut down, and then waits
Packit Service 693862
 * for it to do so.
Packit Service 693862
 *
Packit Service 693862
 * There should not be any new enqueueing of work items done once this
Packit Service 693862
 * function is called. Any pending delayed work items will be
Packit Service 693862
 * processed, as scheduled, before the worker thread shuts down, but
Packit Service 693862
 * they must not re-queue themselves to run again.
Packit Service 693862
 *
Packit Service 693862
 * @param queue  The work queue to shut down
Packit Service 693862
 **/
Packit Service 693862
void finishWorkQueue(KvdoWorkQueue *queue);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Free a work queue and null out the reference to it.
Packit Service 693862
 *
Packit Service 693862
 * @param queuePtr  Where the queue handle is found
Packit Service 693862
 **/
Packit Service 693862
void freeWorkQueue(KvdoWorkQueue **queuePtr);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Print work queue state and statistics to the kernel log.
Packit Service 693862
 *
Packit Service 693862
 * @param queue  The work queue to examine
Packit Service 693862
 **/
Packit Service 693862
void dumpWorkQueue(KvdoWorkQueue *queue);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Write to the buffer some info about the work item, for logging.
Packit Service 693862
 * Since the common use case is dumping info about a lot of work items
Packit Service 693862
 * to syslog all at once, the format favors brevity over readability.
Packit Service 693862
 *
Packit Service 693862
 * @param item    The work item
Packit Service 693862
 * @param buffer  The message buffer to fill in
Packit Service 693862
 * @param length  The length of the message buffer
Packit Service 693862
 **/
Packit Service 693862
void dumpWorkItemToBuffer(KvdoWorkItem *item, char *buffer, size_t length);
Packit Service 693862
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Initialize work queue internals at module load time.
Packit Service 693862
 **/
Packit Service 693862
void initWorkQueueOnce(void);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Checks whether two work items have the same action codes
Packit Service 693862
 *
Packit Service 693862
 * @param item1 The first item
Packit Service 693862
 * @param item2 The second item
Packit Service 693862
 *
Packit Service 693862
 * @return TRUE if the actions are the same, FALSE otherwise
Packit Service 693862
 */
Packit Service 693862
static inline bool areWorkItemActionsEqual(KvdoWorkItem *item1,
Packit Service 693862
                                           KvdoWorkItem *item2)
Packit Service 693862
{
Packit Service 693862
  return item1->action == item2->action;
Packit Service 693862
}
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Returns the private data for the current thread's work queue.
Packit Service 693862
 *
Packit Service 693862
 * @return  The private data pointer, or NULL if none or if the current
Packit Service 693862
 *          thread is not a work queue thread.
Packit Service 693862
 **/
Packit Service 693862
void *getWorkQueuePrivateData(void);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Updates the private data pointer for the current thread's work queue.
Packit Service 693862
 *
Packit Service 693862
 * @param newData  The new private data pointer
Packit Service 693862
 **/
Packit Service 693862
void setWorkQueuePrivateData(void *newData);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Returns the work queue pointer for the current thread, if any.
Packit Service 693862
 *
Packit Service 693862
 * @return   The work queue pointer or NULL
Packit Service 693862
 **/
Packit Service 693862
KvdoWorkQueue *getCurrentWorkQueue(void);
Packit Service 693862
Packit Service 693862
/**
Packit Service 693862
 * Returns the kernel layer that owns the work queue.
Packit Service 693862
 *
Packit Service 693862
 * @param queue  The work queue
Packit Service 693862
 *
Packit Service 693862
 * @return   The owner pointer supplied at work queue creation
Packit Service 693862
 **/
Packit Service 693862
KernelLayer *getWorkQueueOwner(KvdoWorkQueue *queue);
Packit Service 693862
Packit Service 693862
#endif /* ALBIREO_WORK_QUEUE_H */