Commit 293cdc48 authored by Artur Paszkiewicz's avatar Artur Paszkiewicz Committed by Tomasz Zawadzki
Browse files

ftl: management framework



Signed-off-by: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: default avatarKozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: I8261863e80a53a37183b0148d4a08fa97e208dda
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13289


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Community-CI: Mellanox Build Bot
parent 51409588
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -11,9 +11,10 @@ SO_MINOR := 0

CFLAGS += -I.

FTL_SUBDIRS := utils
FTL_SUBDIRS := mngt utils

C_SRCS = ftl_core.c
C_SRCS += mngt/ftl_mngt.c

SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_ftl.map)

+1 −0
Original line number Diff line number Diff line
@@ -14,5 +14,6 @@

#include "ftl_core.h"
#include "ftl_internal.h"
#include "mngt/ftl_mngt.h"

SPDK_LOG_REGISTER_COMPONENT(ftl_core)
+570 −0
Original line number Diff line number Diff line
/*   SPDX-License-Identifier: BSD-3-Clause
 *   Copyright (c) Intel Corporation.
 *   All rights reserved.
 */

#include "spdk/queue.h"
#include "spdk/assert.h"
#include "spdk/env.h"

#include "ftl_mngt.h"
#include "ftl_core.h"

struct ftl_mngt_step_status {
	uint64_t start;
	uint64_t stop;
	int status;
	int silent;
	TAILQ_ENTRY(ftl_mngt_step) entry;
};

struct ftl_mngt_step {
	void *ctx;
	const struct ftl_mngt_step_desc *desc;
	struct ftl_mngt_step_status action;
	struct ftl_mngt_step_status rollback;
};

struct ftl_mngt_process {
	struct spdk_ftl_dev *dev;
	int status;
	int silent;
	bool rollback;
	bool continuing;
	struct  {
		ftl_mngt_fn cb;
		void *cb_ctx;
		struct spdk_thread *thread;
	} caller;
	void *ctx;
	uint64_t tsc_start;
	uint64_t tsc_stop;
	const struct ftl_mngt_process_desc *desc;
	TAILQ_HEAD(, ftl_mngt_step) action_queue_todo;
	TAILQ_HEAD(, ftl_mngt_step) action_queue_done;
	TAILQ_HEAD(, ftl_mngt_step) rollback_queue_todo;
	TAILQ_HEAD(, ftl_mngt_step) rollback_queue_done;
	struct {
		struct ftl_mngt_step step;
		struct ftl_mngt_step_desc desc;
	} cleanup;
	struct ftl_mng_tracer *tracer;
};

static void action_next(struct ftl_mngt_process *mngt);
static void action_msg(void *ctx);
static void action_execute(struct ftl_mngt_process *mngt);
static void action_done(struct ftl_mngt_process *mngt, int status);
static void rollback_next(struct ftl_mngt_process *mngt);
static void rollback_msg(void *ctx);
static void rollback_execute(struct ftl_mngt_process *mngt);
static void rollback_done(struct ftl_mngt_process *mngt, int status);

static inline struct ftl_mngt_step *
get_current_step(struct ftl_mngt_process *mngt)
{
	if (!mngt->rollback) {
		return TAILQ_FIRST(&mngt->action_queue_todo);
	} else {
		return TAILQ_FIRST(&mngt->rollback_queue_todo);
	}
}

static int
init_step(struct ftl_mngt_process *mngt,
	  const struct ftl_mngt_step_desc *desc)
{
	struct ftl_mngt_step *step;

	step = calloc(1, sizeof(*step));
	if (!step) {
		return -ENOMEM;
	}

	/* Initialize the step's argument */
	if (desc->ctx_size) {
		step->ctx = calloc(1, desc->ctx_size);
		if (!step->ctx) {
			free(step);
			return -ENOMEM;
		}
	}
	step->desc = desc;
	TAILQ_INSERT_TAIL(&mngt->action_queue_todo, step, action.entry);

	return 0;
}

static void
free_mngt(struct ftl_mngt_process *mngt)
{
	TAILQ_HEAD(, ftl_mngt_step) steps;

	if (!mngt) {
		return;
	}

	TAILQ_INIT(&steps);
	TAILQ_CONCAT(&steps, &mngt->action_queue_todo, action.entry);
	TAILQ_CONCAT(&steps, &mngt->action_queue_done, action.entry);

	while (!TAILQ_EMPTY(&steps)) {
		struct ftl_mngt_step *step = TAILQ_FIRST(&steps);
		TAILQ_REMOVE(&steps, step, action.entry);

		free(step->ctx);
		free(step);
	}

	free(mngt->ctx);
	free(mngt);
}

