On 05/12/2014 07:22 AM, Michal Privoznik wrote:
On 10.05.2014 01:21, Tomoki Sekiyama wrote:
> Add binding for the new virDomainFSFreeze and virDomainFSThaw functions
> added in libvirt 1.2.5. These require override since these take a list
> of mountpoints path string. The methods are named 'fSFreeze' and
'fSThaw',
> like a existing 'fSTrim' method.
Eww. I'd rather 'fsFreeze' and 'fsThaw' - how baked in is the
'fSTrim'
naming?
> +libvirt_virDomainFSFreeze(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args) {
> + PyObject *py_retval = NULL;
> + int c_retval;
> + virDomainPtr domain;
> + PyObject *pyobj_domain;
> + PyObject *pyobj_list;
> + unsigned int flags;
> + unsigned int nmountpoints = 0;
> + const char **mountpoints = NULL;
This should be 'char **mountpoints = NULL;'...
> + size_t i = 0, j;
> +
> + if (!PyArg_ParseTuple(args, (char *)"OOi:virDomainFSFreeze",
> + &pyobj_domain, &pyobj_list, &flags))
> + return NULL;
> + domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
> +
> + if (PyList_Check(pyobj_list)) {
> + nmountpoints = PyList_Size(pyobj_list);
> +
> + if (VIR_ALLOC_N(mountpoints, nmountpoints) < 0)
> + return PyErr_NoMemory();
> +
> + for (i = 0; i < nmountpoints; i++) {
> + if (libvirt_charPtrUnwrap(PyList_GetItem(pyobj_list, i),
> + (char **)mountpoints+i) < 0 ||
...so you can drop the cast here...
> + mountpoints[i] == NULL)
> + goto cleanup;
> + }
> + }
> +
> + LIBVIRT_BEGIN_ALLOW_THREADS;
> + c_retval = virDomainFSFreeze(domain, mountpoints, nmountpoints, flags);
...at the expense of needing one here.
> + LIBVIRT_END_ALLOW_THREADS;
> + py_retval = libvirt_intWrap((int) c_retval);
> +
> +cleanup:
> + if (mountpoints) {
This if is useless.
> + for (j = 0 ; j < i ; j++)
> + VIR_FREE(mountpoints[j]);
> + VIR_FREE(mountpoints);
Ouch, freeing a const char? I know you are doing it to shut the gcc up, but I'd
rather typecast @mountpoints in the API call a few lines above and satisfy
const-correctness.
It's not just gcc, but ALL C compilers. The C language mandates this to
be an error, although it drives me crazy. Quoting from C99 6.5.16.1 para 6:
EXAMPLE 3
Consider the fragment:
const char **cpp;
char *p;
const char c = 'A';
cpp = &p; //constraint violation
*cpp = &c; //valid
*p = 0; //valid
The first assignment is unsafe because it would allow the following
valid code to attempt to change the
value of the const object c.
> + }
> + return py_retval;
No, you are saying in -api.xml that you'll return -1 on error. But you're
returning NULL. Moreover, I think we should return None rather than -1 if that's the
case.
The C code returns an integer, and the python code should do likewise.
But remember, in python, you return either 'NULL' (witness that a python
exception needs to be raised) or a pointer to a python integer object.
The return looks correct to me.
+++ b/libvirt-override-api.xml
@@ -626,17 +626,17 @@
</function>
<function name='virDomainFSFreeze' file='python'>
<info>Freeze specified filesystems within the guest</info>
- <return type='int' info='the number of frozen filesystems on
success, -1 otherwise.'/>
+ <return type='int' info='the number of frozen filesystems on
success, None otherwise.'/>
NACK to this hunk. If you return an integer on success, you must return
-1 on failure. The generator does not do well with a mix of python
integer vs. non-integer python struct - None is only paired with
non-integer returns.
Having said that, I'll wait a few moments prior squashing that in and pushing just to
allow anybody else to express their opinion. For example, why gcc doesn't like if char
** is passed to a const char ** argument...
(Any reason you didn't have your mailer wrap lines?)
Probably best to send a v2 at this point.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library
http://libvirt.org