mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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:
1 parent
c4f9e14dea
commit
bd1c1ea440
3 files changed
+54
-25
No files matched your search
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||