static struct ftl_mngt_process *
allocate_mngt(struct spdk_ftl_dev *dev,
	      const struct ftl_mngt_process_desc *pdesc,
	      ftl_mngt_fn cb, void *cb_ctx)
{
	struct ftl_mngt_process *mngt;

	/* Initialize management process */
	mngt = calloc(1, sizeof(*mngt));
	if (!mngt) {
		goto error;
	}
	mngt->dev = dev;
	mngt->caller.cb = cb;
	mngt->caller.cb_ctx = cb_ctx;
	mngt->caller.thread = spdk_get_thread();

	/* Initialize process context */
	if (pdesc->ctx_size) {
		mngt->ctx = calloc(1, pdesc->ctx_size);
		if (!mngt->ctx) {
			goto error;
		}
	}
	mngt->tsc_start = spdk_get_ticks();
	mngt->desc = pdesc;
	TAILQ_INIT(&mngt->action_queue_todo);
	TAILQ_INIT(&mngt->action_queue_done);
	TAILQ_INIT(&mngt->rollback_queue_todo);
	TAILQ_INIT(&mngt->rollback_queue_done);

	return mngt;
error:
	free_mngt(mngt);
	return NULL;
}

int
ftl_mngt_process_execute(struct spdk_ftl_dev *dev,
			 const struct ftl_mngt_process_desc *pdesc,
			 ftl_mngt_fn cb, void *cb_ctx)
{
	const struct ftl_mngt_step_desc *sdesc;
	struct ftl_mngt_process *mngt;
	int rc = 0;

	mngt = allocate_mngt(dev, pdesc, cb, cb_ctx);
	if (!mngt) {
		rc = -ENOMEM;
		goto error;
	}

	if (pdesc->error_handler) {
		/* Initialize a step for error handler */
		mngt->cleanup.step.desc = &mngt->cleanup.desc;
		mngt->cleanup.desc.name = "Handle ERROR";
		mngt->cleanup.desc.cleanup = pdesc->error_handler;

		/* Queue error handler to the rollback queue, it will be executed at the end */
		TAILQ_INSERT_HEAD(&mngt->rollback_queue_todo, &mngt->cleanup.step,
				  rollback.entry);
	}

	/* Initialize steps */
	sdesc = mngt->desc->steps;
	while (sdesc->action) {
		rc = init_step(mngt, sdesc);
		if (rc) {
			goto error;
		}
		sdesc++;
	}

	action_execute(mngt);
	return 0;
error:
	free_mngt(mngt);
	return rc;
}

int
ftl_mngt_process_rollback(struct spdk_ftl_dev *dev,
			  const struct ftl_mngt_process_desc *pdesc,
			  ftl_mngt_fn cb, void *cb_ctx)
{
	const struct ftl_mngt_step_desc *sdesc;
	struct ftl_mngt_process *mngt;
	int rc = 0;

	mngt = allocate_mngt(dev, pdesc, cb, cb_ctx);
	if (!mngt) {
		rc = -ENOMEM;
		goto error;
	}

	/* Initialize steps for rollback */
	sdesc = mngt->desc->steps;
	while (sdesc->action) {
		if (!sdesc->cleanup) {
			sdesc++;
			continue;
		}
		rc = init_step(mngt, sdesc);
		if (rc) {
			goto error;
		}
		sdesc++;
	}

	/* Build rollback list */
	struct ftl_mngt_step *step;
	TAILQ_FOREACH(step, &mngt->action_queue_todo, action.entry) {
		step->action.silent = true;
		TAILQ_INSERT_HEAD(&mngt->rollback_queue_todo, step,
				  rollback.entry);
	}

	mngt->rollback = true;
	rollback_execute(mngt);
	return 0;
error:
	free_mngt(mngt);
	return rc;
}

struct spdk_ftl_dev *
ftl_mngt_get_dev(struct ftl_mngt_process *mngt)
{
	return mngt->dev;
}

