diff --git a/SOURCES/0001-config-Add-max_worker_threads.patch b/SOURCES/0001-config-Add-max_worker_threads.patch new file mode 100644 index 0000000..cdbaf01 --- /dev/null +++ b/SOURCES/0001-config-Add-max_worker_threads.patch @@ -0,0 +1,69 @@ +From e722c69cef883af1f7d60cbb2708f0092dbf2ab0 Mon Sep 17 00:00:00 2001 +From: Nir Soffer +Date: Mon, 30 Nov 2020 15:02:33 -0600 +Subject: [PATCH] config: Add max_worker_threads + +Concurrent async add_lockspace calls are limited by the number of worker +threads. Using larger number of worker threads shorten the time to add +many locksapces in large setups. + +Previously this value could be modified only via the command line. Now +it can be modified via the sanlock configuration file for easier +deployment. + +Buglink: https://bugzilla.redhat.com/1902468 +Signed-off-by: Nir Soffer +--- + src/main.c | 7 +++++++ + src/sanlock.8 | 5 +++++ + src/sanlock.conf | 3 +++ + 3 files changed, 15 insertions(+) + +diff --git a/src/main.c b/src/main.c +index e2901f3667a9..63d8cffd036c 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -2877,6 +2877,13 @@ static void read_config_file(void) + } else { + log_error("ignore unknown max_sectors_kb %s", str); + } ++ ++ } else if (!strcmp(str, "max_worker_threads")) { ++ get_val_int(line, &val); ++ if (val < DEFAULT_MIN_WORKER_THREADS) ++ val = DEFAULT_MIN_WORKER_THREADS; ++ com.max_worker_threads = val; ++ + } + } + +diff --git a/src/sanlock.8 b/src/sanlock.8 +index a9126a484cf4..2021b4ac2f5a 100644 +--- a/src/sanlock.8 ++++ b/src/sanlock.8 +@@ -1372,6 +1372,11 @@ The io timeout to use when initializing ondisk lease structures + for a lockspace or resource. This timeout is not used as a part + of either lease algorithm (as the standard io_timeout is.) + ++.IP \[bu] 2 ++max_worker_threads = ++.br ++See -t ++ + .SH SEE ALSO + .BR wdmd (8) + +diff --git a/src/sanlock.conf b/src/sanlock.conf +index 9b78e5cff236..2909a9cbc9d6 100644 +--- a/src/sanlock.conf ++++ b/src/sanlock.conf +@@ -66,3 +66,6 @@ + # + # write_init_io_timeout = + # command line: n/a ++# ++# max_worker_threads = 8 ++# command line: -t 8 +-- +2.7.5 + diff --git a/SOURCES/0002-sanlock-Report-actual-max_worker_threads.patch b/SOURCES/0002-sanlock-Report-actual-max_worker_threads.patch new file mode 100644 index 0000000..361ac35 --- /dev/null +++ b/SOURCES/0002-sanlock-Report-actual-max_worker_threads.patch @@ -0,0 +1,37 @@ +From 32a73a539432dbbca7187ddafd4a2b2ae91ea1f8 Mon Sep 17 00:00:00 2001 +From: Nir Soffer +Date: Sun, 6 Dec 2020 20:14:11 +0200 +Subject: [PATCH] sanlock: Report actual max_worker_threads + +Report actual max_worker_threads in "sanlock client status -D". This +allows detecting the issue when sanlock configuration was updated, but +sanlock daemon needs a restart to pick up the new configuration. + +Signed-off-by: Nir Soffer +--- + src/cmd.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/cmd.c b/src/cmd.c +index a5fa30f0680f..3137df08cd84 100644 +--- a/src/cmd.c ++++ b/src/cmd.c +@@ -2265,6 +2265,7 @@ static int print_state_daemon(char *str) + "max_sectors_kb_ignore=%d " + "max_sectors_kb_align=%d " + "max_sectors_kb_num=%d " ++ "max_worker_threads=%d " + "write_init_io_timeout=%u " + "use_aio=%d " + "kill_grace_seconds=%d " +@@ -2292,6 +2293,7 @@ static int print_state_daemon(char *str) + com.max_sectors_kb_ignore, + com.max_sectors_kb_align, + com.max_sectors_kb_num, ++ com.max_worker_threads, + com.write_init_io_timeout, + main_task.use_aio, + kill_grace_seconds, +-- +2.7.5 + diff --git a/SOURCES/0003-python-add-lvb-flag-to-sanlock.acquire.patch b/SOURCES/0003-python-add-lvb-flag-to-sanlock.acquire.patch new file mode 100644 index 0000000..96ace91 --- /dev/null +++ b/SOURCES/0003-python-add-lvb-flag-to-sanlock.acquire.patch @@ -0,0 +1,78 @@ +From f2457f033f4cd55280628f1033f648d2497d30d0 Mon Sep 17 00:00:00 2001 +From: Benny Zlotnik +Date: Mon, 5 Oct 2020 12:49:31 +0300 +Subject: [PATCH 3/9] python: add lvb flag to sanlock.acquire + +The flag will allow to acquire a resource with the SANLK_ACQUIRE_LVB +flag, allowing the user to write or read data from LVB space. + +Signed-off-by: Benny Zlotnik +--- + python/sanlock.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/python/sanlock.c b/python/sanlock.c +index 7c50abab895a..d26e61837ddb 100644 +--- a/python/sanlock.c ++++ b/python/sanlock.c +@@ -1082,28 +1082,31 @@ finally: + /* acquire */ + PyDoc_STRVAR(pydoc_acquire, "\ + acquire(lockspace, resource, disks \ +-[, slkfd=fd, pid=owner, shared=False, version=None])\n\ ++[, slkfd=fd, pid=owner, shared=False, version=None, lvb=False])\n\ + Acquire a resource lease for the current process (using the slkfd argument\n\ + to specify the sanlock file descriptor) or for an other process (using the\n\ + pid argument). If shared is True the resource will be acquired in the shared\n\ + mode. The version is the version of the lease that must be acquired or fail.\n\ +-The disks must be in the format: [(path, offset), ... ]\n"); ++The disks must be in the format: [(path, offset), ... ]\n\ ++If lvb is True the resource will be acquired with the LVB flag enabled\n\ ++to allow access to LVB data.\n"); + + static PyObject * + py_acquire(PyObject *self __unused, PyObject *args, PyObject *keywds) + { +- int rv = -1, sanlockfd = -1, pid = -1, shared = 0; ++ int rv = -1, sanlockfd = -1, pid = -1, shared = 0, lvb = 0; ++ uint32_t flags = 0; + PyObject *lockspace = NULL, *resource = NULL; + struct sanlk_resource *res = NULL; + PyObject *disks, *version = Py_None; + + static char *kwlist[] = {"lockspace", "resource", "disks", "slkfd", +- "pid", "shared", "version", NULL}; ++ "pid", "shared", "lvb", "version", NULL}; + + /* parse python tuple */ +- if (!PyArg_ParseTupleAndKeywords(args, keywds, "O&O&O!|iiiO", kwlist, ++ if (!PyArg_ParseTupleAndKeywords(args, keywds, "O&O&O!|iiiiO", kwlist, + convert_to_pybytes, &lockspace, convert_to_pybytes, &resource, +- &PyList_Type, &disks, &sanlockfd, &pid, &shared, &version)) { ++ &PyList_Type, &disks, &sanlockfd, &pid, &shared, &lvb, &version)) { + goto finally; + } + +@@ -1127,6 +1130,10 @@ py_acquire(PyObject *self __unused, PyObject *args, PyObject *keywds) + res->flags |= SANLK_RES_SHARED; + } + ++ if (lvb) { ++ flags |= SANLK_ACQUIRE_LVB; ++ } ++ + /* prepare the resource version */ + if (version != Py_None) { + res->flags |= SANLK_RES_LVER; +@@ -1139,7 +1146,7 @@ py_acquire(PyObject *self __unused, PyObject *args, PyObject *keywds) + + /* acquire sanlock resource (gil disabled) */ + Py_BEGIN_ALLOW_THREADS +- rv = sanlock_acquire(sanlockfd, pid, 0, 1, &res, 0); ++ rv = sanlock_acquire(sanlockfd, pid, flags, 1, &res, 0); + Py_END_ALLOW_THREADS + + if (rv != 0) { +-- +2.7.5 + diff --git a/SOURCES/0004-python-expose-set_lvb.patch b/SOURCES/0004-python-expose-set_lvb.patch new file mode 100644 index 0000000..c38eeea --- /dev/null +++ b/SOURCES/0004-python-expose-set_lvb.patch @@ -0,0 +1,91 @@ +From b0681cbc76d7dc398bd79b6f4cbb919dd539a92f Mon Sep 17 00:00:00 2001 +From: Benny Zlotnik +Date: Mon, 5 Oct 2020 13:04:13 +0300 +Subject: [PATCH 4/9] python: expose set_lvb + +Add a binding to the set_lvb function to allow writing data to LVB. + +Signed-off-by: Benny Zlotnik +--- + python/sanlock.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 58 insertions(+) + +diff --git a/python/sanlock.c b/python/sanlock.c +index d26e61837ddb..498cb8825a68 100644 +--- a/python/sanlock.c ++++ b/python/sanlock.c +@@ -1695,6 +1695,61 @@ finally: + Py_RETURN_NONE; + } + ++/* set_lvb */ ++PyDoc_STRVAR(pydoc_set_lvb, "\ ++set_lvb(lockspace, resource, disks, data)\n\ ++Set Lock Value Block for a given resource\n\ ++\n\ ++Arguments\n\ ++ lockspace lockspace name (str)\n\ ++ resource resource name (int)\n\ ++ disks path and offset (tuple)\n\ ++ data data to write (bytes)\n\ ++\n\ ++Notes\n\ ++\n\ ++The resource must be acquired with the SANLK_ACQUIRE_LVB flag\n"); ++static PyObject * ++py_set_lvb(PyObject *self __unused, PyObject *args, PyObject *keywds) ++{ ++ uint32_t flags = 0; ++ int rv = -1; ++ struct sanlk_resource *res = NULL; ++ PyObject *lockspace = NULL, *resource = NULL, *data = NULL; ++ PyObject *disks; ++ ++ static char *kwlist[] = {"lockspace", "resource", "disks", "data", NULL}; ++ if (!PyArg_ParseTupleAndKeywords(args, keywds, "O&O&O!O&", kwlist, ++ convert_to_pybytes, &lockspace, convert_to_pybytes, &resource, ++ &PyList_Type, &disks, convert_to_pybytes, &data)) { ++ goto finally; ++ } ++ ++ if (parse_disks(disks, &res) < 0) { ++ goto finally; ++ } ++ ++ strncpy(res->lockspace_name, PyBytes_AsString(lockspace), SANLK_NAME_LEN); ++ strncpy(res->name, PyBytes_AsString(resource), SANLK_NAME_LEN); ++ ++ Py_BEGIN_ALLOW_THREADS ++ rv = sanlock_set_lvb(flags, res, PyBytes_AS_STRING(data), PyBytes_GET_SIZE(data)); ++ Py_END_ALLOW_THREADS ++ ++ if (rv < 0) { ++ set_sanlock_error(rv, "Unable to set lvb"); ++ goto finally; ++ } ++ ++finally: ++ Py_XDECREF(lockspace); ++ Py_XDECREF(resource); ++ free(res); ++ if (rv < 0) ++ return NULL; ++ Py_RETURN_NONE; ++} ++ + static PyMethodDef + sanlock_methods[] = { + {"register", py_register, METH_NOARGS, pydoc_register}, +@@ -1736,6 +1791,9 @@ sanlock_methods[] = { + {"end_event", (PyCFunction) py_end_event, METH_VARARGS, pydoc_end_event}, + {"set_event", (PyCFunction) py_set_event, + METH_VARARGS|METH_KEYWORDS, pydoc_set_event}, ++ {"set_lvb", (PyCFunction) py_set_lvb, ++ METH_VARARGS|METH_KEYWORDS, pydoc_set_lvb}, ++ + {NULL, NULL, 0, NULL} + }; + +-- +2.7.5 + diff --git a/SOURCES/0005-python-expose-get_lvb.patch b/SOURCES/0005-python-expose-get_lvb.patch new file mode 100644 index 0000000..f9df12d --- /dev/null +++ b/SOURCES/0005-python-expose-get_lvb.patch @@ -0,0 +1,92 @@ +From 54435856a134468c97112bfe44815ca48e1b424f Mon Sep 17 00:00:00 2001 +From: Benny Zlotnik +Date: Mon, 5 Oct 2020 13:18:05 +0300 +Subject: [PATCH 5/9] python: expose get_lvb + +Add a binding to the get_lvb function to allow reading data from LVB. + +Signed-off-by: Benny Zlotnik +--- + python/sanlock.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 59 insertions(+) + +diff --git a/python/sanlock.c b/python/sanlock.c +index 498cb8825a68..40d3b88c182b 100644 +--- a/python/sanlock.c ++++ b/python/sanlock.c +@@ -1750,6 +1750,63 @@ finally: + Py_RETURN_NONE; + } + ++PyDoc_STRVAR(pydoc_get_lvb, "\ ++get_lvb(lockspace, resource, disks) -> bytes\n\ ++Read Lock Value Block for a given resource\n\ ++\n\ ++Arguments\n\ ++ lockspace lockspace name (str)\n\ ++ resource resource name (int)\n\ ++ disks path and offset (tuple)\n\ ++\n\ ++Returns\n\ ++ data data written with set_lvb\n\ ++Notes\n\ ++\n\ ++The resource must be acquired with the SANLK_ACQUIRE_LVB flag\n"); ++static PyObject * ++py_get_lvb(PyObject *self __unused, PyObject *args, PyObject *keywds) ++{ ++ uint32_t flags = 0; ++ int rv = -1; ++ struct sanlk_resource *res = NULL; ++ PyObject *lockspace = NULL, *resource = NULL; ++ PyObject *disks; ++ char data[512]; ++ ++ static char *kwlist[] = {"lockspace", "resource", "disks", NULL}; ++ if (!PyArg_ParseTupleAndKeywords(args, keywds, "O&O&O!", kwlist, ++ convert_to_pybytes, &lockspace, convert_to_pybytes, &resource, ++ &PyList_Type, &disks)) { ++ goto finally; ++ } ++ ++ if (parse_disks(disks, &res) < 0) { ++ goto finally; ++ } ++ ++ strncpy(res->lockspace_name, PyBytes_AsString(lockspace), SANLK_NAME_LEN); ++ strncpy(res->name, PyBytes_AsString(resource), SANLK_NAME_LEN); ++ ++ Py_BEGIN_ALLOW_THREADS ++ rv = sanlock_get_lvb(flags, res, data, sizeof(data)); ++ Py_END_ALLOW_THREADS ++ ++ if (rv < 0) { ++ set_sanlock_error(rv, "Unable to get lvb"); ++ goto finally; ++ } ++ ++finally: ++ Py_XDECREF(lockspace); ++ Py_XDECREF(resource); ++ free(res); ++ if (rv < 0) ++ return NULL; ++ ++ return Py_BuildValue("y", data); ++} ++ + static PyMethodDef + sanlock_methods[] = { + {"register", py_register, METH_NOARGS, pydoc_register}, +@@ -1793,6 +1850,8 @@ sanlock_methods[] = { + METH_VARARGS|METH_KEYWORDS, pydoc_set_event}, + {"set_lvb", (PyCFunction) py_set_lvb, + METH_VARARGS|METH_KEYWORDS, pydoc_set_lvb}, ++ {"get_lvb", (PyCFunction) py_get_lvb, ++ METH_VARARGS|METH_KEYWORDS, pydoc_get_lvb}, + + {NULL, NULL, 0, NULL} + }; +-- +2.7.5 + diff --git a/SOURCES/0006-tests-add-a-test-for-LVB-operation.patch b/SOURCES/0006-tests-add-a-test-for-LVB-operation.patch new file mode 100644 index 0000000..eab1df1 --- /dev/null +++ b/SOURCES/0006-tests-add-a-test-for-LVB-operation.patch @@ -0,0 +1,95 @@ +From 3eff548a846ea756db9f8440511874fcaa4580e0 Mon Sep 17 00:00:00 2001 +From: Benny Zlotnik +Date: Mon, 5 Oct 2020 13:20:27 +0300 +Subject: [PATCH 6/9] tests: add a test for LVB operation + +This patch tests writing and reading to LVB via python bindings. + +Signed-off-by: Benny Zlotnik +--- + tests/python_test.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +diff --git a/tests/python_test.py b/tests/python_test.py +index 719bcb606eba..5e034a75e1c6 100644 +--- a/tests/python_test.py ++++ b/tests/python_test.py +@@ -795,3 +795,75 @@ def test_acquire_path_length(no_sanlock_daemon): + path = "x" * (constants.SANLK_PATH_LEN - 1) + with raises_sanlock_errno(): + sanlock.acquire(b"ls_name", b"res_name", [(path, 0)], pid=os.getpid()) ++ ++ ++def test_lvb(tmpdir, sanlock_daemon): ++ 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, MiB) ++ ++ 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) ++ ++ disks = [(res_path, 0)] ++ sanlock.write_resource(b"ls_name", b"res_name", disks) ++ ++ fd = sanlock.register() ++ ++ sanlock.acquire(b"ls_name", b"res_name", disks, slkfd=fd, lvb=True) ++ sanlock.set_lvb(b"ls_name", b"res_name", disks, b"{gen:0}") ++ ++ result = sanlock.get_lvb(b"ls_name", b"res_name", disks) ++ sanlock.release(b"ls_name", b"res_name", disks, slkfd=fd) ++ ++ assert result == b"{gen:0}" ++ ++ ++def test_lvb_value_too_long(tmpdir, sanlock_daemon): ++ 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, MiB) ++ ++ 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) ++ ++ disks = [(res_path, 0)] ++ sanlock.write_resource(b"ls_name", b"res_name", disks) ++ ++ fd = sanlock.register() ++ ++ long_val = b"a" * 513 ++ sanlock.acquire(b"ls_name", b"res_name", disks, slkfd=fd, lvb=True) ++ with raises_sanlock_errno(errno.E2BIG): ++ sanlock.set_lvb(b"ls_name", b"res_name", disks, long_val) ++ ++ sanlock.release(b"ls_name", b"res_name", disks, slkfd=fd) ++ ++ ++def test_lvb_null_bytes(tmpdir, sanlock_daemon): ++ 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, MiB) ++ ++ 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) ++ ++ disks = [(res_path, 0)] ++ sanlock.write_resource(b"ls_name", b"res_name", disks) ++ ++ fd = sanlock.register() ++ ++ sanlock.acquire(b"ls_name", b"res_name", disks, slkfd=fd, lvb=True) ++ sanlock.set_lvb(b"ls_name", b"res_name", disks, b"{ge\x00:0}") ++ ++ result = sanlock.get_lvb(b"ls_name", b"res_name", disks) ++ sanlock.release(b"ls_name", b"res_name", disks, slkfd=fd) ++ ++ # Check that the string we passed is terminated by the null-byte ++ assert result == b"{ge" +-- +2.7.5 + diff --git a/SOURCES/0007-python-improve-get-set_lvb-documentation.patch b/SOURCES/0007-python-improve-get-set_lvb-documentation.patch new file mode 100644 index 0000000..4a025a4 --- /dev/null +++ b/SOURCES/0007-python-improve-get-set_lvb-documentation.patch @@ -0,0 +1,51 @@ +From 51489e1e5cf346a9e35b300fc2c89588173c839a Mon Sep 17 00:00:00 2001 +From: Benny Zlotnik +Date: Wed, 9 Dec 2020 09:57:54 +0200 +Subject: [PATCH 7/9] python: improve get/set_lvb documentation + +- Specify lvb=True explicitly instead of mentioning the sanlock flag +- Document when data is written and visible +- Unify whitespace in function documentation, consistent with other + functions. + +Signed-off-by: Benny Zlotnik +Signed-off-by: Nir Soffer +--- + python/sanlock.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/python/sanlock.c b/python/sanlock.c +index 40d3b88c182b..2220cf31ec3f 100644 +--- a/python/sanlock.c ++++ b/python/sanlock.c +@@ -1707,8 +1707,11 @@ Arguments\n\ + data data to write (bytes)\n\ + \n\ + Notes\n\ +-\n\ +-The resource must be acquired with the SANLK_ACQUIRE_LVB flag\n"); ++ The resource must be acquired with lvb=true.\n\ ++ The size of data is limited by the sector size (512/4K).\n\ ++ The new data is visible after the resource is released.\n\ ++"); ++ + static PyObject * + py_set_lvb(PyObject *self __unused, PyObject *args, PyObject *keywds) + { +@@ -1761,9 +1764,11 @@ Arguments\n\ + \n\ + Returns\n\ + data data written with set_lvb\n\ +-Notes\n\ + \n\ +-The resource must be acquired with the SANLK_ACQUIRE_LVB flag\n"); ++Notes\n\ ++ The resource must be acquired with lvb=True.\n\ ++"); ++ + static PyObject * + py_get_lvb(PyObject *self __unused, PyObject *args, PyObject *keywds) + { +-- +2.7.5 + diff --git a/SOURCES/0008-python-support-size-in-get_lvb.patch b/SOURCES/0008-python-support-size-in-get_lvb.patch new file mode 100644 index 0000000..394f0ce --- /dev/null +++ b/SOURCES/0008-python-support-size-in-get_lvb.patch @@ -0,0 +1,102 @@ +From 9117f93fa7909dd7b77e1bef6ddcc289d9643db6 Mon Sep 17 00:00:00 2001 +From: Benny Zlotnik +Date: Wed, 9 Dec 2020 16:36:09 +0200 +Subject: [PATCH 8/9] python: support size in get_lvb + +Add a size parameter to allow the user choose how much data to get back, +the API will now look like this: + + sanlock.get_lvb(lockspace, resource, disks, size) + +Signed-off-by: Benny Zlotnik +Signed-off-by: Nir Soffer +--- + python/sanlock.c | 33 ++++++++++++++++++++++++--------- + 1 file changed, 24 insertions(+), 9 deletions(-) + +diff --git a/python/sanlock.c b/python/sanlock.c +index 2220cf31ec3f..e5a0cffcbfe4 100644 +--- a/python/sanlock.c ++++ b/python/sanlock.c +@@ -1754,35 +1754,43 @@ finally: + } + + PyDoc_STRVAR(pydoc_get_lvb, "\ +-get_lvb(lockspace, resource, disks) -> bytes\n\ ++get_lvb(lockspace, resource, disks, size) -> bytes\n\ + Read Lock Value Block for a given resource\n\ + \n\ + Arguments\n\ + lockspace lockspace name (str)\n\ + resource resource name (int)\n\ + disks path and offset (tuple)\n\ ++ size amount of data to read (int)\n\ + \n\ + Returns\n\ + data data written with set_lvb\n\ + \n\ + Notes\n\ + The resource must be acquired with lvb=True.\n\ ++ size has to be in range 0 < n <= 4096.\n\ + "); + + static PyObject * + py_get_lvb(PyObject *self __unused, PyObject *args, PyObject *keywds) + { + uint32_t flags = 0; ++ uint32_t lvb_len = 0; + int rv = -1; + struct sanlk_resource *res = NULL; + PyObject *lockspace = NULL, *resource = NULL; +- PyObject *disks; +- char data[512]; ++ PyObject *disks = NULL; ++ PyObject *result = NULL; + +- static char *kwlist[] = {"lockspace", "resource", "disks", NULL}; +- if (!PyArg_ParseTupleAndKeywords(args, keywds, "O&O&O!", kwlist, ++ static char *kwlist[] = {"lockspace", "resource", "disks", "size", NULL}; ++ if (!PyArg_ParseTupleAndKeywords(args, keywds, "O&O&O!I", kwlist, + convert_to_pybytes, &lockspace, convert_to_pybytes, &resource, +- &PyList_Type, &disks)) { ++ &PyList_Type, &disks, &lvb_len)) { ++ goto finally; ++ } ++ ++ if (lvb_len < 1 || lvb_len > 4096) { ++ PyErr_Format(PyExc_ValueError, "Invalid size %d, must be in range: 0 < size <= 4096", lvb_len); + goto finally; + } + +@@ -1793,8 +1801,15 @@ py_get_lvb(PyObject *self __unused, PyObject *args, PyObject *keywds) + strncpy(res->lockspace_name, PyBytes_AsString(lockspace), SANLK_NAME_LEN); + strncpy(res->name, PyBytes_AsString(resource), SANLK_NAME_LEN); + ++ result = PyBytes_FromStringAndSize(NULL, lvb_len); ++ if (result == NULL) { ++ goto finally; ++ } ++ ++ memset(PyBytes_AS_STRING(result), 0, lvb_len); ++ + Py_BEGIN_ALLOW_THREADS +- rv = sanlock_get_lvb(flags, res, data, sizeof(data)); ++ rv = sanlock_get_lvb(flags, res, PyBytes_AS_STRING(result), lvb_len); + Py_END_ALLOW_THREADS + + if (rv < 0) { +@@ -1807,9 +1822,9 @@ finally: + Py_XDECREF(resource); + free(res); + if (rv < 0) +- return NULL; ++ Py_CLEAR(result); + +- return Py_BuildValue("y", data); ++ return result; + } + + static PyMethodDef +-- +2.7.5 + diff --git a/SOURCES/0009-python-improve-lvb-tests.patch b/SOURCES/0009-python-improve-lvb-tests.patch new file mode 100644 index 0000000..78ca8cd --- /dev/null +++ b/SOURCES/0009-python-improve-lvb-tests.patch @@ -0,0 +1,116 @@ +From 058ad1c7e4566696475241ea0897bbf799144d1c Mon Sep 17 00:00:00 2001 +From: Benny Zlotnik +Date: Wed, 9 Dec 2020 19:14:36 +0200 +Subject: [PATCH 9/9] python: improve lvb tests + +- Remove null byte test, it is now tested in the basic test +- Add test for reading less than sector size + +Testing storage with 4k sector size needs more work. + +Signed-off-by: Benny Zlotnik +Signed-off-by: Nir Soffer +--- + tests/python_test.py | 64 ++++++++++++++++++---------------------------------- + 1 file changed, 22 insertions(+), 42 deletions(-) + +diff --git a/tests/python_test.py b/tests/python_test.py +index 5e034a75e1c6..448b043f7092 100644 +--- a/tests/python_test.py ++++ b/tests/python_test.py +@@ -800,70 +800,50 @@ def test_acquire_path_length(no_sanlock_daemon): + def test_lvb(tmpdir, sanlock_daemon): + 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, MiB) +- + 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) +- + disks = [(res_path, 0)] + sanlock.write_resource(b"ls_name", b"res_name", disks) + + fd = sanlock.register() + +- sanlock.acquire(b"ls_name", b"res_name", disks, slkfd=fd, lvb=True) +- sanlock.set_lvb(b"ls_name", b"res_name", disks, b"{gen:0}") ++ lvb_data = b"first\0second" ++ lvb_sector = lvb_data.ljust(512, b"\0") + +- result = sanlock.get_lvb(b"ls_name", b"res_name", disks) ++ sanlock.acquire(b"ls_name", b"res_name", disks, slkfd=fd, lvb=True) ++ sanlock.set_lvb(b"ls_name", b"res_name", disks, lvb_sector) + sanlock.release(b"ls_name", b"res_name", disks, slkfd=fd) + +- assert result == b"{gen:0}" ++ # Test reading complete sector (typical usage). + ++ sanlock.acquire(b"ls_name", b"res_name", disks, slkfd=fd, lvb=True) ++ result = sanlock.get_lvb(b"ls_name", b"res_name", disks, len(lvb_sector)) ++ sanlock.release(b"ls_name", b"res_name", disks, slkfd=fd) + +-def test_lvb_value_too_long(tmpdir, sanlock_daemon): +- 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, MiB) +- +- 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) +- +- disks = [(res_path, 0)] +- sanlock.write_resource(b"ls_name", b"res_name", disks) ++ assert result == lvb_sector + +- fd = sanlock.register() ++ # Test reading less than sector size. + +- long_val = b"a" * 513 + sanlock.acquire(b"ls_name", b"res_name", disks, slkfd=fd, lvb=True) +- with raises_sanlock_errno(errno.E2BIG): +- sanlock.set_lvb(b"ls_name", b"res_name", disks, long_val) +- ++ result = sanlock.get_lvb(b"ls_name", b"res_name", disks, len(lvb_data)) + sanlock.release(b"ls_name", b"res_name", disks, slkfd=fd) + ++ assert result == lvb_data + +-def test_lvb_null_bytes(tmpdir, sanlock_daemon): +- 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, MiB) +- +- 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) ++ # Test failure to write more then sector size. + +- disks = [(res_path, 0)] +- sanlock.write_resource(b"ls_name", b"res_name", disks) ++ sanlock.acquire(b"ls_name", b"res_name", disks, slkfd=fd, lvb=True) ++ with raises_sanlock_errno(errno.E2BIG): ++ sanlock.set_lvb(b"ls_name", b"res_name", disks, lvb_sector + b"x") + +- fd = sanlock.register() + +- sanlock.acquire(b"ls_name", b"res_name", disks, slkfd=fd, lvb=True) +- sanlock.set_lvb(b"ls_name", b"res_name", disks, b"{ge\x00:0}") ++def test_lvb_invalid_value(): ++ disks = [("/no/such/path", 0)] + +- result = sanlock.get_lvb(b"ls_name", b"res_name", disks) +- sanlock.release(b"ls_name", b"res_name", disks, slkfd=fd) ++ with pytest.raises(ValueError): ++ sanlock.get_lvb(b"ls_name", b"res_name", disks, 0) + +- # Check that the string we passed is terminated by the null-byte +- assert result == b"{ge" ++ with pytest.raises(ValueError): ++ sanlock.get_lvb(b"ls_name", b"res_name", disks, 4097) +-- +2.7.5 + diff --git a/SPECS/sanlock.spec b/SPECS/sanlock.spec index bde81e6..cf85938 100644 --- a/SPECS/sanlock.spec +++ b/SPECS/sanlock.spec @@ -1,6 +1,6 @@ Name: sanlock Version: 3.8.2 -Release: 1%{?dist} +Release: 4%{?dist} Summary: A shared storage lock manager Group: System Environment/Base @@ -23,6 +23,16 @@ Requires(preun): systemd-units Requires(postun): systemd-units Source0: https://releases.pagure.org/sanlock/%{name}-%{version}.tar.gz +Patch0: 0001-config-Add-max_worker_threads.patch +Patch1: 0002-sanlock-Report-actual-max_worker_threads.patch +Patch2: 0003-python-add-lvb-flag-to-sanlock.acquire.patch +Patch3: 0004-python-expose-set_lvb.patch +Patch4: 0005-python-expose-get_lvb.patch +Patch5: 0006-tests-add-a-test-for-LVB-operation.patch +Patch6: 0007-python-improve-get-set_lvb-documentation.patch +Patch7: 0008-python-support-size-in-get_lvb.patch +Patch8: 0009-python-improve-lvb-tests.patch + %global python_package python3-%{name} %description @@ -31,6 +41,16 @@ The sanlock daemon manages leases for applications on hosts using shared storage %prep %setup -q +%patch0 -p1 -b .0001-config-Add-max_worker_threads.patch +%patch1 -p1 -b .0002-sanlock-Report-actual-max_worker_threads.patch +%patch2 -p1 -b .0003-python-add-lvb-flag-to-sanlock.acquire.patch +%patch3 -p1 -b .0004-python-expose-set_lvb.patch +%patch4 -p1 -b .0005-python-expose-get_lvb.patch +%patch5 -p1 -b .0006-tests-add-a-test-for-LVB-operation.patch +%patch6 -p1 -b .0007-python-improve-get-set_lvb-documentation.patch +%patch7 -p1 -b .0008-python-support-size-in-get_lvb.patch +%patch8 -p1 -b .0009-python-improve-lvb-tests.patch + %build # upstream does not require configure # upstream does not support _smp_mflags @@ -89,7 +109,7 @@ getent passwd sanlock > /dev/null || /usr/sbin/useradd \ %systemd_preun wdmd.service sanlock.service %postun -%systemd_postun +%systemd_postun wdmd.service sanlock.service %files /usr/lib/systemd/systemd-wdmd @@ -183,6 +203,15 @@ common sanlock lockspace. %changelog +* Mon Jan 25 2021 David Teigland 3.8.2-4 +- add python bindings for lvb api + +* Tue Jan 12 2021 David Teigland 3.8.2-3 +- rebuild with new version number + +* Wed Jan 06 2021 David Teigland 3.8.2-2 +- allow max_worker_threads to be set in config file + * Mon Aug 10 2020 David Teigland 3.8.2-1 - Update to sanlock-3.8.2