Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[experimental]Set cleaning policy #27

Open
wants to merge 1 commit into
base: experimental
Choose a base branch
from
Open
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
122 changes: 122 additions & 0 deletions module/bdev/ocf/vbdev_ocf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,128 @@ vbdev_ocf_set_cache_mode(struct vbdev_ocf *vbdev,
cb(rc, vbdev, cb_arg);
}

/* Set ALRU cleaning policy with parameters on OCF cache */
void
vbdev_ocf_set_cleaning_alru(
struct vbdev_ocf *vbdev,
int32_t wake_up,
int32_t staleness_time,
int32_t flush_max_buffers,
int32_t activity_threshold,
void (*cb)(int, void *),
void *cb_arg)
{
ocf_cache_t cache;
int rc;

cache = vbdev->ocf_cache;

rc = ocf_mngt_cache_trylock(cache);
if (rc) {
cb(rc, cb_arg);
return;
}

rc = ocf_mngt_cache_cleaning_set_policy(cache, ocf_cleaning_alru);
if (rc)
goto end;

if (wake_up >= 0) {
rc = ocf_mngt_cache_cleaning_set_param(cache, ocf_cleaning_alru,
ocf_alru_wake_up_time, wake_up);
if (rc)
goto end;
}
if (staleness_time >= 0) {
rc = ocf_mngt_cache_cleaning_set_param(cache, ocf_cleaning_alru,
ocf_alru_stale_buffer_time, staleness_time);
if (rc)
goto end;
}
if (flush_max_buffers >= 0) {
rc = ocf_mngt_cache_cleaning_set_param(cache, ocf_cleaning_alru,
ocf_alru_flush_max_buffers, flush_max_buffers);
if (rc)
goto end;
}
if (activity_threshold >= 0) {
rc = ocf_mngt_cache_cleaning_set_param(cache, ocf_cleaning_alru,
ocf_alru_activity_threshold, activity_threshold);
if (rc)
goto end;
}

end:
ocf_mngt_cache_unlock(cache);
cb(rc, cb_arg);
}

/* Set ACP cleaning policy with parameters on OCF cache */
void
vbdev_ocf_set_cleaning_acp(
struct vbdev_ocf *vbdev,
int32_t wake_up,
int32_t flush_max_buffers,
void (*cb)(int, void *),
void *cb_arg)
{
ocf_cache_t cache;
int rc;

cache = vbdev->ocf_cache;

rc = ocf_mngt_cache_trylock(cache);
if (rc) {
cb(rc, cb_arg);
return;
}

rc = ocf_mngt_cache_cleaning_set_policy(cache, ocf_cleaning_acp);
if (rc)
goto end;

if (wake_up >= 0) {
rc = ocf_mngt_cache_cleaning_set_param(cache, ocf_cleaning_acp,
ocf_acp_wake_up_time, wake_up);
if (rc)
goto end;
}
if (flush_max_buffers >= 0) {
rc = ocf_mngt_cache_cleaning_set_param(cache, ocf_cleaning_acp,
ocf_acp_flush_max_buffers, flush_max_buffers);
if (rc)
goto end;
}

end:
ocf_mngt_cache_unlock(cache);
cb(rc, cb_arg);
}

/* Set NOP cleaning policy on OCF cache */
void
vbdev_ocf_set_cleaning_nop(
struct vbdev_ocf *vbdev,
void (*cb)(int, void *),
void *cb_arg)
{
ocf_cache_t cache;
int rc;

cache = vbdev->ocf_cache;

rc = ocf_mngt_cache_trylock(cache);
if (rc) {
cb(rc, cb_arg);
return;
}

rc = ocf_mngt_cache_cleaning_set_policy(cache, ocf_cleaning_nop);

ocf_mngt_cache_unlock(cache);
cb(rc, cb_arg);
}

