Commit 8ce89dde authored by Matthew Sakai's avatar Matthew Sakai Committed by Mike Snitzer

dm vdo: implement external deduplication index interface

The deduplication index interface for index clients includes the
deduplication request and index session structures. This is the interface
that the rest of the vdo target uses to make requests, receive responses,
and collect statistics.

This patch also adds sysfs nodes for inspecting various index properties at
runtime.
Co-developed-by: default avatarJ. corwin Coburn <corwin@hurlbutnet.net>
Signed-off-by: default avatarJ. corwin Coburn <corwin@hurlbutnet.net>
Co-developed-by: default avatarMichael Sclafani <dm-devel@lists.linux.dev>
Signed-off-by: default avatarMichael Sclafani <dm-devel@lists.linux.dev>
Co-developed-by: default avatarThomas Jaskiewicz <tom@jaskiewicz.us>
Signed-off-by: default avatarThomas Jaskiewicz <tom@jaskiewicz.us>
Co-developed-by: default avatarJohn Wiele <jwiele@redhat.com>
Signed-off-by: default avatarJohn Wiele <jwiele@redhat.com>
Signed-off-by: default avatarMatthew Sakai <msakai@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@kernel.org>
parent 766130e8
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2023 Red Hat
*/
#ifndef UDS_INDEX_SESSION_H
#define UDS_INDEX_SESSION_H
#include <linux/atomic.h>
#include <linux/cache.h>
#include "config.h"
#include "uds-threads.h"
#include "uds.h"
/*
* The index session mediates all interactions with a UDS index. Once the index session is created,
* it can be used to open, close, suspend, or recreate an index. It implements the majority of the
* functions in the top-level UDS API.
*
* If any deduplication request fails due to an internal error, the index is marked disabled. It
* will not accept any further requests and can only be closed. Closing the index will clear the
* disabled flag, and the index can then be reopened and recovered using the same index session.
*/
struct __aligned(L1_CACHE_BYTES) session_stats {
/* Post requests that found an entry */
u64 posts_found;
/* Post requests found in the open chapter */
u64 posts_found_open_chapter;
/* Post requests found in the dense index */
u64 posts_found_dense;
/* Post requests found in the sparse index */
u64 posts_found_sparse;
/* Post requests that did not find an entry */
u64 posts_not_found;
/* Update requests that found an entry */
u64 updates_found;
/* Update requests that did not find an entry */
u64 updates_not_found;
/* Delete requests that found an entry */
u64 deletions_found;
/* Delete requests that did not find an entry */
u64 deletions_not_found;
/* Query requests that found an entry */
u64 queries_found;
/* Query requests that did not find an entry */
u64 queries_not_found;
/* Total number of requests */
u64 requests;
};
enum index_suspend_status {
/* An index load has started but the index is not ready for use. */
INDEX_OPENING = 0,
/* The index is able to handle requests. */
INDEX_READY,
/* The index is attempting to suspend a rebuild. */
INDEX_SUSPENDING,
/* An index rebuild has been suspended. */
INDEX_SUSPENDED,
/* An index rebuild is being stopped in order to shut down. */
INDEX_FREEING,
};
struct index_load_context {
struct mutex mutex;
struct cond_var cond;
enum index_suspend_status status;
};
struct uds_index_session {
unsigned int state;
struct uds_index *index;
struct uds_request_queue *callback_queue;
struct uds_parameters parameters;
struct index_load_context load_context;
struct mutex request_mutex;
struct cond_var request_cond;
int request_count;
struct session_stats stats;
};
#endif /* UDS_INDEX_SESSION_H */
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2023 Red Hat
*/
#include "uds-sysfs.h"
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/slab.h>
#include "logger.h"
#include "memory-alloc.h"
#include "string-utils.h"
#include "uds.h"
#define UDS_SYSFS_NAME "uds"
static struct {
/* /sys/uds */
struct kobject kobj;
/* /sys/uds/parameter */
struct kobject parameter_kobj;
/* These flags are used to ensure a clean shutdown */
/* /sys/uds flag */
bool flag;
/* /sys/uds/parameter flag */
bool parameter_flag;
} object_root;
static char *buffer_to_string(const char *buf, size_t length)
{
char *string;
if (uds_allocate(length + 1, char, __func__, &string) != UDS_SUCCESS)
return NULL;
memcpy(string, buf, length);
string[length] = '\0';
if (string[length - 1] == '\n')
string[length - 1] = '\0';
return string;
}
/*
* This is the code for any directory in the /sys/<module_name> tree that contains no regular files
* (only subdirectories).
*/
static void empty_release(struct kobject *kobj)
{
}
static ssize_t empty_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
return 0;
}
static ssize_t empty_store(struct kobject *kobj, struct attribute *attr, const char *buf,
size_t length)
{
return length;
}
static const struct sysfs_ops empty_ops = {
.show = empty_show,
.store = empty_store,
};
static struct attribute *empty_attrs[] = {
NULL,
};
ATTRIBUTE_GROUPS(empty);
static const struct kobj_type empty_object_type = {
.release = empty_release,
.sysfs_ops = &empty_ops,
.default_groups = empty_groups,
};
/*
* This is the code for the /sys/<module_name>/parameter directory.
* <dir>/log_level UDS_LOG_LEVEL
*/
struct parameter_attribute {
struct attribute attr;
const char *(*show_string)(void);
void (*store_string)(const char *string);
};
static ssize_t parameter_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct parameter_attribute *pa;
pa = container_of(attr, struct parameter_attribute, attr);
if (pa->show_string != NULL)
return sprintf(buf, "%s\n", pa->show_string());
else
return -EINVAL;
}
static ssize_t parameter_store(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t length)
{
char *string;
struct parameter_attribute *pa;
pa = container_of(attr, struct parameter_attribute, attr);
if (pa->store_string == NULL)
return -EINVAL;
string = buffer_to_string(buf, length);
if (string == NULL)
return -ENOMEM;
pa->store_string(string);
uds_free(string);
return length;
}
static const char *parameter_show_log_level(void)
{
return uds_log_priority_to_string(uds_get_log_level());
}
static void parameter_store_log_level(const char *string)
{
uds_set_log_level(uds_log_string_to_priority(string));
}
static struct parameter_attribute log_level_attr = {
.attr = { .name = "log_level", .mode = 0600 },
.show_string = parameter_show_log_level,
.store_string = parameter_store_log_level,
};
static struct attribute *parameter_attrs[] = {
&log_level_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(parameter);
static const struct sysfs_ops parameter_ops = {
.show = parameter_show,
.store = parameter_store,
};
static const struct kobj_type parameter_object_type = {
.release = empty_release,
.sysfs_ops = &parameter_ops,
.default_groups = parameter_groups,
};
int uds_init_sysfs(void)
{
int result;
memset(&object_root, 0, sizeof(object_root));
kobject_init(&object_root.kobj, &empty_object_type);
result = kobject_add(&object_root.kobj, NULL, UDS_SYSFS_NAME);
if (result == 0) {
object_root.flag = true;
kobject_init(&object_root.parameter_kobj, &parameter_object_type);
result = kobject_add(&object_root.parameter_kobj, &object_root.kobj,
"parameter");
if (result == 0)
object_root.parameter_flag = true;
}
if (result != 0)
uds_put_sysfs();
return result;
}
void uds_put_sysfs(void)
{
if (object_root.parameter_flag)
kobject_put(&object_root.parameter_kobj);
if (object_root.flag)
kobject_put(&object_root.kobj);
}
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2023 Red Hat
*/
#ifndef UDS_SYSFS_H
#define UDS_SYSFS_H
int uds_init_sysfs(void);
void uds_put_sysfs(void);
#endif /* UDS_SYSFS_H */
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment