From b73c52f10b0fe228ce3443d8ba8280039dd35198 Mon Sep 17 00:00:00 2001 From: Rafal Stefanowski Date: Sun, 6 Jun 2021 12:02:55 +0200 Subject: [PATCH] Set cleaning policy Add RPC methods for changing cleaning policy and parameters: - bdev_ocf_set_cleaning_alru - bdev_ocf_set_cleaning_acp - bdev_ocf_set_cleaning_nop Signed-off-by: Rafal Stefanowski --- module/bdev/ocf/vbdev_ocf.c | 122 ++++++++++++++++++++++ module/bdev/ocf/vbdev_ocf.h | 24 +++++ module/bdev/ocf/vbdev_ocf_rpc.c | 174 ++++++++++++++++++++++++++++++++ scripts/rpc.py | 43 ++++++++ scripts/rpc/bdev.py | 54 ++++++++++ 5 files changed, 417 insertions(+) diff --git a/module/bdev/ocf/vbdev_ocf.c b/module/bdev/ocf/vbdev_ocf.c index fa777969b15..4733011419d 100644 --- a/module/bdev/ocf/vbdev_ocf.c +++ b/module/bdev/ocf/vbdev_ocf.c @@ -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 */ diff --git a/module/bdev/ocf/vbdev_ocf.h b/module/bdev/ocf/vbdev_ocf.h index fa3814834e2..a98f9139e74 100644 --- a/module/bdev/ocf/vbdev_ocf.h +++ b/module/bdev/ocf/vbdev_ocf.h @@ -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 */ diff --git a/module/bdev/ocf/vbdev_ocf_rpc.c b/module/bdev/ocf/vbdev_ocf_rpc.c index ff1173bb3dc..411683289f2 100644 --- a/module/bdev/ocf/vbdev_ocf_rpc.c +++ b/module/bdev/ocf/vbdev_ocf_rpc.c @@ -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) diff --git a/scripts/rpc.py b/scripts/rpc.py index 87ba5e1d6fa..b7fe2229289 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -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, + 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, diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index c65896981bc..af223cb5d89 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -229,6 +229,60 @@ def bdev_ocf_set_cache_mode(client, name, mode): return client.call('bdev_ocf_set_cache_mode', params) +def bdev_ocf_set_cleaning_alru(client, name, wake_up, staleness_time, + flush_max_buffers, activity_threshold): + """Set ALRU cleaning policy with parameters on OCF cache device + + Args: + name: name of OCF bdev + wake_up: Period of time between awakenings of flushing thread <0-3600>[s] + staleness_time: Time that has to pass from the last write operation before a + dirty cache block can be scheduled to be flushed <1-3600>[s] + flush_max_buffers: Number of dirty cache blocks to be flushed + in one cleaning cycle <1-10000> + activity_threshold: Cache idle time before flushing + thread can start <0-1000000>[ms] + """ + params = { + 'name': name, + 'wake_up': wake_up, + 'staleness_time': staleness_time, + 'flush_max_buffers': flush_max_buffers, + 'activity_threshold': activity_threshold, + } + + return client.call('bdev_ocf_set_cleaning_alru', params) + + +def bdev_ocf_set_cleaning_acp(client, name, wake_up, flush_max_buffers): + """Set ACP cleaning policy with parameters on OCF cache device + + Args: + name: name of OCF bdev + wake_up: Time between ACP cleaning thread iterations <0-10000>[ms] + flush_max_buffers: Number of cache lines flushed in single + ACP cleaning thread iteration <1-10000> + """ + params = { + 'name': name, + 'wake_up': wake_up, + 'flush_max_buffers': flush_max_buffers, + } + + return client.call('bdev_ocf_set_cleaning_acp', params) + + +def bdev_ocf_set_cleaning_nop(client, name): + """Set NOP cleaning policy on OCF cache device + + Args: + name: name of OCF bdev + """ + params = {'name': name} + + return client.call('bdev_ocf_set_cleaning_nop', params) + + @deprecated_alias('construct_malloc_bdev') def bdev_malloc_create(client, num_blocks, block_size, name=None, uuid=None): """Construct a malloc block device.