|
Description
|
Part of what 'zpool status' does in status_callback() is:
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
&nerr) == 0) {
nvlist_t *nverrlist = NULL;
/*
* If the approximate error count is small, get a
* precise count by fetching the entire log and
* uniquifying the results.
*/
if (nerr < 100 && !cbp->cb_verbose &&
zpool_get_errlog(zhp, &nverrlist) == 0) {
nvpair_t *elem;
elem = NULL;
nerr = 0;
while ((elem = nvlist_next_nvpair(nverrlist,
elem)) != NULL) {
nerr++;
}
}
nvlist_free(nverrlist);
And in zpool_get_errlog(), we do:
verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT,
&count) == 0);
if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl,
count * sizeof (zbookmark_t))) == (uintptr_t)NULL)
return (-1);
Note, in most cases, there won't be any errors, so 'count' will be zero. We will then
try to alloc size 0. That's pretty ugly.
Further, looking at zfs_alloc():
void *
zfs_alloc(libzfs_handle_t *hdl, size_t size)
{
void *data;
if ((data = calloc(1, size)) == NULL)
(void) no_memory(hdl);
return (data);
}
If calloc() returns NULL, we don't just simply return an error up the stack, we bail
completely.
This works ok on OpenSolaris (partly because we're using libumem), but if another platform
say had a different underlying calloc() routine that returned NULL if size was 0, then
we'd have badness.
It also unnecessary for us to call zpool_get_errlog() in the first place if 'nerr' is 0.
|