From ea6174cf3680334e8313d628910b8e6f10ed3ecc Mon Sep 17 00:00:00 2001 From: Jordan Henderson Date: Tue, 28 Sep 2021 14:22:45 -0500 Subject: [PATCH 1/3] Update compact dataset I/O routines to handle driver-level memory copy --- src/H5Dcompact.c | 162 ++++++++++++++++++++++++++++++++++++++++++++--- src/H5FDpublic.h | 24 +++++++ src/H5Fprivate.h | 5 +- src/H5Fquery.c | 23 +++++++ 4 files changed, 201 insertions(+), 13 deletions(-) diff --git a/src/H5Dcompact.c b/src/H5Dcompact.c index fe412988081..6f0628c481f 100644 --- a/src/H5Dcompact.c +++ b/src/H5Dcompact.c @@ -47,6 +47,24 @@ /* Local Typedefs */ /******************/ +/* Callback info for readvv operation when file driver + * uses special memory management functions + */ +typedef struct H5D_compact_readvv_special_mem_ud_t { + H5F_shared_t *f_sh; /* Shared file for dataset */ + void * rbuf; /* Pointer to buffer to be read from */ + void * dstbuf; /* Pointer to buffer to be read into */ +} H5D_compact_readvv_special_mem_ud_t; + +/* Callback info for writevv operation when file driver + * uses special memory management functions + */ +typedef struct H5D_compact_writevv_special_mem_ud_t { + H5F_shared_t *f_sh; /* Shared file for dataset */ + const void * wbuf; /* Pointer to buffer to be written from */ + void * dstbuf; /* Pointer to buffer to be written into */ +} H5D_compact_writevv_special_mem_ud_t; + /********************/ /* Local Prototypes */ /********************/ @@ -57,9 +75,11 @@ static hbool_t H5D__compact_is_space_alloc(const H5O_storage_t *storage); static herr_t H5D__compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t *cm); +static herr_t H5D__compact_readvv_special_mem_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata); static ssize_t H5D__compact_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]); +static herr_t H5D__compact_writevv_special_mem_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata); static ssize_t H5D__compact_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]); @@ -239,6 +259,50 @@ H5D__compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5D__compact_io_init() */ +/*------------------------------------------------------------------------- + * Function: H5D__compact_readvv_special_mem_cb + * + * Purpose: Callback operator for H5D__compact_readvv() to send a + * memory copy request to the underlying file driver. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__compact_readvv_special_mem_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata) +{ + H5D_compact_readvv_special_mem_ud_t *udata = (H5D_compact_readvv_special_mem_ud_t *)_udata; + H5FD_ctl_memcpy_args_t op_args; + uint64_t op_flags; + H5FD_t *file_handle = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + /* Retrieve lower-level file handle for I/O */ + if (H5F_shared_get_file_handle(udata->f_sh, &file_handle) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "can't get file handle") + + /* Setup operation flags and arguments */ + op_flags = H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG | + H5FD_CTL__FAIL_IF_UNKNOWN_FLAG; + + op_args.dstbuf = udata->dstbuf; + op_args.dst_off = dst_off; + op_args.srcbuf = udata->rbuf; + op_args.src_off = src_off; + op_args.len = len; + + /* Make request to file driver */ + if (H5FD_ctl(file_handle, H5FD_CTL__MEM_COPY, op_flags, + &op_args, NULL) < 0) + HGOTO_ERROR(H5E_IO, H5E_FCNTL, FAIL, "VFD memcpy request failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__compact_readvv_special_mem_cb() */ + /*------------------------------------------------------------------------- * Function: H5D__compact_readvv * @@ -268,16 +332,77 @@ H5D__compact_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t * HDassert(io_info); - /* Use the vectorized memory copy routine to do actual work */ - if ((ret_value = H5VM_memcpyvv(io_info->u.rbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, - io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, - dset_offset_arr)) < 0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + /* Check if file driver uses special memory management routines */ + if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_SPECIAL_MEMMANAGE)) { + H5D_compact_readvv_special_mem_ud_t udata; + + /* Set up udata for memory copy operation */ + udata.f_sh = io_info->f_sh; + udata.rbuf = io_info->store->compact.buf; + udata.dstbuf = io_info->u.rbuf; + + /* Request that file driver does the memory copy */ + if ((ret_value = H5VM_opvv(mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, + dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr, H5D__compact_readvv_special_mem_cb, + &udata)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + } + else { + /* Use the vectorized memory copy routine to do actual work */ + if ((ret_value = H5VM_memcpyvv(io_info->u.rbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, + io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, + dset_offset_arr)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + } done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__compact_readvv() */ +/*------------------------------------------------------------------------- + * Function: H5D__compact_writevv_special_mem_cb + * + * Purpose: Callback operator for H5D__compact_writevv() to send a + * memory copy request to the underlying file driver. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__compact_writevv_special_mem_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata) +{ + H5D_compact_writevv_special_mem_ud_t *udata = (H5D_compact_writevv_special_mem_ud_t *)_udata; + H5FD_ctl_memcpy_args_t op_args; + uint64_t op_flags; + H5FD_t *file_handle = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + /* Retrieve lower-level file handle for I/O */ + if (H5F_shared_get_file_handle(udata->f_sh, &file_handle) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "can't get file handle") + + /* Setup operation flags and arguments */ + op_flags = H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG | + H5FD_CTL__FAIL_IF_UNKNOWN_FLAG; + + op_args.dstbuf = udata->dstbuf; + op_args.dst_off = dst_off; + op_args.srcbuf = udata->wbuf; + op_args.src_off = src_off; + op_args.len = len; + + /* Make request to file driver */ + if (H5FD_ctl(file_handle, H5FD_CTL__MEM_COPY, op_flags, + &op_args, NULL) < 0) + HGOTO_ERROR(H5E_IO, H5E_FCNTL, FAIL, "VFD memcpy request failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__compact_writevv_special_mem_cb() */ + /*------------------------------------------------------------------------- * Function: H5D__compact_writevv * @@ -310,11 +435,28 @@ H5D__compact_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t HDassert(io_info); - /* Use the vectorized memory copy routine to do actual work */ - if ((ret_value = H5VM_memcpyvv(io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, - dset_offset_arr, io_info->u.wbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, - mem_offset_arr)) < 0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + /* Check if file driver uses special memory management routines */ + if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_SPECIAL_MEMMANAGE)) { + H5D_compact_writevv_special_mem_ud_t udata; + + /* Set up udata for memory copy operation */ + udata.f_sh = io_info->f_sh; + udata.wbuf = io_info->u.wbuf; + udata.dstbuf = io_info->store->compact.buf; + + /* Request that file driver does the memory copy */ + if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, H5D__compact_writevv_special_mem_cb, + &udata)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + } + else { + /* Use the vectorized memory copy routine to do actual work */ + if ((ret_value = H5VM_memcpyvv(io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, + dset_offset_arr, io_info->u.wbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, + mem_offset_arr)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + } /* Mark the compact dataset's buffer as dirty */ *io_info->store->compact.dirty = TRUE; diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index a72dc8004b2..0a012a8dfa9 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -170,6 +170,14 @@ * enabled may be used as the Write-Only (W/O) channel driver. */ #define H5FD_FEAT_DEFAULT_VFD_COMPATIBLE 0x00008000 +/* + * Defining H5FD_FEAT_SPECIAL_MEMMANAGE for a VFL driver means + * that the driver uses special memory management routines. + * Therefore, HDF5 should request that the driver handle any + * memory management operations that would otherwise be performed + * with standard library routines. + */ +#define H5FD_FEAT_SPECIAL_MEMMANAGE 0x00010000 /* ctl function definitions: */ #define H5FD_CTL_OPC_RESERVED 512 /* Opcodes below this value are reserved for library use */ @@ -185,6 +193,9 @@ #define H5FD_CTL__GET_MPI_COMMUNICATOR_OPCODE 2 #define H5FD_CTL__GET_MPI_RANK_OPCODE 3 #define H5FD_CTL__GET_MPI_SIZE_OPCODE 4 +#define H5FD_CTL__MEM_ALLOC 5 +#define H5FD_CTL__MEM_FREE 6 +#define H5FD_CTL__MEM_COPY 7 /* ctl function flags: */ @@ -367,6 +378,19 @@ typedef struct { } H5FD_file_image_callbacks_t; //! +/** + * Define structure to hold "ctl memory copy" parameters + */ +//! +typedef struct H5FD_ctl_memcpy_args_t { + void * dstbuf; /**< Destination buffer */ + hsize_t dst_off; /**< Offset within destination buffer */ + const void *srcbuf; /**< Source buffer */ + hsize_t src_off; /**< Offset within source buffer */ + size_t len; /**< Length of data to copy from source buffer */ +} H5FD_ctl_memcpy_args_t; +//! + /********************/ /* Public Variables */ /********************/ diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 051abd94212..85f60cfe9e0 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -24,11 +24,9 @@ typedef struct H5F_t H5F_t; /* Include package's public header */ #include "H5Fpublic.h" -/* Public headers needed by this file */ -#include "H5FDpublic.h" /* File drivers */ - /* Private headers needed by this file */ #include "H5MMprivate.h" /* Memory management */ +#include "H5FDprivate.h" /* File drivers */ #ifdef H5_HAVE_PARALLEL #include "H5Pprivate.h" /* Property lists */ #endif /* H5_HAVE_PARALLEL */ @@ -906,6 +904,7 @@ H5_DLL hbool_t H5F_shared_has_feature(const H5F_shared_t *f, unsigned feature); H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature); H5_DLL haddr_t H5F_shared_get_eoa(const H5F_shared_t *f_sh, H5FD_mem_t type); H5_DLL haddr_t H5F_get_eoa(const H5F_t *f, H5FD_mem_t type); +H5_DLL herr_t H5F_shared_get_file_handle(const H5F_shared_t *f_sh, H5FD_t **file_handle); H5_DLL herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void **file_handle); /* File mounting routines */ diff --git a/src/H5Fquery.c b/src/H5Fquery.c index 04792b42750..3496a84c444 100644 --- a/src/H5Fquery.c +++ b/src/H5Fquery.c @@ -949,6 +949,29 @@ H5F_get_eoa(const H5F_t *f, H5FD_mem_t type) FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_get_eoa() */ +/*------------------------------------------------------------------------- + * Function: H5F_shared_get_file_handle + * + * Purpose: Returns a pointer to the lower-level I/O file handle of the + * file's 'shared' structure. + * + * Return: file handle on success/abort on failure (shouldn't fail) + *------------------------------------------------------------------------- + */ +herr_t +H5F_shared_get_file_handle(const H5F_shared_t *f_sh, H5FD_t **file_handle) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(f_sh); + HDassert(file_handle); + + *file_handle = f_sh->lf; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5F_shared_get_file_handle() */ + /*------------------------------------------------------------------------- * Function: H5F_get_vfd_handle * From 626d651950ce96a3af52908f6464a3e6bb623ac6 Mon Sep 17 00:00:00 2001 From: Jordan Henderson Date: Wed, 29 Sep 2021 16:08:47 -0500 Subject: [PATCH 2/3] Combine compact I/O read/write struct into single I/O struct Rename CTL memory copy flag and H5Fquery routine to get file driver structure --- src/H5Dcompact.c | 140 ++++++++++++++--------------------------------- src/H5FDpublic.h | 12 ++-- src/H5Fprivate.h | 2 +- src/H5Fquery.c | 8 +-- 4 files changed, 53 insertions(+), 109 deletions(-) diff --git a/src/H5Dcompact.c b/src/H5Dcompact.c index 6f0628c481f..88926c2c909 100644 --- a/src/H5Dcompact.c +++ b/src/H5Dcompact.c @@ -47,23 +47,14 @@ /* Local Typedefs */ /******************/ -/* Callback info for readvv operation when file driver - * uses special memory management functions +/* Callback info for I/O operation when file driver + * wishes to do its own memory management */ -typedef struct H5D_compact_readvv_special_mem_ud_t { +typedef struct H5D_compact_iovv_memmanage_ud_t { H5F_shared_t *f_sh; /* Shared file for dataset */ - void * rbuf; /* Pointer to buffer to be read from */ - void * dstbuf; /* Pointer to buffer to be read into */ -} H5D_compact_readvv_special_mem_ud_t; - -/* Callback info for writevv operation when file driver - * uses special memory management functions - */ -typedef struct H5D_compact_writevv_special_mem_ud_t { - H5F_shared_t *f_sh; /* Shared file for dataset */ - const void * wbuf; /* Pointer to buffer to be written from */ - void * dstbuf; /* Pointer to buffer to be written into */ -} H5D_compact_writevv_special_mem_ud_t; + void * dstbuf; /* Pointer to buffer to be read into/written into */ + const void * srcbuf; /* Pointer to buffer to be read from/written from */ +} H5D_compact_iovv_memmanage_ud_t; /********************/ /* Local Prototypes */ @@ -75,11 +66,10 @@ static hbool_t H5D__compact_is_space_alloc(const H5O_storage_t *storage); static herr_t H5D__compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t *cm); -static herr_t H5D__compact_readvv_special_mem_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata); +static herr_t H5D__compact_iovv_memmanage_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata); static ssize_t H5D__compact_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]); -static herr_t H5D__compact_writevv_special_mem_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata); static ssize_t H5D__compact_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]); @@ -260,48 +250,46 @@ H5D__compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR } /* end H5D__compact_io_init() */ /*------------------------------------------------------------------------- - * Function: H5D__compact_readvv_special_mem_cb + * Function: H5D__compact_iovv_memmanage_cb * - * Purpose: Callback operator for H5D__compact_readvv() to send a - * memory copy request to the underlying file driver. + * Purpose: Callback operator for H5D__compact_readvv()/_writevv() to + * send a memory copy request to the underlying file driver. * * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ static herr_t -H5D__compact_readvv_special_mem_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata) +H5D__compact_iovv_memmanage_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata) { - H5D_compact_readvv_special_mem_ud_t *udata = (H5D_compact_readvv_special_mem_ud_t *)_udata; - H5FD_ctl_memcpy_args_t op_args; - uint64_t op_flags; - H5FD_t *file_handle = NULL; - herr_t ret_value = SUCCEED; + H5D_compact_iovv_memmanage_ud_t *udata = (H5D_compact_iovv_memmanage_ud_t *)_udata; + H5FD_ctl_memcpy_args_t op_args; + uint64_t op_flags; + H5FD_t * file_handle = NULL; + herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC - /* Retrieve lower-level file handle for I/O */ - if (H5F_shared_get_file_handle(udata->f_sh, &file_handle) < 0) + /* Retrieve pointer to file driver structure for ctl call */ + if (H5F_shared_get_file_driver(udata->f_sh, &file_handle) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "can't get file handle") /* Setup operation flags and arguments */ - op_flags = H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG | - H5FD_CTL__FAIL_IF_UNKNOWN_FLAG; + op_flags = H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG | H5FD_CTL__FAIL_IF_UNKNOWN_FLAG; op_args.dstbuf = udata->dstbuf; op_args.dst_off = dst_off; - op_args.srcbuf = udata->rbuf; + op_args.srcbuf = udata->srcbuf; op_args.src_off = src_off; op_args.len = len; /* Make request to file driver */ - if (H5FD_ctl(file_handle, H5FD_CTL__MEM_COPY, op_flags, - &op_args, NULL) < 0) + if (H5FD_ctl(file_handle, H5FD_CTL__MEM_COPY, op_flags, &op_args, NULL) < 0) HGOTO_ERROR(H5E_IO, H5E_FCNTL, FAIL, "VFD memcpy request failed") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__compact_readvv_special_mem_cb() */ +} /* end H5D__compact_iovv_memmanage_cb() */ /*------------------------------------------------------------------------- * Function: H5D__compact_readvv @@ -332,26 +320,26 @@ H5D__compact_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t * HDassert(io_info); - /* Check if file driver uses special memory management routines */ - if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_SPECIAL_MEMMANAGE)) { - H5D_compact_readvv_special_mem_ud_t udata; + /* Check if file driver wishes to do its own memory management */ + if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_MEMMANAGE)) { + H5D_compact_iovv_memmanage_ud_t udata; /* Set up udata for memory copy operation */ udata.f_sh = io_info->f_sh; - udata.rbuf = io_info->store->compact.buf; udata.dstbuf = io_info->u.rbuf; + udata.srcbuf = io_info->store->compact.buf; /* Request that file driver does the memory copy */ - if ((ret_value = H5VM_opvv(mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, - dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr, H5D__compact_readvv_special_mem_cb, - &udata)) < 0) + if ((ret_value = H5VM_opvv(mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, dset_max_nseq, + dset_curr_seq, dset_size_arr, dset_offset_arr, + H5D__compact_iovv_memmanage_cb, &udata)) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") } else { /* Use the vectorized memory copy routine to do actual work */ - if ((ret_value = H5VM_memcpyvv(io_info->u.rbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, - io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, - dset_offset_arr)) < 0) + if ((ret_value = H5VM_memcpyvv(io_info->u.rbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, + mem_offset_arr, io_info->store->compact.buf, dset_max_nseq, + dset_curr_seq, dset_size_arr, dset_offset_arr)) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") } @@ -359,50 +347,6 @@ H5D__compact_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t * FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__compact_readvv() */ -/*------------------------------------------------------------------------- - * Function: H5D__compact_writevv_special_mem_cb - * - * Purpose: Callback operator for H5D__compact_writevv() to send a - * memory copy request to the underlying file driver. - * - * Return: Non-negative on success/Negative on failure - * - *------------------------------------------------------------------------- - */ -static herr_t -H5D__compact_writevv_special_mem_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata) -{ - H5D_compact_writevv_special_mem_ud_t *udata = (H5D_compact_writevv_special_mem_ud_t *)_udata; - H5FD_ctl_memcpy_args_t op_args; - uint64_t op_flags; - H5FD_t *file_handle = NULL; - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC - - /* Retrieve lower-level file handle for I/O */ - if (H5F_shared_get_file_handle(udata->f_sh, &file_handle) < 0) - HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "can't get file handle") - - /* Setup operation flags and arguments */ - op_flags = H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG | - H5FD_CTL__FAIL_IF_UNKNOWN_FLAG; - - op_args.dstbuf = udata->dstbuf; - op_args.dst_off = dst_off; - op_args.srcbuf = udata->wbuf; - op_args.src_off = src_off; - op_args.len = len; - - /* Make request to file driver */ - if (H5FD_ctl(file_handle, H5FD_CTL__MEM_COPY, op_flags, - &op_args, NULL) < 0) - HGOTO_ERROR(H5E_IO, H5E_FCNTL, FAIL, "VFD memcpy request failed") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__compact_writevv_special_mem_cb() */ - /*------------------------------------------------------------------------- * Function: H5D__compact_writevv * @@ -435,26 +379,26 @@ H5D__compact_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t HDassert(io_info); - /* Check if file driver uses special memory management routines */ - if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_SPECIAL_MEMMANAGE)) { - H5D_compact_writevv_special_mem_ud_t udata; + /* Check if file driver wishes to do its own memory management */ + if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_MEMMANAGE)) { + H5D_compact_iovv_memmanage_ud_t udata; /* Set up udata for memory copy operation */ udata.f_sh = io_info->f_sh; - udata.wbuf = io_info->u.wbuf; udata.dstbuf = io_info->store->compact.buf; + udata.srcbuf = io_info->u.wbuf; /* Request that file driver does the memory copy */ - if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr, - mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, H5D__compact_writevv_special_mem_cb, - &udata)) < 0) + if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr, mem_max_nseq, + mem_curr_seq, mem_size_arr, mem_offset_arr, H5D__compact_iovv_memmanage_cb, + &udata)) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") } else { /* Use the vectorized memory copy routine to do actual work */ - if ((ret_value = H5VM_memcpyvv(io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, - dset_offset_arr, io_info->u.wbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, - mem_offset_arr)) < 0) + if ((ret_value = H5VM_memcpyvv(io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, + dset_size_arr, dset_offset_arr, io_info->u.wbuf, mem_max_nseq, + mem_curr_seq, mem_size_arr, mem_offset_arr)) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") } diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index 0a012a8dfa9..d774210464d 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -171,13 +171,13 @@ */ #define H5FD_FEAT_DEFAULT_VFD_COMPATIBLE 0x00008000 /* - * Defining H5FD_FEAT_SPECIAL_MEMMANAGE for a VFL driver means - * that the driver uses special memory management routines. - * Therefore, HDF5 should request that the driver handle any - * memory management operations that would otherwise be performed - * with standard library routines. + * Defining H5FD_FEAT_MEMMANAGE for a VFL driver means that + * the driver uses special memory management routines or wishes + * to do memory management in a specific manner. Therefore, HDF5 + * should request that the driver handle any memory management + * operations when appropriate. */ -#define H5FD_FEAT_SPECIAL_MEMMANAGE 0x00010000 +#define H5FD_FEAT_MEMMANAGE 0x00010000 /* ctl function definitions: */ #define H5FD_CTL_OPC_RESERVED 512 /* Opcodes below this value are reserved for library use */ diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 85f60cfe9e0..a5ccbabdd1a 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -904,7 +904,7 @@ H5_DLL hbool_t H5F_shared_has_feature(const H5F_shared_t *f, unsigned feature); H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature); H5_DLL haddr_t H5F_shared_get_eoa(const H5F_shared_t *f_sh, H5FD_mem_t type); H5_DLL haddr_t H5F_get_eoa(const H5F_t *f, H5FD_mem_t type); -H5_DLL herr_t H5F_shared_get_file_handle(const H5F_shared_t *f_sh, H5FD_t **file_handle); +H5_DLL herr_t H5F_shared_get_file_driver(const H5F_shared_t *f_sh, H5FD_t **file_handle); H5_DLL herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void **file_handle); /* File mounting routines */ diff --git a/src/H5Fquery.c b/src/H5Fquery.c index 3496a84c444..a625897e8c9 100644 --- a/src/H5Fquery.c +++ b/src/H5Fquery.c @@ -950,16 +950,16 @@ H5F_get_eoa(const H5F_t *f, H5FD_mem_t type) } /* end H5F_get_eoa() */ /*------------------------------------------------------------------------- - * Function: H5F_shared_get_file_handle + * Function: H5F_shared_get_file_driver * - * Purpose: Returns a pointer to the lower-level I/O file handle of the + * Purpose: Returns a pointer to the file driver structure of the * file's 'shared' structure. * * Return: file handle on success/abort on failure (shouldn't fail) *------------------------------------------------------------------------- */ herr_t -H5F_shared_get_file_handle(const H5F_shared_t *f_sh, H5FD_t **file_handle) +H5F_shared_get_file_driver(const H5F_shared_t *f_sh, H5FD_t **file_handle) { /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -970,7 +970,7 @@ H5F_shared_get_file_handle(const H5F_shared_t *f_sh, H5FD_t **file_handle) *file_handle = f_sh->lf; FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5F_shared_get_file_handle() */ +} /* end H5F_shared_get_file_driver() */ /*------------------------------------------------------------------------- * Function: H5F_get_vfd_handle From c3fa7ba14826b368f2be173e50daf0e117e332c6 Mon Sep 17 00:00:00 2001 From: Jordan Henderson Date: Wed, 29 Sep 2021 22:34:52 -0500 Subject: [PATCH 3/3] Add RELEASE.txt entry for new "ctl" memory copy operation --- release_docs/RELEASE.txt | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 0c3a398acf0..ec558c6db6c 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -469,6 +469,48 @@ New Features Library: -------- + - Adds new file driver-level memory copy operation for + "ctl" callback and updates compact dataset I/O routines + to utilize it + + When accessing an HDF5 file with a file driver that uses + memory allocated in special ways (e.g., without standard + library's `malloc`), a crash could be observed when HDF5 + tries to perform `memcpy` operations on such a memory + region. + + These changes add a new H5FD_FEAT_MEMMANAGE VFD feature + flag, which, if specified as supported by a VFD, will + inform HDF5 that the VFD either uses special memory + management routines or wishes to perform memory management + in a specific way. Therefore, this flag instructs HDF5 to + ask the file driver to perform memory management for + certain operations. + + These changes also introduce a new "ctl" callback + operation identified by the H5FD_CTL__MEM_COPY op code. + This operation simply asks a VFD to perform a memory copy. + The arguments to this operation are passed to the "ctl" + callback's "input" parameter as a pointer to a struct + defined as: + + struct H5FD_ctl_memcpy_args_t { + void * dstbuf; /**< Destination buffer */ + hsize_t dst_off; /**< Offset within destination buffer */ + const void *srcbuf; /**< Source buffer */ + hsize_t src_off; /**< Offset within source buffer */ + size_t len; /**< Length of data to copy from source buffer */ + } H5FD_ctl_memcpy_args_t; + + Further, HDF5's compact dataset I/O routines were + identified as a problematic area that could cause a crash + for VFDs that make use of special memory management. Those + I/O routines were therefore updated to make use of this new + "ctl" callback operation in order to ask the underlying + file driver to correctly handle memory copies. + + (JTH - 2021/09/28) + - Adds new "ctl" callback to VFD H5FD_class_t structure with the following prototype: