diff --git a/.gitignore b/.gitignore index 2ac3120..61fde41 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/sanlock-3.8.3.tar.gz +SOURCES/sanlock-3.8.4.tar.gz diff --git a/.sanlock.metadata b/.sanlock.metadata index 4b5fe8c..b069991 100644 --- a/.sanlock.metadata +++ b/.sanlock.metadata @@ -1 +1 @@ -b860d082a129a6d80e6e79353fd9da1d60269bfa SOURCES/sanlock-3.8.3.tar.gz +494d5efc260b643ed9a3ee6bbdb0d31ecb14c201 SOURCES/sanlock-3.8.4.tar.gz diff --git a/SOURCES/python-Add-inquire.patch b/SOURCES/python-Add-inquire.patch deleted file mode 100644 index 0b86194..0000000 --- a/SOURCES/python-Add-inquire.patch +++ /dev/null @@ -1,342 +0,0 @@ -From 2d3e2fceb615a5bd12d26b09fe95668152fb0743 Mon Sep 17 00:00:00 2001 -From: Nir Soffer -Date: Wed, 28 Apr 2021 02:20:28 +0300 -Subject: [PATCH] python: Add inquire() - -Use sanlock_inquire() to query the resource held by the current process -(using the slkfd= argument) or held by another program (using the pid= -argument). - -When using the slkfd= argument, we communicate with sanlock daemon using -slkfd, ensuring that the current process is connected to sanlock. If the -current process is not connected, sanlock assumes that the process is -dead, and release all the leases acquired by the process. - -When using the pid= argument, the function opens a new socket to sanlock -daemon and query the status of resources owned by specified pid. - -In both cases the information comes from sanlock daemon, without -accessing storage. To verify storage content, the caller should use -read_resource() and read_resource_owners(). - -The call returns list of resources dicts that can be used for verifying -that sanlock state matches the program state. - -sanlock_inquire() reports the SANLOCK_RES_LVER or sanlock.RES_SHARED -flags in the resource flags field. Add the field to the returned dict -and add sanlock constants for the flag. - -The resource flags are needed if you want to restore a lease after it -was released, ensuring that nobody else acquired the lease after it was -released. This flow is used by libvirt using libsanlock. With this -change we can implement the same flow using the python binding. - -Signed-off-by: Nir Soffer ---- - python/sanlock.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++ - tests/python_test.py | 84 +++++++++++++++++++++++++ - 2 files changed, 257 insertions(+) - -diff --git a/python/sanlock.c b/python/sanlock.c -index 67d34fc23a20..c4814640c874 100644 ---- a/python/sanlock.c -+++ b/python/sanlock.c -@@ -323,6 +323,88 @@ exit_fail: - return NULL; - } - -+/* Convert disks array to list of tuples. */ -+static PyObject * -+disks_to_list(struct sanlk_disk *disks, uint32_t disks_count) -+{ -+ PyObject *result = NULL; -+ PyObject *disk = NULL; -+ -+ result = PyList_New(disks_count); -+ if (result == NULL) -+ return NULL; -+ -+ for (uint32_t i = 0; i < disks_count; i++) { -+ disk = Py_BuildValue( -+ "(s,K)", -+ disks[i].path, -+ disks[i].offset); -+ if (disk == NULL) -+ goto exit_fail; -+ -+ /* Steals reference to disk. */ -+ if (PyList_SetItem(result, i, disk) != 0) -+ goto exit_fail; -+ -+ disk = NULL; -+ } -+ -+ return result; -+ -+exit_fail: -+ Py_XDECREF(result); -+ Py_XDECREF(disk); -+ -+ return NULL; -+} -+ -+/* Convert resources array returned from sanlock_inquire() to list of resource -+ * dicts. */ -+static PyObject * -+resources_to_list(struct sanlk_resource **res, int res_count) -+{ -+ PyObject *result = NULL; -+ PyObject *info = NULL; -+ PyObject *disks = NULL; -+ -+ if ((result = PyList_New(res_count)) == NULL) -+ return NULL; -+ -+ for (int i = 0; i < res_count; i++) { -+ disks = disks_to_list(res[i]->disks, res[i]->num_disks); -+ if (disks == NULL) -+ goto exit_fail; -+ -+ /* Steals reference to disks. */ -+ info = Py_BuildValue( -+ "{s:y,s:y,s:k,s:K,s:N}", -+ "lockspace", res[i]->lockspace_name, -+ "resource", res[i]->name, -+ "flags", res[i]->flags, -+ "version", res[i]->lver, -+ "disks", disks); -+ if (info == NULL) -+ goto exit_fail; -+ -+ disks = NULL; -+ -+ /* Steals reference to info. */ -+ if (PyList_SetItem(result, i, info) != 0) -+ goto exit_fail; -+ -+ info = NULL; -+ } -+ -+ return result; -+ -+exit_fail: -+ Py_XDECREF(result); -+ Py_XDECREF(info); -+ Py_XDECREF(disks); -+ -+ return NULL; -+} -+ - /* register */ - PyDoc_STRVAR(pydoc_register, "\ - register() -> int\n\ -@@ -1062,6 +1144,89 @@ finally: - Py_RETURN_NONE; - } - -+/* inquire */ -+PyDoc_STRVAR(pydoc_inquire, "\ -+inquire(slkfd=-1, pid=-1)\n\ -+Return list of resources held by current process (using the slkfd \n\ -+argument to specify the sanlock file descriptor) or for another \n\ -+process (using the pid argument).\n\ -+\n\ -+Does not access storage. To learn about resource state on storage,\n\ -+use sanlock.read_resource() and sanlock.read_resource_owners().\n\ -+\n\ -+Arguments\n\ -+ slkfd (int): The file descriptor returned from sanlock.register().\n\ -+ pid (int): The program pid to query.\n\ -+\n\ -+Returns\n\ -+ List of resource dicts with the following keys:\n\ -+ lockspace (bytes): lockspace name\n\ -+ resource (bytes): resource name\n\ -+ flags (int): resource flags (sanlock.RES_*)\n\ -+ version (int): resource version\n\ -+ disks (list): list of disk tuples (path, offset)\n\ -+"); -+ -+static PyObject * -+py_inquire(PyObject *self __unused, PyObject *args, PyObject *keywds) -+{ -+ int sanlockfd = -1; -+ int pid = -1; -+ char *kwlist[] = {"slkfd", "pid", NULL}; -+ int rv = -1; -+ -+ /* sanlock_inquire() return values. */ -+ int res_count = 0; -+ char *res_state = NULL; -+ -+ /* Array of resoruces parsed from res_state. */ -+ struct sanlk_resource **res_arr = NULL; -+ -+ /* List of resource dicts. */ -+ PyObject *result = NULL; -+ -+ if (!PyArg_ParseTupleAndKeywords( -+ args, keywds, "|ii", kwlist, &sanlockfd, &pid)) { -+ return NULL; -+ } -+ -+ /* Check if any of the slkfd or pid parameters was given. */ -+ if (sanlockfd == -1 && pid == -1) { -+ set_sanlock_error(-EINVAL, "Invalid slkfd and pid values"); -+ return NULL; -+ } -+ -+ /* Inquire sanlock (gil disabled) */ -+ Py_BEGIN_ALLOW_THREADS -+ rv = sanlock_inquire(sanlockfd, pid, 0, &res_count, &res_state); -+ Py_END_ALLOW_THREADS -+ -+ if (rv != 0) { -+ set_sanlock_error(rv, "Inquire error"); -+ return NULL; -+ } -+ -+ if (res_count > 0) { -+ rv = sanlock_state_to_args(res_state, &res_count, &res_arr); -+ if (rv != 0) { -+ /* TODO: Include res_state in the error. */ -+ set_sanlock_error(rv, "Error parsing inquire state string"); -+ goto finally; -+ } -+ } -+ -+ result = resources_to_list(res_arr, res_count); -+ -+finally: -+ free(res_state); -+ -+ for (int i = 0; i < res_count; i++) -+ free(res_arr[i]); -+ free(res_arr); -+ -+ return result; -+} -+ - /* release */ - PyDoc_STRVAR(pydoc_release, "\ - release(lockspace, resource, disks [, slkfd=fd, pid=owner])\n\ -@@ -1752,6 +1917,8 @@ sanlock_methods[] = { - METH_VARARGS|METH_KEYWORDS, pydoc_read_resource_owners}, - {"acquire", (PyCFunction) py_acquire, - METH_VARARGS|METH_KEYWORDS, pydoc_acquire}, -+ {"inquire", (PyCFunction) py_inquire, -+ METH_VARARGS|METH_KEYWORDS, pydoc_inquire}, - {"release", (PyCFunction) py_release, - METH_VARARGS|METH_KEYWORDS, pydoc_release}, - {"request", (PyCFunction) py_request, -@@ -1850,6 +2017,12 @@ module_init(PyObject* m) - if (PyModule_AddIntConstant(m, "SETEV_ALL_HOSTS", SANLK_SETEV_ALL_HOSTS)) - return -1; - -+ /* sanlock_inquire() result resource flags */ -+ if (PyModule_AddIntConstant(m, "RES_LVER", SANLK_RES_LVER)) -+ return -1; -+ if (PyModule_AddIntConstant(m, "RES_SHARED", SANLK_RES_SHARED)) -+ return -1; -+ - /* Tuples with supported sector size and alignment values */ - - PyObject *sector = Py_BuildValue("ii", SECTOR_SIZE_512, SECTOR_SIZE_4K); -diff --git a/tests/python_test.py b/tests/python_test.py -index 58a22c71995c..caf2f3e7594a 100644 ---- a/tests/python_test.py -+++ b/tests/python_test.py -@@ -479,6 +479,90 @@ def test_acquire_release_resource(tmpdir, sanlock_daemon, size, offset): - assert owners == [] - - -+@pytest.mark.parametrize("res_name", [ -+ "ascii", -+ "\u05d0", # Hebrew Alef -+]) -+def test_inquire(tmpdir, sanlock_daemon, res_name): -+ ls_path = str(tmpdir.join("ls_name")) -+ util.create_file(ls_path, MiB) -+ -+ res_path = str(tmpdir.join(res_name)) -+ util.create_file(res_path, 10 * MiB) -+ -+ fd = sanlock.register() -+ -+ # No lockspace yet. -+ assert sanlock.inquire(slkfd=fd) == [] -+ -+ sanlock.write_lockspace(b"ls_name", ls_path, offset=0, iotimeout=1) -+ sanlock.add_lockspace(b"ls_name", 1, ls_path, offset=0, iotimeout=1) -+ -+ # No resources created yet. -+ assert sanlock.inquire(slkfd=fd) == [] -+ -+ resources = [ -+ # name, offset, acquire -+ (b"res-0", 0 * MiB, True), -+ (b"res-1", 1 * MiB, False), -+ (b"res-2", 2 * MiB, True), -+ (b"res-8", 8 * MiB, False), -+ (b"res-9", 9 * MiB, True), -+ ] -+ -+ for res_name, res_offset, acquire in resources: -+ sanlock.write_resource(b"ls_name", res_name, [(res_path, res_offset)]) -+ -+ # No resource acquired yet. -+ assert sanlock.inquire(slkfd=fd) == [] -+ -+ # Acquire resources. -+ for res_name, res_offset, acquire in resources: -+ if acquire: -+ sanlock.acquire( -+ b"ls_name", res_name, [(res_path, res_offset)], slkfd=fd) -+ -+ time.sleep(1) -+ -+ expected = [ -+ { -+ "lockspace": b"ls_name", -+ "resource": b"res-0", -+ "flags": sanlock.RES_LVER, -+ "version": 1, -+ "disks": [(res_path, 0 * MiB)], -+ }, -+ { -+ "lockspace": b"ls_name", -+ "resource": b"res-2", -+ "flags": sanlock.RES_LVER, -+ "version": 1, -+ "disks": [(res_path, 2 * MiB)], -+ }, -+ { -+ "lockspace": b"ls_name", -+ "resource": b"res-9", -+ "flags": sanlock.RES_LVER, -+ "version": 1, -+ "disks": [(res_path, 9 * MiB)], -+ }, -+ ] -+ -+ # Check acquired resources using snlkfd. -+ assert sanlock.inquire(slkfd=fd) == expected -+ -+ # Check acquired resources using pid. -+ assert sanlock.inquire(pid=os.getpid()) == expected -+ -+ for res_name, res_offset, acquire in resources: -+ if acquire: -+ sanlock.release( -+ b"ls_name", res_name, [(res_path, res_offset)], slkfd=fd) -+ -+ # All resource released. -+ assert sanlock.inquire(slkfd=fd) == [] -+ -+ - @pytest.mark.parametrize("align, sector", [ - # Invalid alignment - (KiB, sanlock.SECTOR_SIZE[0]), --- -2.7.5 - diff --git a/SOURCES/sanlock-do-not-close-connection-in-error-handling.patch b/SOURCES/sanlock-do-not-close-connection-in-error-handling.patch deleted file mode 100644 index ec326a8..0000000 --- a/SOURCES/sanlock-do-not-close-connection-in-error-handling.patch +++ /dev/null @@ -1,452 +0,0 @@ -From bb70c220b51720a46a1bdc6b824936fc7269d5d8 Mon Sep 17 00:00:00 2001 -From: David Teigland -Date: Mon, 3 May 2021 12:52:17 -0500 -Subject: [PATCH] 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(-) - create mode 100644 tests/sanlk_mixmsg.c - -diff --git a/src/main.c b/src/main.c -index 622dc8e39f2a..026f7dae7d6a 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 80178d194b6b..48e448969b3c 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 1e7f7f487915..80123d3dc633 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 000000000000..1b9376e981b6 ---- /dev/null -+++ b/tests/sanlk_mixmsg.c -@@ -0,0 +1,208 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 \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; -+} -+ --- -2.7.5 - diff --git a/SPECS/sanlock.spec b/SPECS/sanlock.spec index 3289691..c611502 100644 --- a/SPECS/sanlock.spec +++ b/SPECS/sanlock.spec @@ -1,6 +1,6 @@ Name: sanlock -Version: 3.8.3 -Release: 3%{?dist} +Version: 3.8.4 +Release: 1%{?dist} Summary: A shared storage lock manager Group: System Environment/Base @@ -23,9 +23,6 @@ Requires(preun): systemd-units Requires(postun): systemd-units Source0: https://releases.pagure.org/sanlock/%{name}-%{version}.tar.gz -Patch0: sanlock-do-not-close-connection-in-error-handling.patch -Patch1: python-Add-inquire.patch - %global python_package python3-%{name} %description @@ -34,9 +31,6 @@ The sanlock daemon manages leases for applications on hosts using shared storage %prep %setup -q -%patch0 -p1 -b .sanlock-do-not-close-connection-in-error-handling.patch -%patch1 -p1 -b .python-Add-inquire.patch - %build # upstream does not require configure # upstream does not support _smp_mflags @@ -189,7 +183,10 @@ common sanlock lockspace. %changelog -* Thu May 27 2021 David Teigland 3.8.3-3 +* Tue Jun 01 2021 David Teigland 3.8.4-1 +- Update to sanlock-3.8.4 + +* Thu May 20 2021 David Teigland 3.8.3-2 - Fix connection close and add python inquire api * Tue Jan 19 2021 David Teigland 3.8.3-1