int
ftl_mngt_alloc_step_ctx(struct ftl_mngt_process *mngt, size_t size)
{
	struct ftl_mngt_step *step = get_current_step(mngt);
	void *arg = calloc(1, size);

	if (!arg) {
		return -ENOMEM;
	}

	free(step->ctx);
	step->ctx = arg;

	return 0;
}

void *
ftl_mngt_get_step_ctx(struct ftl_mngt_process *mngt)
{
	return get_current_step(mngt)->ctx;
}

void *
ftl_mngt_get_process_ctx(struct ftl_mngt_process *mngt)
{
	return mngt->ctx;
}

void *
ftl_mngt_get_caller_ctx(struct ftl_mngt_process *mngt)
{
	return mngt->caller.cb_ctx;
}

int
ftl_mngt_get_status(struct ftl_mngt_process *mngt)
{
	return mngt->status;
}

void
ftl_mngt_next_step(struct ftl_mngt_process *mngt)
{
	if (false == mngt->rollback) {
		action_next(mngt);
	} else {
		rollback_next(mngt);
	}
}

void
ftl_mngt_skip_step(struct ftl_mngt_process *mngt)
{
	if (mngt->rollback) {
		get_current_step(mngt)->rollback.silent = true;
	} else {
		get_current_step(mngt)->action.silent = true;
	}
	ftl_mngt_next_step(mngt);
}

void
ftl_mngt_continue_step(struct ftl_mngt_process *mngt)
{

	if (!mngt->continuing) {
		if (false == mngt->rollback) {
			action_execute(mngt);
		} else {
			rollback_execute(mngt);
		}
	}

	mngt->continuing = true;
}

static void
child_cb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *child)
{
	int status = ftl_mngt_get_status(child);
	struct ftl_mngt_process *parent = ftl_mngt_get_caller_ctx(child);

	child->silent = true;

	if (status) {
		ftl_mngt_fail_step(parent);
	} else {
		ftl_mngt_next_step(parent);
	}
}

void
ftl_mngt_call_process(struct ftl_mngt_process *mngt,
		      const struct ftl_mngt_process_desc *pdesc)
{
	if (ftl_mngt_process_execute(mngt->dev, pdesc, child_cb, mngt)) {
		ftl_mngt_fail_step(mngt);
	} else {
		if (mngt->rollback) {
			get_current_step(mngt)->rollback.silent = true;
		} else {
			get_current_step(mngt)->action.silent = true;
		}
	}
}

void
ftl_mngt_call_process_rollback(struct ftl_mngt_process *mngt,
			       const struct ftl_mngt_process_desc *pdesc)
{
	if (ftl_mngt_process_rollback(mngt->dev, pdesc, child_cb, mngt)) {
		ftl_mngt_fail_step(mngt);
	} else {
		if (mngt->rollback) {
			get_current_step(mngt)->rollback.silent = true;
		} else {
			get_current_step(mngt)->action.silent = true;
		}
	}
}

void
ftl_mngt_fail_step(struct ftl_mngt_process *mngt)
{
	mngt->status = -1;

	if (false == mngt->rollback) {
		action_done(mngt, -1);
	} else {
		rollback_done(mngt, -1);
	}

	mngt->rollback = true;
	rollback_execute(mngt);
}

static inline float
tsc_to_ms(uint64_t tsc)
{
	float ms = tsc;
	ms /= (float)spdk_get_ticks_hz();
	ms *= 1000.0;
	return ms;
}

static void
trace_step(struct spdk_ftl_dev *dev, struct ftl_mngt_step *step, bool rollback)
{
	uint64_t duration;
	const char *what = rollback ? "Rollback" : "Action";
	int silent = rollback ? step->rollback.silent : step->action.silent;

	if (silent) {
		return;
	}

	FTL_NOTICELOG(dev, "%s\n", what);
	FTL_NOTICELOG(dev, "\t name:     %s\n", step->desc->name);
	duration = step->action.stop - step->action.start;
	FTL_NOTICELOG(dev, "\t duration: %.3f ms\n", tsc_to_ms(duration));
	FTL_NOTICELOG(dev, "\t status:   %d\n", step->action.status);
}

static void
process_summary(struct ftl_mngt_process *mngt)
{
	uint64_t duration;

	if (mngt->silent) {
		return;
	}

	duration = mngt->tsc_stop - mngt->tsc_start;
	FTL_NOTICELOG(mngt->dev, "Management process finished, "
		      "name '%s', duration = %.3f ms, result %d\n",
		      mngt->desc->name,
		      tsc_to_ms(duration),
		      mngt->status);
}

