[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v3 12/12] livepatch: Add python bindings for livepatch operations
On 9/16/19 12:40 PM, Pawel Wieczorkiewicz wrote: Extend the XC python bindings library to support also all common livepatch operations and actions. Add the python bindings for the following operations: - status (pyxc_livepatch_status): Requires a payload name as an input. Returns a status dict containing a state string and a return code integer. - action (pyxc_livepatch_action): Requires a payload name and an action id as an input. Timeout and flags are optional parameters. Returns a return code integer. - upload (pyxc_livepatch_upload): Requires a payload name and a module's filename as an input. Returns a return code integer. - list (pyxc_livepatch_list): Takes no parameters. Returns a list of dicts containing each payload's: * name as a string * state as a string * return code as an integer * list of metadata key=value strings Each functions throws an exception error based on the errno value received from its corresponding libxc function call. Signed-off-by: Pawel Wieczorkiewicz <wipawel@xxxxxxxxx> Reviewed-by: Martin Mazein <amazein@xxxxxxxxx> Reviewed-by: Andra-Irina Paraschiv <andraprs@xxxxxxxxxx> Reviewed-by: Leonard Foerster <foersleo@xxxxxxxxx> Reviewed-by: Norbert Manthey <nmanthey@xxxxxxxxx> Acked-by: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx> This will be very useful, thanks! --- Changed since v1: * changed PyList_Append() with PyList_SetItem() as requested by Marek tools/python/xen/lowlevel/xc/xc.c | 273 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) snip> +static PyObject *pyxc_livepatch_action(XcObject *self, + PyObject *args, + PyObject *kwds) +{ + int (*action_func)(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags); + char *name; + unsigned int action; + uint32_t timeout; + uint64_t flags; + int rc; + + static char *kwd_list[] = { "name", "action", "timeout", "flags", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "sI|Ik", kwd_list, + &name, &action, &timeout, &flags) ) + goto error; + + switch (action) + { + case LIVEPATCH_ACTION_UNLOAD: + action_func = xc_livepatch_unload; + break; + case LIVEPATCH_ACTION_REVERT: + action_func = xc_livepatch_revert; + break; + case LIVEPATCH_ACTION_APPLY: + action_func = xc_livepatch_apply; + break; + case LIVEPATCH_ACTION_REPLACE: + action_func = xc_livepatch_replace; + break; + default: + goto error; + } + + rc = action_func(self->xc_handle, name, timeout, flags); + if ( rc ) + goto error; + + return Py_BuildValue("i", rc); For this and all the other functions which return zero on success, IMO returning None would be more Pythonic. +error: + return pyxc_error_to_exception(self->xc_handle); +} + +static PyObject *pyxc_livepatch_upload(XcObject *self, + PyObject *args, + PyObject *kwds) +{ + unsigned char *fbuf = MAP_FAILED; + char *name, *filename; + struct stat buf; + int fd = 0, rc; + ssize_t len; + + static char *kwd_list[] = { "name", "filename", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwd_list, + &name, &filename)) + goto error; + + fd = open(filename, O_RDONLY); + if ( fd < 0 ) + goto error; + + if ( stat(filename, &buf) != 0 ) + goto error; I think it would be better to use fstat() to avoid a second path lookup potentially pointing to a different file. + + len = buf.st_size; + fbuf = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0); + if ( fbuf == MAP_FAILED ) + goto error; + + rc = xc_livepatch_upload(self->xc_handle, name, fbuf, len); + if ( rc ) + goto error; + + if ( munmap(fbuf, len) ) + { + fbuf = MAP_FAILED; + goto error; + } + close(fd); + + return Py_BuildValue("i", rc);; Stray semicolon +error: + if ( fbuf != MAP_FAILED ) + munmap(fbuf, len); + if ( fd >= 0 ) + close(fd); You should probably save & restore errno so you can return the original error. + return pyxc_error_to_exception(self->xc_handle); Maybe you can have a conditional return to avoid duplicating the munmap() & close()? E.g. return rc ? pyxc_error_to_exception(self->xc_handle) : ... +} + +static PyObject *pyxc_livepatch_list(XcObject *self) +{ + PyObject *list; + unsigned int nr, done, left, i; + xen_livepatch_status_t *info = NULL; + char *name = NULL; + char *metadata = NULL; + uint32_t *len = NULL; + uint32_t *metadata_len = NULL; + uint64_t name_total_size, metadata_total_size; + off_t name_off, metadata_off; + int rc; + + rc = xc_livepatch_list_get_sizes(self->xc_handle, &nr, + &name_total_size, &metadata_total_size); + if ( rc ) + goto error; + + if ( nr == 0 ) + return PyList_New(0); + + rc = ENOMEM; + info = malloc(nr * sizeof(*info)); + if ( !info ) + goto error; + + name = malloc(name_total_size * sizeof(*name)); + if ( !name ) + goto error; + + len = malloc(nr * sizeof(*len)); + if ( !len ) + goto error; + + metadata = malloc(metadata_total_size * sizeof(*metadata)); + if ( !metadata ) + goto error; + + metadata_len = malloc(nr * sizeof(*metadata_len)); + if ( !metadata_len ) + goto error; + + rc = xc_livepatch_list(self->xc_handle, nr, 0, info, + name, len, name_total_size, + metadata, metadata_len, metadata_total_size, + &done, &left); + if ( rc ) + goto error; Should you also check done and left as is done in xen-livepatch.c? if ( rc || done != nr || left > 0) + + list = PyList_New(done); + name_off = metadata_off = 0; + for ( i = 0; i < done; i++ ) + { + PyObject *info_dict, *metadata_list; + char *name_str, *metadata_str; + + name_str = name + name_off; + metadata_str = metadata + metadata_off; + + metadata_list = PyList_New(0); + for ( char *s = metadata_str; s < metadata_str + metadata_len[i]; s += strlen(s) + 1 ) + { + PyObject *field = Py_BuildValue("s", s); + if ( field == NULL ) + { + Py_DECREF(list); + Py_DECREF(metadata_list); + rc = EFAULT; + goto error; + } + + PyList_Append(metadata_list, field); + Py_DECREF(field); + } + + info_dict = Py_BuildValue( + "{s:s,s:i,s:i,s:N}", + "name", name_str, + "state", info[i].state, + "rc", info[i].rc, + "metadata", metadata_list); + + if ( info_dict == NULL ) + { + Py_DECREF(list); + Py_DECREF(metadata_list); + rc = EFAULT; + goto error; + } + PyList_SetItem(list, i, info_dict); + Py_DECREF(info_dict); You can use PyList_SET_ITEM() to avoid the need for PyDECREF. Thanks, -- Ross Lagerwall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |