Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions src/control/cmd/ddb/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// (C) Copyright 2022-2024 Intel Corporation.
// (C) Copyright 2025 Hewlett Packard Enterprise Development LP
// (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
Expand Down Expand Up @@ -179,10 +179,36 @@ Example Paths:
return nil
}

if os.Getenv("DD_MASK") == "" {
os.Setenv("DD_MASK", "mgmt,epc,csum,md,df,io,trace")
}
if opts.Debug {
log.WithLogLevel(logging.LogLevelDebug)
log.Debug("debug output enabled")
log.WithLogLevel(logging.LogLevelTrace)
if os.Getenv("D_LOG_MASK") == "" {
os.Setenv("D_LOG_MASK", "INFO,DDB=DEBUG")
}
// Show debug output and above on stderr to not pollute stdout
// NOTE: DD_STDERR can only be used with INFO and above.
if os.Getenv("DD_STDERR") == "" {
os.Setenv("DD_STDERR", "EMIT")
}
if os.Getenv("D_LOG_FILE") == "" {
os.Setenv("D_LOG_FILE", "/dev/stderr")
}
} else {
log.WithLogLevel(logging.LogLevelError)
if os.Getenv("D_LOG_MASK") == "" {
os.Setenv("D_LOG_MASK", "ERR,DDB=WARN")
}
// Only show warnings and above on stderr to not pollute stdout
if os.Getenv("DD_STDERR") == "" {
os.Setenv("DD_STDERR", "WARN")
}
if os.Getenv("D_LOG_FILE") == "" {
os.Setenv("D_LOG_FILE", "/dev/null")
}
}
log.Debug("debug output enabled")