/* This called if new device is created in SPDK application
* If that device named as one of base bdevs of OCF vbdev,
* claim and open them */
Expand Down
24 changes: 24 additions & 0 deletions module/bdev/ocf/vbdev_ocf.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,30 @@ void vbdev_ocf_set_cache_mode(
void (*cb)(int, struct vbdev_ocf *, void *),
void *cb_arg);

/* Set ALRU cleaning policy with parameters on OCF cache */
void vbdev_ocf_set_cleaning_alru(
struct vbdev_ocf *vbdev,
int32_t wake_up,
int32_t staleness_time,
int32_t flush_max_buffers,
int32_t activity_threshold,
void (*cb)(int, void *),
void *cb_arg);

/* Set ACP cleaning policy with parameters on OCF cache */
void vbdev_ocf_set_cleaning_acp(
struct vbdev_ocf *vbdev,
int32_t wake_up,
int32_t flush_max_buffers,
void (*cb)(int, void *),
void *cb_arg);

/* Set NOP cleaning policy on OCF cache */
void vbdev_ocf_set_cleaning_nop(
struct vbdev_ocf *vbdev,
void (*cb)(int, void *),
void *cb_arg);

typedef void (*vbdev_ocf_foreach_fn)(struct vbdev_ocf *, void *);

/* Execute fn for each OCF device that is online or waits for base devices */
Expand Down
174 changes: 174 additions & 0 deletions module/bdev/ocf/vbdev_ocf_rpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,177 @@ rpc_bdev_ocf_set_cache_mode(struct spdk_jsonrpc_request *request,
free_rpc_bdev_ocf_set_cache_mode(&req);
}
SPDK_RPC_REGISTER("bdev_ocf_set_cache_mode", rpc_bdev_ocf_set_cache_mode, SPDK_RPC_RUNTIME)

static void
cleaning_cb(int status, void *cb_arg)
{
struct spdk_jsonrpc_request *request = cb_arg;

if (status) {
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"OCF could not set cleaning policy: %d", status);
} else {
spdk_jsonrpc_send_bool_response(request, true);
}
}

/* Structure to hold the parameters for this RPC method. */
struct rpc_bdev_ocf_set_cleaning_alru {
char *name; /* main vbdev name */
int32_t wake_up;
int32_t staleness_time;
int32_t flush_max_buffers;
int32_t activity_threshold;
};

static void
free_rpc_bdev_ocf_set_cleaning_alru(struct rpc_bdev_ocf_set_cleaning_alru *r)
{
free(r->name);
}

/* Structure to decode the input parameters for this RPC method. */
static const struct spdk_json_object_decoder rpc_bdev_ocf_set_cleaning_alru_decoders[] = {
{"name", offsetof(struct rpc_bdev_ocf_set_cleaning_alru, name),
spdk_json_decode_string},
{"wake_up", offsetof(struct rpc_bdev_ocf_set_cleaning_alru, wake_up),
spdk_json_decode_int32},
{"staleness_time", offsetof(struct rpc_bdev_ocf_set_cleaning_alru, staleness_time),
spdk_json_decode_int32},
{"flush_max_buffers", offsetof(struct rpc_bdev_ocf_set_cleaning_alru, flush_max_buffers),
spdk_json_decode_int32},
{"activity_threshold", offsetof(struct rpc_bdev_ocf_set_cleaning_alru, activity_threshold),
spdk_json_decode_int32},
};

static void
rpc_bdev_ocf_set_cleaning_alru(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_bdev_ocf_set_cleaning_alru req = {NULL};
struct vbdev_ocf *vbdev;
int ret;

ret = spdk_json_decode_object(params, rpc_bdev_ocf_set_cleaning_alru_decoders,
SPDK_COUNTOF(rpc_bdev_ocf_set_cleaning_alru_decoders), &req);
if (ret) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"Invalid parameters");
goto end;
}

