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. The Rpc configuration file section, which was deprecated in v18.01, has been removed.
Users should switch to the `-r` command-line parameter instead. 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 ### NVMe Driver
EXPERIMENTAL: Adds support for WDS and RDS capable CMBs in NVMe controllers. This support is 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" #include "spdk_internal/log.h"
#define SPDK_JSONRPC_RECV_BUF_SIZE (32 * 1024) #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_ID_MAX_LEN 128
#define SPDK_JSONRPC_MAX_CONNS 64 #define SPDK_JSONRPC_MAX_CONNS 64
#define SPDK_JSONRPC_MAX_VALUES 1024 #define SPDK_JSONRPC_MAX_VALUES 1024
@ -54,9 +55,15 @@ struct spdk_jsonrpc_request {
struct spdk_json_val id; struct spdk_json_val id;
uint8_t id_data[SPDK_JSONRPC_ID_MAX_LEN]; 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_len;
size_t send_offset; size_t send_offset;
uint8_t send_buf[SPDK_JSONRPC_SEND_BUF_SIZE];
uint8_t *send_buf;
}; };
struct spdk_jsonrpc_server_conn { 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->id.type = SPDK_JSON_VAL_INVALID;
request->send_offset = 0; request->send_offset = 0;
request->send_len = 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) { if (rc < 0 || rc > SPDK_JSONRPC_MAX_VALUES) {
SPDK_DEBUGLOG(SPDK_LOG_RPC, "JSON parse error\n"); 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) spdk_jsonrpc_server_write_cb(void *cb_ctx, const void *data, size_t size)
{ {
struct spdk_jsonrpc_request *request = cb_ctx; 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) { while (new_size - request->send_len < size) {
SPDK_ERRLOG("Not enough space in send buf\n"); if (new_size >= SPDK_JSONRPC_SEND_BUF_SIZE_MAX) {
return -1; 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); memcpy(request->send_buf + request->send_len, data, size);
@ -229,6 +256,7 @@ void
spdk_jsonrpc_free_request(struct spdk_jsonrpc_request *request) spdk_jsonrpc_free_request(struct spdk_jsonrpc_request *request)
{ {
request->conn->outstanding_requests--; request->conn->outstanding_requests--;
free(request->send_buf);
free(request); free(request);
} }

View File

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