jsonrpc: allow send_buf to grow as needed

Reallocate the send buffer if more data is written by the RPC handler
than currently fits in the buffer.

Change-Id: I590dd173b843aba48c768adfafaf87e4b47bcc19
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/399925
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Daniel Verkamp 2018-02-14 10:12:50 -07:00 committed by Jim Harris
parent 114a91fdea
commit c7852cf98d
4 changed files with 56 additions and 8 deletions

View File

@ -7,6 +7,9 @@
The Rpc configuration file section, which was deprecated in v18.01, has been removed.
Users should switch to the `-r` command-line parameter instead.
The JSON-RPC server implementation now allows up to 32 megabyte responses, growing as
needed; previously, the response was limited to 32 kilobytes.
### NVMe Driver
EXPERIMENTAL: Adds support for WDS and RDS capable CMBs in NVMe controllers. This support is

View File

@ -42,7 +42,8 @@
#include "spdk_internal/log.h"
#define SPDK_JSONRPC_RECV_BUF_SIZE (32 * 1024)
#define SPDK_JSONRPC_SEND_BUF_SIZE (32 * 1024)
#define SPDK_JSONRPC_SEND_BUF_SIZE_INIT (32 * 1024)
#define SPDK_JSONRPC_SEND_BUF_SIZE_MAX (32 * 1024 * 1024)
#define SPDK_JSONRPC_ID_MAX_LEN 128
#define SPDK_JSONRPC_MAX_CONNS 64
#define SPDK_JSONRPC_MAX_VALUES 1024
@ -54,9 +55,15 @@ struct spdk_jsonrpc_request {
struct spdk_json_val id;
uint8_t id_data[SPDK_JSONRPC_ID_MAX_LEN];
/* Total space allocated for send_buf */
size_t send_buf_size;
/* Number of bytes used in send_buf (<= send_buf_size) */
size_t send_len;
size_t send_offset;
uint8_t send_buf[SPDK_JSONRPC_SEND_BUF_SIZE];
uint8_t *send_buf;
};
struct spdk_jsonrpc_server_conn {

View File

@ -144,6 +144,13 @@ spdk_jsonrpc_parse_request(struct spdk_jsonrpc_server_conn *conn, void *json, si
request->id.type = SPDK_JSON_VAL_INVALID;
request->send_offset = 0;
request->send_len = 0;
request->send_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT;
request->send_buf = malloc(request->send_buf_size);
if (request->send_buf == NULL) {
SPDK_ERRLOG("Failed to allocate send_buf (%zu bytes)\n", request->send_buf_size);
free(request);
return -1;
}
if (rc < 0 || rc > SPDK_JSONRPC_MAX_VALUES) {
SPDK_DEBUGLOG(SPDK_LOG_RPC, "JSON parse error\n");
@ -184,10 +191,30 @@ static int
spdk_jsonrpc_server_write_cb(void *cb_ctx, const void *data, size_t size)
{
struct spdk_jsonrpc_request *request = cb_ctx;
size_t new_size = request->send_buf_size;
if (SPDK_JSONRPC_SEND_BUF_SIZE - request->send_len < size) {
SPDK_ERRLOG("Not enough space in send buf\n");
return -1;
while (new_size - request->send_len < size) {
if (new_size >= SPDK_JSONRPC_SEND_BUF_SIZE_MAX) {
SPDK_ERRLOG("Send buf exceeded maximum size (%zu)\n",
(size_t)SPDK_JSONRPC_SEND_BUF_SIZE_MAX);
return -1;
}
new_size *= 2;
}
if (new_size != request->send_buf_size) {
uint8_t *new_buf;
new_buf = realloc(request->send_buf, new_size);
if (new_buf == NULL) {
SPDK_ERRLOG("Resizing send_buf failed (current size %zu, new size %zu)\n",
request->send_buf_size, new_size);
return -1;
}
request->send_buf = new_buf;
request->send_buf_size = new_size;
}
memcpy(request->send_buf + request->send_len, data, size);
@ -229,6 +256,7 @@ void
spdk_jsonrpc_free_request(struct spdk_jsonrpc_request *request)
{
request->conn->outstanding_requests--;
free(request->send_buf);
free(request);
}

View File

@ -61,14 +61,21 @@ static size_t g_num_reqs;
memcpy(g_buf, in, sizeof(in) - 1); \
g_num_reqs = 0; \
g_cur_req = NULL; \
CU_ASSERT(spdk_jsonrpc_parse_request(conn, g_buf, sizeof(in) - 1) == sizeof(in) - sizeof(trailing))
CU_ASSERT(spdk_jsonrpc_parse_request(conn, g_buf, sizeof(in) - 1) == sizeof(in) - sizeof(trailing)); \
if (g_cur_req && g_cur_req->request) { \
free(g_cur_req->request->send_buf); \
g_cur_req->request->send_buf = NULL; \
}
#define PARSE_FAIL(in) \
memcpy(g_buf, in, sizeof(in) - 1); \
g_num_reqs = 0; \
g_cur_req = 0; \
CU_ASSERT(spdk_jsonrpc_parse_request(conn, g_buf, sizeof(in) - 1) < 0)
CU_ASSERT(spdk_jsonrpc_parse_request(conn, g_buf, sizeof(in) - 1) < 0); \
if (g_cur_req && g_cur_req->request) { \
free(g_cur_req->request->send_buf); \
g_cur_req->request->send_buf = NULL; \
}
#define REQ_BEGIN(expected_error) \
if (g_cur_req == NULL) { \
@ -148,6 +155,9 @@ static size_t g_num_reqs;
g_params++
#define FREE_REQUEST() \
if (g_reqs->request) { \
free(g_reqs->request->send_buf); \
} \
free(g_reqs->request); \
g_reqs->request = NULL