ctx, cleanup, err := InitDdb(log)
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions src/include/daos/debug.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* (C) Copyright 2015-2024 Intel Corporation.
* (C) Copyright 2025 Hewlett Packard Enterprise Development LP
* (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
Expand Down Expand Up @@ -55,7 +55,8 @@
ACTION(il, il, arg) \
ACTION(csum, csum, arg) \
ACTION(pipeline, pipeline, arg) \
ACTION(stack, stack, arg)
ACTION(stack, stack, arg) \
ACTION(ddb, ddb, arg)

#define DAOS_FOREACH_DB(ACTION, arg) \
/** metadata operation */ \
Expand Down
3 changes: 3 additions & 0 deletions src/utils/ddb/ddb.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
#define D_LOGFAC DD_FAC(ddb)

#include <stdlib.h>
#include <string.h>
#include <limits.h>

#include <daos_errno.h>
#include <daos_srv/vos.h>

Expand Down
16 changes: 8 additions & 8 deletions src/utils/ddb/ddb_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
#define D_LOGFAC DD_FAC(ddb)

#include <daos/common.h>
#include <daos_srv/vos.h>
#include <sys/types.h>
#include <time.h>

#include "daos_errno.h"
#include "daos_srv/vos_types.h"
#include "daos_types.h"
#include <daos.h>
#include <daos_errno.h>
#include <daos_types.h>
#include <daos/common.h>
#include <daos_srv/vos.h>
#include <daos_srv/vos_types.h>

#include "ddb_common.h"
#include "ddb_parse.h"
#include "ddb.h"
#include "ddb_vos.h"
#include "ddb_printer.h"
#include "daos.h"
#include "ddb_tree_path.h"
#include "gurt/common.h"
#include "gurt/debug.h"

#define ilog_path_required_error_message "Path to object, dkey, or akey required\n"
#define error_msg_write_mode_only "Can only modify the VOS tree in 'write mode'\n"
Expand Down
9 changes: 6 additions & 3 deletions src/utils/ddb/ddb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
#define D_LOGFAC DD_FAC(ddb)

#include <stdarg.h>
#include <sys/stat.h>

#include <daos/common.h>
#include <daos/object.h>

#include "ddb.h"
#include "ddb_common.h"
#include "ddb_parse.h"
#include "ddb_vos.h"
#include "ddb.h"
#include <stdarg.h>
#include <sys/stat.h>

int
ddb_init()
Expand Down
4 changes: 2 additions & 2 deletions src/utils/ddb/ddb_mgmt.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/**
* (C) Copyright 2025 Vdura Inc.
* (C) Copyright 2025 Hewlett Packard Enterprise Development LP
* (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
#define D_LOGFAC DD_FAC(ddb)

#include <ftw.h>
#include <unistd.h>
Expand All @@ -13,7 +14,6 @@
#include <sys/sysinfo.h>
#include <linux/magic.h>

#include <gurt/debug.h>
#include <daos_srv/control.h>
#include <daos_srv/smd.h>
#include <daos_srv/mgmt_tgt_common.h>
Expand Down
147 changes: 110 additions & 37 deletions src/utils/ddb/ddb_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
#define D_LOGFAC DD_FAC(ddb)

#include <wordexp.h>
#include <getopt.h>
#include <gurt/common.h>
#include "daos_errno.h"
#include <regex.h>
#include <errno.h>
#include <string.h>

#include <daos_errno.h>

#include "ddb_common.h"
#include "ddb_parse.h"

Expand All @@ -20,55 +25,123 @@ safe_strcat(char *dst, const char *src, size_t dst_size)
strncat(dst, src, remaining_space);
}

static void
print_regx_error(int rc, regex_t *preg, const char *regex_buf)
{
char *buf;
size_t buf_size;

buf_size = regerror(rc, preg, NULL, 0);
D_ALLOC_ARRAY(buf, buf_size);
D_ASSERT(buf != NULL);
regerror(rc, preg, buf, buf_size);
D_CRIT("Invalid regex '%s': %s", regex_buf, buf);
D_FREE(buf);
}

int
vos_path_parse(const char *path, struct vos_file_parts *vos_file_parts)
{
uint32_t path_len = strlen(path) + 1;
char *path_copy;
char *tok;
int rc = -DER_INVAL;
enum {
DB_PATH_IDX = 1,
POOL_UUID_IDX = 3,
VOS_FILE_NAME_IDX = 5,
TARGET_IDX_IDX = 6,
MATCH_SIZE = 7,
POOL_UUID_LEN = 36
};
const char *regex_buf =
"^(/?([^/]+/)*)([0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12})/"
"(vos-([0-9]|([1-9][0-9]+)))$";
char *endptr;
uint64_t target_idx;
regex_t preg;
char pool_uuid[POOL_UUID_LEN + 1];
regmatch_t match[MATCH_SIZE + 1];
size_t vos_file_name_len;
int rc;

D_ASSERT(path != NULL && vos_file_parts != NULL);

D_ALLOC(path_copy, path_len);
if (path_copy == NULL)
return -DER_NOMEM;
strcpy(path_copy, path);

tok = strtok(path_copy, "/");
while (tok != NULL && rc != 0) {
rc = uuid_parse(tok, vos_file_parts->vf_pool_uuid);
if (!SUCCESS(rc)) {
safe_strcat(vos_file_parts->vf_db_path, "/", DB_PATH_LEN);
safe_strcat(vos_file_parts->vf_db_path, tok, DB_PATH_LEN);
rc = regcomp(&preg, regex_buf, REG_EXTENDED);
if (rc != 0) {
print_regx_error(rc, &preg, regex_buf);
rc = -DER_INVAL;
goto out;
}

rc = regexec(&preg, path, MATCH_SIZE, match, 0);
if (rc == REG_NOMATCH) {
D_ERROR("Innvalid VOS path: '%s'\n", path);
rc = -DER_INVAL;
goto out_preg;
}
D_ASSERT(SUCCESS(rc));

vos_file_parts->vf_db_path[0] = '\0';
if ((match[DB_PATH_IDX].rm_eo - match[DB_PATH_IDX].rm_so) != 0) {
D_ASSERT(match[DB_PATH_IDX].rm_so == 0);
if (match[DB_PATH_IDX].rm_eo > DB_PATH_SIZE) {
D_ERROR("DB path '%.*s' too long in VOS path '%s': get=%i, max=%i\n",
match[DB_PATH_IDX].rm_eo - 1, &path[match[DB_PATH_IDX].rm_so], path,
match[DB_PATH_IDX].rm_eo - 1, DB_PATH_SIZE - 1);
rc = -DER_INVAL;
goto out_preg;
}
tok = strtok(NULL, "/");
memcpy(vos_file_parts->vf_db_path, path, match[DB_PATH_IDX].rm_eo - 1);
vos_file_parts->vf_db_path[match[DB_PATH_IDX].rm_eo - 1] = '\0';
}

if (rc != 0 || tok == NULL) {
D_ERROR("Incomplete path: %s\n", path);
D_GOTO(done, rc = -DER_INVAL);
D_ASSERT(match[POOL_UUID_IDX].rm_so != (regoff_t)-1);
D_ASSERT(match[POOL_UUID_IDX].rm_eo - match[POOL_UUID_IDX].rm_so == POOL_UUID_LEN);
memcpy(pool_uuid, &path[match[POOL_UUID_IDX].rm_so], POOL_UUID_LEN);
pool_uuid[POOL_UUID_LEN] = '\0';
rc = uuid_parse(pool_uuid, vos_file_parts->vf_pool_uuid);
if (!SUCCESS(rc)) {
D_CRIT("Invalid Pool UUID '%s' in VOS path '%s'\n", pool_uuid, path);
rc = -DER_INVAL;
goto out_preg;
}

strncpy(vos_file_parts->vf_vos_file, tok, ARRAY_SIZE(vos_file_parts->vf_vos_file) - 1);

/*
* file name should be vos-N ... split on "-"
* If not, might be test, just assume target of 0
*/
strtok(tok, "-");
tok = strtok(NULL, "-");
if (tok != NULL) {
D_WARN("vos file name not in correct format: %s\n", vos_file_parts->vf_vos_file);
vos_file_parts->vf_target_idx = atoi(tok);
D_ASSERT(match[VOS_FILE_NAME_IDX].rm_so != (regoff_t)-1);
vos_file_name_len = match[VOS_FILE_NAME_IDX].rm_eo - match[VOS_FILE_NAME_IDX].rm_so;
if (vos_file_name_len + 1 > VOS_FILE_NAME_SIZE) {
D_ERROR("VOS file name '%.*s' too long in VOS path '%s': get=%zu, max=%i\n",
(int)vos_file_name_len, &path[match[VOS_FILE_NAME_IDX].rm_so], path,
vos_file_name_len, VOS_FILE_NAME_SIZE - 1);
rc = -DER_INVAL;
goto out_preg;
}
memcpy(vos_file_parts->vf_vos_file_name, &path[match[VOS_FILE_NAME_IDX].rm_so],
vos_file_name_len);
vos_file_parts->vf_vos_file_name[vos_file_name_len] = '\0';

D_ASSERT(match[TARGET_IDX_IDX].rm_so != (regoff_t)-1);
errno = 0;
target_idx = strtoull(&path[match[TARGET_IDX_IDX].rm_so], &endptr, 10);
if (errno != 0 || endptr == &path[match[TARGET_IDX_IDX].rm_so] || *endptr != '\0') {
D_CRIT("Invalid target index '%s' in VOS path '%s': %s\n",
&path[match[TARGET_IDX_IDX].rm_so], path, strerror(errno));
rc = -DER_INVAL;
goto out_preg;
}
if (target_idx > UINT32_MAX) {
D_ERROR("Target index " DF_U64
"' out of range in VOS path '%s': min=0 , max=%" PRIu32 "\n",
target_idx, path, UINT32_MAX);
rc = -DER_INVAL;
goto out_preg;
}
vos_file_parts->vf_target_idx = target_idx;

done:
if (!SUCCESS(rc)) {
/* Reset to if not valid */
rc = -DER_SUCCESS;

out_preg:
regfree(&preg);
out:
/* Reset to zero if not valid */
if (!SUCCESS(rc))
memset(vos_file_parts, 0, sizeof(*vos_file_parts));
}
D_FREE(path_copy);
return rc;
}

Expand Down
10 changes: 5 additions & 5 deletions src/utils/ddb/ddb_parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
#include <daos_types.h>
#include "ddb_common.h"

#define DB_PATH_LEN 64
enum { DB_PATH_SIZE = 64, VOS_FILE_NAME_SIZE = 16 };
struct vos_file_parts {
char vf_db_path[DB_PATH_LEN];
uuid_t vf_pool_uuid;
char vf_vos_file[16];
uint32_t vf_target_idx;
char vf_db_path[DB_PATH_SIZE];
uuid_t vf_pool_uuid;
char vf_vos_file_name[VOS_FILE_NAME_SIZE];
uint32_t vf_target_idx;
};

/* Parse a path to a VOS file to get needed parts for initializing vos */
Expand Down
3 changes: 2 additions & 1 deletion src/utils/ddb/ddb_printer.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/**
* (C) Copyright 2022-2024 Intel Corporation.
* (C) Copyright 2025 Hewlett Packard Enterprise Development LP
* (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
#define D_LOGFAC DD_FAC(ddb)

#include "ddb_printer.h"

Expand Down
10 changes: 6 additions & 4 deletions src/utils/ddb/ddb_spdk.c
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
/**
* (C) Copyright 2022 Intel Corporation.
* (C) Copyright 2025 Hewlett Packard Enterprise Development LP
* (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
#define D_LOGFAC DD_FAC(ddb)

#include <bio_internal.h>
#include <bio_wal.h>
#include <uuid/uuid.h>
#include <spdk/stdinc.h>
#include <spdk/bdev.h>
#include <spdk/env.h>
#include <spdk/event.h>
#include <spdk/blob_bdev.h>
#include <spdk/blob.h>
#include <spdk/string.h>
#include <uuid/uuid.h>

#include <bio_internal.h>
#include <bio_wal.h>

#include "ddb_common.h"
#include "ddb_spdk.h"
Expand Down
2 changes: 2 additions & 0 deletions src/utils/ddb/ddb_tree_path.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/**
* (C) Copyright 2023-2024 Intel Corporation.
* (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
#define D_LOGFAC DD_FAC(ddb)

#include "ddb_tree_path.h"
#include "ddb_printer.h"
Expand Down
Loading
Loading