static void
finish_msg(void *ctx)
{
	struct ftl_mngt_process *mngt = ctx;

	mngt->caller.cb(mngt->dev, mngt);
	process_summary(mngt);
	free_mngt(mngt);
}

void
ftl_mngt_finish(struct ftl_mngt_process *mngt)
{
	mngt->tsc_stop = spdk_get_ticks();
	spdk_thread_send_msg(mngt->caller.thread, finish_msg, mngt);
}

/*
 * Actions
 */
static void
action_next(struct ftl_mngt_process *mngt)
{
	if (TAILQ_EMPTY(&mngt->action_queue_todo)) {
		/* Nothing to do, finish the management process */
		ftl_mngt_finish(mngt);
		return;
	} else {
		action_done(mngt, 0);
		action_execute(mngt);
	}
}

static void
action_msg(void *ctx)
{
	struct ftl_mngt_process *mngt = ctx;
	struct ftl_mngt_step *step;

	mngt->continuing = false;

	if (TAILQ_EMPTY(&mngt->action_queue_todo)) {
		ftl_mngt_finish(mngt);
		return;
	}

	step = TAILQ_FIRST(&mngt->action_queue_todo);
	if (!step->action.start) {
		step->action.start = spdk_get_ticks();
	}
	step->desc->action(mngt->dev, mngt);
}

static void
action_execute(struct ftl_mngt_process *mngt)
{
	spdk_thread_send_msg(mngt->dev->core_thread, action_msg, mngt);
}

static void
action_done(struct ftl_mngt_process *mngt, int status)
{
	struct ftl_mngt_step *step;

	assert(!TAILQ_EMPTY(&mngt->action_queue_todo));
	step = TAILQ_FIRST(&mngt->action_queue_todo);
	TAILQ_REMOVE(&mngt->action_queue_todo, step, action.entry);

	TAILQ_INSERT_TAIL(&mngt->action_queue_done, step, action.entry);
	if (step->desc->cleanup) {
		TAILQ_INSERT_HEAD(&mngt->rollback_queue_todo, step,
				  rollback.entry);
	}

	step->action.stop = spdk_get_ticks();
	step->action.status = status;

	trace_step(mngt->dev, step, false);
}

/*
 * Rollback
 */
static void
rollback_next(struct ftl_mngt_process *mngt)
{
	if (TAILQ_EMPTY(&mngt->rollback_queue_todo)) {
		/* Nothing to do, finish the management process */
		ftl_mngt_finish(mngt);
		return;
	} else {
		rollback_done(mngt, 0);
		rollback_execute(mngt);
	}
}

static void
rollback_msg(void *ctx)
{
	struct ftl_mngt_process *mngt = ctx;
	struct ftl_mngt_step *step;

	mngt->continuing = false;

	if (TAILQ_EMPTY(&mngt->rollback_queue_todo)) {
		ftl_mngt_finish(mngt);
		return;
	}

	step = TAILQ_FIRST(&mngt->rollback_queue_todo);
	if (!step->rollback.start) {
		step->rollback.start = spdk_get_ticks();
	}
	step->desc->cleanup(mngt->dev, mngt);
}

static void
rollback_execute(struct ftl_mngt_process *mngt)
{
	spdk_thread_send_msg(mngt->dev->core_thread, rollback_msg, mngt);
}

void
rollback_done(struct ftl_mngt_process *mngt, int status)
{
	struct ftl_mngt_step *step;

	assert(!TAILQ_EMPTY(&mngt->rollback_queue_todo));
	step = TAILQ_FIRST(&mngt->rollback_queue_todo);
	TAILQ_REMOVE(&mngt->rollback_queue_todo, step, rollback.entry);
	TAILQ_INSERT_TAIL(&mngt->rollback_queue_done, step, rollback.entry);

	step->rollback.stop = spdk_get_ticks();
	step->rollback.status = status;

	trace_step(mngt->dev, step,  true);
}
+294 −0
Original line number Diff line number Diff line
/*   SPDX-License-Identifier: BSD-3-Clause
 *   Copyright (c) Intel Corporation.
 *   All rights reserved.
 */

#ifndef FTL_MNGT_H
#define FTL_MNGT_H

