[sanlock] branch master updated: sanlock: socket send and recv
retries
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
teigland pushed a commit to branch master
in repository sanlock.
The following commit(s) were added to refs/heads/master by this push:
new 8e4af6e sanlock: socket send and recv retries
8e4af6e is described below
commit 8e4af6ef6201aa7c7aa9aaeeadee9fc7ce2f476d
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue May 4 13:38:53 2021 -0500
sanlock: socket send and recv retries
ignore EINTR from send() and recv()
check for and handle partial send()
for completeness, not seen in practice.
---
src/client.c | 28 ++++++--
src/client_cmd.c | 24 ++++++-
src/cmd.c | 206 ++++++++++++++++++++++++++++++++-----------------------
src/lockspace.c | 4 +-
src/main.c | 19 ++++-
5 files changed, 183 insertions(+), 98 deletions(-)
diff --git a/src/client.c b/src/client.c
index 89fb68e..5dc7650 100644
--- a/src/client.c
+++ b/src/client.c
@@ -74,7 +74,9 @@ static int send_header(int sock, int cmd, uint32_t cmd_flags, int datalen,
uint32_t data, uint32_t data2)
{
struct sm_header header;
- int rv;
+ size_t rem = sizeof(header);
+ size_t off = 0;
+ ssize_t rv;
memset(&header, 0, sizeof(header));
header.magic = SM_MAGIC;
@@ -86,24 +88,36 @@ static int send_header(int sock, int cmd, uint32_t cmd_flags, int datalen,
header.data2 = data2;
retry:
- rv = send(sock, (void *) &header, sizeof(header), 0);
+ rv = send(sock, (char *)&header + off, rem, 0);
if (rv == -1 && errno == EINTR)
goto retry;
-
if (rv < 0)
return -errno;
-
+ if (rv < rem) {
+ rem -= rv;
+ off += rv;
+ goto retry;
+ }
return 0;
}
static ssize_t send_data(int sockfd, const void *buf, size_t len, int flags)
{
+ size_t rem = len;
+ size_t off = 0;
ssize_t rv;
retry:
- rv = send(sockfd, buf, len, flags);
+ rv = send(sockfd, (char *)buf + off, rem, flags);
if (rv == -1 && errno == EINTR)
goto retry;
- return rv;
+ if (rv < 0)
+ return -errno;
+ if (rv < rem) {
+ rem -= rv;
+ off += rv;
+ goto retry;
+ }
+ return 0;
}
static ssize_t recv_data(int sockfd, void *buf, size_t len, int flags)
@@ -138,7 +152,7 @@ int send_command(int cmd, uint32_t data)
static int recv_result(int fd)
{
struct sm_header h;
- int rv;
+ ssize_t rv;
memset(&h, 0, sizeof(h));
retry:
diff --git a/src/client_cmd.c b/src/client_cmd.c
index fb22435..e06d0f7 100644
--- a/src/client_cmd.c
+++ b/src/client_cmd.c
@@ -56,6 +56,26 @@ static void print_debug(char *str, int len)
printf(" %s\n", p);
}
+static ssize_t send_all(int sockfd, const void *buf, size_t len, int flags)
+{
+ size_t rem = len;
+ size_t off = 0;
+ ssize_t rv;
+
+retry:
+ rv = send(sockfd, (char *)buf + off, rem, flags);
+ if (rv == -1 && errno == EINTR)
+ goto retry;
+ if (rv < 0)
+ return -errno;
+ if (rv < rem) {
+ rem -= rv;
+ off += rv;
+ goto retry;
+ }
+ return 0;
+}
+
static void status_daemon(struct sanlk_state *st, char *str, int debug)
{
printf("daemon %.48s\n", st->name);
@@ -474,7 +494,7 @@ static int lockspace_host_status(int debug, char *lockspace_name)
memset(&lockspace, 0, sizeof(lockspace));
snprintf(lockspace.name, SANLK_NAME_LEN, "%s", lockspace_name);
- rv = send(fd, &lockspace, sizeof(lockspace), 0);
+ rv = send_all(fd, &lockspace, sizeof(lockspace), 0);
if (rv < 0)
goto out;
@@ -603,7 +623,7 @@ int sanlock_renewal(char *lockspace_name)
memset(&lockspace, 0, sizeof(lockspace));
snprintf(lockspace.name, SANLK_NAME_LEN, "%s", lockspace_name);
- rv = send(fd, &lockspace, sizeof(lockspace), 0);
+ rv = send_all(fd, &lockspace, sizeof(lockspace), 0);
if (rv < 0)
goto out;
diff --git a/src/cmd.c b/src/cmd.c
index 3137df0..6815585 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -57,6 +57,38 @@ void send_result(int ci, int fd, struct sm_header *h_recv, int result);
static uint32_t token_id_counter = 1;
+static ssize_t recv_loop(int sockfd, void *buf, size_t len, int flags)
+{
+ ssize_t rv;
+
+ for (;;) {
+ rv = recv(sockfd, buf, len, flags);
+ if (rv == -1 && errno == EINTR)
+ continue;
+ return rv;
+ }
+}
+
+static ssize_t send_all(int sockfd, const void *buf, size_t len, int flags)
+{
+ size_t rem = len;
+ size_t off = 0;
+ ssize_t rv;
+
+retry:
+ rv = send(sockfd, (char *)buf + off, rem, flags);
+ if (rv == -1 && errno == EINTR)
+ goto retry;
+ if (rv < 0)
+ return -errno;
+ if (rv < rem) {
+ rem -= rv;
+ off += rv;
+ goto retry;
+ }
+ return 0;
+}
+
static void release_cl_tokens(struct task *task, struct client *cl)
{
struct token *token;
@@ -251,7 +283,7 @@ static void cmd_acquire(struct task *task, struct cmd_args *ca, uint32_t cmd)
* receive sanlk_resource, create token for it
*/
- rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv > 0)
pos += rv;
if (rv != sizeof(struct sanlk_resource)) {
@@ -295,7 +327,7 @@ static void cmd_acquire(struct task *task, struct cmd_args *ca, uint32_t cmd)
* in sanlk_disk (TODO: let these differ?)
*/
- rv = recv(fd, token->disks, disks_len, MSG_WAITALL);
+ rv = recv_loop(fd, token->disks, disks_len, MSG_WAITALL);
if (rv > 0)
pos += rv;
if (rv != disks_len) {
@@ -317,7 +349,7 @@ static void cmd_acquire(struct task *task, struct cmd_args *ca, uint32_t cmd)
alloc_count++;
}
- rv = recv(fd, &opt, sizeof(struct sanlk_options), MSG_WAITALL);
+ rv = recv_loop(fd, &opt, sizeof(struct sanlk_options), MSG_WAITALL);
if (rv > 0)
pos += rv;
if (rv != sizeof(struct sanlk_options)) {
@@ -336,7 +368,7 @@ static void cmd_acquire(struct task *task, struct cmd_args *ca, uint32_t cmd)
goto done;
}
- rv = recv(fd, opt_str, opt.len, MSG_WAITALL);
+ rv = recv_loop(fd, opt_str, opt.len, MSG_WAITALL);
if (rv > 0)
pos += rv;
if (rv != opt.len) {
@@ -575,7 +607,7 @@ static void cmd_release(struct task *task, struct cmd_args *ca, uint32_t cmd)
}
if (ca->header.cmd_flags & SANLK_REL_ORPHAN) {
- rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv != sizeof(struct sanlk_resource)) {
log_error("cmd_release %d,%d,%d recv res %d %d",
cl_ci, cl_fd, cl_pid, rv, errno);
@@ -588,7 +620,7 @@ static void cmd_release(struct task *task, struct cmd_args *ca, uint32_t cmd)
}
if (ca->header.cmd_flags & SANLK_REL_RENAME) {
- rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv != sizeof(struct sanlk_resource)) {
log_error("cmd_release %d,%d,%d recv res %d %d",
cl_ci, cl_fd, cl_pid, rv, errno);
@@ -597,7 +629,7 @@ static void cmd_release(struct task *task, struct cmd_args *ca, uint32_t cmd)
}
/* second res struct has new name for first res */
- rv = recv(fd, &new, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &new, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv != sizeof(struct sanlk_resource)) {
log_error("cmd_release %d,%d,%d recv new %d %d",
cl_ci, cl_fd, cl_pid, rv, errno);
@@ -638,7 +670,7 @@ static void cmd_release(struct task *task, struct cmd_args *ca, uint32_t cmd)
/* caller is specifying specific resources to release */
for (i = 0; i < ca->header.data; i++) {
- rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv != sizeof(struct sanlk_resource)) {
log_error("cmd_release %d,%d,%d recv res %d %d",
cl_ci, cl_fd, cl_pid, rv, errno);
@@ -851,12 +883,12 @@ static void cmd_inquire(struct task *task, struct cmd_args *ca, uint32_t cmd)
if (state) {
h.length = sizeof(h) + state_strlen + 1;
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
- send(fd, state, state_strlen + 1, MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, state, state_strlen + 1, MSG_NOSIGNAL);
free(state);
} else {
h.length = sizeof(h);
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
}
client_resume(ca->ci_in);
@@ -899,7 +931,7 @@ static void cmd_convert(struct task *task, struct cmd_args *ca, uint32_t cmd)
log_cmd(cmd, "cmd_convert %d,%d,%d ci_in %d fd %d",
cl_ci, cl_fd, cl_pid, ca->ci_in, fd);
- rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv != sizeof(struct sanlk_resource)) {
result = -ENOTCONN;
goto reply;
@@ -963,7 +995,7 @@ static void cmd_request(struct task *task, struct cmd_args *ca, uint32_t cmd)
/* receiving and setting up token copied from cmd_acquire */
- rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv != sizeof(struct sanlk_resource)) {
log_error("cmd_request %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -1004,7 +1036,7 @@ static void cmd_request(struct task *task, struct cmd_args *ca, uint32_t cmd)
* in sanlk_disk (TODO: let these differ?)
*/
- rv = recv(fd, token->disks, disks_len, MSG_WAITALL);
+ rv = recv_loop(fd, token->disks, disks_len, MSG_WAITALL);
if (rv != disks_len) {
result = -ENOTCONN;
goto reply_free;
@@ -1078,7 +1110,7 @@ static void cmd_examine(struct task *task GNUC_UNUSED, struct cmd_args *ca, uint
ls = &buf.s;
}
- rv = recv(fd, &buf, datalen, MSG_WAITALL);
+ rv = recv_loop(fd, &buf, datalen, MSG_WAITALL);
if (rv != datalen) {
log_error("cmd_examine %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -1113,7 +1145,7 @@ static void cmd_set_lvb(struct task *task GNUC_UNUSED, struct cmd_args *ca, uint
fd = client[ca->ci_in].fd;
- rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv != sizeof(struct sanlk_resource)) {
log_error("cmd_set_lvb %d,%d recv %d %d", ca->ci_in, fd, rv, errno);
result = -ENOTCONN;
@@ -1137,7 +1169,7 @@ static void cmd_set_lvb(struct task *task GNUC_UNUSED, struct cmd_args *ca, uint
goto reply;
}
- rv = recv(fd, lvb, lvblen, MSG_WAITALL);
+ rv = recv_loop(fd, lvb, lvblen, MSG_WAITALL);
if (rv != lvblen) {
log_error("cmd_set_lvb %d,%d recv lvblen %d lvb %d %d",
ca->ci_in, fd, lvblen, rv, errno);
@@ -1166,7 +1198,7 @@ static void cmd_get_lvb(struct task *task GNUC_UNUSED, struct cmd_args *ca, uint
fd = client[ca->ci_in].fd;
- rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv != sizeof(struct sanlk_resource)) {
log_error("cmd_get_lvb %d,%d recv %d %d", ca->ci_in, fd, rv, errno);
result = -ENOTCONN;
@@ -1187,10 +1219,10 @@ static void cmd_get_lvb(struct task *task GNUC_UNUSED, struct cmd_args *ca, uint
h.data2 = 0;
h.length = sizeof(h) + lvblen;
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
if (lvb) {
- send(fd, lvb, lvblen, MSG_NOSIGNAL);
+ send_all(fd, lvb, lvblen, MSG_NOSIGNAL);
free(lvb);
}
@@ -1259,7 +1291,7 @@ void daemon_shutdown_reply(void)
h.version = SM_PROTO;
h.length = sizeof(h);
- send(shutdown_reply_fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(shutdown_reply_fd, &h, sizeof(h), MSG_NOSIGNAL);
close(shutdown_reply_fd);
client_resume(shutdown_reply_ci);
@@ -1275,7 +1307,7 @@ static void cmd_add_lockspace(struct cmd_args *ca, uint32_t cmd)
fd = client[ca->ci_in].fd;
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
log_error("cmd_add_lockspace %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -1324,7 +1356,7 @@ static void cmd_inq_lockspace(struct cmd_args *ca, uint32_t cmd)
fd = client[ca->ci_in].fd;
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
log_error("cmd_inq_lockspace %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -1408,7 +1440,7 @@ static void cmd_rem_lockspace(struct cmd_args *ca, uint32_t cmd)
fd = client[ca->ci_in].fd;
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
log_error("cmd_rem_lockspace %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -1456,7 +1488,7 @@ static void cmd_align(struct task *task GNUC_UNUSED, struct cmd_args *ca, uint32
fd = client[ca->ci_in].fd;
- rv = recv(fd, &disk, sizeof(struct sanlk_disk), MSG_WAITALL);
+ rv = recv_loop(fd, &disk, sizeof(struct sanlk_disk), MSG_WAITALL);
if (rv != sizeof(struct sanlk_disk)) {
log_error("cmd_align %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -1504,7 +1536,7 @@ static void cmd_read_lockspace(struct task *task, struct cmd_args *ca, uint32_t
fd = client[ca->ci_in].fd;
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
log_error("cmd_read_lockspace %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -1568,8 +1600,8 @@ static void cmd_read_lockspace(struct task *task, struct cmd_args *ca, uint32_t
h.data = result;
h.data2 = io_timeout;
h.length = sizeof(h) + sizeof(lockspace);
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
- send(fd, &lockspace, sizeof(lockspace), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, &lockspace, sizeof(lockspace), MSG_NOSIGNAL);
client_resume(ca->ci_in);
}
@@ -1585,7 +1617,7 @@ static void cmd_read_resource(struct task *task, struct cmd_args *ca, uint32_t c
/* receiving and setting up token copied from cmd_acquire */
- rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv != sizeof(struct sanlk_resource)) {
log_error("cmd_read_resource %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -1620,7 +1652,7 @@ static void cmd_read_resource(struct task *task, struct cmd_args *ca, uint32_t c
* in sanlk_disk (TODO: let these differ?)
*/
- rv = recv(fd, token->disks, disks_len, MSG_WAITALL);
+ rv = recv_loop(fd, token->disks, disks_len, MSG_WAITALL);
if (rv != disks_len) {
result = -ENOTCONN;
goto reply;
@@ -1668,8 +1700,8 @@ static void cmd_read_resource(struct task *task, struct cmd_args *ca, uint32_t c
h.data = result;
h.data2 = 0;
h.length = sizeof(h) + sizeof(res);
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
- send(fd, &res, sizeof(res), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, &res, sizeof(res), MSG_NOSIGNAL);
client_resume(ca->ci_in);
}
@@ -1686,7 +1718,7 @@ static void cmd_read_resource_owners(struct task *task, struct cmd_args *ca, uin
/* receiving and setting up token copied from cmd_acquire */
- rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv != sizeof(struct sanlk_resource)) {
log_error("cmd_read_resource_owners %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -1721,7 +1753,7 @@ static void cmd_read_resource_owners(struct task *task, struct cmd_args *ca, uin
* in sanlk_disk (TODO: let these differ?)
*/
- rv = recv(fd, token->disks, disks_len, MSG_WAITALL);
+ rv = recv_loop(fd, token->disks, disks_len, MSG_WAITALL);
if (rv != disks_len) {
result = -ENOTCONN;
goto reply;
@@ -1771,10 +1803,10 @@ static void cmd_read_resource_owners(struct task *task, struct cmd_args *ca, uin
h.data = result;
h.data2 = count;
h.length = sizeof(h) + sizeof(res) + send_len;
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
- send(fd, &res, sizeof(res), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, &res, sizeof(res), MSG_NOSIGNAL);
if (send_len && send_buf) {
- send(fd, send_buf, send_len, MSG_NOSIGNAL);
+ send_all(fd, send_buf, send_len, MSG_NOSIGNAL);
free(send_buf);
}
@@ -1790,7 +1822,7 @@ static void cmd_write_lockspace(struct task *task, struct cmd_args *ca, uint32_t
fd = client[ca->ci_in].fd;
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
log_error("cmd_write_lockspace %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -1849,7 +1881,7 @@ static void cmd_write_resource(struct task *task, struct cmd_args *ca, uint32_t
/* receiving and setting up token copied from cmd_acquire */
- rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ rv = recv_loop(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
if (rv != sizeof(struct sanlk_resource)) {
log_error("cmd_write_resource %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -1885,7 +1917,7 @@ static void cmd_write_resource(struct task *task, struct cmd_args *ca, uint32_t
* in sanlk_disk (TODO: let these differ?)
*/
- rv = recv(fd, token->disks, disks_len, MSG_WAITALL);
+ rv = recv_loop(fd, token->disks, disks_len, MSG_WAITALL);
if (rv != disks_len) {
result = -ENOTCONN;
goto reply;
@@ -1948,7 +1980,7 @@ static void cmd_killpath(struct task *task, struct cmd_args *ca, uint32_t cmd)
log_cmd(cmd, "cmd_killpath %d,%d,%d flags %x",
cl_ci, cl_fd, cl_pid, ca->header.cmd_flags);
- rv = recv(cl_fd, cl->killpath, SANLK_HELPER_PATH_LEN, MSG_WAITALL);
+ rv = recv_loop(cl_fd, cl->killpath, SANLK_HELPER_PATH_LEN, MSG_WAITALL);
if (rv != SANLK_HELPER_PATH_LEN) {
log_error("cmd_killpath %d,%d,%d recv path %d %d",
cl_ci, cl_fd, cl_pid, rv, errno);
@@ -1958,7 +1990,7 @@ static void cmd_killpath(struct task *task, struct cmd_args *ca, uint32_t cmd)
goto done;
}
- rv = recv(cl_fd, cl->killargs, SANLK_HELPER_ARGS_LEN, MSG_WAITALL);
+ rv = recv_loop(cl_fd, cl->killargs, SANLK_HELPER_ARGS_LEN, MSG_WAITALL);
if (rv != SANLK_HELPER_ARGS_LEN) {
log_error("cmd_killpath %d,%d,%d recv args %d %d",
cl_ci, cl_fd, cl_pid, rv, errno);
@@ -2001,13 +2033,13 @@ static void cmd_set_event(struct task *task GNUC_UNUSED, struct cmd_args *ca, ui
fd = client[ca->ci_in].fd;
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
result = -ENOTCONN;
goto reply;
}
- rv = recv(fd, &he, sizeof(struct sanlk_host_event), MSG_WAITALL);
+ rv = recv_loop(fd, &he, sizeof(struct sanlk_host_event), MSG_WAITALL);
if (rv != sizeof(struct sanlk_host_event)) {
result = -ENOTCONN;
goto reply;
@@ -2030,7 +2062,7 @@ static void cmd_format_rindex(struct task *task, struct cmd_args *ca, uint32_t c
fd = client[ca->ci_in].fd;
- rv = recv(fd, &ri, sizeof(struct sanlk_rindex), MSG_WAITALL);
+ rv = recv_loop(fd, &ri, sizeof(struct sanlk_rindex), MSG_WAITALL);
if (rv != sizeof(struct sanlk_rindex)) {
log_error("cmd_format_rindex %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -2058,7 +2090,7 @@ static void cmd_rebuild_rindex(struct task *task, struct cmd_args *ca, uint32_t
fd = client[ca->ci_in].fd;
- rv = recv(fd, &ri, sizeof(struct sanlk_rindex), MSG_WAITALL);
+ rv = recv_loop(fd, &ri, sizeof(struct sanlk_rindex), MSG_WAITALL);
if (rv != sizeof(struct sanlk_rindex)) {
log_error("cmd_rebuild_rindex %d,%d recv %d %d",
ca->ci_in, fd, rv, errno);
@@ -2091,14 +2123,14 @@ static void rindex_op(struct task *task, struct cmd_args *ca, const char *ri_cmd
fd = client[ca->ci_in].fd;
- rv = recv(fd, &ri, sizeof(struct sanlk_rindex), MSG_WAITALL);
+ rv = recv_loop(fd, &ri, sizeof(struct sanlk_rindex), MSG_WAITALL);
if (rv != sizeof(struct sanlk_rindex)) {
log_error("%s %d,%d recv %d %d", ri_cmd_str, ca->ci_in, fd, rv, errno);
result = -ENOTCONN;
goto reply;
}
- rv = recv(fd, &re, sizeof(struct sanlk_rentry), MSG_WAITALL);
+ rv = recv_loop(fd, &re, sizeof(struct sanlk_rentry), MSG_WAITALL);
if (rv != sizeof(struct sanlk_rentry)) {
log_error("%s %d,%d recv %d %d", ri_cmd_str, ca->ci_in, fd, rv, errno);
result = -ENOTCONN;
@@ -2129,8 +2161,8 @@ static void rindex_op(struct task *task, struct cmd_args *ca, const char *ri_cmd
h.data = result;
h.data2 = 0;
h.length = sizeof(h) + sizeof(re_ret);
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
- send(fd, &re_ret, sizeof(re), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, &re_ret, sizeof(re), MSG_NOSIGNAL);
client_resume(ca->ci_in);
}
@@ -2479,9 +2511,9 @@ static void send_state_daemon(int fd)
st.str_len = str_len;
- send(fd, &st, sizeof(st), MSG_NOSIGNAL);
+ send_all(fd, &st, sizeof(st), MSG_NOSIGNAL);
if (str_len)
- send(fd, str, str_len, MSG_NOSIGNAL);
+ send_all(fd, str, str_len, MSG_NOSIGNAL);
}
static void send_state_client(int fd, struct client *cl, int ci)
@@ -2500,9 +2532,9 @@ static void send_state_client(int fd, struct client *cl, int ci)
st.str_len = str_len;
- send(fd, &st, sizeof(st), MSG_NOSIGNAL);
+ send_all(fd, &st, sizeof(st), MSG_NOSIGNAL);
if (str_len)
- send(fd, str, str_len, MSG_NOSIGNAL);
+ send_all(fd, str, str_len, MSG_NOSIGNAL);
}
static void send_state_lockspace(int fd, struct space *sp, const char *list_name)
@@ -2522,16 +2554,16 @@ static void send_state_lockspace(int fd, struct space *sp, const char *list_name
st.str_len = str_len;
- send(fd, &st, sizeof(st), MSG_NOSIGNAL);
+ send_all(fd, &st, sizeof(st), MSG_NOSIGNAL);
if (str_len)
- send(fd, str, str_len, MSG_NOSIGNAL);
+ send_all(fd, str, str_len, MSG_NOSIGNAL);
memset(&lockspace, 0, sizeof(struct sanlk_lockspace));
strncpy(lockspace.name, sp->space_name, NAME_ID_SIZE);
lockspace.host_id = sp->host_id;
memcpy(&lockspace.host_id_disk, &sp->host_id_disk, sizeof(struct sanlk_disk));
- send(fd, &lockspace, sizeof(lockspace), MSG_NOSIGNAL);
+ send_all(fd, &lockspace, sizeof(lockspace), MSG_NOSIGNAL);
}
void send_state_resource(int fd, struct resource *r, const char *list_name,
@@ -2556,14 +2588,14 @@ void send_state_resource(int fd, struct resource *r, const char *list_name,
st.str_len = str_len;
- send(fd, &st, sizeof(st), MSG_NOSIGNAL);
+ send_all(fd, &st, sizeof(st), MSG_NOSIGNAL);
if (str_len)
- send(fd, str, str_len, MSG_NOSIGNAL);
+ send_all(fd, str, str_len, MSG_NOSIGNAL);
- send(fd, &r->r, sizeof(struct sanlk_resource), MSG_NOSIGNAL);
+ send_all(fd, &r->r, sizeof(struct sanlk_resource), MSG_NOSIGNAL);
for (i = 0; i < r->r.num_disks; i++) {
- send(fd, &r->r.disks[i], sizeof(struct sanlk_disk), MSG_NOSIGNAL);
+ send_all(fd, &r->r.disks[i], sizeof(struct sanlk_disk), MSG_NOSIGNAL);
}
}
@@ -2583,9 +2615,9 @@ static void send_state_host(int fd, struct host_status *hs, int host_id)
st.str_len = str_len;
- send(fd, &st, sizeof(st), MSG_NOSIGNAL);
+ send_all(fd, &st, sizeof(st), MSG_NOSIGNAL);
if (str_len)
- send(fd, str, str_len, MSG_NOSIGNAL);
+ send_all(fd, str, str_len, MSG_NOSIGNAL);
}
static void send_state_renewal(int fd, struct renewal_history *hi)
@@ -2603,9 +2635,9 @@ static void send_state_renewal(int fd, struct renewal_history *hi)
st.str_len = str_len;
- send(fd, &st, sizeof(st), MSG_NOSIGNAL);
+ send_all(fd, &st, sizeof(st), MSG_NOSIGNAL);
if (str_len)
- send(fd, str, str_len, MSG_NOSIGNAL);
+ send_all(fd, str, str_len, MSG_NOSIGNAL);
}
static void cmd_status(int ci, int fd, struct sm_header *h_recv, int client_maxi, uint32_t cmd)
@@ -2623,7 +2655,7 @@ static void cmd_status(int ci, int fd, struct sm_header *h_recv, int client_maxi
h.length = sizeof(h);
h.data = 0;
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
send_state_daemon(fd);
@@ -2687,7 +2719,7 @@ static void cmd_host_status(int ci, int fd, struct sm_header *h_recv, uint32_t c
goto fail;
}
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
h.data = -ENOTCONN;
goto fail;
@@ -2704,7 +2736,7 @@ static void cmd_host_status(int ci, int fd, struct sm_header *h_recv, uint32_t c
goto fail;
}
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
for (i = 0; i < DEFAULT_MAX_HOSTS; i++) {
hs = &status[i];
@@ -2717,7 +2749,7 @@ static void cmd_host_status(int ci, int fd, struct sm_header *h_recv, uint32_t c
free(status);
return;
fail:
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
if (status)
free(status);
@@ -2751,7 +2783,7 @@ static void cmd_renewal(int fd, struct sm_header *h_recv)
goto fail;
}
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
h.data = -ENOTCONN;
goto fail;
@@ -2786,7 +2818,7 @@ static void cmd_renewal(int fd, struct sm_header *h_recv)
h.data2 = io_timeout;
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
/* If next slot is non-zero, then we've wrapped and
should begin sending history from next to end
@@ -2808,7 +2840,7 @@ static void cmd_renewal(int fd, struct sm_header *h_recv)
free(history);
return;
fail:
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(h), MSG_NOSIGNAL);
if (history)
free(history);
@@ -2825,8 +2857,8 @@ static void cmd_log_dump(int fd, struct sm_header *h_recv)
h_recv->version = SM_PROTO;
h_recv->data = len;
- send(fd, h_recv, sizeof(struct sm_header), MSG_NOSIGNAL);
- send(fd, send_data_buf, len, MSG_NOSIGNAL);
+ send_all(fd, h_recv, sizeof(struct sm_header), MSG_NOSIGNAL);
+ send_all(fd, send_data_buf, len, MSG_NOSIGNAL);
}
static void cmd_get_lockspaces(int ci, int fd, struct sm_header *h_recv, uint32_t cmd)
@@ -2842,8 +2874,8 @@ static void cmd_get_lockspaces(int ci, int fd, struct sm_header *h_recv, uint32_
h_recv->data = rv;
h_recv->data2 = count;
- send(fd, h_recv, sizeof(struct sm_header), MSG_NOSIGNAL);
- send(fd, send_data_buf, len, MSG_NOSIGNAL);
+ send_all(fd, h_recv, sizeof(struct sm_header), MSG_NOSIGNAL);
+ send_all(fd, send_data_buf, len, MSG_NOSIGNAL);
}
static void cmd_get_hosts(int ci, int fd, struct sm_header *h_recv, uint32_t cmd)
@@ -2860,7 +2892,7 @@ static void cmd_get_hosts(int ci, int fd, struct sm_header *h_recv, uint32_t cmd
h.length = sizeof(h);
h.data = 0;
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
h.data = -ENOTCONN;
goto out;
@@ -2872,9 +2904,9 @@ static void cmd_get_hosts(int ci, int fd, struct sm_header *h_recv, uint32_t cmd
h.data = rv;
h.data2 = count;
out:
- send(fd, &h, sizeof(struct sm_header), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(struct sm_header), MSG_NOSIGNAL);
if (len)
- send(fd, send_data_buf, len, MSG_NOSIGNAL);
+ send_all(fd, send_data_buf, len, MSG_NOSIGNAL);
}
static void cmd_restrict(int ci, int fd, struct sm_header *h_recv, uint32_t cmd)
@@ -2899,7 +2931,7 @@ static void cmd_version(int ci GNUC_UNUSED, int fd, struct sm_header *h_recv)
h_recv->data = 0;
h_recv->data2 = sanlock_version_combined;
- send(fd, h_recv, sizeof(struct sm_header), MSG_NOSIGNAL);
+ send_all(fd, h_recv, sizeof(struct sm_header), MSG_NOSIGNAL);
}
static void cmd_reg_event(int fd, struct sm_header *h_recv, uint32_t cmd)
@@ -2913,14 +2945,14 @@ static void cmd_reg_event(int fd, struct sm_header *h_recv, uint32_t cmd)
h.version = SM_PROTO;
h.length = sizeof(struct sm_header);
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
h.data = -ENOTCONN;
goto out;
}
/* currently unused */
- rv = recv(fd, &he, sizeof(he), MSG_WAITALL);
+ rv = recv_loop(fd, &he, sizeof(he), MSG_WAITALL);
if (rv != sizeof(he)) {
h.data = -ENOTCONN;
goto out;
@@ -2931,7 +2963,7 @@ static void cmd_reg_event(int fd, struct sm_header *h_recv, uint32_t cmd)
h.data = rv;
out:
log_cmd(cmd, "cmd_reg_event fd %d rv %d", fd, rv);
- send(fd, &h, sizeof(struct sm_header), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(struct sm_header), MSG_NOSIGNAL);
}
static void cmd_end_event(int fd, struct sm_header *h_recv, uint32_t cmd)
@@ -2944,7 +2976,7 @@ static void cmd_end_event(int fd, struct sm_header *h_recv, uint32_t cmd)
h.version = SM_PROTO;
h.length = sizeof(struct sm_header);
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
h.data = -ENOTCONN;
goto out;
@@ -2955,7 +2987,7 @@ static void cmd_end_event(int fd, struct sm_header *h_recv, uint32_t cmd)
h.data = rv;
out:
log_cmd(cmd, "cmd_end_event fd %d rv %d", fd, rv);
- send(fd, &h, sizeof(struct sm_header), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(struct sm_header), MSG_NOSIGNAL);
}
static void cmd_set_config(int fd, struct sm_header *h_recv, uint32_t cmd)
@@ -2968,7 +3000,7 @@ static void cmd_set_config(int fd, struct sm_header *h_recv, uint32_t cmd)
h.version = SM_PROTO;
h.length = sizeof(struct sm_header);
- rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
+ rv = recv_loop(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL);
if (rv != sizeof(struct sanlk_lockspace)) {
h.data = -ENOTCONN;
goto out;
@@ -2979,7 +3011,7 @@ static void cmd_set_config(int fd, struct sm_header *h_recv, uint32_t cmd)
h.data = rv;
out:
log_cmd(cmd, "cmd_set_config fd %d rv %d", fd, rv);
- send(fd, &h, sizeof(struct sm_header), MSG_NOSIGNAL);
+ send_all(fd, &h, sizeof(struct sm_header), MSG_NOSIGNAL);
}
static int get_peer_pid(int fd, int *pid)
diff --git a/src/lockspace.c b/src/lockspace.c
index 41f96cb..2ebc247 100644
--- a/src/lockspace.c
+++ b/src/lockspace.c
@@ -1813,8 +1813,10 @@ int send_event_callbacks(uint32_t space_id,
continue;
fd = sp->event_fds[i];
-
+retry:
rv = send(fd, &cb, sizeof(cb), MSG_NOSIGNAL | MSG_DONTWAIT);
+ if (rv == -1 && errno == EINTR)
+ goto retry;
if (rv < 0) {
log_erros(sp, "send_event_callbacks error %d %d close fd %d", rv, errno, fd);
close(fd);
diff --git a/src/main.c b/src/main.c
index 026f7da..5b6fabc 100644
--- a/src/main.c
+++ b/src/main.c
@@ -458,6 +458,9 @@ void send_result(int ci, int fd, struct sm_header *h_recv, int result);
void send_result(int ci, int fd, struct sm_header *h_recv, int result)
{
struct sm_header h;
+ size_t rem = sizeof(h);
+ size_t off = 0;
+ ssize_t rv;
log_client(ci, fd, "send %d", result);
@@ -466,7 +469,18 @@ void send_result(int ci, int fd, struct sm_header *h_recv, int result)
h.length = sizeof(h);
h.data = result;
h.data2 = 0;
- send(fd, &h, sizeof(h), MSG_NOSIGNAL);
+
+retry:
+ rv = send(fd, (char *)&h + off, rem, MSG_NOSIGNAL);
+ if (rv == -1 && errno == EINTR)
+ goto retry;
+ if (rv < 0)
+ return;
+ if (rv < rem) {
+ rem -= rv;
+ off += rv;
+ goto retry;
+ }
}
void client_pid_dead(int ci);
@@ -1231,7 +1245,10 @@ static void process_connection(int ci)
memset(&h, 0, sizeof(h));
+ retry:
rv = recv(client[ci].fd, &h, sizeof(h), MSG_WAITALL);
+ if (rv == -1 && errno == EINTR)
+ goto retry;
if (!rv)
goto dead;
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
2 years, 11 months
[sanlock] branch master updated: sanlock: do not close connection in
error handling
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
teigland pushed a commit to branch master
in repository sanlock.
The following commit(s) were added to refs/heads/master by this push:
new bb70c22 sanlock: do not close connection in error handling
bb70c22 is described below
commit bb70c220b51720a46a1bdc6b824936fc7269d5d8
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Mon May 3 12:52:17 2021 -0500
sanlock: do not close connection in error handling
When processing a client connection, a problem with the message
or with the client handling would cause the sanlock daemon to
close the client connection (the socket fd) and release any
leases if the connection was "registered". If this happened,
the client may be unaware of it, and may continue running,
using the leases that have been dropped. This could lead to
different clients on different hosts believing that they hold
the same lease concurrently.
A known cause of this is when a sanlock client program makes
libsanlock calls on a registered connection concurrently
from multiple threads without serialization. These calls are:
sanlock_acquire, sanlock_release, sanlock_inquire,
sanlock_convert, sanlock_restrict, sanlock_killpath.
These calls involve:
- sending a header to the sanlock daemon
- sending a body to the sanlock daemon
- receving a reply from the sanlock daemon
If these steps are interleaved from multiple threads, the
sanlock daemon will read incorrect data when processing
a request, or the wrong result could be received by the caller.
A specific example that's been seen involves two concurrent
sanlock_release calls from different threads. The proper
sequence would be:
sanlock_release_1
send header_1
send body_1
recv result_1
sanlock_release_2
send header_2
send body_2
recv result_2
Without locking, data from both requests are interleaved,
causing a sequence to be received in the daemon:
header_1
header_2
body_1
The sanlock daemon expects the correct sequence of data,
so it misinterprets the mixed data and reports errors when
it finds unexpected fields in what it thinks are headers
and body structs.
The sanlock daemon recvs header_1, then recvs header_2,
and thinks header_2 is body_1. When it finds an unknown
resource name in what it thinks is body_1 (really header_2),
it logs an error to sanlock.log:
cmd_release 19,86,41799 no resource ...
Then the sanlock dameon recvs data from body_1, and thinks
it is header_2. When it finds an invalid magic number in
header_2 (really body_1), it logs an error to sanlock.log:
ci 19 recv 32 magic 0 vs 4282010
The error path after seeing a bad magic number in a message
header is to call deadfn(). For a registered connection,
this is client_pid_dead() which closes the socket fd for
the client and drops leases held by the client.
Closing the connection is the wrong way to handle a bad message
because the client is still running, and a closed connection
implies that a registered client has exited.
The fix is to simply ignore the bad data (logging an error).
By ignoring the messages, the sanlock clients will likely be
stuck waiting for replies, or possibly receive errors from
their calls. So, this fix only prevents leases from being
dropped incorrectly. Clients must still serialize access
to sockets.
Other error conditions in processing a client connection also
use this same incorrect error handling, and they are also
changed to simply ignore the issue and log an error.
---
src/main.c | 44 ++++++-----
src/sanlock_resource.h | 3 +
tests/Makefile | 9 ++-
tests/sanlk_mixmsg.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 242 insertions(+), 22 deletions(-)
diff --git a/src/main.c b/src/main.c
index 622dc8e..026f7da 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1235,33 +1235,33 @@ static void process_connection(int ci)
if (!rv)
goto dead;
- log_client(ci, client[ci].fd, "recv %d %d", rv, h.cmd);
+ log_client(ci, client[ci].fd, "recv %d %u", rv, h.cmd);
if (rv < 0) {
- log_error("ci %d fd %d pid %d recv errno %d",
- ci, client[ci].fd, client[ci].pid, errno);
- goto dead;
+ log_error("client connection %d %d %d recv msg header rv %d errno %d",
+ ci, client[ci].fd, client[ci].pid, rv, errno);
+ goto bad;
}
if (rv != sizeof(h)) {
- log_error("ci %d fd %d pid %d recv size %d",
- ci, client[ci].fd, client[ci].pid, rv);
- goto dead;
+ log_error("client connection %d %d %d recv msg header rv %d cmd %u len %u",
+ ci, client[ci].fd, client[ci].pid, rv, h.cmd, h.length);
+ goto bad;
}
if (h.magic != SM_MAGIC) {
- log_error("ci %d recv %d magic %x vs %x",
- ci, rv, h.magic, SM_MAGIC);
- goto dead;
+ log_error("client connection %d %d %d recv msg header rv %d cmd %u len %u magic %x vs %x",
+ ci, client[ci].fd, client[ci].pid, rv, h.cmd, h.length, h.magic, SM_MAGIC);
+ goto bad;
}
if (client[ci].restricted & SANLK_RESTRICT_ALL) {
- log_error("ci %d fd %d pid %d cmd %d restrict all",
- ci, client[ci].fd, client[ci].pid, h.cmd);
- goto dead;
+ log_error("client connection %d %d %d recv msg header rv %d cmd %u len %u restrict all",
+ ci, client[ci].fd, client[ci].pid, rv, h.cmd, h.length);
+ goto bad;
}
if (h.version && (h.cmd != SM_CMD_VERSION) &&
(h.version & 0xFFFF0000) > (SM_PROTO & 0xFFFF0000)) {
- log_error("ci %d recv %d proto %x vs %x",
- ci, rv, h.version , SM_PROTO);
- goto dead;
+ log_error("client connection %d %d %d recv msg header rv %d cmd %u len %u version %x",
+ ci, client[ci].fd, client[ci].pid, rv, h.cmd, h.length, h.version);
+ goto bad;
}
client[ci].cmd_last = h.cmd;
@@ -1306,7 +1306,7 @@ static void process_connection(int ci)
case SM_CMD_DELETE_RESOURCE:
rv = client_suspend(ci);
if (rv < 0)
- goto dead;
+ goto bad;
process_cmd_thread_unregistered(ci, &h);
break;
case SM_CMD_ACQUIRE:
@@ -1318,16 +1318,20 @@ static void process_connection(int ci)
while the thread is working on it */
rv = client_suspend(ci);
if (rv < 0)
- goto dead;
+ goto bad;
process_cmd_thread_registered(ci, &h);
break;
default:
- log_error("process_connection ci %d fd %d cmd %d unknown", ci, client[ci].fd, h.cmd);
- goto dead;
+ log_error("client connection ci %d fd %d pid %d cmd %d unknown",
+ ci, client[ci].fd, client[ci].pid, h.cmd);
+ goto bad;
};
return;
+ bad:
+ return;
+
dead:
log_client(ci, client[ci].fd, "recv dead");
deadfn = client[ci].deadfn;
diff --git a/src/sanlock_resource.h b/src/sanlock_resource.h
index 80178d1..48e4489 100644
--- a/src/sanlock_resource.h
+++ b/src/sanlock_resource.h
@@ -15,6 +15,9 @@
* process creates registered connection and acquires/releases leases on
* that connection for itself
*
+ * A threaded sanlock client must serialize libsanlock calls that are
+ * made using a registered socket connection.
+ *
* sock == -1, pid is used:
* process asks daemon to acquire/release leases for another separately
* registered pid
diff --git a/tests/Makefile b/tests/Makefile
index 1e7f7f4..80123d3 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -5,6 +5,7 @@ TARGET4 = killpath
TARGET5 = sanlk_path
TARGET6 = sanlk_testr
TARGET7 = sanlk_events
+TARGET8 = sanlk_mixmsg
SOURCE1 = devcount.c
SOURCE2 = sanlk_load.c
@@ -13,6 +14,7 @@ SOURCE4 = killpath.c
SOURCE5 = sanlk_path.c
SOURCE6 = sanlk_testr.c
SOURCE7 = sanlk_events.c
+SOURCE8 = sanlk_mixmsg.c
CFLAGS += -D_GNU_SOURCE -g \
-Wall \
@@ -36,7 +38,7 @@ CFLAGS += -D_GNU_SOURCE -g \
LDFLAGS = -lrt -laio -lblkid -lsanlock
-all: $(TARGET1) $(TARGET2) $(TARGET3) $(TARGET4) $(TARGET5) $(TARGET6) $(TARGET7)
+all: $(TARGET1) $(TARGET2) $(TARGET3) $(TARGET4) $(TARGET5) $(TARGET6) $(TARGET7) $(TARGET8)
$(TARGET1): $(SOURCE1)
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ -L. -I../src -L../src
@@ -59,6 +61,9 @@ $(TARGET6): $(SOURCE6)
$(TARGET7): $(SOURCE7)
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ -L. -I../src -L../src
+$(TARGET8): $(SOURCE8)
+ $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ -L. -I../src -L../src
+
clean:
- rm -f *.o *.so *.so.* $(TARGET) $(TARGET2) $(TARGET3) $(TARGET4) $(TARGET5) $(TARGET6) $(TARGET7)
+ rm -f *.o *.so *.so.* $(TARGET) $(TARGET2) $(TARGET3) $(TARGET4) $(TARGET5) $(TARGET6) $(TARGET7) $(TARGET8)
diff --git a/tests/sanlk_mixmsg.c b/tests/sanlk_mixmsg.c
new file mode 100644
index 0000000..1b9376e
--- /dev/null
+++ b/tests/sanlk_mixmsg.c
@@ -0,0 +1,208 @@
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/mount.h>
+#include <sys/signalfd.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/socket.h>
+
+#include "sanlock.h"
+#include "sanlock_resource.h"
+#include "sanlock_admin.h"
+#include "sanlock_sock.h"
+
+/* gcc with -lsanlock */
+
+/*
+ * sanlock direct init -s 1271384c-24db-4c9b-bebf-61a1916b6cb1:0:/dev/test/main:0
+ * sanlock add_lockspace -s 1271384c-24db-4c9b-bebf-61a1916b6cb1:1:/dev/test/main:0
+ */
+
+/* copied from client.c */
+static int send_header(int sock, int cmd, uint32_t cmd_flags, int datalen,
+ uint32_t data, uint32_t data2)
+{
+ struct sm_header header;
+ int rv;
+
+ memset(&header, 0, sizeof(header));
+ header.magic = SM_MAGIC;
+ header.version = SM_PROTO;
+ header.cmd = cmd;
+ header.cmd_flags = cmd_flags;
+ header.length = sizeof(header) + datalen;
+ header.data = data;
+ header.data2 = data2;
+
+retry:
+ rv = send(sock, (void *) &header, sizeof(header), 0);
+ if (rv == -1 && errno == EINTR)
+ goto retry;
+
+ if (rv < 0)
+ return -errno;
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ char rd1[sizeof(struct sanlk_resource) + sizeof(struct sanlk_disk)];
+ char rd2[sizeof(struct sanlk_resource) + sizeof(struct sanlk_disk)];
+ struct sanlk_resource *res1;
+ struct sanlk_resource *res2;
+ const char *lsname;
+ const char *resname1;
+ const char *resname2;
+ char *path;
+ int fd, rv;
+
+ if (argc < 2) {
+ printf("%s <path>\n", argv[0]);
+ return -1;
+ }
+
+ path = argv[1];
+
+ lsname = "1271384c-24db-4c9b-bebf-61a1916b6cb1";
+ resname1 = "2e794e7a-5a9c-4617-8cd0-dc03c917d7a1";
+ resname2 = "2e794e7a-5a9c-4617-8cd0-dc03c917d7a2";
+
+ memset(rd1, 0, sizeof(rd1));
+ memset(rd2, 0, sizeof(rd2));
+
+ res1 = (struct sanlk_resource *)&rd1;
+ res2 = (struct sanlk_resource *)&rd2;
+
+ strcpy(res1->lockspace_name, lsname);
+ sprintf(res1->name, "%s", resname1);
+ res1->num_disks = 1;
+ strcpy(res1->disks[0].path, path);
+ res1->disks[0].offset = 1048576;
+
+ strcpy(res2->lockspace_name, lsname);
+ sprintf(res2->name, "%s", resname2);
+ res2->num_disks = 1;
+ strcpy(res2->disks[0].path, path);
+ res2->disks[0].offset = 2 * 1048576;
+
+ /*
+ struct sanlk_lockspace ls = { 0 };
+ sprintf(ls.name, lsname);
+ sprintf(ls.host_id_disk.path, path);
+
+ rv = sanlock_write_lockspace(&ls, 0, 0, 0);
+ if (rv < 0) {
+ printf("write_lockspace error %d\n", rv);
+ return -1;
+ }
+ */
+
+ rv = sanlock_write_resource(res1, 0, 0, 0);
+ if (rv < 0) {
+ printf("write_resource1 error %d\n", rv);
+ return -1;
+ }
+ rv = sanlock_write_resource(res2, 0, 0, 0);
+ if (rv < 0) {
+ printf("write_resource2 error %d\n", rv);
+ return -1;
+ }
+
+ fd = sanlock_register();
+ if (fd < 0) {
+ printf("register error %d\n", fd);
+ return -1;
+ }
+
+ printf("acquiring both leases for registered fd %d\n", fd);
+
+ rv = sanlock_acquire(fd, -1, 0, 1, &res1, NULL);
+ if (rv < 0) {
+ printf("acquire res1 error %d\n", rv);
+ return -1;
+ }
+
+ rv = sanlock_acquire(fd, -1, 0, 1, &res2, NULL);
+ if (rv < 0) {
+ printf("acquire res2 error %d\n", rv);
+ return -1;
+ }
+
+ printf("sleeping... check that both leases are held\n");
+ sleep(20);
+
+ printf("sending res1 release header only\n");
+ rv = send_header(fd, SM_CMD_RELEASE, 0, sizeof(struct sanlk_resource), 1, -1);
+ if (rv < 0)
+ printf("send bad header error %d\n", rv);
+ else
+ printf("send bad header ok\n");
+
+ printf("sending res2 release interleaved\n");
+ rv = sanlock_release(fd, -1, 0, 1, &res2);
+ if (rv < 0)
+ printf("odd release res2 error %d\n", rv);
+ else
+ printf("odd release res2 ok\n");
+
+ printf("sending res1 release body only\n");
+ rv = send(fd, res1, sizeof(struct sanlk_resource), 0);
+ if (rv < 0)
+ printf("send bad body error %d\n", rv);
+ else
+ printf("send bad body ok\n");
+
+ /*
+ * This is not simulating the recv() that each sanlock_release
+ * would do in libsanlock to get a result for each release.
+ * These would likely just cause the client block indefinitely
+ * waiting for a reply that won't come because the bad release
+ * calls were ignored.
+ */
+
+ printf("sleeping... check which leases are held\n");
+ sleep(20);
+
+ printf("releasing both leases normally\n");
+ rv = sanlock_release(fd, -1, 0, 1, &res1);
+ if (rv < 0)
+ printf("release res1 error %d\n", rv);
+ else
+ printf("release res1 ok\n");
+
+ rv = sanlock_release(fd, -1, 0, 1, &res2);
+ if (rv < 0)
+ printf("release res2 error %d\n", rv);
+ else
+ printf("release res2 ok\n");
+
+ printf("sleeping... check that both leases are released\n");
+ sleep(20);
+
+ printf("acquiring lease res1\n");
+ rv = sanlock_acquire(fd, -1, 0, 1, &res1, NULL);
+ if (rv < 0)
+ printf("acquire res1 error %d\n", rv);
+ else
+ printf("acquire res1 ok\n");
+
+ /* exit should close our registered connection and
+ automatically release res1 */
+
+ printf("exiting... check if held lease is released after exit\n");
+
+ return 0;
+}
+
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
2 years, 11 months