summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@koziol.gov>2019-06-28 21:13:36 (GMT)
committerQuincey Koziol <koziol@koziol.gov>2019-06-28 21:13:36 (GMT)
commit2042c775f0d9240609527e621d84e4911ad7f6a5 (patch)
treeb90dd86bd7d25534102b6e929d9cbbdf01c77389 /src
parentd5130bb57332ce0049302c5836bbf666b23513cd (diff)
parent13d951d37205bcd48723330a898e5d67c5e1ecb2 (diff)
downloadhdf5-2042c775f0d9240609527e621d84e4911ad7f6a5.zip
hdf5-2042c775f0d9240609527e621d84e4911ad7f6a5.tar.gz
hdf5-2042c775f0d9240609527e621d84e4911ad7f6a5.tar.bz2
Merge branch 'develop' into feature/update_gcc_flags
Diffstat (limited to 'src')
-rw-r--r--src/H5AC.c68
-rw-r--r--src/H5ACprivate.h1
-rw-r--r--src/H5Cprivate.h1
-rw-r--r--src/H5Cquery.c28
-rw-r--r--src/H5FScache.c60
-rw-r--r--src/H5FSsection.c333
-rw-r--r--src/H5Fint.c6
-rw-r--r--src/H5Fpkg.h11
-rw-r--r--src/H5Fprivate.h9
-rw-r--r--src/H5Fquery.c36
-rw-r--r--src/H5Fsuper.c127
-rw-r--r--src/H5MF.c592
-rw-r--r--src/H5MFaggr.c16
-rw-r--r--src/H5MFdbg.c8
-rw-r--r--src/H5Ocache_image.c33
-rw-r--r--src/H5Ofsinfo.c85
-rw-r--r--src/H5Oprivate.h4
-rw-r--r--src/H5Rint.c2
18 files changed, 565 insertions, 855 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index dc88fd4..f6243ad 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -698,46 +698,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5AC_force_cache_image_load()
- *
- * Purpose: On rare occasions, it is necessary to run
- * H5MF_tidy_self_referential_fsm_hack() prior to the first
- * metadata cache access. This is a problem as if there is a
- * cache image at the end of the file, that routine will
- * discard it.
- *
- * We solve this issue by calling this function, which will
- * load the cache image and then call
- * H5MF_tidy_self_referential_fsm_hack() to discard it.
- *
- * Return: SUCCEED on success, and FAIL on failure.
- *
- * Programmer: John Mainzer
- * 1/11/17
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC_force_cache_image_load(H5F_t *f)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->cache);
-
- if(H5C_force_cache_image_load(f) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, FAIL, "Can't load cache image")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC_force_cache_image_load() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5AC_get_entry_status
*
* Purpose: Given a file address, determine whether the metadata
@@ -1744,6 +1704,33 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5AC_get_cache_flush_in_progess
+ *
+ * Purpose: Wrapper function for H5C_get_cache_flush_in_progress().
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Programmer: John Mainzer
+ * 3/11/05
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_get_cache_flush_in_progress(H5AC_t *cache_ptr, hbool_t *flush_in_progress_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if(H5C_get_cache_flush_in_progress((H5C_t *)cache_ptr, flush_in_progress_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_get_cache_flush_in_progress() failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5AC_get_cache_flush_in_progress() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5AC_get_cache_hit_rate
*
* Purpose: Wrapper function for H5C_get_cache_hit_rate().
@@ -2682,4 +2669,3 @@ H5AC_get_mdc_image_info(H5AC_t *cache_ptr, haddr_t *image_addr, hsize_t *image_l
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_get_mdc_image_info() */
-
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index e1fdedf..691f7c6 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -411,6 +411,7 @@ H5_DLL herr_t H5AC_get_cache_auto_resize_config(const H5AC_t * cache_ptr,
H5AC_cache_config_t *config_ptr);
H5_DLL herr_t H5AC_get_cache_size(H5AC_t *cache_ptr, size_t *max_size_ptr,
size_t *min_clean_size_ptr, size_t *cur_size_ptr, uint32_t *cur_num_entries_ptr);
+H5_DLL herr_t H5AC_get_cache_flush_in_progress(H5AC_t *cache_ptr, hbool_t *flush_in_progress_ptr);
H5_DLL herr_t H5AC_get_cache_hit_rate(H5AC_t *cache_ptr, double *hit_rate_ptr);
H5_DLL herr_t H5AC_reset_cache_hit_rate_stats(H5AC_t *cache_ptr);
H5_DLL herr_t H5AC_set_cache_auto_resize_config(H5AC_t *cache_ptr,
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index d4ed6fc..bd200e0 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -2258,6 +2258,7 @@ H5_DLL herr_t H5C_get_cache_image_config(const H5C_t * cache_ptr,
H5_DLL herr_t H5C_get_cache_size(H5C_t *cache_ptr, size_t *max_size_ptr,
size_t *min_clean_size_ptr, size_t *cur_size_ptr,
uint32_t *cur_num_entries_ptr);
+H5_DLL herr_t H5C_get_cache_flush_in_progress(H5C_t *cache_ptr, hbool_t *flush_in_progress_ptr);
H5_DLL herr_t H5C_get_cache_hit_rate(H5C_t *cache_ptr, double *hit_rate_ptr);
H5_DLL herr_t H5C_get_entry_status(const H5F_t *f, haddr_t addr,
size_t *size_ptr, hbool_t *in_cache_ptr, hbool_t *is_dirty_ptr,
diff --git a/src/H5Cquery.c b/src/H5Cquery.c
index 51ce1c2..a1267c5 100644
--- a/src/H5Cquery.c
+++ b/src/H5Cquery.c
@@ -156,6 +156,34 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5C_get_cache_flush_in_progress
+ *
+ * Purpose: Return flush_in_progress in *flush_in_progress_ptr
+ * If the parameter is NULL, skip that value.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_get_cache_flush_in_progress(H5C_t * cache_ptr, hbool_t *flush_in_progress_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC))
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry.")
+
+ if(flush_in_progress_ptr != NULL)
+ *flush_in_progress_ptr = cache_ptr->flush_in_progress;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_get_cache_flush_in_progress() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5C_get_cache_hit_rate
*
* Purpose: Compute and return the current cache hit rate in
diff --git a/src/H5FScache.c b/src/H5FScache.c
index 7525a9a..b520458 100644
--- a/src/H5FScache.c
+++ b/src/H5FScache.c
@@ -517,14 +517,36 @@ H5FS__cache_hdr_pre_serialize(H5F_t *f, void *_thing,
if(!H5F_addr_defined(fspace->sect_addr)) { /* case 1 */
haddr_t tag = HADDR_UNDEF;
+ haddr_t sect_addr;
+ hsize_t saved_sect_size, new_sect_size;
/* allocate file space for the section info, and insert it
* into the metadata cache.
*/
- if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, fspace->sect_size)))
+ saved_sect_size = fspace->sect_size;
+ if(HADDR_UNDEF == (sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, fspace->sect_size)))
HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
- fspace->alloc_sect_size = (size_t)fspace->sect_size;
+ /* fspace->sect_size may change in size after H5MF_alloc().
+ * If increased in size, free the previous allocation and
+ * allocate again with the bigger fspace->sect_size.
+ */
+ if(fspace->sect_size > saved_sect_size) {
+
+ new_sect_size = fspace->sect_size;
+
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, sect_addr, saved_sect_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections")
+
+ if(HADDR_UNDEF == (sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, new_sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+ fspace->sect_size = new_sect_size;
+ fspace->alloc_sect_size = new_sect_size;
+ } else {
+ fspace->alloc_sect_size = saved_sect_size;
+ fspace->sect_size = saved_sect_size;
+ }
+ fspace->sect_addr = sect_addr;
/* Get the tag for this free space manager and use it to insert the entry */
if(H5AC_get_tag((const void *)fspace, &tag) < 0)
@@ -593,7 +615,6 @@ H5FS__cache_hdr_pre_serialize(H5F_t *f, void *_thing,
* a nonsense section info address.
*/
if(!H5F_POINT_OF_NO_RETURN(f)) {
- HDassert(fspace->serial_sect_count > 0);
HDassert(fspace->sect_size > 0);
HDassert(fspace->alloc_sect_size == (size_t)fspace->sect_size);
} /* end if */
@@ -703,9 +724,8 @@ H5FS__cache_hdr_serialize(const H5F_t *f, void *_image, size_t len,
if(!H5F_POINT_OF_NO_RETURN(f))
HDassert((! H5F_addr_defined(fspace->sect_addr)) ||
- ((fspace->serial_sect_count > 0) &&
- (fspace->sect_size > 0) &&
- (fspace->alloc_sect_size == (size_t)fspace->sect_size)));
+ ((fspace->sect_size > 0) &&
+ (fspace->alloc_sect_size == (size_t)fspace->sect_size)));
/* Magic number */
H5MM_memcpy(image, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
@@ -968,6 +988,7 @@ H5FS__cache_sinfo_deserialize(const void *_image, size_t len, void *_udata,
haddr_t fs_addr; /* Free space header address */
size_t old_sect_size; /* Old section size */
const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ const uint8_t *chksum_image; /* Points to chksum location */
uint32_t stored_chksum; /* Stored metadata checksum */
void * ret_value = NULL; /* Return value */
@@ -1064,10 +1085,14 @@ H5FS__cache_sinfo_deserialize(const void *_image, size_t len, void *_udata,
if(H5FS_sect_add(udata->f, fspace, new_sect, H5FS_ADD_DESERIALIZING, udata) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, NULL, "can't add section to free space manager")
} /* end for */
+
+ if(fspace->tot_sect_count == old_tot_sect_count)
+ break;
+
} while(image < (((const uint8_t *)_image + old_sect_size) - H5FS_SIZEOF_CHKSUM));
/* Sanity check */
- HDassert((size_t)(image - (const uint8_t *)_image) == (old_sect_size - H5FS_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) <= (old_sect_size - H5FS_SIZEOF_CHKSUM));
HDassert(old_sect_size == fspace->sect_size);
HDassert(old_tot_sect_count == fspace->tot_sect_count);
HDassert(old_serial_sect_count == fspace->serial_sect_count);
@@ -1077,11 +1102,14 @@ H5FS__cache_sinfo_deserialize(const void *_image, size_t len, void *_udata,
/* checksum verification already done in verify_chksum cb */
+ /* There may be empty space between entries and chksum */
+ chksum_image = (const uint8_t *)(_image) + old_sect_size - H5FS_SIZEOF_CHKSUM;
/* Metadata checksum */
- UINT32DECODE(image, stored_chksum);
+ UINT32DECODE(chksum_image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(image - (const uint8_t *)_image) == old_sect_size);
+ HDassert((image == chksum_image) ||
+ ((size_t)((image - (const uint8_t *)_image) + (chksum_image - image)) == old_sect_size));
/* Set return value */
ret_value = sinfo;
@@ -1177,10 +1205,6 @@ H5FS__cache_sinfo_pre_serialize(H5F_t *f, void *_thing, haddr_t addr,
HDassert(new_len);
HDassert(flags);
- /* we shouldn't be called if the section info is empty, unless we hit the point of no return. */
- if(!H5F_POINT_OF_NO_RETURN(f))
- HDassert(fspace->serial_sect_count > 0);
-
sinfo_addr = addr; /* this will change if we relocate the section data */
/* Check for section info at temporary address */
@@ -1246,6 +1270,7 @@ H5FS__cache_sinfo_serialize(const H5F_t *f, void *_image, size_t len,
H5FS_t *fspace; /* Free space header */
H5FS_iter_ud_t udata; /* User data for callbacks */
uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint8_t *chksum_image = NULL; /* Points to chksum location */
uint32_t metadata_chksum; /* Computed metadata checksum value */
unsigned bin; /* Current bin we are on */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1290,13 +1315,16 @@ H5FS__cache_sinfo_serialize(const H5F_t *f, void *_image, size_t len,
/* Compute checksum */
- metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
+ /* There may be empty space between entries and chksum */
+ chksum_image = (uint8_t *)(_image) + len - H5FS_SIZEOF_CHKSUM;
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(chksum_image - (uint8_t *)_image), 0);
/* Metadata checksum */
- UINT32ENCODE(image, metadata_chksum);
+ UINT32ENCODE(chksum_image, metadata_chksum);
/* Sanity check */
- HDassert((size_t)(image - (uint8_t *)_image) == sinfo->fspace->sect_size);
+ HDassert((chksum_image == image) ||
+ ((size_t)((image - (uint8_t *)_image) + (chksum_image - image)) == sinfo->fspace->sect_size));
HDassert(sinfo->fspace->sect_size <= sinfo->fspace->alloc_sect_size);
done:
diff --git a/src/H5FSsection.c b/src/H5FSsection.c
index 27486f1..d15e299 100644
--- a/src/H5FSsection.c
+++ b/src/H5FSsection.c
@@ -307,6 +307,20 @@ HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n"
* Purpose: Release the section info, either giving ownership back to
* the cache or letting the free space header keep it.
*
+ * Add the fix in this routine to resolve the potential infinite loop
+ * problem when allocating file space for the meta data of the
+ * self-referential free-space managers at file closing.
+ *
+ * On file close or flushing, when the section info is modified
+ * and protected/unprotected, does not allow the section info size
+ * to shrink:
+ * --if the current allocated section info size in fspace->sect_size is
+ * larger than the previous section info size in fpsace->alloc_sect_size,
+ * release the section info
+ * --Otherwise, set the fspace->sect_size to be the same as
+ * fpsace->alloc_sect_size. This means fspace->sect_size may be larger
+ * than what is actually needed.
+ *
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
@@ -357,6 +371,11 @@ HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n"
/* Check if section info lock count dropped to zero */
if(fspace->sinfo_lock_count == 0) {
hbool_t release_sinfo_space = FALSE; /* Flag to indicate section info space in file should be released */
+ hbool_t flush_in_progress = FALSE; /* Is flushing in progress */
+
+ /* Check whether cache is flush_in_progress */
+ if(H5AC_get_cache_flush_in_progress(f->shared->cache, &flush_in_progress) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't get flush_in_progress")
/* Check if we actually protected the section info */
if(fspace->sinfo_protected) {
@@ -370,9 +389,17 @@ HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n"
/* Note that we've modified the section info */
cache_flags |= H5AC__DIRTIED_FLAG;
+ /* On file close or flushing, does not allow section info to shrink in size */
+ if(f->closing || flush_in_progress) {
+ if(fspace->sect_size > fspace->alloc_sect_size)
+ cache_flags |= H5AC__DELETED_FLAG | H5AC__TAKE_OWNERSHIP_FLAG;
+ else
+ fspace->sect_size = fspace->alloc_sect_size;
+
/* Check if the section info size in the file has changed */
- if(fspace->sect_size != fspace->alloc_sect_size)
+ } else if(fspace->sect_size != fspace->alloc_sect_size)
cache_flags |= H5AC__DELETED_FLAG | H5AC__TAKE_OWNERSHIP_FLAG;
+
} /* end if */
/* Sanity check */
@@ -410,11 +437,20 @@ HDfprintf(stderr, "%s: Relinquishing section info ownership\n", FUNC);
/* Check if the section info was modified */
if(fspace->sinfo_modified) {
/* Check if we need to release section info in the file */
- if(H5F_addr_defined(fspace->sect_addr))
+ if(H5F_addr_defined(fspace->sect_addr)) {
/* Set flag to release section info space in file */
- release_sinfo_space = TRUE;
- else
+ /* On file close or flushing, only need to release section info with size
+ bigger than previous section */
+ if(f->closing || flush_in_progress) {
+ if(fspace->sect_size > fspace->alloc_sect_size)
+ release_sinfo_space = TRUE;
+ else
+ fspace->sect_size = fspace->alloc_sect_size;
+ } else
+ release_sinfo_space = TRUE;
+ } else
HDassert(fspace->alloc_sect_size == 0);
+
} /* end if */
else {
/* Sanity checks... */
@@ -2414,84 +2450,31 @@ done:
/*-------------------------------------------------------------------------
* Function: H5FS_vfd_alloc_hdr_and_section_info_if_needed
*
- * Purpose: This function is part of a hack to patch over a design
- * flaw in the free space managers for file space allocation.
- * Specifically, if a free space manager allocates space for
- * its own section info, it is possible for it to
- * go into an infinite loop as it:
- *
- * 1) computes the size of the section info
- *
- * 2) allocates file space for the section info
- *
- * 3) notices that the size of the section info
- * has changed
- *
- * 4) deallocates the section info file space and
- * returns to 1) above.
- *
- * Similarly, if it allocates space for its own header, it
- * can go into an infinite loop as it:
- *
- * 1) allocates space for the header
- *
- * 2) notices that the free space manager is empty
- * and thus should not have file space allocated
- * to its header
- *
- * 3) frees the space allocated to the header
- *
- * 4) notices that the free space manager is not
- * empty and thus must have file space allocated
- * to it, and thus returns to 1) above.
- *
- * In a nutshell, the solution applied in this hack is to
- * deallocate file space for the free space manager(s) that
- * handle FSM header and/or section info file space allocations,
- * wait until all other allocation/deallocation requests have
- * been handled, and then test to see if the free space manager(s)
- * in question are empty. If they are, do nothing. If they
- * are not, allocate space for them at end of file bypassing the
- * usual file space allocation calls, and thus avoiding the
- * potential infinite loops.
- *
- * The purpose of this function is to allocate file space for
+ * Purpose: The purpose of this function is to allocate file space for
* the header and section info of the target free space manager
- * directly from the VFD if needed. In this case the function
- * also re-inserts the header and section info in the metadata
- * cache with this allocation.
- *
- * When paged allocation is not enabled, allocation of space
- * for the free space manager header and section info is
- * straight forward -- we simply allocate the space directly
- * from file driver.
- *
- * Note that if f->shared->alignment > 1, and EOA is not a
- * multiple of the alignment, it is possible that performing
- * these allocations may generate a fragment of file space in
- * addition to the space allocated for the section info. This
- * excess space is dropped on the floor. As shall be seen,
- * it will usually be reclaimed later.
- *
- * When page allocation is enabled, things are more difficult,
- * as there is the possibility that page buffering will be
- * enabled when the free space managers are read. To allow
- * for this, we must ensure that space allocated for the
- * free space manager header and section info is either larger
- * than a page, or resides completely within a page.
- *
- * Do this by allocating space for the free space header and
- * section info starting at page boundaries, and extending
- * allocation to the next page boundary. This of course wastes
- * space, but see below.
- *
- * On the first free space allocation / deallocation after the
- * next file open, we will read the self referential free space
- * managers, float them and reduce the EOA to its value prior
- * to allocation of file space for the self referential free
- * space managers on the preceeding file close. This EOA value
- * is stored in the free space manager superblock extension
- * message.
+ * if they are not allocated yet.
+ *
+ * The previous hack in this routine to avoid the potential infinite
+ * loops by allocating file space directly from the end of the file
+ * is removed. The allocation can now be done via the usual
+ * file space allocation call H5MF_alloc().
+ *
+ * The design flaw is addressed by not allowing the size
+ * of section info to shrink. This means, when trying to allocate
+ * section info size X via H5MF_alloc() and the section info size
+ * after H5MF_alloc() changes to Y:
+ * --if Y is larger than X, free the just allocated file space X
+ * via H5MF_xfree() and set fspace->sect_size to Y.
+ * This routine will be called again later from
+ * H5MF_settle_meta_data_fsm() to allocate section info with the
+ * larger fpsace->sect_size Y.
+ * --if Y is smaller than X, no further allocation is needed and
+ * fspace->sect_size and fspace->alloc_sect_size are set to X.
+ * This means fspace->sect_size may be larger than what is
+ * actually needed.
+ *
+ * This routine also re-inserts the header and section info in the
+ * metadata cache with this allocation.
*
* Return: Success: non-negative
* Failure: negative
@@ -2508,8 +2491,6 @@ H5FS_vfd_alloc_hdr_and_section_info_if_needed(H5F_t *f, H5FS_t *fspace,
hsize_t hdr_alloc_size;
hsize_t sinfo_alloc_size;
haddr_t sect_addr = HADDR_UNDEF; /* address of sinfo */
- haddr_t eoa_frag_addr = HADDR_UNDEF; /* Address of fragment at EOA */
- hsize_t eoa_frag_size = 0; /* Size of fragment at EOA */
haddr_t eoa = HADDR_UNDEF; /* Initial EOA for the file */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2525,12 +2506,6 @@ H5FS_vfd_alloc_hdr_and_section_info_if_needed(H5F_t *f, H5FS_t *fspace,
/* the section info should be unlocked */
HDassert(fspace->sinfo_lock_count == 0);
- /* no space should be allocated */
- HDassert(*fs_addr_ptr == HADDR_UNDEF);
- HDassert(fspace->addr == HADDR_UNDEF);
- HDassert(fspace->sect_addr == HADDR_UNDEF);
- HDassert(fspace->alloc_sect_size == 0);
-
/* persistent free space managers must be enabled */
HDassert(f->shared->fs_persist);
@@ -2542,125 +2517,109 @@ H5FS_vfd_alloc_hdr_and_section_info_if_needed(H5F_t *f, H5FS_t *fspace,
HDassert((f->shared->fs_strategy == H5F_FSPACE_STRATEGY_FSM_AGGR) ||
(f->shared->fs_strategy == H5F_FSPACE_STRATEGY_PAGE));
- if(fspace->serial_sect_count > 0) {
+ if(fspace->serial_sect_count > 0 && fspace->sinfo) {
/* the section info is floating, so space->sinfo should be defined */
- HDassert(fspace->sinfo);
-
- /* start by allocating file space for the header */
-
- /* Get the EOA for the file -- need for sanity check below */
- if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_FSPACE_HDR)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "Unable to get eoa")
- /* check for overlap into temporary allocation space */
- if(H5F_IS_TMP_ADDR(f, (eoa + fspace->sect_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_BADRANGE, FAIL, "hdr file space alloc will overlap into 'temporary' file space")
+ if(!H5F_addr_defined(fspace->addr)) {
- hdr_alloc_size = H5FS_HEADER_SIZE(f);
-
- /* if page allocation is enabled, extend the hdr_alloc_size to the
- * next page boundary.
- */
- if(H5F_PAGED_AGGR(f)) {
- HDassert(0 == (eoa % f->shared->fs_page_size));
+ /* start by allocating file space for the header */
- hdr_alloc_size = ((hdr_alloc_size / f->shared->fs_page_size) + 1) * f->shared->fs_page_size;
+ /* Get the EOA for the file -- need for sanity check below */
+ if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_FSPACE_HDR)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "Unable to get eoa")
- HDassert(hdr_alloc_size >= H5FS_HEADER_SIZE(f));
- HDassert((hdr_alloc_size % f->shared->fs_page_size) == 0);
- } /* end if */
+ /* check for overlap into temporary allocation space */
+ if(H5F_IS_TMP_ADDR(f, (eoa + fspace->sect_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_BADRANGE, FAIL, "hdr file space alloc will overlap into 'temporary' file space")
- /* allocate space for the hdr */
- if(HADDR_UNDEF == (fspace->addr = H5FD_alloc(f->shared->lf, H5FD_MEM_FSPACE_HDR,
- f, hdr_alloc_size, &eoa_frag_addr, &eoa_frag_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTALLOC, FAIL, "can't allocate file space for hdr")
+ hdr_alloc_size = H5FS_HEADER_SIZE(f);
- /* if the file alignment is 1, there should be no
- * eoa fragment. Otherwise, drop any fragment on the floor.
- */
- HDassert((eoa_frag_size == 0) || (f->shared->alignment != 1));
+ if(H5F_PAGED_AGGR(f))
+ HDassert(0 == (eoa % f->shared->fs_page_size));
- /* Cache the new free space header (pinned) */
- if(H5AC_insert_entry(f, H5AC_FSPACE_HDR, fspace->addr, fspace, H5AC__PIN_ENTRY_FLAG) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space header to cache")
+ /* Allocate space for the free space header */
+ if(HADDR_UNDEF == (fspace->addr = H5MF_alloc(f, H5FD_MEM_FSPACE_HDR, hdr_alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for free space header")
- *fs_addr_ptr = fspace->addr;
+ /* Cache the new free space header (pinned) */
+ if(H5AC_insert_entry(f, H5AC_FSPACE_HDR, fspace->addr, fspace, H5AC__PIN_ENTRY_FLAG) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space header to cache")
- /* now allocate file space for the section info */
+ *fs_addr_ptr = fspace->addr;
+ }
- /* Get the EOA for the file -- need for sanity check below */
- if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_FSPACE_SINFO)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "Unable to get eoa")
+ if(!H5F_addr_defined(fspace->sect_addr)) {
- /* check for overlap into temporary allocation space */
- if(H5F_IS_TMP_ADDR(f, (eoa + fspace->sect_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_BADRANGE, FAIL, "sinfo file space alloc will overlap into 'temporary' file space")
+ /* now allocate file space for the section info */
- sinfo_alloc_size = fspace->sect_size;
+ /* Get the EOA for the file -- need for sanity check below */
+ if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_FSPACE_SINFO)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "Unable to get eoa")
- /* if paged allocation is enabled, extend the sinfo_alloc_size to the
- * next page boundary.
- */
- if(H5F_PAGED_AGGR(f)) {
- HDassert(0 == (eoa % f->shared->fs_page_size));
+ /* check for overlap into temporary allocation space */
+ if(H5F_IS_TMP_ADDR(f, (eoa + fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADRANGE, FAIL, "sinfo file space alloc will overlap into 'temporary' file space")
- sinfo_alloc_size = ((sinfo_alloc_size / f->shared->fs_page_size) + 1) * f->shared->fs_page_size;
+ sinfo_alloc_size = fspace->sect_size;
- HDassert(sinfo_alloc_size >= fspace->sect_size);
- HDassert((sinfo_alloc_size % f->shared->fs_page_size) == 0);
- } /* end if */
+ if(H5F_PAGED_AGGR(f))
+ HDassert(0 == (eoa % f->shared->fs_page_size));
- /* allocate space for the section info */
- if(HADDR_UNDEF == (sect_addr = H5FD_alloc(f->shared->lf, H5FD_MEM_FSPACE_SINFO,
- f, sinfo_alloc_size, &eoa_frag_addr, &eoa_frag_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTALLOC, FAIL, "can't allocate file space")
+ /* allocate space for the section info */
+ if(HADDR_UNDEF == (sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, sinfo_alloc_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for section info")
- /* if the file alignment is 1, there should be no
- * eoa fragment. Otherwise, drop the fragment on the floor.
- */
- HDassert((eoa_frag_size == 0) || (f->shared->alignment != 1));
+ /* update fspace->alloc_sect_size and fspace->sect_addr to reflect
+ * the allocation
+ */
+ if(fspace->sect_size > sinfo_alloc_size) {
+ hsize_t saved_sect_size = fspace->sect_size;
- /* update fspace->alloc_sect_size and fspace->sect_addr to reflect
- * the allocation
- */
- fspace->alloc_sect_size = fspace->sect_size;
- fspace->sect_addr = sect_addr;
-
- /* insert the new section info into the metadata cache. */
-
- /* Question: Do we need to worry about this insertion causing an
- * eviction from the metadata cache? Think on this. If so, add a
- * flag to H5AC_insert() to force it to skip the call to make space in
- * cache.
- *
- * On reflection, no.
- *
- * On a regular file close, any eviction will not change the
- * the contents of the free space manager(s), as all entries
- * should have correct file space allocated by the time this
- * function is called.
- *
- * In the cache image case, the selection of entries for inclusion
- * in the cache image will not take place until after this call.
- * (Recall that this call is made during the metadata fsm settle
- * routine, which is called during the serialization routine in
- * the cache image case. Entries are not selected for inclusion
- * in the image until after the cache is serialized.)
- *
- * JRM -- 11/4/16
- */
- if(H5AC_insert_entry(f, H5AC_FSPACE_SINFO, sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space sinfo to cache")
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, sect_addr, sinfo_alloc_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections")
+ fspace->sect_size = saved_sect_size;
+ } else {
+ fspace->alloc_sect_size = sinfo_alloc_size;
+ fspace->sect_size = sinfo_alloc_size;
+ fspace->sect_addr = sect_addr;
+
+ /* insert the new section info into the metadata cache. */
+
+ /* Question: Do we need to worry about this insertion causing an
+ * eviction from the metadata cache? Think on this. If so, add a
+ * flag to H5AC_insert() to force it to skip the call to make space in
+ * cache.
+ *
+ * On reflection, no.
+ *
+ * On a regular file close, any eviction will not change the
+ * the contents of the free space manager(s), as all entries
+ * should have correct file space allocated by the time this
+ * function is called.
+ *
+ * In the cache image case, the selection of entries for inclusion
+ * in the cache image will not take place until after this call.
+ * (Recall that this call is made during the metadata fsm settle
+ * routine, which is called during the serialization routine in
+ * the cache image case. Entries are not selected for inclusion
+ * in the image until after the cache is serialized.)
+ *
+ * JRM -- 11/4/16
+ */
+ if(H5AC_insert_entry(f, H5AC_FSPACE_SINFO, sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space sinfo to cache")
- /* We have changed the sinfo address -- Mark free space header dirty */
- if(H5AC_mark_entry_dirty(fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
+ /* We have changed the sinfo address -- Mark free space header dirty */
+ if(H5AC_mark_entry_dirty(fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
- /* since space has been allocated for the section info and the sinfo
- * has been inserted into the cache, relinquish ownership (i.e. float)
- * the section info.
- */
- fspace->sinfo = NULL;
+ /* since space has been allocated for the section info and the sinfo
+ * has been inserted into the cache, relinquish ownership (i.e. float)
+ * the section info.
+ */
+ fspace->sinfo = NULL;
+ }
+ }
} /* end if */
done:
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 030fda8..4021e41 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -934,9 +934,9 @@ H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_
f->shared->fs_addr[u] = HADDR_UNDEF;
f->shared->fs_man[u] = NULL;
}
- f->shared->first_alloc_dealloc = FALSE;
- f->shared->eoa_pre_fsm_fsalloc = HADDR_UNDEF;
- f->shared->eoa_post_fsm_fsalloc = HADDR_UNDEF;
+ /* This will be stored as eoa_pre_fsm_fsalloc in the fsinfo message */
+ /* This is done to be backward compatible with 1.10 library that has the FSM hack */
+ f->shared->eoa_fsm_fsalloc = HADDR_UNDEF;
f->shared->eoa_post_mdci_fsalloc = HADDR_UNDEF;
/* Initialization for handling file space (for paged aggregation) */
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 6c1156f..5f25ddc 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -328,14 +328,9 @@ struct H5F_file_t {
H5F_fs_state_t fs_state[H5F_MEM_PAGE_NTYPES]; /* State of free space manager for each type */
haddr_t fs_addr[H5F_MEM_PAGE_NTYPES]; /* Address of free space manager info for each type */
H5FS_t *fs_man[H5F_MEM_PAGE_NTYPES]; /* Free space manager for each file space type */
- hbool_t first_alloc_dealloc; /* TRUE iff free space managers */
- /* are persistent and have not */
- /* been used accessed for either */
- /* allocation or deallocation */
- /* since file open. */
- haddr_t eoa_pre_fsm_fsalloc; /* eoa pre file space allocation */
- /* for self referential FSMs */
- haddr_t eoa_post_fsm_fsalloc; /* eoa post file space allocation */
+ hbool_t null_fsm_addr; /* Used by h5clear tool to tell the library */
+ /* to drop free-space to the floor */
+ haddr_t eoa_fsm_fsalloc; /* eoa after file space allocation */
/* for self referential FSMs */
haddr_t eoa_post_mdci_fsalloc; /* eoa past file space allocation */
/* for metadata cache image, or */
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index e9b6c32..a8ac158 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -330,8 +330,7 @@ typedef struct H5F_t H5F_t;
#define H5F_THRESHOLD(F) ((F)->shared->threshold)
#define H5F_PGEND_META_THRES(F) ((F)->shared->fs.pgend_meta_thres)
#define H5F_POINT_OF_NO_RETURN(F) ((F)->shared->fs.point_of_no_return)
-#define H5F_FIRST_ALLOC_DEALLOC(F) ((F)->shared->first_alloc_dealloc)
-#define H5F_EOA_PRE_FSM_FSALLOC(F) ((F)->shared->eoa_pre_fsm_fsalloc)
+#define H5F_NULL_FSM_ADDR(F) ((F)->shared->null_fsm_addr)
#define H5F_GET_MIN_DSET_OHDR(F) ((F)->shared->crt_dset_min_ohdr_flag)
#define H5F_SET_MIN_DSET_OHDR(F, V) ((F)->shared->crt_dset_min_ohdr_flag = (V))
#else /* H5F_MODULE */
@@ -389,8 +388,7 @@ typedef struct H5F_t H5F_t;
#define H5F_THRESHOLD(F) (H5F_get_threshold(F))
#define H5F_PGEND_META_THRES(F) (H5F_get_pgend_meta_thres(F))
#define H5F_POINT_OF_NO_RETURN(F) (H5F_get_point_of_no_return(F))
-#define H5F_FIRST_ALLOC_DEALLOC(F) (H5F_get_first_alloc_dealloc(F))
-#define H5F_EOA_PRE_FSM_FSALLOC(F) (H5F_get_eoa_pre_fsm_fsalloc(F))
+#define H5F_NULL_FSM_ADDR(F) (H5F_get_null_fsm_addr(F))
#define H5F_GET_MIN_DSET_OHDR(F) (H5F_get_min_dset_ohdr(F))
#define H5F_SET_MIN_DSET_OHDR(F, V) (H5F_set_min_dset_ohdr((F), (V)))
#endif /* H5F_MODULE */
@@ -744,8 +742,7 @@ H5_DLL herr_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref,
H5_DLL herr_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr);
H5_DLL hsize_t H5F_get_pgend_meta_thres(const H5F_t *f);
H5_DLL hbool_t H5F_get_point_of_no_return(const H5F_t *f);
-H5_DLL hbool_t H5F_get_first_alloc_dealloc(const H5F_t *f);
-H5_DLL haddr_t H5F_get_eoa_pre_fsm_fsalloc(const H5F_t *f);
+H5_DLL hbool_t H5F_get_null_fsm_addr(const H5F_t *f);
H5_DLL hbool_t H5F_get_min_dset_ohdr(const H5F_t *f);
H5_DLL herr_t H5F_set_min_dset_ohdr(H5F_t *f, hbool_t minimize);
diff --git a/src/H5Fquery.c b/src/H5Fquery.c
index 103ad3b..c168535 100644
--- a/src/H5Fquery.c
+++ b/src/H5Fquery.c
@@ -1190,40 +1190,17 @@ H5F_get_point_of_no_return(const H5F_t *f)
FUNC_LEAVE_NOAPI(f->shared->point_of_no_return)
} /* end H5F_get_point_of_no_return() */
-
/*-------------------------------------------------------------------------
- * Function: H5F_get_first_alloc_dealloc
+ * Function: H5F_get_null_fsm_addr
*
- * Purpose: Retrieve the 'first alloc / dealloc' value for the file.
+ * Purpose: Retrieve the 'null_fsm_addr' value for the file.
*
- * Return: Success: Non-negative, the 'first_alloc_dealloc'
+ * Return: Success: Non-negative, the 'null_fsm_addr'
* Failure: (can't happen)
*-------------------------------------------------------------------------
*/
hbool_t
-H5F_get_first_alloc_dealloc(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- HDassert(f);
- HDassert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->first_alloc_dealloc)
-} /* end H5F_get_first_alloc_dealloc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_eoa_pre_fsm_fsalloc
- *
- * Purpose: Retrieve the 'EOA pre-FSM fsalloc' value for the file.
- *
- * Return: Success: Non-negative, the 'EOA pre-FSM fsalloc'
- * Failure: (can't happen)
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5F_get_eoa_pre_fsm_fsalloc(const H5F_t *f)
+H5F_get_null_fsm_addr(const H5F_t *f)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -1231,6 +1208,5 @@ H5F_get_eoa_pre_fsm_fsalloc(const H5F_t *f)
HDassert(f);
HDassert(f->shared);
- FUNC_LEAVE_NOAPI(f->shared->eoa_pre_fsm_fsalloc)
-} /* end H5F_get_eoa_pre_fsm_fsalloc() */
-
+ FUNC_LEAVE_NOAPI(f->shared->null_fsm_addr)
+} /* end H5F_get_null_fsm_addr() */
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index 631937b..4fcc164 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -81,15 +81,6 @@ static const unsigned HDF5_superblock_ver_bounds[] = {
HDF5_SUPERBLOCK_VERSION_LATEST /* H5F_LIBVER_LATEST */
};
-/* Format version bounds for fsinfo message */
-/* This message exists starting library release v1.10 */
-static const unsigned H5O_fsinfo_ver_bounds[] = {
- H5O_INVALID_VERSION, /* H5F_LIBVER_EARLIEST */
- H5O_INVALID_VERSION, /* H5F_LIBVER_V18 */
- H5O_FSINFO_VERSION_1, /* H5F_LIBVER_V110 */
- H5O_FSINFO_VERSION_LATEST /* H5F_LIBVER_LATEST */
-};
-
/*-------------------------------------------------------------------------
* Function: H5F__super_ext_create
@@ -778,28 +769,26 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
/* If message is NOT marked "unknown"--set up file space info */
if(!(flags & H5O_MSG_FLAG_WAS_UNKNOWN)) {
H5O_fsinfo_t fsinfo; /* File space info message from superblock extension */
- hbool_t null_fsm_addr = FALSE; /* Whether to drop free-space to the floor */
+ /* f->shared->null_fsm_addr: Whether to drop free-space to the floor */
/* The h5clear tool uses this property to tell the library
* to drop free-space to the floor
*/
if(H5P_exist_plist(fa_plist, H5F_ACS_NULL_FSM_ADDR_NAME) > 0)
- if(H5P_get(fa_plist, H5F_ACS_NULL_FSM_ADDR_NAME, &null_fsm_addr) < 0)
+ if(H5P_get(fa_plist, H5F_ACS_NULL_FSM_ADDR_NAME, &f->shared->null_fsm_addr) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get clearance for persisting fsm addr")
/* Retrieve the 'file space info' structure */
if(NULL == H5O_msg_read(&ext_loc, H5O_FSINFO_ID, &fsinfo))
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get free-space manager info message")
- /* Update changed values */
-
/* Version bounds check */
- if(H5O_fsinfo_ver_bounds[H5F_HIGH_BOUND(f)] == H5O_INVALID_VERSION ||
- fsinfo.version > H5O_fsinfo_ver_bounds[H5F_HIGH_BOUND(f)])
+ if(H5O_fsinfo_check_version(H5F_HIGH_BOUND(f), &fsinfo) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "File space info message's version out of bounds")
+
+ /* Update changed values */
if(f->shared->fs_version != fsinfo.version)
f->shared->fs_version = fsinfo.version;
-
if(f->shared->fs_strategy != fsinfo.strategy) {
f->shared->fs_strategy = fsinfo.strategy;
@@ -835,35 +824,42 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
/* Initialize page end meta threshold */
f->shared->pgend_meta_thres = fsinfo.pgend_meta_thres;
- if(f->shared->eoa_pre_fsm_fsalloc != fsinfo.eoa_pre_fsm_fsalloc)
- f->shared->eoa_pre_fsm_fsalloc = fsinfo.eoa_pre_fsm_fsalloc;
+ if(f->shared->eoa_fsm_fsalloc != fsinfo.eoa_pre_fsm_fsalloc)
+ f->shared->eoa_fsm_fsalloc = fsinfo.eoa_pre_fsm_fsalloc;
- /* f->shared->eoa_pre_fsm_fsalloc must always be HADDR_UNDEF
- * in the absence of persistent free space managers.
- */
- /* If the following two conditions are true:
+ /*
+ * If the following two conditions are true:
* (1) skipping EOF check (skip_eof_check)
- * (2) dropping free-space to the floor (null_fsm_addr)
- * skip the asserts as "eoa_pre_fsm_fsalloc" may be undefined
+ * (2) dropping free-space to the floor (f->shared->null_fsm_addr)
+ * skip the asserts as "eoa_fsm_fsalloc" may be undefined
* for a crashed file with persistent free space managers.
- * #1 and #2 are enabled when the tool h5clear --increment
+ * The above two conditions are enabled when the tool h5clear --increment
* option is used.
*/
- if(!skip_eof_check && !null_fsm_addr) {
- HDassert((!f->shared->fs_persist) || (f->shared->eoa_pre_fsm_fsalloc != HADDR_UNDEF));
- HDassert(!f->shared->first_alloc_dealloc);
- }
-
- /* As "eoa_pre_fsm_fsalloc" may be undefined for a crashed file
- * with persistent free space managers, therefore, set
- * "first_alloc_dealloc" when the condition
- * "dropping free-space to the floor is true.
- * This will ensure that no action is done to settle things on file
- * close via H5MF_settle_meta_data_fsm() and H5MF_settle_raw_data_fsm().
+ if(!skip_eof_check && !f->shared->null_fsm_addr)
+ HDassert((!f->shared->fs_persist) || (f->shared->eoa_fsm_fsalloc != HADDR_UNDEF));
+
+ /*
+ * A crashed file with persistent free-space managers may have
+ * undefined f->shared->eoa_fsm_fsalloc.
+ * eoa_fsm_fsalloc is the final eoa which is saved in the free-space
+ * info message's eoa_pre_fsm_fsalloc field for backward compatibility.
+ * If the tool h5clear sets to dropping free-space to the floor
+ * as indicated by f->shared->null_fsm_addr, we are not going to
+ * perform actions to settle things on file close in the routines
+ * H5MF_settle_meta_data_fsm() and H5MF_settle_raw_data_fsm().
+ *
+ * We remove the following check:
+ * if((f->shared->eoa_pre_fsm_fsalloc != HADDR_UNDEF || null_fsm_addr) &&
+ * (H5F_INTENT(f) & H5F_ACC_RDWR))
+ * f->shared->first_alloc_dealloc = TRUE;
+ *
+ * Because:
+ * --there is no more f->shared->eoa_pre_fsm_fsalloc and
+ * f->shared->first_alloc_dealloc
+ * --the check for null_fsm_addr is directly done in H5MF_settle_meta_data_fsm()
+ * and H5MF_settle_raw_data_fsm()
*/
- if((f->shared->eoa_pre_fsm_fsalloc != HADDR_UNDEF || null_fsm_addr) &&
- (H5F_INTENT(f) & H5F_ACC_RDWR))
- f->shared->first_alloc_dealloc = TRUE;
f->shared->fs_addr[0] = HADDR_UNDEF;
for(u = 1; u < NELMTS(f->shared->fs_addr); u++)
@@ -871,17 +867,17 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
/* If the following two conditions are true:
* (1) file is persisting free-space
- * (2) dropping free-space to the floor (null_fsm_addr)
+ * (2) dropping free-space to the floor (f->shared->null_fsm_addr)
* nullify the addresses of the FSMs
*/
- if(f->shared->fs_persist && null_fsm_addr)
+ if(f->shared->fs_persist && f->shared->null_fsm_addr)
for(u = 0; u < NELMTS(fsinfo.fs_addr); u++)
f->shared->fs_addr[u] = fsinfo.fs_addr[u] = HADDR_UNDEF;
/* For fsinfo.mapped: remove the FSINFO message from the superblock extension
and write a new message to the extension */
- /* For null_fsm_addr: just update FSINFO message in the superblock extension */
- if(((fsinfo.mapped || null_fsm_addr) && (rw_flags & H5AC__READ_ONLY_FLAG) == 0)) {
+ /* For f->shared->null_fsm_addr: just update FSINFO message in the superblock extension */
+ if(((fsinfo.mapped || f->shared->null_fsm_addr) && (rw_flags & H5AC__READ_ONLY_FLAG) == 0)) {
/* Do the same kluge until we know for sure. VC */
#if 1 /* bug fix test code -- tidy this up if all goes well */ /* JRM */
@@ -895,7 +891,7 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
f->shared->sblock = sblock;
#endif /* JRM */
- if(null_fsm_addr) {
+ if(f->shared->null_fsm_addr) {
if(H5F__super_ext_write_msg(f, H5O_FSINFO_ID, &fsinfo, FALSE, H5O_MSG_FLAG_MARK_IF_UNKNOWN) < 0)
HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error in writing fsinfo message to superblock extension")
}
@@ -1394,7 +1390,7 @@ H5F__super_init(H5F_t *f)
fsinfo.mapped = FALSE;
/* Set the version for the fsinfo message */
- if(H5F__fsinfo_set_version(f, &fsinfo) < 0)
+ if(H5O_fsinfo_set_version(H5F_LOW_BOUND(f), H5F_HIGH_BOUND(f), &fsinfo) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set version of fsinfo")
f->shared->fs_version = fsinfo.version;
@@ -1824,44 +1820,3 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F__super_ext_remove_msg() */
-
-/*-------------------------------------------------------------------------
- * Function: H5F__fsinfo_set_version
- *
- * Purpose: Set the version to encode the fsinfo message with.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Vailin Choi; June 2019
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5F__fsinfo_set_version(const H5F_t *f, H5O_fsinfo_t *fsinfo)
-{
- unsigned version; /* Message version */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_STATIC
-
- /* Sanity check */
- HDassert(f);
- HDassert(fsinfo);
-
- version = H5O_FSINFO_VERSION_1;
-
- /* Upgrade to the version indicated by the file's low bound if higher */
- if(H5O_fsinfo_ver_bounds[H5F_LOW_BOUND(f)] != H5O_INVALID_VERSION)
- version = MAX(version, H5O_fsinfo_ver_bounds[H5F_LOW_BOUND(f)]);
-
- /* Version bounds check */
- if(H5O_fsinfo_ver_bounds[H5F_HIGH_BOUND(f)] == H5O_INVALID_VERSION ||
- version > H5O_fsinfo_ver_bounds[H5F_HIGH_BOUND(f)])
- HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "File space info message's version out of bounds")
-
- /* Set the message version */
- fsinfo->version = version;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F__fsinfo_set_version() */
diff --git a/src/H5MF.c b/src/H5MF.c
index 8d7ab96..3d9ddb0 100644
--- a/src/H5MF.c
+++ b/src/H5MF.c
@@ -50,6 +50,11 @@
#define H5MF_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */
#define H5MF_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */
+#define H5MF_CHECK_FSM(FSM, CF) \
+ HDassert(*CF == FALSE); \
+ if(!H5F_addr_defined(FSM->addr) || !H5F_addr_defined(FSM->sect_addr)) \
+ *CF = TRUE;
+
/******************/
/* Local Typedefs */
/******************/
@@ -90,6 +95,8 @@ static herr_t H5MF__close_shrink_eoa(H5F_t *f);
static herr_t H5MF__get_free_sects(H5F_t *f, H5FS_t *fspace, H5MF_sect_iter_ud_t *sect_udata, size_t *nums);
static hbool_t H5MF__fsm_type_is_self_referential(H5F_t *f, H5F_mem_page_t fsm_type);
static hbool_t H5MF__fsm_is_self_referential(H5F_t *f, H5FS_t *fspace);
+static herr_t H5MF__continue_alloc_fsm(H5F_t *f, H5FS_t *sm_hdr_fspace, H5FS_t *sm_sinfo_fspace,
+ H5FS_t *lg_hdr_fspace, H5FS_t *lg_sinfo_fspace, hbool_t *continue_alloc_fsm);
/* Free-space type manager routines */
static herr_t H5MF__create_fstype(H5F_t *f, H5F_mem_page_t type);
@@ -794,12 +801,6 @@ HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", FUNC, (unsigned)alloc_typ
HDassert(f->shared->lf);
HDassert(size > 0);
- if(f->shared->first_alloc_dealloc) {
- HDassert(! H5AC_cache_image_pending(f));
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, HADDR_UNDEF, "tidy of self referential fsm hack failed")
- } /* end if */
-
H5MF__alloc_to_fs_type(f, alloc_type, size, &fs_type);
#ifdef H5MF_ALLOC_DEBUG_MORE
@@ -1107,12 +1108,6 @@ HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUN
HGOTO_DONE(SUCCEED)
HDassert(addr != 0); /* Can't deallocate the superblock :-) */
- if(f->shared->first_alloc_dealloc) {
- HDassert(!H5AC_cache_image_pending(f));
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "tidy of self referential fsm hack failed")
- } /* end if */
-
H5MF__alloc_to_fs_type(f, alloc_type, size, &fs_type);
/* Set the ring type in the API context */
@@ -1302,12 +1297,6 @@ HDfprintf(stderr, "%s: Entering: alloc_type = %u, addr = %a, size = %Hu, extra_r
HDassert(f);
HDassert(H5F_INTENT(f) & H5F_ACC_RDWR);
- if(f->shared->first_alloc_dealloc) {
- HDassert(! H5AC_cache_image_pending(f));
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "tidy of self referential fsm hack failed")
- } /* end if */
-
/* Set mapped type, treating global heap as raw data */
map_type = (alloc_type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : alloc_type;
@@ -1680,16 +1669,6 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
* H5MF_tidy_self_referential_fsm_hack() to discard the cache image
* block.
*/
- if(f->shared->first_alloc_dealloc) {
- if(H5AC_cache_image_pending(f)) {
- if(H5AC_force_cache_image_load(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "forced cache image load failed")
- } /* end if */
- else {
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "tidy of self referential fsm hack failed")
- } /* end else */
- } /* end if */
/* Set the ring type in the API context. In most cases, we will
* need H5AC_RING_RDFSM, so initially set the ring in
@@ -1834,7 +1813,7 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
fsinfo.threshold = f->shared->fs_threshold;
fsinfo.page_size = f->shared->fs_page_size;
fsinfo.pgend_meta_thres = f->shared->pgend_meta_thres;
- fsinfo.eoa_pre_fsm_fsalloc = f->shared->eoa_pre_fsm_fsalloc;
+ fsinfo.eoa_pre_fsm_fsalloc = f->shared->eoa_fsm_fsalloc;
fsinfo.version = f->shared->fs_version;
/* Write the free space manager message -- message must already exist */
@@ -1892,7 +1871,7 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
* been no file space allocation or deallocation since file
* open.
*/
- HDassert((f->shared->first_alloc_dealloc) || (final_eoa == f->shared->eoa_post_fsm_fsalloc));
+ HDassert(H5F_NULL_FSM_ADDR(f) || final_eoa == f->shared->eoa_fsm_fsalloc);
} /* end if */
else { /* super_vers can be 0, 1, 2 */
for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
@@ -2000,7 +1979,7 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
*/
for(ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype))
fsinfo.fs_addr[ptype-1] = f->shared->fs_addr[ptype];
- fsinfo.eoa_pre_fsm_fsalloc = f->shared->eoa_pre_fsm_fsalloc;
+ fsinfo.eoa_pre_fsm_fsalloc = f->shared->eoa_fsm_fsalloc;
/* Write the free space manager message -- message must already exist */
if(H5F__super_ext_write_msg(f, H5O_FSINFO_ID, &fsinfo, FALSE, H5O_MSG_FLAG_MARK_IF_UNKNOWN) < 0)
@@ -2061,8 +2040,8 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
* the file driver layer. However, as this possibility seems remote,
* it is ignored in the following assert.
*/
- HDassert((f->shared->first_alloc_dealloc) ||
- (final_eoa == f->shared->eoa_post_fsm_fsalloc) ||
+ HDassert((H5F_NULL_FSM_ADDR(f)) ||
+ (final_eoa == f->shared->eoa_fsm_fsalloc) ||
((H5F_addr_defined(f->shared->eoa_post_mdci_fsalloc)) &&
(final_eoa == f->shared->eoa_post_mdci_fsalloc)));
} /* end if */
@@ -2395,16 +2374,6 @@ H5MF_get_free_sections(H5F_t *f, H5FD_mem_t type, size_t nsects, H5F_sect_info_t
* H5MF_tidy_self_referential_fsm_hack() to discard the cache image
* block.
*/
- if(f->shared->first_alloc_dealloc) {
- if(H5AC_cache_image_pending(f)) {
- if(H5AC_force_cache_image_load(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, (-1), "forced cache image load failed")
- } /* end if */
- else {
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, (-1), "tidy of self referential fsm hack failed")
- } /* end else */
- } /* end if */
if(type == H5FD_MEM_DEFAULT) {
start_type = H5F_MEM_PAGE_SUPER;
@@ -2676,10 +2645,11 @@ H5MF_settle_raw_data_fsm(H5F_t *f, hbool_t *fsm_settled)
HDassert(f->shared);
HDassert(fsm_settled);
- /* Only need to settle things if we are persisting the free space info
- * and allocation/deallocation has occurred.
+ /*
+ * Only need to settle things if we are persisting free space and
+ * the private property in f->shared->null_fsm_addr is not enabled.
*/
- if(f->shared->fs_persist && !f->shared->first_alloc_dealloc) {
+ if(f->shared->fs_persist && !H5F_NULL_FSM_ADDR(f)) {
hbool_t fsm_opened[H5F_MEM_PAGE_NTYPES]; /* State of FSM */
hbool_t fsm_visited[H5F_MEM_PAGE_NTYPES]; /* State of FSM */
@@ -3017,6 +2987,7 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* H5MF_settle_raw_data_fsm() */
+
/*-------------------------------------------------------------------------
* Function: H5MF_settle_meta_data_fsm()
@@ -3035,7 +3006,7 @@ done:
* On entry to this function, the raw data settle routine
* (H5MF_settle_raw_data_fsm()) should have:
*
- * 1) Freed the aggregators.
+ * 1) Freed the aggregators.
*
* 2) Freed all file space allocated to the free space managers.
*
@@ -3071,12 +3042,12 @@ done:
* 1) Verify that the free space manager(s) involved in file
* space allocation for free space managers are still floating.
*
- * 2) Free the aggregators.
+ * 2) Free the aggregators.
*
- * 3) Reduce the EOA to the extent possible, and make note
+ * 3) Reduce the EOA to the extent possible, and make note
* of the resulting value. This value will be stored
* in the fsinfo superblock extension message and be used
- * in the subsequent file open.
+ * in the subsequent file open.
*
* 4) Re-allocate space for any free space manager(s) that:
*
@@ -3097,21 +3068,15 @@ done:
* allocation has changed the size of the section info --
* forcing us to deallocate and start the loop over again.
*
- * To avoid this, simply allocate file space for these
- * FSM(s) directly from the VFD layer if allocation is
- * indicated. This avoids the issue by bypassing the FSMs
- * in this case.
- *
- * Note that this may increase the size of the file needlessly.
- * A better solution would be to modify the FSM code to
+ * The solution is to modify the FSM code to
* save empty FSMs to file, and to allow section info blocks
- * to be oversized. However, given that the FSM code is
- * also used by the fractal heaps, and that we are under
- * severe time pressure at the moment, the above brute
- * force solution is attractive.
+ * to be oversized. That is, only allow section info to increase
+ * in size, not shrink. The solution is now implemented.
*
- * 5) Make note of the EOA -- used for sanity checking on
- * FSM shutdown.
+ * 5) Make note of the EOA -- used for sanity checking on
+ * FSM shutdown. This is saved as eoa_pre_fsm_fsalloc in
+ * the free-space info message for backward compatibility
+ * with the 1.10 library that has the hack.
*
* Return: SUCCEED/FAIL
*
@@ -3131,10 +3096,9 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
H5FS_t *sm_sinfo_fspace = NULL; /* ptr to sm FSM sinfo alloc FSM */
H5FS_t *lg_hdr_fspace = NULL; /* ptr to lg FSM hdr alloc FSM */
H5FS_t *lg_sinfo_fspace = NULL; /* ptr to lg FSM sinfo alloc FSM */
- haddr_t eoa_pre_fsm_fsalloc; /* eoa pre file space allocation */
- /* for self referential FSMs */
- haddr_t eoa_post_fsm_fsalloc; /* eoa post file space allocation */
+ haddr_t eoa_fsm_fsalloc; /* eoa after file space allocation */
/* for self referential FSMs */
+ hbool_t continue_alloc_fsm = FALSE; /* Continue allocating addr and sect_addr for FSMs */
H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */
herr_t ret_value = SUCCEED; /* Return value */
@@ -3145,10 +3109,11 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
HDassert(f->shared);
HDassert(fsm_settled);
- /* Only need to settle things if we are persisting the free space info
- * and allocation/deallocation has occurred.
+ /*
+ * Only need to settle things if we are persisting free space and
+ * the private property in f->shared->null_fsm_addr is not enabled.
*/
- if(f->shared->fs_persist && !f->shared->first_alloc_dealloc) {
+ if(f->shared->fs_persist && !H5F_NULL_FSM_ADDR(f)) {
/* Sanity check */
HDassert(f->shared->lf);
@@ -3196,7 +3161,6 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
{
H5FS_stat_t fs_stat; /* Information for hdr FSM */
- /* Verify that sm_hdr_fspace is floating if it exists */
if(sm_hdr_fspace) {
/* Query free space manager info for this type */
if(H5FS_stat_info(f, sm_hdr_fspace, &fs_stat) < 0)
@@ -3253,7 +3217,6 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
* Note that the aggregators will not exist if paged aggregation
* is enabled -- don't attempt to free if this is the case.
*/
- /* Vailin -- is this correct? */
/* (for space not at EOF, it may be put into free space managers) */
if((!H5F_PAGED_AGGR(f)) && (H5MF_free_aggrs(f) < 0))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free aggregators")
@@ -3262,21 +3225,7 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
if(H5MF__close_shrink_eoa(f) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa")
- /* At this point, the EOA should be set to a value that contains
- * the allocation for all user data, all non self referential FSMs,
- * the superblock and all superblock extension messages.
- *
- * Make note of the current EOA. We will store this value in the
- * free space manager superblock extension message. Since space for
- * everything other than the self referential FSMs (and possibly the
- * cache image) has been allocated at this point, this allows us to
- * to float the self referential FSMs on the first file space allocation /
- * deallocation and then set the EOA to this value before we handle
- * the allocation / deallocation. (If a cache image exists, the
- * first allocation / deallocation will be the deallocation of space
- * for the cache image).
- *
- * WARNING: This approach settling the self referential free space
+ /* WARNING: This approach settling the self referential free space
* managers and allocating space for them in the file will
* not work as currently implemented with the split and
* multi file drivers, as the self referential free space
@@ -3295,97 +3244,67 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
* We should be able to support the split file driver
* without a file format change. However, the code to
* do so does not exist at present.
+ * NOTE: not sure whether to remove or keep the above comments
*/
- if(HADDR_UNDEF == (eoa_pre_fsm_fsalloc = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get EOA")
-
- /* ******************* PROBLEM: ********************
- *
- * If the file has an alignment other than 1, and if
- * the EOA is not a multiple of this alignment, allocating space
- * for the section via the VFD info has the potential of generating
- * a fragment that will be added to the free space manager. This
- * of course undoes everything we have been doing here.
- *
- * Need a way around this. Obvious solution is to force the EOA to
- * be a multiple of the alignment.
- *
- * Fortunately, alignment is typically 1, so this is a non-issue in
- * most cases. In cases where the alignment is not 1, for now we
- * have decided to drop the fragment on the floor.
- *
- * Eventually, we should fix this by modifying the on disk representations
- * of free space managers to allow for empty space, so as to bypass the
- * issues created by self-referential free space managers, and make
- * this issue moot.
+ /*
+ * Continue allocating file space for the header and section info until
+ * they are all settled,
*/
- /* HDassert(f->shared->alignment == 1); */
-
+ do {
+ continue_alloc_fsm = FALSE;
+ if(sm_hdr_fspace)
+ if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, sm_hdr_fspace, &(f->shared->fs_addr[sm_fshdr_fs_type])) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate sm hdr FSM file space")
+
+ if(sm_sinfo_fspace && (sm_sinfo_fspace != sm_hdr_fspace))
+ if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, sm_sinfo_fspace, &(f->shared->fs_addr[sm_fssinfo_fs_type])) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate sm sinfo FSM file space")
+
+ if(H5F_PAGED_AGGR(f)) {
+ if(lg_hdr_fspace)
+ if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, lg_hdr_fspace, &(f->shared->fs_addr[lg_fshdr_fs_type])) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate lg hdr FSM file space")
+
+ if(lg_sinfo_fspace && (lg_sinfo_fspace != lg_hdr_fspace))
+ if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, lg_sinfo_fspace, &(f->shared->fs_addr[lg_fssinfo_fs_type])) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate lg sinfo FSM file space")
+ } /* end if */
- /* The free space manager(s) that handle space allocations for free
- * space managers should be settled now, albeit without file space
- * allocated to them. To avoid the possibility of changing the sizes
- * of their section info blocks, allocate space for them now at the
- * end of file via H5FD_alloc().
- *
- * In the past, this issue of allocating space without touching the
- * free space managers has been dealt with by calling
- * H5MF_aggr_vfd_alloc(), which in turn calls H5MF_aggr_alloc().
- * This is problematic since (if I read the code correctly) it will
- * re-constitute the metadata aggregator, which will add any leftover
- * space to one of the free space managers when freed.
- *
- * This is a non-starter, since the entire objective is to settle the
- * free space managers.
- *
- * Hence the decision to call H5FD_alloc() directly.
- *
- * As discussed in PROBLEM above, if f->shared->alignment is not 1,
- * this has the possibility of generating a fragment of file space
- * that would typically be inserted into one of the free space managers.
- *
- * This is isn't good, but due to schedule pressure, we will just drop
- * the fragment on the floor for now.
- */
- if(sm_hdr_fspace)
- if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, sm_hdr_fspace, &(f->shared->fs_addr[sm_fshdr_fs_type])) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate sm hdr FSM file space")
+ sm_hdr_fspace = f->shared->fs_man[sm_fshdr_fs_type];
+ sm_sinfo_fspace = f->shared->fs_man[sm_fssinfo_fs_type];
+ if(H5F_PAGED_AGGR(f)) {
+ lg_hdr_fspace = f->shared->fs_man[lg_fshdr_fs_type];
+ lg_sinfo_fspace = f->shared->fs_man[lg_fssinfo_fs_type];
+ }
- if(sm_sinfo_fspace && (sm_sinfo_fspace != sm_hdr_fspace))
- if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, sm_sinfo_fspace, &(f->shared->fs_addr[sm_fssinfo_fs_type])) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate sm sinfo FSM file space")
+ if(H5MF__continue_alloc_fsm(f, sm_hdr_fspace, sm_sinfo_fspace, lg_hdr_fspace, lg_sinfo_fspace, &continue_alloc_fsm) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate lg sinfo FSM file space")
- if(H5F_PAGED_AGGR(f)) {
- if(lg_hdr_fspace)
- if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, lg_hdr_fspace, &(f->shared->fs_addr[lg_fshdr_fs_type])) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate lg hdr FSM file space")
+ } while(continue_alloc_fsm);
- if(lg_sinfo_fspace && (lg_sinfo_fspace != lg_hdr_fspace))
- if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, lg_sinfo_fspace, &(f->shared->fs_addr[lg_fssinfo_fs_type])) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate lg sinfo FSM file space")
- } /* end if */
+ /* All free space managers should have file space allocated for them
+ * now, and should see no further allocations / deallocations.
+ * For backward compatibility, store the eoa in f->shared->eoa_fsm_fsalloc
+ * which will be set to fsinfo.eoa_pre_fsm_fsalloc when we actually write
+ * the free-space info message to the superblock extension.
+ * This will allow the 1.10 library with the hack to open the file with
+ * the new solution.
+ */
/* Get the eoa after allocation of file space for the self referential
* free space managers. Assuming no cache image, this should be the
* final EOA of the file.
*/
- if(HADDR_UNDEF == (eoa_post_fsm_fsalloc = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
+ if(HADDR_UNDEF == (eoa_fsm_fsalloc = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
-
- /* All free space managers should have file space allocated for them
- * now, and should see no further allocations / deallocations. Store
- * the pre and post file space allocation for self referential FSMs EOA
- * for use when we actually write the free space manager superblock
- * extension message.
- */
- f->shared->eoa_pre_fsm_fsalloc = eoa_pre_fsm_fsalloc;
- f->shared->eoa_post_fsm_fsalloc = eoa_post_fsm_fsalloc;
+ f->shared->eoa_fsm_fsalloc = eoa_fsm_fsalloc;
/* Indicate that the FSM was settled successfully */
*fsm_settled = TRUE;
} /* end if */
+
done:
/* Reset the ring in the API context */
if(orig_ring != H5AC_RING_INV)
@@ -3396,6 +3315,61 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5MF__continue_alloc_fsm
+ *
+ * Purpose: To determine whether any of the input FSMs has allocated
+ * its "addr" and "sect_addr".
+ * Return TRUE or FALSE in *continue_alloc_fsm.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Vailin Choi
+ * 6/24/2019
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MF__continue_alloc_fsm(H5F_t *f, H5FS_t *sm_hdr_fspace, H5FS_t *sm_sinfo_fspace,
+ H5FS_t *lg_hdr_fspace, H5FS_t *lg_sinfo_fspace, hbool_t *continue_alloc_fsm)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(continue_alloc_fsm);
+
+ /* Check sm_hdr_fspace */
+ if(sm_hdr_fspace && sm_hdr_fspace->serial_sect_count > 0 && sm_hdr_fspace->sinfo) {
+ H5MF_CHECK_FSM(sm_hdr_fspace, continue_alloc_fsm);
+ }
+
+ if(!(*continue_alloc_fsm)) {
+ if(sm_sinfo_fspace && sm_sinfo_fspace != sm_hdr_fspace &&
+ sm_sinfo_fspace->serial_sect_count > 0 && sm_sinfo_fspace->sinfo) {
+ H5MF_CHECK_FSM(sm_hdr_fspace, continue_alloc_fsm);
+ }
+ }
+
+ if(H5F_PAGED_AGGR(f) && !(*continue_alloc_fsm)) {
+ /* Check lg_hdr_fspace */
+ if(lg_hdr_fspace && lg_hdr_fspace->serial_sect_count > 0 && lg_hdr_fspace->sinfo) {
+ H5MF_CHECK_FSM(lg_hdr_fspace, continue_alloc_fsm);
+ }
+
+ /* Check lg_sinfo_fspace */
+ if(!(*continue_alloc_fsm)) {
+ if(lg_sinfo_fspace && lg_sinfo_fspace != lg_hdr_fspace &&
+ lg_sinfo_fspace->serial_sect_count > 0 && lg_sinfo_fspace->sinfo) {
+ H5MF_CHECK_FSM(lg_sinfo_fspace, continue_alloc_fsm);
+ }
+ }
+ }
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5MF__continue_alloc_fsm() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5MF__fsm_type_is_self_referential()
*
* Purpose: Return TRUE if the indicated free space manager allocates
@@ -3500,303 +3474,3 @@ H5MF__fsm_is_self_referential(H5F_t *f, H5FS_t *fspace)
FUNC_LEAVE_NOAPI(result)
} /* H5MF__fsm_is_self_referential() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5MF_tidy_self_referential_fsm_hack
- *
- * Purpose: As discussed in the comments of the settle routines above,
- * the existence of self referential free space managers
- * as currently implemented creates the possibility of
- * infinite loops at file close.
- *
- * As a hack to avoid this, we have added code to settle
- * self referential free space managers, and then allocate
- * space for them directly from the file driver.
- *
- * To avoid dropping ever increasing amounts of file space
- * on the floor with each subsequent file close/open cycle,
- * we need to clean this up on file open. To avoid this,
- * this function is called on the first file space allocation
- * or deallocation after file open to float the self referential
- * free space managers and reduce the EOA to the value it
- * had before the direct allocation of space for the self
- * referential free space managers.
- *
- * The function proceeds as follows:
- *
- * 1) Verify that f->shared->first_alloc_dealloc is TRUE,
- * and then set it to FALSE.
- *
- * 2) Get the current EOA. Verify that it is greater than
- * or equal to f->shared->eoa_pre_fsm_fsalloc. If the
- * current eoa is equal to f->shared->eoa_pre_fsm_fsalloc,
- * no self referential FSMs were stored, and we are done.
- *
- * NOTE: This will have to be reworked somewhat for
- * cache image.
- *
- * 3) Load the self referential FSMs. In passing verify that
- * the lowest address of a FSM header is equal to
- * f->shared->eoa_pre_fsm_fsalloc.
- *
- * Note that we don't have to use any special I/O for
- * this -- we can use the regular I/O methods even if
- * paged aggregation and page buffering is enabled.
- *
- * 4) Float the FSMs. Ensure that the file space is NOT
- * released.
- *
- * 5) Set EOA equal to f->shared->eoa_pre_fsm_fsalloc,
- * and then set f->shared->eoa_pre_fsm_fsalloc to
- * HADDR_UNDEF.
- *
- * If page buffering, verify that the new EOA is
- * on a page boundary, and expunge any pages in the
- * page buffer after the new EOA.
- *
- * Note that this function is also called from test code
- * when it is necessary to startup a self referential
- * free space manager prior to the first file space
- * allocation / deallocation. Failure to do so will
- * result in assertion failures in this function on
- * the first file space allocation / deallocation.
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: John Mainzer
- * 12/11/16
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5MF_tidy_self_referential_fsm_hack(H5F_t *f)
-{
- haddr_t eoa; /* EOA of file */
- hsize_t tail_size = 0; /* Size of chunk to free */
- H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */
- haddr_t first_srfsm_hdr = HADDR_UNDEF; /* Addr of first self referential */
- /* fsm header in file */
- H5FS_stat_t fs_stat; /* Information for hdr FSM */
- H5F_mem_page_t sm_fshdr_fs_type; /* Small fs hdr fsm */
- H5F_mem_page_t sm_fssinfo_fs_type; /* Small fs sinfo fsm */
- H5F_mem_page_t lg_fshdr_fs_type; /* Large fs hdr fsm */
- H5F_mem_page_t lg_fssinfo_fs_type; /* Large fs sinfo fsm */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL)
-
- /* check args */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->fs_persist);
- HDassert(f->shared->first_alloc_dealloc);
-
- /* Set the ring type in the API context. Since we are only dealing with
- * self referential FSMs, we will only need H5AC_RING_MDFSM.
- */
- H5AC_set_ring(H5AC_RING_MDFSM, &orig_ring);
-
- /* 1) Verify that f->shared->first_alloc_dealloc is TRUE,
- * and then set it to FALSE.
- */
- HDassert(f->shared->first_alloc_dealloc);
- f->shared->first_alloc_dealloc = FALSE;
-
-
- /* 2) Get the current EOA. Verify that it is greater than
- * or equal to f->shared->eoa_pre_fsm_fsalloc. If the
- * current eoa is equal to f->shared->eoa_pre_fsm_fsalloc,
- * no self referential FSMs were stored, and we are done.
- *
- * NOTE: This will have to be reworked somewhat for
- * cache image.
- */
- if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get EOA")
- HDassert(H5F_addr_le(f->shared->eoa_pre_fsm_fsalloc, eoa));
-
- if(H5F_addr_eq(f->shared->eoa_pre_fsm_fsalloc, eoa))
- HGOTO_DONE(SUCCEED)
-
-
- /* 3) Load the self referential FSMs. In passing verify that
- * the lowest address of a FSM header is equal to
- * f->shared->eoa_pre_fsm_fsalloc.'
- *
- * Note that we don't have to use any special I/O for
- * this -- we can use the regular I/O methods even if
- * paged aggregation and page buffering is enabled.
- */
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_HDR, (size_t)1, &sm_fshdr_fs_type);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_SINFO, (size_t)1, &sm_fssinfo_fs_type);
- HDassert(sm_fshdr_fs_type > H5F_MEM_PAGE_DEFAULT);
- HDassert(sm_fshdr_fs_type < H5F_MEM_PAGE_LARGE_SUPER);
-
- HDassert(sm_fssinfo_fs_type > H5F_MEM_PAGE_DEFAULT);
- HDassert(sm_fssinfo_fs_type < H5F_MEM_PAGE_LARGE_SUPER);
-
- HDassert(NULL == f->shared->fs_man[sm_fshdr_fs_type]);
- HDassert(NULL == f->shared->fs_man[sm_fssinfo_fs_type]);
-
- if(H5F_addr_defined(f->shared->fs_addr[sm_fshdr_fs_type])) {
- first_srfsm_hdr = f->shared->fs_addr[sm_fshdr_fs_type];
-
- /* open the FSM */
- if(H5MF__open_fstype(f, sm_fshdr_fs_type) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space manager")
-
- HDassert(f->shared->fs_man[sm_fshdr_fs_type]);
- } /* end if */
-
- if((sm_fshdr_fs_type != sm_fssinfo_fs_type) &&
- (H5F_addr_defined(f->shared->fs_addr[sm_fssinfo_fs_type]))) {
-
- if(!H5F_addr_defined(first_srfsm_hdr) ||
- (H5F_addr_defined(first_srfsm_hdr) &&
- H5F_addr_lt(f->shared->fs_addr[sm_fssinfo_fs_type], first_srfsm_hdr)))
- first_srfsm_hdr = f->shared->fs_addr[sm_fssinfo_fs_type];
-
- HDassert(NULL == f->shared->fs_man[sm_fssinfo_fs_type]);
-
- /* open the FSM */
- if(H5MF__open_fstype(f, sm_fssinfo_fs_type) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space manager")
-
- HDassert(f->shared->fs_man[sm_fssinfo_fs_type]);
- } /* end if */
-
- if(H5F_PAGED_AGGR(f)) {
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_HDR, f->shared->fs_page_size + 1, &lg_fshdr_fs_type);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_SINFO, f->shared->fs_page_size + 1, &lg_fssinfo_fs_type);
-
- HDassert(lg_fshdr_fs_type >= H5F_MEM_PAGE_LARGE_SUPER);
- HDassert(lg_fshdr_fs_type < H5F_MEM_PAGE_NTYPES);
-
- HDassert(lg_fssinfo_fs_type >= H5F_MEM_PAGE_LARGE_SUPER);
- HDassert(lg_fssinfo_fs_type < H5F_MEM_PAGE_NTYPES);
-
- HDassert(NULL == f->shared->fs_man[lg_fshdr_fs_type]);
- HDassert(NULL == f->shared->fs_man[lg_fssinfo_fs_type]);
-
- if(H5F_addr_defined(f->shared->fs_addr[lg_fshdr_fs_type])) {
- if(!H5F_addr_defined(first_srfsm_hdr) ||
- (H5F_addr_defined(first_srfsm_hdr) &&
- H5F_addr_lt(f->shared->fs_addr[lg_fshdr_fs_type], first_srfsm_hdr)))
- first_srfsm_hdr = f->shared->fs_addr[lg_fshdr_fs_type];
-
- HDassert(NULL == f->shared->fs_man[lg_fshdr_fs_type]);
-
- /* open the FSM */
- if(H5MF__open_fstype(f, lg_fshdr_fs_type) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space manager")
- HDassert(f->shared->fs_man[lg_fshdr_fs_type]);
- } /* end if */
-
- if(lg_fshdr_fs_type != lg_fssinfo_fs_type && H5F_addr_defined(f->shared->fs_addr[lg_fssinfo_fs_type])) {
- if(!H5F_addr_defined(first_srfsm_hdr) ||
- (H5F_addr_defined(first_srfsm_hdr) &&
- H5F_addr_lt(f->shared->fs_addr[lg_fssinfo_fs_type], first_srfsm_hdr)))
- first_srfsm_hdr = f->shared->fs_addr[lg_fssinfo_fs_type];
-
- HDassert(NULL == f->shared->fs_man[lg_fssinfo_fs_type]);
-
- /* open the FSM */
- if(H5MF__open_fstype(f, lg_fssinfo_fs_type) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space manager")
- HDassert(f->shared->fs_man[lg_fssinfo_fs_type]);
- } /* end if */
- } /* end if */
- HDassert(H5F_addr_eq(first_srfsm_hdr, f->shared->eoa_pre_fsm_fsalloc));
-
- /* 4) Float the FSMs. Ensure that the file space is NOT released. */
- if(f->shared->fs_man[sm_fshdr_fs_type]) {
- /* Sanity check: Query free space manager info for this type */
- if(H5FS_stat_info(f, f->shared->fs_man[sm_fshdr_fs_type], &fs_stat) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't get free-space info")
-
- HDassert(H5F_addr_defined(fs_stat.addr));
- HDassert(H5F_addr_defined(fs_stat.sect_addr));
- if(H5FS_free(f, f->shared->fs_man[sm_fshdr_fs_type], FALSE) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't release free-space headers")
- f->shared->fs_addr[sm_fshdr_fs_type] = HADDR_UNDEF;
- } /* end if */
-
- if(sm_fshdr_fs_type != sm_fssinfo_fs_type && f->shared->fs_man[sm_fssinfo_fs_type]) {
- /* Sanity check: Query free space manager info for this type */
- if(H5FS_stat_info(f, f->shared->fs_man[sm_fssinfo_fs_type], &fs_stat) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't get free-space info")
-
- HDassert(H5F_addr_defined(fs_stat.addr));
- HDassert(H5F_addr_defined(fs_stat.sect_addr));
- if(H5FS_free(f, f->shared->fs_man[sm_fssinfo_fs_type], FALSE) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't release free-space headers")
- f->shared->fs_addr[sm_fssinfo_fs_type] = HADDR_UNDEF;
- } /* end if */
-
- if(H5F_PAGED_AGGR(f)) {
- if(f->shared->fs_man[lg_fshdr_fs_type]) {
- /* Sanity check: Query free space manager info for this type */
- if(H5FS_stat_info(f, f->shared->fs_man[lg_fshdr_fs_type], &fs_stat) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get free-space info")
-
- HDassert(H5F_addr_defined(fs_stat.addr));
- HDassert(H5F_addr_defined(fs_stat.sect_addr));
- if(H5FS_free(f, f->shared->fs_man[lg_fshdr_fs_type], FALSE) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't float free-space headers")
- f->shared->fs_addr[lg_fshdr_fs_type] = HADDR_UNDEF;
- } /* end if */
-
- if(lg_fshdr_fs_type != lg_fssinfo_fs_type && f->shared->fs_man[lg_fssinfo_fs_type]) {
- /* Sanity check: Query free space manager info for this type */
- if(H5FS_stat_info(f, f->shared->fs_man[lg_fssinfo_fs_type], &fs_stat) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get free-space info")
-
- HDassert(H5F_addr_defined(fs_stat.addr));
- HDassert(H5F_addr_defined(fs_stat.sect_addr));
- if(H5FS_free(f, f->shared->fs_man[lg_fssinfo_fs_type], FALSE) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't float free-space headers")
- f->shared->fs_addr[lg_fssinfo_fs_type] = HADDR_UNDEF;
- } /* end if */
- } /* end if */
-
- /* 5) Set EOA equal to f->shared->eoa_pre_fsm_fsalloc,
- * and then set f->shared->eoa_pre_fsm_fsalloc to
- * HADDR_UNDEF.
- *
- * If page buffering, verify that the new EOA is
- * on a page boundary, and expunge any pages in the
- * page buffer after the new EOA.
- */
- if(!H5F_PAGED_AGGR(f)) {
- /* Verify that the aggregators are still shutdown. */
- HDassert(f->shared->sdata_aggr.tot_size == 0);
- HDassert(f->shared->sdata_aggr.addr == 0);
- HDassert(f->shared->sdata_aggr.size == 0);
-
- HDassert(f->shared->meta_aggr.tot_size == 0);
- HDassert(f->shared->meta_aggr.addr == 0);
- HDassert(f->shared->meta_aggr.size == 0);
- } /* end if */
-
- tail_size = (hsize_t)(eoa - f->shared->eoa_pre_fsm_fsalloc);
-
- /* Release file space allocated to self referential FSMs */
- if(H5F__free(f, H5FD_MEM_DEFAULT, f->shared->eoa_pre_fsm_fsalloc, tail_size) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "driver free request failed")
- if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get EOA")
- HDassert(H5F_addr_eq(f->shared->eoa_pre_fsm_fsalloc, eoa));
-
- f->shared->eoa_pre_fsm_fsalloc = HADDR_UNDEF;
-
- HDassert((!H5F_PAGED_AGGR(f)) || (0 == (eoa % f->shared->fs_page_size)));
-
-done:
- /* Reset the ring in the API context */
- if(orig_ring != H5AC_RING_INV)
- H5AC_set_ring(orig_ring, NULL);
-
- FUNC_LEAVE_NOAPI_TAG(ret_value)
-} /* H5MF_tidy_self_referential_fsm_hack() */
-
diff --git a/src/H5MFaggr.c b/src/H5MFaggr.c
index 3db7f73..c726341 100644
--- a/src/H5MFaggr.c
+++ b/src/H5MFaggr.c
@@ -183,7 +183,21 @@ HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
* allocate "generic" space and sub-allocate out of that, if possible.
* Otherwise just allocate through H5F__alloc().
*/
- if((f->shared->feature_flags & aggr->feature_flag) && f->shared->fs_strategy != H5F_FSPACE_STRATEGY_NONE) {
+
+ /*
+ * Replace the following line with the line in #ifdef REPLACE/#endif.
+ * The line in #ifdef REPLACE triggers the following problem:
+ * test/objcopy.c: test_copy_group_deep() test fails with the family driver
+ *
+ * When closing the destination file after H5Ocopy, the library flushes the fractal
+ * heap direct block via H5HF__cache_dblock_pre_serialize(). While doing so,
+ * the cache eventually adjusts/evicts ageout entries and ends up flushing out the
+ * same entry that is being serialized (flush_in_progress).
+ */
+ if((f->shared->feature_flags & aggr->feature_flag) && f->shared->fs_strategy != H5F_FSPACE_STRATEGY_NONE && (!f->closing || !f->shared->fs_persist)) {
+#ifdef REPLACE
+ if((f->shared->feature_flags & aggr->feature_flag) && f->shared->fs_strategy != H5F_FSPACE_STRATEGY_NONE && !f->closing) {
+#endif
haddr_t aggr_frag_addr = HADDR_UNDEF; /* Address of aggregrator fragment */
hsize_t aggr_frag_size = 0; /* Size of aggregator fragment */
hsize_t alignment; /* Alignment of this section */
diff --git a/src/H5MFdbg.c b/src/H5MFdbg.c
index eedb72e..e11476b 100644
--- a/src/H5MFdbg.c
+++ b/src/H5MFdbg.c
@@ -215,14 +215,14 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5MF_sects_dump(H5F_t *f, FILE *stream)
+H5MF__sects_dump(H5F_t *f, FILE *stream)
{
haddr_t eoa; /* End of allocated space in the file */
int indent = 0; /* Amount to indent */
int fwidth = 50; /* Field width */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_PACKAGE_TAG(H5AC__FREESPACE_TAG, FAIL)
+ FUNC_ENTER_PACKAGE_TAG(H5AC__FREESPACE_TAG)
#ifdef H5MF_ALLOC_DEBUG
HDfprintf(stderr, "%s: Dumping file free space sections\n", FUNC);
#endif /* H5MF_ALLOC_DEBUG */
@@ -261,7 +261,7 @@ HDfprintf(stderr, "%s: for type = H5FD_MEM_DEFAULT, eoa = %a\n", FUNC, eoa);
udata.fwidth = MAX(0, fwidth - 6);
/* Iterate over all the free space sections */
- if(H5FS_sect_iterate(f, f->shared->fs_man[ptype], H5MF_sects_debug_cb, &udata) < 0)
+ if(H5FS_sect_iterate(f, f->shared->fs_man[ptype], H5MF__sects_debug_cb, &udata) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
} /* end if */
else
@@ -314,7 +314,7 @@ HDfprintf(stderr, "%s: sda_addr = %a, sda_size = %Hu, end of sda = %a\n", FUNC,
udata.fwidth = MAX(0, fwidth - 6);
/* Iterate over all the free space sections */
- if(H5FS_sect_iterate(f, f->shared->fs_man[atype], H5MF_sects_debug_cb, &udata) < 0)
+ if(H5FS_sect_iterate(f, f->shared->fs_man[atype], H5MF__sects_debug_cb, &udata) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
} /* end if */
else /* No sections of this type */
diff --git a/src/H5Ocache_image.c b/src/H5Ocache_image.c
index 591ac4a..7336211 100644
--- a/src/H5Ocache_image.c
+++ b/src/H5Ocache_image.c
@@ -27,11 +27,12 @@
*/
#include "H5Omodule.h" /* This source code file is part of the H5O module */
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* Files */
+#include "H5Fpkg.h" /* Files */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Opkg.h" /* Object headers */
#include "H5MFprivate.h" /* File space management */
@@ -275,16 +276,16 @@ H5O__mdci_free(void *mesg)
*-------------------------------------------------------------------------
*/
static herr_t
-H5O__mdci_delete(H5F_t *f, H5O_t *open_oh, void *_mesg)
+H5O__mdci_delete(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, void *_mesg)
{
H5O_mdci_t *mesg = (H5O_mdci_t *)_mesg;
- herr_t ret_value = SUCCEED; /* Return value */
+ haddr_t final_eoa; /* For sanity check */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
/* check args */
HDassert(f);
- HDassert(open_oh);
HDassert(mesg);
/* Free file space for cache image */
@@ -321,16 +322,24 @@ H5O__mdci_delete(H5F_t *f, H5O_t *open_oh, void *_mesg)
* before the first metadata cache access. However, given
* time constraints, I don't want to go there now.
*/
- if(H5F_FIRST_ALLOC_DEALLOC(f)) {
- HDassert(HADDR_UNDEF != H5F_EOA_PRE_FSM_FSALLOC(f));
- HDassert(H5F_addr_ge(mesg->addr, H5F_EOA_PRE_FSM_FSALLOC(f)));
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "tidy of self referential fsm hack failed")
- } /* end if */
- else {
+
+
+
+ if(f->closing) {
+
+ /* Get the eoa, and verify that it has the expected value */
+ if(HADDR_UNDEF == (final_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)) )
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "unable to get file size")
+
+ HDassert(H5F_addr_eq(final_eoa, mesg->addr + mesg->size));
+
+ if(H5FD_free(f->shared->lf, H5FD_MEM_SUPER, f, mesg->addr, mesg->size) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "can't free MDC image")
+ } else {
if(H5MF_xfree(f, H5FD_MEM_SUPER, mesg->addr, mesg->size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free file space for cache image block")
- } /* end else */
+ }
+
} /* end if */
done:
diff --git a/src/H5Ofsinfo.c b/src/H5Ofsinfo.c
index ec2328c..2a71b05 100644
--- a/src/H5Ofsinfo.c
+++ b/src/H5Ofsinfo.c
@@ -65,6 +65,16 @@ const H5O_msg_class_t H5O_MSG_FSINFO[1] = {{
H5O__fsinfo_debug /* debug the message */
}};
+/* Format version bounds for fsinfo message */
+/* This message exists starting library release v1.10 */
+static const unsigned H5O_fsinfo_ver_bounds[] = {
+ H5O_INVALID_VERSION, /* H5F_LIBVER_EARLIEST */
+ H5O_INVALID_VERSION, /* H5F_LIBVER_V18 */
+ H5O_FSINFO_VERSION_1, /* H5F_LIBVER_V110 */
+ H5O_FSINFO_VERSION_LATEST /* H5F_LIBVER_LATEST */
+};
+#define N_FSINFO_VERSION_BOUNDS 4
+
/* Declare a free list to manage the H5O_fsinfo_t struct */
H5FL_DEFINE_STATIC(H5O_fsinfo_t);
@@ -257,7 +267,7 @@ H5O_fsinfo_copy(const void *_mesg, void *_dest)
/* check args */
HDassert(fsinfo);
if(!dest && NULL == (dest = H5FL_CALLOC(H5O_fsinfo_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* copy */
*dest = *fsinfo;
@@ -331,6 +341,79 @@ H5O__fsinfo_free(void *mesg)
/*-------------------------------------------------------------------------
+ * Function: H5O_fsinfo_set_version
+ *
+ * Purpose: Set the version to encode the fsinfo message with.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Vailin Choi; June 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_fsinfo_set_version(H5F_libver_t low, H5F_libver_t high, H5O_fsinfo_t *fsinfo)
+{
+ unsigned version; /* Message version */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDcompile_assert(N_FSINFO_VERSION_BOUNDS == H5F_LIBVER_NBOUNDS);
+ HDassert(fsinfo);
+
+ version = H5O_FSINFO_VERSION_1;
+
+ /* Upgrade to the version indicated by the file's low bound if higher */
+ if(H5O_fsinfo_ver_bounds[low] != H5O_INVALID_VERSION)
+ version = MAX(version, H5O_fsinfo_ver_bounds[low]);
+
+ /* Version bounds check */
+ if(H5O_fsinfo_ver_bounds[high] == H5O_INVALID_VERSION || version > H5O_fsinfo_ver_bounds[high])
+ HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "File space info message's version out of bounds")
+
+ /* Set the message version */
+ fsinfo->version = version;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_fsinfo_set_version() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_fsinfo_check_version
+ *
+ * Purpose: Validate the fsinfo message version
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Summer 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_fsinfo_check_version(H5F_libver_t high, H5O_fsinfo_t *fsinfo)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDcompile_assert(N_FSINFO_VERSION_BOUNDS == H5F_LIBVER_NBOUNDS);
+ HDassert(fsinfo);
+
+ /* Check the version */
+ if(H5O_fsinfo_ver_bounds[high] == H5O_INVALID_VERSION || fsinfo->version > H5O_fsinfo_ver_bounds[high])
+ HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "File space info message's version out of bounds")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_fsinfo_check_version() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O__fsinfo_debug
*
* Purpose: Prints debugging info for a message.
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index d143f31..354a00b 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -997,6 +997,10 @@ H5_DLL H5O_loc_t *H5O_get_loc(hid_t id);
/* EFL operators */
H5_DLL hsize_t H5O_efl_total_size(H5O_efl_t *efl);
+/* File space info routines */
+H5_DLL herr_t H5O_fsinfo_set_version(H5F_libver_t low, H5F_libver_t high, H5O_fsinfo_t *fsinfo);
+H5_DLL herr_t H5O_fsinfo_check_version(H5F_libver_t high, H5O_fsinfo_t *fsinfo);
+
/* Fill value operators */
H5_DLL herr_t H5O_fill_reset_dyn(H5O_fill_t *fill);
H5_DLL herr_t H5O_fill_convert(H5O_fill_t *fill, H5T_t *type, hbool_t *fill_changed);
diff --git a/src/H5Rint.c b/src/H5Rint.c
index 05c6ddf..2355ec1 100644
--- a/src/H5Rint.c
+++ b/src/H5Rint.c
@@ -84,7 +84,7 @@ H5R__init_package(void)
{
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Mark "top" of interface as initialized */
H5R_top_package_initialize_s = TRUE;