#include "spdk/stdinc.h"
#include "spdk/ftl.h"

struct spdk_ftl_dev;
struct ftl_mngt_process;

/**
 * The FTL management callback function
 *
 * @param dev FTL device
 * @param mngt FTL management handle
 */
typedef void (*ftl_mngt_fn)(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);

/**
 * The FTL management step descriptior
 */
struct ftl_mngt_step_desc {
	/**
	 * Name of the step
	 */
	const char *name;

	/**
	 * Size of the step argument (context)
	 *
	 * The step context will be allocated before execution of step's
	 * callback.
	 *
	 * @note The context can be reallocated (freed and newly allocated
	 * when calling ftl_mngt_alloc_step_ctx). The main usage is the ability
	 * to set this value to 0 and only allocate as needed if the step is
	 * going to be extremely similar - eg. recovery from shared memory and
	 * disk - in case of shm all the data is already available in memory, while
	 * recovery from disk needs extra context to be able to synchronize IO. This
	 * allows for saving a little bit of time on alloc/dealloc in the cases where
	 * execution time may be critical.
	 * @note It doesn't work like realloc
	 * @note The context can be retrieved within callback when calling
	 * ftl_mngt_get_step_ctx
	 */
	size_t ctx_size;

	/**
	 * Step callback function
	 */
	ftl_mngt_fn action;

	/**
	 * It the step requires cleanup this is right place to put your handler.
	 * When a FTL management process fails cleanup callbacks are executed
	 * in rollback procedure. Cleanup functions are executed in reverse
	 * order to actions already called.
	 */
	ftl_mngt_fn cleanup;
};

/**
 * The FTL management process descriptor
 */
struct ftl_mngt_process_desc {
	/**
	 * The name of the process
	 */
	const char *name;

	/**
	 * Size of the process argument (context)
	 *
	 * The process context will be allocated before execution of the first
	 * step
	 *
	 * @note To get context of the process within FTL management callback,
	 * execute ftl_mngt_get_process_ctx
	 */
	size_t ctx_size;

	/**
	 * Pointer to the additional error handler when the process fails
	 */
	ftl_mngt_fn error_handler;

	/**
	 * The FTL process steps
	 *
	 * The process context will be allocated before execution of the first
	 * step
	 *
	 * @note The step array terminator shall end with action equals NULL
	 */
	struct ftl_mngt_step_desc steps[];
};

/**
 * @brief Executes the FTL management process defined by the process descriptor
 *
 * In case of an error all already executed steps will have their rollback functions
 * called in reverse order.
 *
 * @param dev FTL device
 * @param process The descriptor of process to be executed
 * @param cb Caller callback
 * @param cb_ctx Caller context
 *
 * @return Result of invoking the operation
 * @retval 0 - The FTL management process has been started
 * @retval Non-zero An error occurred when starting The FTL management process
 */
int ftl_mngt_process_execute(struct spdk_ftl_dev *dev,
			     const struct ftl_mngt_process_desc *process,
			     ftl_mngt_fn cb, void *cb_ctx);

/**
 * @brief Executes rollback on the FTL management process defined by the process
 * descriptor
 *
 * All cleanup function from steps will be executed in reversed order
 *
 * @param dev FTL device
 * @param process The descriptor of process to be rollback
 * @param cb Caller callback
 * @param cb_ctx Caller context
 *
 * @return Result of invoking the rollback operation
 * @retval 0 - Rollback of the FTL management process has been started
 * @retval Non-zero An error occurred when starting the rollback
 */
int ftl_mngt_process_rollback(struct spdk_ftl_dev *dev,
			      const struct ftl_mngt_process_desc *process,
			      ftl_mngt_fn cb, void *cb_ctx);

/*
 * FTL management API for steps
 */

/**
 * @brief Gets FTL device
 *
 * @param mngt FTL management handle
 *
 * @note This function can be invoked within step handler only
 *
 * @return FTL device
 */
struct spdk_ftl_dev *ftl_mngt_get_dev(struct ftl_mngt_process *mngt);

/**
 * @brief Allocates a context for the management step
 *
 * @param mngt FTL management handle
 * @param size Size of the step context
 *
 * @note This function can be invoked within ftl_mngt_fn callback only
 *
 * @return Operation result
 * @retval 0 Operation successful
 * @retval Non-zero Operation failure
 */