vbdev = vbdev_ocf_get_by_name(req.name);
if (vbdev == NULL) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
spdk_strerror(ENODEV));
goto end;
}

vbdev_ocf_set_cleaning_alru(vbdev, req.wake_up, req.staleness_time,
req.flush_max_buffers, req.activity_threshold, cleaning_cb, request);

end:
free_rpc_bdev_ocf_set_cleaning_alru(&req);
}
SPDK_RPC_REGISTER("bdev_ocf_set_cleaning_alru", rpc_bdev_ocf_set_cleaning_alru, SPDK_RPC_RUNTIME)

/* Structure to hold the parameters for this RPC method. */
struct rpc_bdev_ocf_set_cleaning_acp {
char *name; /* main vbdev name */
int32_t wake_up;
int32_t flush_max_buffers;
};

static void
free_rpc_bdev_ocf_set_cleaning_acp(struct rpc_bdev_ocf_set_cleaning_acp *r)
{
free(r->name);
}

/* Structure to decode the input parameters for this RPC method. */
static const struct spdk_json_object_decoder rpc_bdev_ocf_set_cleaning_acp_decoders[] = {
{"name", offsetof(struct rpc_bdev_ocf_set_cleaning_acp, name),
spdk_json_decode_string},
{"wake_up", offsetof(struct rpc_bdev_ocf_set_cleaning_acp, wake_up),
spdk_json_decode_int32},
{"flush_max_buffers", offsetof(struct rpc_bdev_ocf_set_cleaning_acp, flush_max_buffers),
spdk_json_decode_int32},
};

static void
rpc_bdev_ocf_set_cleaning_acp(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_bdev_ocf_set_cleaning_acp req = {NULL};
struct vbdev_ocf *vbdev;
int ret;

ret = spdk_json_decode_object(params, rpc_bdev_ocf_set_cleaning_acp_decoders,
SPDK_COUNTOF(rpc_bdev_ocf_set_cleaning_acp_decoders), &req);
if (ret) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"Invalid parameters");
goto end;
}

vbdev = vbdev_ocf_get_by_name(req.name);
if (vbdev == NULL) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
spdk_strerror(ENODEV));
goto end;
}

vbdev_ocf_set_cleaning_acp(vbdev, req.wake_up, req.flush_max_buffers,
cleaning_cb, request);

end:
free_rpc_bdev_ocf_set_cleaning_acp(&req);
}
SPDK_RPC_REGISTER("bdev_ocf_set_cleaning_acp", rpc_bdev_ocf_set_cleaning_acp, SPDK_RPC_RUNTIME)

/* Structure to hold the parameters for this RPC method. */
struct rpc_bdev_ocf_set_cleaning_nop {
char *name; /* main vbdev name */
};

static void
free_rpc_bdev_ocf_set_cleaning_nop(struct rpc_bdev_ocf_set_cleaning_nop *r)
{
free(r->name);
}

/* Structure to decode the input parameters for this RPC method. */
static const struct spdk_json_object_decoder rpc_bdev_ocf_set_cleaning_nop_decoders[] = {
{"name", offsetof(struct rpc_bdev_ocf_set_cleaning_nop, name),
spdk_json_decode_string},
};

static void
rpc_bdev_ocf_set_cleaning_nop(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_bdev_ocf_set_cleaning_nop req = {NULL};
struct vbdev_ocf *vbdev;
int ret;

ret = spdk_json_decode_object(params, rpc_bdev_ocf_set_cleaning_nop_decoders,
SPDK_COUNTOF(rpc_bdev_ocf_set_cleaning_nop_decoders), &req);
if (ret) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"Invalid parameters");
goto end;
}

vbdev = vbdev_ocf_get_by_name(req.name);
if (vbdev == NULL) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
spdk_strerror(ENODEV));
goto end;
}

vbdev_ocf_set_cleaning_nop(vbdev, cleaning_cb, request);

