Skip to content

Commit

Permalink
Merge pull request #41 from CCI-MOC/rpc_integration
Browse files Browse the repository at this point in the history
Add RPC support and overhaul configuration system
  • Loading branch information
knikolla authored Aug 13, 2024
2 parents 7e12c27 + 644e08a commit b3e7810
Show file tree
Hide file tree
Showing 21 changed files with 426 additions and 298 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ qemu/bzImage

subprojects/liburing-*
subprojects/packagecache
subprojects/nlohmann_json-*
14 changes: 14 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Configuring LSVD

LSVD is configured using a JSON file. When creating an image, we will
try to read the following paths and parse them for configuration options:

- Default built-in configuration
- `/usr/local/etc/lsvd.json`
- `./lsvd.json`
- user supplied path

The file read last has highest priority.

We will also first try to parse the user-supplied path as a JSON object, and if
that fails try treat it as a path and read it from a file.
18 changes: 18 additions & 0 deletions docs/example_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"rcache_dir": "/tmp/lsvd",
"rcache_size": 524288000,
"rcache_fetch_window": 12,
"wlog_dir": "/tmp/lsvd",
"wlog_bytes": 524288000,
"wlog_write_window": 8,
"wlog_chunk_bytes": 2097152,
"antithrash_ratio": 67,
"backend_obj_bytes": 8388608,
"backend_write_window": 8,
"checkpoint_interval_objs": 500,
"flush_timeout_ms": 2000,
"flush_interval_ms": 1000,
"gc_threshold_pc": 60,
"gc_write_window": 4,
"no_gc": false
}
6 changes: 6 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ executable(
dependencies: lsvd_deps + [dependency('_spdk')],
)

executable(
'lsvd_tgt',
lsvd_tgt,
dependencies: lsvd_deps + [dependency('_spdk')],
)

executable(
'imgtool',
['src/imgtool.cc'],
Expand Down
33 changes: 26 additions & 7 deletions src/bdev_lsvd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
#include "spdk/bdev_module.h"
#include <future>

#include "backend.h"
#include "bdev_lsvd.h"
#include "config.h"
#include "image.h"
#include "request.h"
#include "smartiov.h"
Expand Down Expand Up @@ -217,15 +219,32 @@ int bdev_lsvd_create(str img_name, rados_ioctx_t ioctx, lsvd_config cfg)
return 0;
}

int bdev_lsvd_delete(std::string img_name)
int bdev_lsvd_create(str pool_name, str image_name, str user_cfg)
{
auto p = std::promise<int>();
spdk_bdev_unregister_by_name(
auto be = connect_to_pool(pool_name);
auto cfg = lsvd_config::from_user_cfg(user_cfg);
PR_RET_IF(!cfg.has_value(), -1, "Failed to read config file");

return bdev_lsvd_create(image_name, be, cfg.value());
}

void bdev_lsvd_delete(str img_name, std::function<void(int)> cb)
{
log_info("Deleting image '{}'", img_name);
auto rc = spdk_bdev_unregister_by_name(
img_name.c_str(), &lsvd_if,
// some of the ugliest lifetime management code you'll ever see, but
// it should work
[](void *arg, int rc) {
auto p = (std::promise<int> *)arg;
p->set_value(rc);
log_info("Image deletion done, rc = {}", rc);
auto cb = (std::function<void(int)> *)arg;
(*cb)(rc);
delete cb;
},
&p);
return p.get_future().get();
new std::function<void(int)>(cb));

if (rc != 0) {
log_error("Failed to delete image '{}': {}", img_name, rc);
cb(rc);
}
}
4 changes: 3 additions & 1 deletion src/bdev_lsvd.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#pragma once

#include <rados/librados.h>
#include <functional>

#include "config.h"

int bdev_lsvd_create(str img_name, rados_ioctx_t io_ctx, lsvd_config cfg);
int bdev_lsvd_delete(str img_name);
int bdev_lsvd_create(str pool_name, str image_name, str cfg_path);
void bdev_lsvd_delete(str img_name, std::function<void(int)> cb);
104 changes: 104 additions & 0 deletions src/bdev_lsvd_rpc.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include "spdk/bdev.h"
#include "spdk/json.h"
#include "spdk/jsonrpc.h"
#include "spdk/likely.h"
#include "spdk/log.h"
#include "spdk/nvme.h"
#include "spdk/rpc.h"
#include "spdk/util.h"

#include "bdev_lsvd.h"
#include "utils.h"

/**
* We only expose 2 RPC endpoints: create and delete. Unlike RBD, we will not
* have commands to manage ceph clusters; each image will create its own.
*/

struct rpc_create_lsvd {
char *image_name;
char *pool_name;
char *config;
};

static const struct spdk_json_object_decoder rpc_create_lsvd_decoders[] = {
{"image_name", offsetof(rpc_create_lsvd, image_name),
spdk_json_decode_string, false},
{"pool_name", offsetof(rpc_create_lsvd, pool_name), spdk_json_decode_string,
false},
{"config", offsetof(rpc_create_lsvd, config), spdk_json_decode_string,
true},
};

static void rpc_bdev_lsvd_create(spdk_jsonrpc_request *req_json,
const spdk_json_val *params)
{
std::unique_ptr<rpc_create_lsvd, decltype([](auto p) {
free(p->image_name);
free(p->pool_name);
free(p->config);
})>
req(new rpc_create_lsvd());

auto rc = spdk_json_decode_object(params, rpc_create_lsvd_decoders,
SPDK_COUNTOF(rpc_create_lsvd_decoders),
req.get());
if (rc != 0) {
spdk_jsonrpc_send_error_response(req_json, rc,
"Failed to parse rpc json");
return;
}

rc = bdev_lsvd_create(req->pool_name, req->image_name, req->config);
if (rc != 0) {
spdk_jsonrpc_send_error_response(req_json, rc,
"Failed to create lsvd bdev");
return;
}

auto w = spdk_jsonrpc_begin_result(req_json);
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(req_json, w);
}

SPDK_RPC_REGISTER("bdev_lsvd_create", rpc_bdev_lsvd_create, SPDK_RPC_RUNTIME)

struct rpc_delete_lsvd {
char *image_name;
};

static const struct spdk_json_object_decoder rpc_delete_lsvd_decoders[] = {
{"image_name", offsetof(rpc_delete_lsvd, image_name),
spdk_json_decode_string, false},
};

static void rpc_bdev_lsvd_delete(struct spdk_jsonrpc_request *req_json,
const struct spdk_json_val *params)
{
std::unique_ptr<rpc_delete_lsvd,
decltype([](auto p) { free(p->image_name); })>
req(new rpc_delete_lsvd());

int rc = spdk_json_decode_object(params, rpc_delete_lsvd_decoders,
SPDK_COUNTOF(rpc_delete_lsvd_decoders),
req.get());
if (rc != 0) {
spdk_jsonrpc_send_error_response(req_json, rc,
"Failed to parse rpc json");
return;
}

bdev_lsvd_delete(req->image_name, [=](int rc) {
if (rc == 0) {
auto w = spdk_jsonrpc_begin_result(req_json);
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(req_json, w);
} else {
log_error("Failed to destroy lsvd bdev, rc = {}", rc);
spdk_jsonrpc_send_error_response(req_json, rc,
"Failed to destroy lsvd bdev");
}
});
}

SPDK_RPC_REGISTER("bdev_lsvd_delete", rpc_bdev_lsvd_delete, SPDK_RPC_RUNTIME)
Loading

0 comments on commit b3e7810

Please sign in to comment.