Commit d8e2f663 authored by Krzysztof Karas's avatar Krzysztof Karas Committed by Tomasz Zawadzki
Browse files

rpc: encapsulate RPC server specific data



Move listen address, lock path and lock fd to a new structure
describing RPC server.

RPC state and allowlist remain application wide parameters.

Next patch will introduce new set of APIs to manage RPC server
objects instead of using a single global instance in lib/rpc.

spdk_rpc_listen() and spdk_rpc_close() must be deprecated first and
the new listening functions will use majority of the code from
spdk_rpc_listen() in an unchanged form (apart from using a server
pointer instead of reference to global instance).

Change-Id: I5e59f63c5c796f0b4a47832cc67d1595b058a4b9
Signed-off-by: default avatarKrzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/21078


Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
parent 158d15b7
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
extern "C" {
#endif

struct spdk_rpc_server;

/**
 * Verify correctness of registered RPC methods and aliases.
 *
+78 −56
Original line number Diff line number Diff line
@@ -16,15 +16,19 @@
#include "spdk/util.h"
#include "spdk/version.h"

static struct sockaddr_un g_rpc_listen_addr_unix = {};
static char g_rpc_lock_path[sizeof(g_rpc_listen_addr_unix.sun_path) + sizeof(".lock")];
static int g_rpc_lock_fd = -1;

static struct spdk_jsonrpc_server *g_jsonrpc_server = NULL;
static uint32_t g_rpc_state = SPDK_RPC_STARTUP;
static bool g_rpcs_correct = true;
static char **g_rpcs_allowlist = NULL;

struct spdk_rpc_server {
	struct sockaddr_un listen_addr_unix;
	char lock_path[sizeof(((struct sockaddr_un *)0)->sun_path) + sizeof(".lock")];
	int lock_fd;
	struct spdk_jsonrpc_server *jsonrpc_server;
};

static struct spdk_rpc_server g_rpc_server;

struct spdk_rpc_method {
	const char *name;
	spdk_rpc_method_handler func;
@@ -141,47 +145,40 @@ jsonrpc_handler(struct spdk_jsonrpc_request *request,
	}
}

int
spdk_rpc_listen(const char *listen_addr)
static int
_spdk_rpc_listen(const char *listen_addr, struct spdk_rpc_server *server)
{
	int rc;

	memset(&g_rpc_listen_addr_unix, 0, sizeof(g_rpc_listen_addr_unix));
	assert(listen_addr != NULL);

	g_rpc_listen_addr_unix.sun_family = AF_UNIX;
	rc = snprintf(g_rpc_listen_addr_unix.sun_path,
		      sizeof(g_rpc_listen_addr_unix.sun_path),
	server->listen_addr_unix.sun_family = AF_UNIX;
	rc = snprintf(server->listen_addr_unix.sun_path,
		      sizeof(server->listen_addr_unix.sun_path),
		      "%s", listen_addr);
	if (rc < 0 || (size_t)rc >= sizeof(g_rpc_listen_addr_unix.sun_path)) {
	if (rc < 0 || (size_t)rc >= sizeof(server->listen_addr_unix.sun_path)) {
		SPDK_ERRLOG("RPC Listen address Unix socket path too long\n");
		g_rpc_listen_addr_unix.sun_path[0] = '\0';
		return -1;
	}

	rc = snprintf(g_rpc_lock_path, sizeof(g_rpc_lock_path), "%s.lock",
		      g_rpc_listen_addr_unix.sun_path);
	if (rc < 0 || (size_t)rc >= sizeof(g_rpc_lock_path)) {
	rc = snprintf(server->lock_path, sizeof(server->lock_path), "%s.lock",
		      server->listen_addr_unix.sun_path);
	if (rc < 0 || (size_t)rc >= sizeof(server->lock_path)) {
		SPDK_ERRLOG("RPC lock path too long\n");
		g_rpc_listen_addr_unix.sun_path[0] = '\0';
		g_rpc_lock_path[0] = '\0';
		return -1;
	}

	g_rpc_lock_fd = open(g_rpc_lock_path, O_RDWR | O_CREAT, 0600);
	if (g_rpc_lock_fd == -1) {
	server->lock_fd = open(server->lock_path, O_RDWR | O_CREAT, 0600);
	if (server->lock_fd == -1) {
		SPDK_ERRLOG("Cannot open lock file %s: %s\n",
			    g_rpc_lock_path, spdk_strerror(errno));
		g_rpc_listen_addr_unix.sun_path[0] = '\0';
		g_rpc_lock_path[0] = '\0';
			    server->lock_path, spdk_strerror(errno));
		return -1;
	}

	rc = flock(g_rpc_lock_fd, LOCK_EX | LOCK_NB);
	rc = flock(server->lock_fd, LOCK_EX | LOCK_NB);
	if (rc != 0) {
		SPDK_ERRLOG("RPC Unix domain socket path %s in use. Specify another.\n",
			    g_rpc_listen_addr_unix.sun_path);
		g_rpc_listen_addr_unix.sun_path[0] = '\0';
		g_rpc_lock_path[0] = '\0';
			    server->listen_addr_unix.sun_path);
		return -1;
	}

@@ -189,28 +186,44 @@ spdk_rpc_listen(const char *listen_addr)
	 * Since we acquired the lock, it is safe to delete the Unix socket file
	 * if it still exists from a previous process.
	 */
	unlink(g_rpc_listen_addr_unix.sun_path);
	unlink(server->listen_addr_unix.sun_path);

	g_jsonrpc_server = spdk_jsonrpc_server_listen(AF_UNIX, 0,
			   (struct sockaddr *)&g_rpc_listen_addr_unix,
			   sizeof(g_rpc_listen_addr_unix),
	server->jsonrpc_server = spdk_jsonrpc_server_listen(AF_UNIX, 0,
				 (struct sockaddr *) & server->listen_addr_unix,
				 sizeof(server->listen_addr_unix),
				 jsonrpc_handler);
	if (g_jsonrpc_server == NULL) {
	if (server->jsonrpc_server == NULL) {
		SPDK_ERRLOG("spdk_jsonrpc_server_listen() failed\n");
		close(g_rpc_lock_fd);
		g_rpc_lock_fd = -1;
		unlink(g_rpc_lock_path);
		g_rpc_lock_path[0] = '\0';
		close(server->lock_fd);
		unlink(server->lock_path);
		return -1;
	}

	return 0;
}

int
spdk_rpc_listen(const char *listen_addr)
{
	struct spdk_rpc_server *server;
	int rc;

	memset(&g_rpc_server.listen_addr_unix, 0, sizeof(g_rpc_server.listen_addr_unix));
	server = &g_rpc_server;

	rc = _spdk_rpc_listen(listen_addr, server);
	if (rc) {
		server->listen_addr_unix.sun_path[0] = '\0';
		server->lock_path[0] = '\0';
	}

	return rc;
}

void
spdk_rpc_accept(void)
{
	spdk_jsonrpc_server_poll(g_jsonrpc_server);
	spdk_jsonrpc_server_poll(g_rpc_server.jsonrpc_server);
}

void
@@ -330,28 +343,37 @@ spdk_rpc_set_allowlist(const char **rpc_allowlist)
	assert(g_rpcs_allowlist != NULL);
}

void
spdk_rpc_close(void)
static void
_spdk_rpc_close(struct spdk_rpc_server *server)
{
	if (g_jsonrpc_server) {
		if (g_rpc_listen_addr_unix.sun_path[0]) {
	assert(server != NULL);
	assert(server->jsonrpc_server != NULL);

	if (server->listen_addr_unix.sun_path[0]) {
		/* Delete the Unix socket file */
			unlink(g_rpc_listen_addr_unix.sun_path);
			g_rpc_listen_addr_unix.sun_path[0] = '\0';
		unlink(server->listen_addr_unix.sun_path);
		server->listen_addr_unix.sun_path[0] = '\0';
	}

		spdk_jsonrpc_server_shutdown(g_jsonrpc_server);
		g_jsonrpc_server = NULL;
	spdk_jsonrpc_server_shutdown(server->jsonrpc_server);
	server->jsonrpc_server = NULL;

		if (g_rpc_lock_fd != -1) {
			close(g_rpc_lock_fd);
			g_rpc_lock_fd = -1;
	if (server->lock_fd != -1) {
		close(server->lock_fd);
		server->lock_fd = -1;
	}

		if (g_rpc_lock_path[0]) {
			unlink(g_rpc_lock_path);
			g_rpc_lock_path[0] = '\0';
	if (server->lock_path[0]) {
		unlink(server->lock_path);
		server->lock_path[0] = '\0';
	}
}

void
spdk_rpc_close(void)
{
	if (g_rpc_server.jsonrpc_server) {
		_spdk_rpc_close(&g_rpc_server);
	}
}

+10 −10
Original line number Diff line number Diff line
@@ -222,20 +222,20 @@ test_spdk_rpc_listen_close(void)
	MOCK_SET(flock, 0);

	spdk_rpc_listen(listen_addr);
	snprintf(rpc_lock_path, sizeof(g_rpc_lock_path), "%s.lock",
		 g_rpc_listen_addr_unix.sun_path);
	snprintf(rpc_lock_path, sizeof(g_rpc_server.lock_path), "%s.lock",
		 g_rpc_server.listen_addr_unix.sun_path);

	CU_ASSERT(g_rpc_listen_addr_unix.sun_family == AF_UNIX);
	CU_ASSERT(strcmp(g_rpc_listen_addr_unix.sun_path, listen_addr) == 0);
	CU_ASSERT(strcmp(g_rpc_lock_path, rpc_lock_path) == 0);
	CU_ASSERT(g_jsonrpc_server == (struct spdk_jsonrpc_server *)0Xdeaddead);
	CU_ASSERT(g_rpc_server.listen_addr_unix.sun_family == AF_UNIX);
	CU_ASSERT(strcmp(g_rpc_server.listen_addr_unix.sun_path, listen_addr) == 0);
	CU_ASSERT(strcmp(g_rpc_server.lock_path, rpc_lock_path) == 0);
	CU_ASSERT(g_rpc_server.jsonrpc_server == (struct spdk_jsonrpc_server *)0Xdeaddead);

	spdk_rpc_close();

	CU_ASSERT(g_rpc_listen_addr_unix.sun_path[0] == '\0');
	CU_ASSERT(g_jsonrpc_server == NULL);
	CU_ASSERT(g_rpc_lock_fd == -1);
	CU_ASSERT(g_rpc_lock_path[0] == '\0');
	CU_ASSERT(g_rpc_server.listen_addr_unix.sun_path[0] == '\0');
	CU_ASSERT(g_rpc_server.jsonrpc_server == NULL);
	CU_ASSERT(g_rpc_server.lock_fd == -1);
	CU_ASSERT(g_rpc_server.lock_path[0] == '\0');

	MOCK_CLEAR(open);
	MOCK_CLEAR(close);