end:
free_rpc_bdev_ocf_set_cleaning_nop(&req);
}
SPDK_RPC_REGISTER("bdev_ocf_set_cleaning_nop", rpc_bdev_ocf_set_cleaning_nop, SPDK_RPC_RUNTIME)
43 changes: 43 additions & 0 deletions scripts/rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,49 @@ def bdev_ocf_set_cache_mode(args):
p.add_argument('mode', help='OCF cache mode', choices=['wb', 'wt', 'pt', 'wa', 'wi', 'wo'])
p.set_defaults(func=bdev_ocf_set_cache_mode)

def bdev_ocf_set_cleaning_alru(args):
print_json(rpc.bdev.bdev_ocf_set_cleaning_alru(args.client,
name=args.name,
wake_up=args.wake_up,
staleness_time=args.staleness_time,
flush_max_buffers=args.flush_max_buffers,
activity_threshold=args.activity_threshold))
p = subparsers.add_parser('bdev_ocf_set_cleaning_alru',
help='Set ALRU cleaning policy with parameters on OCF cache device')
p.add_argument('name', help='Name of OCF bdev')
p.add_argument('-w', '--wake-up', type=int, default=-1,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be better to set the default implicitly to 20 here (and other default values too) and not base it on defaults in OCF? In that case changing the type to uint32 would also be useful, I think.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are two problems with your proposed approach:

  1. SPDK maintainers prefer to be as independent as possible from any hard-coded values. This way, when we change OCF defaults in the future, there will be no need to update them also in SPDK adapter.
  2. Some of those parameters takes a range from 0 to some value, so the default=-1 informs of no change to that particular parameter. I think it will be much more obfuscated to handle this situation using different type of variable here.

help='Period of time between awakenings of flushing thread <0-3600>[s] (default: 20 s)')
p.add_argument('-s', '--staleness-time', type=int, default=-1,
help='Time that has to pass from the last write operation before a dirty cache block '
'can be scheduled to be flushed <1-3600>[s] (default: 120 s)')
p.add_argument('-b', '--flush-max-buffers', type=int, default=-1,
help='Number of dirty cache blocks to be flushed in one cleaning cycle <1-10000> (default: 100)')
p.add_argument('-t', '--activity-threshold', type=int, default=-1,
help='Cache idle time before flushing thread can start <0-1000000>[ms] (default: 10000 ms)')
p.set_defaults(func=bdev_ocf_set_cleaning_alru)

def bdev_ocf_set_cleaning_acp(args):
print_json(rpc.bdev.bdev_ocf_set_cleaning_acp(args.client,
name=args.name,
wake_up=args.wake_up,
flush_max_buffers=args.flush_max_buffers))
p = subparsers.add_parser('bdev_ocf_set_cleaning_acp',
help='Set ACP cleaning policy with parameters on OCF cache device')
p.add_argument('name', help='Name of OCF bdev')
p.add_argument('-w', '--wake-up', type=int, default=-1,
help='Time between ACP cleaning thread iterations <0-10000>[ms] (default: 10 ms)')
p.add_argument('-b', '--flush-max-buffers', type=int, default=-1,
help='Number of cache lines flushed in single ACP cleaning thread iteration <1-10000> (default: 128)')
p.set_defaults(func=bdev_ocf_set_cleaning_acp)

def bdev_ocf_set_cleaning_nop(args):
print_json(rpc.bdev.bdev_ocf_set_cleaning_nop(args.client,
name=args.name))
p = subparsers.add_parser('bdev_ocf_set_cleaning_nop',
help='Set NOP cleaning policy on OCF cache device')
p.add_argument('name', help='Name of OCF bdev')
p.set_defaults(func=bdev_ocf_set_cleaning_nop)

def bdev_malloc_create(args):
num_blocks = (args.total_size * 1024 * 1024) // args.block_size
print_json(rpc.bdev.bdev_malloc_create(args.client,
Expand Down
Loading