On Wed, Dec 9, 2020 at 7:43 PM Benny Zlotnik <bzlotnik(a)redhat.com> wrote:
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 <bzlotnik(a)redhat.com>
---
python/sanlock.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/python/sanlock.c b/python/sanlock.c
index 567d86c..41bbb43 100644
--- a/python/sanlock.c
+++ b/python/sanlock.c
@@ -1659,26 +1659,28 @@ 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\
Missing \n
Notes\n\
\n\
Remove \n
-The resource must be acquired with lvb=True\n");
+The resource must be acquired with lvb=True\n\
+size is required and has to be > 0.\n");
Add the upper limit, see comment I posted by mistake on the previous patch.
static PyObject *
py_get_lvb(PyObject *self __unused, PyObject *args, PyObject *keywds)
{
- uint32_t flags = 0;
+ uint32_t flags = 0, lvb_size = 0;
Lets use one variable per line in new code.
int rv = -1;
struct sanlk_resource *res = NULL;
PyObject *lockspace = NULL, *resource = NULL;
PyObject *disks;
- char data[512];
+ char *lvb_data = 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!K", kwlist,
K is unsigned long, we can use I (capital i) for int.
convert_to_pybytes, &lockspace, convert_to_pybytes,
&resource,
- &PyList_Type, &disks)) {
+ &PyList_Type, &disks, &lvb_size)) {
goto finally;
}
We need to validate lvb_len. If it is out of range (0 < lvb_len
<4096), we want to
raise a ValueError right here.
@@ -1688,9 +1690,10 @@ 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);
+ lvb_data = calloc(lvb_size, sizeof(char));
calloc(1, lv_len)
(see line 195)
Py_BEGIN_ALLOW_THREADS
- rv = sanlock_get_lvb(flags, res, data, sizeof(data));
+ rv = sanlock_get_lvb(flags, res, lvb_data, lvb_size);
Py_END_ALLOW_THREADS
if (rv < 0) {
@@ -1705,7 +1708,7 @@ finally:
if (rv < 0)
return NULL;
You leak lvb_data here...
- return Py_BuildValue("y", data);
+ return Py_BuildValue("y#", lvb_data, lvb_size);
and here.
The nicest way would be to create a bytes object from lvb_data,
so it owns the data so we don't have to copy it twice. Python does
not support this, but we can do:
PyObject *result = NULL;
...
result = PyBytes_FromStringAndSize(NULL, lvb_len);
memset(PyBytes_AS_STRING(result), 0, lvb_len);
And pass the internal buffer to sanlock in the same way.
If the call fail we will clear the value, which decref the object and set
the pointer to NULL;
finally:
Py_XDECREF(lockspace);
Py_XDECREF(resource);
free(res);
if (rv < 0)
Py_CLEAR(result);
return result;
}
static PyMethodDef
--
2.28.0