tools/libs/foreignmemory: Support err == NULL to map.

The existing xc_map_foreign_bulk-like interface encourages callers to
miss error checking for partial failure (by forgetting to scan the err
array).

Add support for passing err==NULL which behaves in a
xc_map_foreign_pages-like manner and returns a global error for any
failure.

While documenting this also clarify the overall behaviour and the
behaviour with err!=NULL.

With this the compat wrapper of xc_map_foreign_pages() can be
simplified.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
This commit is contained in:
Ian Campbell committed 2016-01-22 12:24:18 +00:00
1 parent c4f9e14dea
commit bd1c1ea440
3 files changed
+54 -25

No files matched your search

+32 -1
View File
@@ -14,6 +14,8 @@
*/
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include "private.h"
@@ -64,7 +66,36 @@ void *xenforeignmemory_map(xenforeignmemory_handle *fmem,
uint32_t dom, int prot,
const xen_pfn_t *arr, int *err, size_t num)
{
return osdep_xenforeignmemory_map(fmem, dom, prot, arr, err, num);
void *ret;
int *err_to_free = NULL;
if ( err == NULL )
err = err_to_free = malloc(num * sizeof(int));
if ( err == NULL )
return NULL;
ret = osdep_xenforeignmemory_map(fmem, dom, prot, arr, err, num);
if ( ret == 0 && err_to_free )
{
int i;
for ( i = 0 ; i < num ; i++ )
{
if ( err[i] )
{
errno = -err[i];
(void)osdep_xenforeignmemory_unmap(fmem, ret, num);
ret = NULL;
break;
}
}
}
free(err_to_free);
return ret;
}
int xenforeignmemory_unmap(xenforeignmemory_handle *fmem,
@@ -80,10 +80,28 @@ int xenforeignmemory_close(xenforeignmemory_handle *fmem);
*
* prot is as for mmap(2).
*
* Can partially succeed. When a page cannot be mapped, its respective
* field in @err is set to the corresponding errno value.
* @arr is an array of @pages gfns to be mapped linearly in the local
* address range. @err is an (optional) output array used to report
* per-page errors, as errno values.
*
* Returns NULL if no pages can be mapped.
* If @err is given (is non-NULL) then the mapping may partially
* succeed and return a valid pointer while also using @err to
* indicate the success (0) or failure (errno value) of the individual
* pages. The global errno thread local variable is not valid in this
* case.
*
* If @err is not given (is NULL) then on failure to map any page any
* successful mappings will be undone and NULL will be returned. errno
* will be set to correspond to the first failure (which may not be
* the most critical).
*
* It is also possible to return NULL due to a complete failure,
* i.e. failure to even attempt the mapping, in this case the global
* errno will have been set and the contents of @err (if given) is
* invalid.
*
* Note that it is also possible to return non-NULL with the contents
* of @err indicating failure to map every page.
*/
void *xenforeignmemory_map(xenforeignmemory_handle *fmem, uint32_t dom,
int prot, const xen_pfn_t *arr, int *err,
+1 -21
View File
@@ -23,32 +23,12 @@
void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
const xen_pfn_t *arr, int num)
{
void *res;
int i, *err;
if (num < 0) {
errno = EINVAL;
return NULL;
}
err = malloc(num * sizeof(*err));
if (!err)
return NULL;
res = xenforeignmemory_map(xch->fmem, dom, prot, arr, err, num);
if (res) {
for (i = 0; i < num; i++) {
if (err[i]) {
errno = -err[i];
munmap(res, num * PAGE_SIZE);
res = NULL;
break;
}
}
}
free(err);
return res;
return xenforeignmemory_map(xch->fmem, dom, prot, arr, NULL, num);
}
void *xc_map_foreign_range(xc_interface *xch,
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.