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