Commit 5b50d3e8 authored by Mike Gerdts's avatar Mike Gerdts Committed by Jim Harris
Browse files

log: add deprecated tracking API



When use of deprecated featues is encountered, SPDK now calls
SPDK_LOG_DEPRECATED(). This logs the use of deprecated functionality in
a consistent way, making it easy to add further instrumentation to catch
code paths that trigger deprecated behavior.

Change-Id: Idfd33ade171307e5e8235a7aa0d969dc5d93e33d
Signed-off-by: default avatarMike Gerdts <mgerdts@nvidia.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15689


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Community-CI: Mellanox Build Bot
parent d0cdaf0f
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -90,6 +90,15 @@ its exit process has started using `spdk_thread_exit`.
Added API `spdk_spin_init`, `spdk_spin_destroy`, `spdk_spin_lock`, `spdk_spin_unlock`, and
`spdk_spin_held` to support spinlocks that are aware of the SPDK concurrency model.

### log

Added consistent tracking of use of deprecated behavior. Deprecations continue to be
listed in deprecation.md and now are in subsections with headers matching a tag
used in `SPDK_LOG_DEPRECATED()` calls. When deprecated behavior is used, these
tags will appear in SPDK's log at the warn level. As the SPDK application exits, it
will log a summary of how many times `SPDK_LOG_DEPRECATED()` was called for each
tag that was logged at least once.

## v22.09

### accel
+5 −0
Original line number Diff line number Diff line
@@ -12,6 +12,11 @@ Each entry must describe what will be removed and can suggest the future use or
Specific future SPDK release for the removal must be provided.
ABI cannot be removed without providing deprecation notice for at least single SPDK release.

Deprecated code paths must be registered with `SPDK_DEPRECATION_REGISTER()` and logged with
`SPDK_LOG_DEPRECATED()`. The tag used with these macros will appear in the SPDK
log at the warn level when `SPDK_LOG_DEPRECATED()` is called, subject to rate limits.
The tags can be matched with the level 4 headers below.

## Deprecation Notices {#deprecation-notices}

### nvme
+96 −0
Original line number Diff line number Diff line
/*   SPDX-License-Identifier: BSD-3-Clause
 *   Copyright (C) 2016 Intel Corporation.
 *   All rights reserved.
 *   Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 */

/**
@@ -252,6 +253,101 @@ int spdk_log_clear_flag(const char *flag);
 */
void spdk_log_usage(FILE *f, const char *log_arg);

struct spdk_deprecation;

/**
 * Register a deprecation. Most consumers will use SPDK_LOG_DEPRECATION_REGISTER() instead.
 *
 * \param tag A unique string that will appear in each log message and should appear in
 * documentation.
 * \param description A descriptive string that will also be logged.
 * \param rate_limit_seconds If non-zero, log messages related to this deprecation will appear no
 * more frequently than this interval.
 * \param remove_release The release when the deprecated support will be removed.
 * \param reg Pointer to storage for newly allocated deprecation handle.
 * \return 0 on success or negative errno on failure.
 */
int spdk_log_deprecation_register(const char *tag, const char *description,
				  const char *remove_release, uint32_t rate_limit_seconds,
				  struct spdk_deprecation **reg);

#define SPDK_LOG_DEPRECATION_REGISTER(tag, desc, release, rate) \
	static struct spdk_deprecation *_deprecated_##tag; \
	static void __attribute__((constructor)) _spdk_deprecation_register_##tag(void) \
	{ \
		int rc; \
		rc = spdk_log_deprecation_register(#tag, desc, release, rate, &_deprecated_##tag); \
		(void)rc; \
		assert(rc == 0); \
	}

/**
 * Indicate that a deprecated feature was used. Most consumers will use SPDK_LOG_DEPRECATED()
 * instead.
 *
 * \param deprecation The deprecated feature that was used.
 * \param file The name of the source file where the deprecated feature was used.
 * \param line The line in file where where the deprecated feature was used.
 * \param func The name of the function where where the deprecated feature was used.
 */
void spdk_log_deprecated(struct spdk_deprecation *deprecation, const char *file, uint32_t line,
			 const char *func);

#define SPDK_LOG_DEPRECATED(tag) \
	spdk_log_deprecated(_deprecated_##tag, __FILE__, __LINE__, __func__)

/**
 * Callback function for spdk_log_for_each_deprecation().
 *
 * \param ctx Context passed via spdk_log_for_each_deprecation().
 * \param deprecation Pointer to a deprecation structure.
 * \return 0 to continue iteration or non-zero to stop iteration.
 */
typedef int (*spdk_log_for_each_deprecation_fn)(void *ctx, struct spdk_deprecation *deprecation);

/**
 * Iterate over all deprecations, calling a callback on each of them.
 *
 * Iteration will stop early if the callback function returns non-zero.
 *
 * \param ctx Context to pass to the callback.
 * \param fn Callback function
 * \return The value from the last callback called or 0 if there are no deprecations.
 */
int spdk_log_for_each_deprecation(void *ctx, spdk_log_for_each_deprecation_fn fn);

/**
 * Get a deprecation's tag.
 *
 * \param deprecation A pointer to an spdk_deprecation.
 * \return The deprecation's tag.
 */
const char *spdk_deprecation_get_tag(const struct spdk_deprecation *deprecation);

/**
 * Get a deprecation's description.
 *
 * \param deprecation A pointer to an spdk_deprecation.
 * \return The deprecation's description.
 */
const char *spdk_deprecation_get_description(const struct spdk_deprecation *deprecation);

/**
 * Get a deprecation's planned removal release.
 *
 * \param deprecation A pointer to an spdk_deprecation.
 * \return The deprecation's planned removal release.
 */
const char *spdk_deprecation_get_remove_release(const struct spdk_deprecation *deprecation);

/**
 * Get the number of times that a deprecation's code has been executed.
 *
 * \param deprecation A pointer to an spdk_deprecation.
 * \return The deprecation's planned removal release.
 */
uint64_t spdk_deprecation_get_hits(const struct spdk_deprecation *deprecation);

#ifdef __cplusplus
}
#endif
+16 −0
Original line number Diff line number Diff line
@@ -772,6 +772,21 @@ _start_subsystem_fini(void *arg1)
	spdk_subsystem_fini(spdk_reactors_stop, NULL);
}

static int
log_deprecation_hits(void *ctx, struct spdk_deprecation *dep)
{
	uint64_t hits = spdk_deprecation_get_hits(dep);

	if (hits == 0) {
		return 0;
	}

	SPDK_WARNLOG("%s: deprecation '%s' scheduled for removal in %s hit %" PRIu64 " times\n",
		     spdk_deprecation_get_tag(dep), spdk_deprecation_get_remove_release(dep),
		     spdk_deprecation_get_description(dep), hits);
	return 0;
}

static void
app_stop(void *arg1)
{
@@ -786,6 +801,7 @@ app_stop(void *arg1)

	spdk_rpc_finish();
	g_spdk_app.stopped = true;
	spdk_log_for_each_deprecation(NULL, log_deprecation_hits);
	_start_subsystem_fini(NULL);
}

+2 −2
Original line number Diff line number Diff line
@@ -7,10 +7,10 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk

SO_VER := 5
SO_MINOR := 0
SO_MINOR := 1
SO_SUFFIX := $(SO_VER).$(SO_MINOR)

C_SRCS = log.c log_flags.c
C_SRCS = log.c log_flags.c log_deprecated.c
LIBNAME = log

SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_log.map)
Loading