int ftl_mngt_alloc_step_ctx(struct ftl_mngt_process *mngt, size_t size);

/**
 * @brief Gets the management step context
 *
 * @param mngt FTL management handle
 *
 * @note This function can be invoked within ftl_mngt_fn callback only
 *
 * @return Context of the step containing pointer to buffer and its size
 */
void *ftl_mngt_get_step_ctx(struct ftl_mngt_process *mngt);

/**
 * @brief Gets the management process context
 *
 * @param mngt FTL management handle
 *
 * @note This function can be invoked within ftl_mngt_fn callback only
 *
 * @return Context of the process containing pointer to buffer and its size
 */
void *ftl_mngt_get_process_ctx(struct ftl_mngt_process *mngt);

/**
 * @brief Gets the caller context
 *
 * @param mngt FTL management handle
 *
 * @note This function can be invoked within ftl_mngt_fn callback only
 *
 * @return Pointer to the caller context
 */
void *ftl_mngt_get_caller_ctx(struct ftl_mngt_process *mngt);

/**
 * @brief Gets the status of executed management process
 *
 * @param mngt FTL management handle
 *
 * @note This function can be invoked within ftl_mngt_fn callback only
 *
 * @return The operation result of the management process
 * @retval 0 Operation successful
 * @retval Non-zero Operation failure
 */
int ftl_mngt_get_status(struct ftl_mngt_process *mngt);

/**
 * @brief Finishes the management process immediately
 *
 * @note This function can be invoked within ftl_mngt_fn callback only
 *
 * @param mngt FTL management handle of process to be finished
 */
void ftl_mngt_finish(struct ftl_mngt_process *mngt);

/**
 * @brief Completes the step currently in progress and jump to a next one
 *
 * If no more steps to be executed then the management process is finished and
 * caller callback is invoked
 *
 * @note This function can be invoked within ftl_mngt_fn callback only
 *
 * @param mngt FTL management handle
 */
void ftl_mngt_next_step(struct ftl_mngt_process *mngt);

/**
 * @brief Skips the step currently in progress and jump to a next one
 *
 * @note This function can be invoked within ftl_mngt_fn callback only
 *
 * @param mngt FTL management handle
 */
void ftl_mngt_skip_step(struct ftl_mngt_process *mngt);

/**
 * @brief Continue the step currently in progress
 *
 * This causes invoking the same step handler in next iteration of the
 * management process. This mechanism can be used by a job when polling for
 * something.
 *
 * @note This function can be invoked within ftl_mngt_fn callback only
 *
 * @param mngt FTL management handle
 */
void ftl_mngt_continue_step(struct ftl_mngt_process *mngt);

/**
 * @brief Fail the step currently in progress.
 *
 * It stops executing all steps and starts the rollback procedure (calling
 * the cleanup functions of all already executed steps).
 * If executed from a cleanup function, it will stop executing and the following
 * cleanup functions (if any) will be executed.
 *
 * @param mngt FTL management handle
 */
void ftl_mngt_fail_step(struct ftl_mngt_process *mngt);

/**
 * @brief Calls another management process
 *
 * Ends the current step and executes specified process and finally continues
 * executing the the remaining steps
 *
 * @param mngt The management handle
 * @param process The management process to be called
 */
void ftl_mngt_call_process(struct ftl_mngt_process *mngt,
			   const struct ftl_mngt_process_desc *process);

/**
 * @brief Calls rollback steps of another management process
 *
 * Ends the current step and executes rollback steps of specified process
 * and finally continues executing the remaining steps in the original process
 *
 * @param mngt The management handle
 * @param process The management process to be called to execute rollback
 */
void ftl_mngt_call_process_rollback(struct ftl_mngt_process *mngt,
				    const struct ftl_mngt_process_desc *process);

#endif /* LIB_FTL_FTL_MNGT_H */
+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ DEPDIRS-blobfs := log thread blob trace util
DEPDIRS-event := log util thread $(JSON_LIBS) trace init
DEPDIRS-init := jsonrpc json log rpc thread util

DEPDIRS-ftl := log
DEPDIRS-ftl := log thread
DEPDIRS-nbd := log util thread $(JSON_LIBS) bdev
DEPDIRS-nvmf := accel log sock util nvme thread $(JSON_LIBS) trace bdev
ifeq ($(CONFIG_RDMA),y)
Loading