diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2012-08-12 02:20:43 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2012-08-12 02:20:43 (GMT) |
commit | cd5ad177a23698c1daf6fb8c4195336865d795d2 (patch) | |
tree | 13720372b8dcf964d99cbec2d7ff5de1bdbdd565 /src | |
parent | cd3f42096b9a957e37c9df48aa0d31d9ed4bc537 (diff) | |
download | hdf5-cd5ad177a23698c1daf6fb8c4195336865d795d2.zip hdf5-cd5ad177a23698c1daf6fb8c4195336865d795d2.tar.gz hdf5-cd5ad177a23698c1daf6fb8c4195336865d795d2.tar.bz2 |
[svn-r22669] Description:
Merge r22634:2266 from trunk to revise_chunks branch
Tested on:
Mac OSX/64 10.7.4 (amazon) w/debug, gcc-4.7.x, C++, FORTRAN and threadsafe
(h5committest not needed on this branch)
Diffstat (limited to 'src')
-rw-r--r-- | src/H5ACprivate.h | 2 | ||||
-rw-r--r-- | src/H5C.c | 464 | ||||
-rw-r--r-- | src/H5Cpkg.h | 19 | ||||
-rw-r--r-- | src/H5Cprivate.h | 27 | ||||
-rw-r--r-- | src/H5Dchunk.c | 4 | ||||
-rw-r--r-- | src/H5Doh.c | 2 | ||||
-rw-r--r-- | src/H5Eint.c | 10 | ||||
-rw-r--r-- | src/H5F.c | 12 | ||||
-rw-r--r-- | src/H5FDcore.c | 10 | ||||
-rw-r--r-- | src/H5FDmpi.c | 19 | ||||
-rw-r--r-- | src/H5FDmpiposix.c | 20 | ||||
-rw-r--r-- | src/H5FS.c | 129 | ||||
-rw-r--r-- | src/H5FScache.c | 33 | ||||
-rw-r--r-- | src/H5FSsection.c | 6 | ||||
-rw-r--r-- | src/H5Fsuper.c | 2 | ||||
-rw-r--r-- | src/H5Fsuper_cache.c | 44 | ||||
-rw-r--r-- | src/H5HFsection.c | 12 | ||||
-rw-r--r-- | src/H5HG.c | 2 | ||||
-rw-r--r-- | src/H5MF.c | 4 | ||||
-rw-r--r-- | src/H5Ocopy.c | 5 | ||||
-rw-r--r-- | src/H5Otest.c | 2 | ||||
-rw-r--r-- | src/H5Pfapl.c | 47 | ||||
-rw-r--r-- | src/H5Shyper.c | 2 | ||||
-rw-r--r-- | src/H5Spoint.c | 2 | ||||
-rw-r--r-- | src/H5Sselect.c | 2 | ||||
-rw-r--r-- | src/H5Tarray.c | 3 | ||||
-rw-r--r-- | src/H5trace.c | 1 |
27 files changed, 627 insertions, 258 deletions
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 2987c16..9efdc2d 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -325,6 +325,8 @@ H5_DLLVAR hid_t H5AC_ind_dxpl_id; #define H5AC__FLUSH_IGNORE_PROTECTED_FLAG H5C__FLUSH_IGNORE_PROTECTED_FLAG #define H5AC__FREE_FILE_SPACE_FLAG H5C__FREE_FILE_SPACE_FLAG #define H5AC__TAKE_OWNERSHIP_FLAG H5C__TAKE_OWNERSHIP_FLAG +#define H5AC__FLUSH_LAST_FLAG H5C__FLUSH_LAST_FLAG +#define H5AC__FLUSH_COLLECTIVELY_FLAG H5C__FLUSH_COLLECTIVELY_FLAG /* #defines of flags used to report entry status in the @@ -410,12 +410,6 @@ done: * Programmer: John Mainzer * 3/17/10 * - * Modifications: - * - * Heavily reworked to have each process flush a group of - * adjacent entries. - * JRM -- 4/15/10 - * *------------------------------------------------------------------------- */ #ifdef H5_HAVE_PARALLEL @@ -438,8 +432,13 @@ H5C_apply_candidate_list(H5F_t * f, int last_entry_to_flush; int entries_to_clear = 0; int entries_to_flush = 0; + int entries_to_flush_or_clear_last = 0; + int entries_to_flush_collectively = 0; int entries_cleared = 0; int entries_flushed = 0; + int entries_delayed = 0; + int entries_flushed_or_cleared_last = 0; + int entries_flushed_collectively = 0; int entries_examined = 0; int initial_list_len; int * candidate_assignment_table = NULL; @@ -447,6 +446,7 @@ H5C_apply_candidate_list(H5F_t * f, H5C_cache_entry_t * clear_ptr = NULL; H5C_cache_entry_t * entry_ptr = NULL; H5C_cache_entry_t * flush_ptr = NULL; + H5C_cache_entry_t * delayed_ptr = NULL; #if H5C_DO_SANITY_CHECKS haddr_t last_addr; #endif /* H5C_DO_SANITY_CHECKS */ @@ -608,12 +608,28 @@ H5C_apply_candidate_list(H5F_t * f, (int)(cache_ptr->LRU_list_len)); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + /* ====================================================================== * + * Now scan the LRU and PEL lists, flushing or clearing entries as + * needed. + * + * The flush_me_last and flush_me_collectively flags may dictate how or + * when some entries can be flushed, and should be addressed here. + * However, in their initial implementation, these flags only apply to the + * superblock, so there's only a relatively small change to this function + * to account for this one case where they come into play. If these flags + * are ever expanded upon, this function and the following flushing steps + * should be reworked to account for additional cases. + * ====================================================================== */ + entries_examined = 0; initial_list_len = cache_ptr->LRU_list_len; entry_ptr = cache_ptr->LRU_tail_ptr; + /* Examine each entry in the LRU list */ while((entry_ptr != NULL) && (entries_examined <= initial_list_len) && ((entries_cleared + entries_flushed) < num_candidates)) { + + /* If this process needs to clear this entry. */ if(entry_ptr->clear_on_unprotect) { entry_ptr->clear_on_unprotect = FALSE; clear_ptr = entry_ptr; @@ -621,7 +637,7 @@ H5C_apply_candidate_list(H5F_t * f, entries_cleared++; #if ( H5C_APPLY_CANDIDATE_LIST__DEBUG > 1 ) - HDfprintf(stdout, "%s:%d: clearing 0x%llx.\n", FUNC, mpi_rank, + HDfprintf(stdout, "%s:%d: clearing 0x%llx.\n", FUNC, mpi_rank, (long long)clear_ptr->addr); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ @@ -634,14 +650,18 @@ H5C_apply_candidate_list(H5F_t * f, &first_flush, TRUE) < 0) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") - } else if(entry_ptr->flush_immediately) { + } /* end if */ + + /* Else, if this process needs to flush this entry. */ + else if (entry_ptr->flush_immediately) { + entry_ptr->flush_immediately = FALSE; flush_ptr = entry_ptr; entry_ptr = entry_ptr->prev; entries_flushed++; #if ( H5C_APPLY_CANDIDATE_LIST__DEBUG > 1 ) - HDfprintf(stdout, "%s:%d: flushing 0x%llx.\n", FUNC, mpi_rank, + HDfprintf(stdout, "%s:%d: flushing 0x%llx.\n", FUNC, mpi_rank, (long long)flush_ptr->addr); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ @@ -653,17 +673,20 @@ H5C_apply_candidate_list(H5F_t * f, H5C__NO_FLAGS_SET, &first_flush, TRUE) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") - } else { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't flush entry.") + } /* end else-if */ + + /* Otherwise, no action to be taken on this entry. Grab the next. */ + else { entry_ptr = entry_ptr->prev; - } + } /* end else */ entries_examined++; } /* end while */ #if H5C_APPLY_CANDIDATE_LIST__DEBUG - HDfprintf(stdout, "%s:%d: entries examined/cleared/flushed = %d/%d/%d.\n", - FUNC, mpi_rank, entries_examined, + HDfprintf(stdout, "%s:%d: entries examined/cleared/flushed = %d/%d/%d.\n", + FUNC, mpi_rank, entries_examined, entries_cleared, entries_flushed); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ @@ -672,69 +695,168 @@ H5C_apply_candidate_list(H5F_t * f, */ #if H5C_APPLY_CANDIDATE_LIST__DEBUG - HDfprintf(stdout, "%s:%d: scanning pinned entry list. len = %d\n", + HDfprintf(stdout, "%s:%d: scanning pinned entry list. len = %d\n", FUNC, mpi_rank, (int)(cache_ptr->pel_len)); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ entry_ptr = cache_ptr->pel_head_ptr; while((entry_ptr != NULL) && - ((entries_cleared + entries_flushed) < num_candidates)) { - if(entry_ptr->clear_on_unprotect) { - entry_ptr->clear_on_unprotect = FALSE; - clear_ptr = entry_ptr; - entry_ptr = entry_ptr->next; - entries_cleared++; + ((entries_cleared + entries_flushed + entries_delayed) + < num_candidates)) { + + /* If entry is marked for flush or for clear */ + if((entry_ptr->clear_on_unprotect||entry_ptr->flush_immediately)) { + + /* If this entry needs to be flushed last */ + if (entry_ptr->flush_me_last) { + + /* At this time, only the superblock supports being + flushed last. Conveniently, it also happens to be the only + entry that supports being flushed collectively, as well. Also + conveniently, it's always pinned, so we only need to check + for it while scanning the PEL here. Finally, it's never + included in a candidate list that excludes other dirty + entries in a cache, so we can handle this relatively simple + case here. + + For now, this function asserts this and saves the entry + to flush it after scanning the rest of the PEL list. + + If there are ever more entries that either need to be + flushed last and/or flushed collectively, this whole routine + will need to be reworked to handle all additional cases. As + it is the simple case of a single pinned entry needing + flushed last and collectively is just a minor addition to + this routine, but signficantly buffing up the usage of + flush_me_last or flush_me_collectively will require a more + intense rework of this function and potentially the function + of candidate lists as a whole. */ + + HDassert(entry_ptr->flush_me_collectively); + entries_to_flush_or_clear_last++; + entries_to_flush_collectively++; + HDassert(entries_to_flush_or_clear_last == 1); + HDassert(entries_to_flush_collectively == 1); + + /* Delay the entry. It will be flushed later. */ + delayed_ptr = entry_ptr; + entries_delayed++; + HDassert(entries_delayed == 1); + + } /* end if */ + + /* Else, this process needs to clear this entry. */ + else if (entry_ptr->clear_on_unprotect) { + HDassert(!entry_ptr->flush_immediately); + entry_ptr->clear_on_unprotect = FALSE; + clear_ptr = entry_ptr; + entry_ptr = entry_ptr->next; + entries_cleared++; #if ( H5C_APPLY_CANDIDATE_LIST__DEBUG > 1 ) - HDfprintf(stdout, "%s:%d: clearing 0x%llx.\n", FUNC, mpi_rank, + HDfprintf(stdout, "%s:%d: clearing 0x%llx.\n", FUNC, mpi_rank, (long long)clear_ptr->addr); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ - if(H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - clear_ptr->type, - clear_ptr->addr, - H5C__FLUSH_CLEAR_ONLY_FLAG, - &first_flush, - TRUE) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") - } else if(entry_ptr->flush_immediately) { - entry_ptr->flush_immediately = FALSE; - flush_ptr = entry_ptr; - entry_ptr = entry_ptr->next; - entries_flushed++; + if(H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + clear_ptr->type, + clear_ptr->addr, + H5C__FLUSH_CLEAR_ONLY_FLAG, + &first_flush, + TRUE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") + } /* end else-if */ + + /* Else, if this process needs to independently flush this entry. */ + else if (entry_ptr->flush_immediately) { + entry_ptr->flush_immediately = FALSE; + flush_ptr = entry_ptr; + entry_ptr = entry_ptr->next; + entries_flushed++; #if ( H5C_APPLY_CANDIDATE_LIST__DEBUG > 1 ) - HDfprintf(stdout, "%s:%d: flushing 0x%llx.\n", FUNC, mpi_rank, + HDfprintf(stdout, "%s:%d: flushing 0x%llx.\n", FUNC, mpi_rank, (long long)flush_ptr->addr); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ - if(H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - flush_ptr->type, - flush_ptr->addr, - H5C__NO_FLAGS_SET, - &first_flush, - TRUE) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") - } else { + if(H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + flush_ptr->type, + flush_ptr->addr, + H5C__NO_FLAGS_SET, + &first_flush, + TRUE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't flush entry.") + } /* end else-if */ + } /* end if */ + + /* Otherwise, this entry is not marked for flush or clear. Grab the next. */ + else { entry_ptr = entry_ptr->next; - } + } /* end else */ + } /* end while */ #if H5C_APPLY_CANDIDATE_LIST__DEBUG - HDfprintf(stdout, - "%s:%d: pel entries examined/cleared/flushed = %d/%d/%d.\n", - FUNC, mpi_rank, entries_examined, + HDfprintf(stdout, + "%s:%d: pel entries examined/cleared/flushed = %d/%d/%d.\n", + FUNC, mpi_rank, entries_examined, entries_cleared, entries_flushed); HDfprintf(stdout, "%s:%d: done.\n", FUNC, mpi_rank); fsync(stdout); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ - if((entries_flushed != entries_to_flush) || (entries_cleared != entries_to_clear)) + /* ====================================================================== * + * Now, handle all delayed entries. * + * * + * This can *only* be the superblock at this time, so it's relatively * + * easy to deal with. We're collectively flushing the entry saved from * + * above. This will need to be handled differently if there are ever more * + * than one entry needing this special treatment.) * + * ====================================================================== */ + + if (delayed_ptr) { + + if (delayed_ptr->clear_on_unprotect) { + entry_ptr->clear_on_unprotect = FALSE; + entries_cleared++; + } else if (delayed_ptr->flush_immediately) { + entry_ptr->flush_immediately = FALSE; + entries_flushed++; + } /* end if */ + + if(H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + delayed_ptr->type, + delayed_ptr->addr, + H5C__NO_FLAGS_SET, + &first_flush, + TRUE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, + "Can't flush entry collectively.") + + entries_flushed_collectively++; + entries_flushed_or_cleared_last++; + } /* end if */ + + /* ====================================================================== * + * Finished flushing everything. * + * ====================================================================== */ + + HDassert((entries_flushed == entries_to_flush)); + HDassert((entries_cleared == entries_to_clear)); + HDassert((entries_flushed_or_cleared_last == entries_to_flush_or_clear_last)); + HDassert((entries_flushed_collectively == entries_to_flush_collectively)); + + if((entries_flushed != entries_to_flush) || + (entries_cleared != entries_to_clear) || + (entries_flushed_or_cleared_last != entries_to_flush_or_clear_last) || + (entries_flushed_collectively != entries_to_flush_collectively)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry count mismatch.") done: @@ -920,7 +1042,8 @@ H5C_construct_candidate_list__min_clean(H5C_t * cache_ptr) entry_ptr = cache_ptr->dLRU_tail_ptr; while((nominated_entries_size < space_needed) && (nominated_entries_count < cache_ptr->slist_len) && - (entry_ptr != NULL)) { + (entry_ptr != NULL) && + (!entry_ptr->flush_me_last)) { haddr_t nominated_addr; HDassert( ! (entry_ptr->is_protected) ); @@ -1767,8 +1890,12 @@ H5C_flush_cache(H5F_t *f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, unsign HDassert( entry_ptr != NULL ); HDassert( entry_ptr->in_slist ); - if ( ( ! flush_marked_entries ) || - ( entry_ptr->flush_marker ) ) { + if ( ( ( ! flush_marked_entries ) || + ( entry_ptr->flush_marker ) ) && + ( ( ! entry_ptr->flush_me_last ) || + ( ( entry_ptr->flush_me_last ) && + ( cache_ptr->num_last_entries >= + cache_ptr->slist_len ) ) ) ) { if ( entry_ptr->is_protected ) { @@ -2520,6 +2647,10 @@ H5C_insert_entry(H5F_t * f, herr_t result; hbool_t first_flush = TRUE; hbool_t insert_pinned; + hbool_t flush_last; +#ifdef H5_HAVE_PARALLEL + hbool_t flush_collectively; +#endif hbool_t set_flush_marker; hbool_t write_permitted = TRUE; size_t empty_space; @@ -2558,8 +2689,12 @@ H5C_insert_entry(H5F_t * f, } #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ - set_flush_marker = ( (flags & H5C__SET_FLUSH_MARKER_FLAG) != 0 ); - insert_pinned = ( (flags & H5C__PIN_ENTRY_FLAG) != 0 ); + set_flush_marker = ( (flags & H5C__SET_FLUSH_MARKER_FLAG) != 0 ); + insert_pinned = ( (flags & H5C__PIN_ENTRY_FLAG) != 0 ); + flush_last = ( (flags & H5C__FLUSH_LAST_FLAG) != 0 ); +#ifdef H5_HAVE_PARALLEL + flush_collectively = ( (flags & H5C__FLUSH_COLLECTIVELY_FLAG) != 0 ); +#endif entry_ptr = (H5C_cache_entry_t *)thing; @@ -2600,6 +2735,10 @@ H5C_insert_entry(H5F_t * f, entry_ptr->is_pinned = insert_pinned; entry_ptr->pinned_from_client = insert_pinned; + entry_ptr->flush_me_last = flush_last; +#ifdef H5_HAVE_PARALLEL + entry_ptr->flush_me_collectively = flush_collectively; +#endif /* newly inserted entries are assumed to be dirty */ entry_ptr->is_dirty = TRUE; @@ -7679,85 +7818,91 @@ H5C_flush_invalidate_cache(H5F_t * f, HDassert( entry_ptr != NULL ); HDassert( entry_ptr->in_slist ); -#if H5C_DO_SANITY_CHECKS - /* update actual_slist_len & actual_slist_size before - * the flush. Note that the entry will be removed - * from the slist after the flush, and thus may be - * resized by the flush callback. This is OK, as - * we will catch the size delta in - * cache_ptr->slist_size_increase. - * - * Note that we include pinned entries in this count, even - * though we will not actually flush them. - */ - actual_slist_len++; - actual_slist_size += entry_ptr->size; -#endif /* H5C_DO_SANITY_CHECKS */ + if ( ( ! entry_ptr->flush_me_last ) || + ( ( entry_ptr->flush_me_last ) && + ( cache_ptr->num_last_entries >= + cache_ptr->slist_len ) ) ) { + + #if H5C_DO_SANITY_CHECKS + /* update actual_slist_len & actual_slist_size before + * the flush. Note that the entry will be removed + * from the slist after the flush, and thus may be + * resized by the flush callback. This is OK, as + * we will catch the size delta in + * cache_ptr->slist_size_increase. + * + * Note that we include pinned entries in this count, even + * though we will not actually flush them. + */ + actual_slist_len++; + actual_slist_size += entry_ptr->size; + #endif /* H5C_DO_SANITY_CHECKS */ - if ( entry_ptr->is_protected ) { + if ( entry_ptr->is_protected ) { - /* we have major problems -- but lets flush - * everything we can before we flag an error. - */ - protected_entries++; + /* we have major problems -- but lets flush + * everything we can before we flag an error. + */ + protected_entries++; - } else if ( entry_ptr->is_pinned ) { + } else if ( entry_ptr->is_pinned ) { - /* Test to see if we are can flush the entry now. - * If we can, go ahead and flush, but don't tell - * H5C_flush_single_entry() to destroy the entry - * as pinned entries can't be evicted. - */ - if(entry_ptr->flush_dep_height == curr_flush_dep_height ) { - status = H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - NULL, - entry_ptr->addr, - H5C__NO_FLAGS_SET, - &first_flush, - FALSE); - if ( status < 0 ) { + /* Test to see if we are can flush the entry now. + * If we can, go ahead and flush, but don't tell + * H5C_flush_single_entry() to destroy the entry + * as pinned entries can't be evicted. + */ + if(entry_ptr->flush_dep_height == curr_flush_dep_height ) { + status = H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + NULL, + entry_ptr->addr, + H5C__NO_FLAGS_SET, + &first_flush, + FALSE); + if ( status < 0 ) { - /* This shouldn't happen -- if it does, we are toast - * so just scream and die. - */ + /* This shouldn't happen -- if it does, we are toast + * so just scream and die. + */ - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "dirty pinned entry flush failed.") + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "dirty pinned entry flush failed.") + } /* end if */ + flushed_during_dep_loop = TRUE; } /* end if */ - flushed_during_dep_loop = TRUE; + else if(entry_ptr->flush_dep_height < curr_flush_dep_height) + /* This shouldn't happen -- if it does, just scream and die. */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry below current flush dep. height.") } /* end if */ - else if(entry_ptr->flush_dep_height < curr_flush_dep_height) - /* This shouldn't happen -- if it does, just scream and die. */ - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry below current flush dep. height.") - } /* end if */ - else { - if(entry_ptr->flush_dep_height == curr_flush_dep_height ){ + else { + if(entry_ptr->flush_dep_height == curr_flush_dep_height ){ - status = H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - NULL, - entry_ptr->addr, - (cooked_flags | H5C__FLUSH_INVALIDATE_FLAG), - &first_flush, - TRUE); - if ( status < 0 ) { + status = H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + NULL, + entry_ptr->addr, + (cooked_flags | H5C__FLUSH_INVALIDATE_FLAG), + &first_flush, + TRUE); + if ( status < 0 ) { - /* This shouldn't happen -- if it does, we are toast so - * just scream and die. - */ + /* This shouldn't happen -- if it does, we are toast so + * just scream and die. + */ - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "dirty entry flush destroy failed.") + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "dirty entry flush destroy failed.") + } /* end if */ + flushed_during_dep_loop = TRUE; } /* end if */ - flushed_during_dep_loop = TRUE; - } /* end if */ - else if(entry_ptr->flush_dep_height < curr_flush_dep_height) - /* This shouldn't happen -- if it does, just scream and die. */ - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry below current flush dep. height.") - } /* end else */ + else if(entry_ptr->flush_dep_height < curr_flush_dep_height) + /* This shouldn't happen -- if it does, just scream and die. */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry below current flush dep. height.") + } /* end else */ + } /* end if */ } /* end while loop scanning skip list */ #if H5C_DO_SANITY_CHECKS @@ -7804,45 +7949,52 @@ H5C_flush_invalidate_cache(H5F_t * f, next_entry_ptr = entry_ptr->ht_next; HDassert ( ( next_entry_ptr == NULL ) || ( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC ) ); - if ( entry_ptr->is_protected ) { - /* we have major problems -- but lets flush and destroy - * everything we can before we flag an error. - */ - protected_entries++; - - if ( ! entry_ptr->in_slist ) { + if ( ( ! entry_ptr->flush_me_last ) || + ( ( entry_ptr->flush_me_last ) && + ( cache_ptr->num_last_entries >= + cache_ptr->slist_len ) ) ) { - HDassert( !(entry_ptr->is_dirty) ); - } - } else if ( ! ( entry_ptr->is_pinned ) ) { + if ( entry_ptr->is_protected ) { - /* Test to see if we are can flush the entry now. - * If we can, go ahead and flush. - */ - if(entry_ptr->flush_dep_height == curr_flush_dep_height ){ - status = H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - NULL, - entry_ptr->addr, - (cooked_flags | H5C__FLUSH_INVALIDATE_FLAG), - &first_flush, - TRUE); - if ( status < 0 ) { + /* we have major problems -- but lets flush and destroy + * everything we can before we flag an error. + */ + protected_entries++; - /* This shouldn't happen -- if it does, we are toast so - * just scream and die. - */ + if ( ! entry_ptr->in_slist ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "Entry flush destroy failed.") + HDassert( !(entry_ptr->is_dirty) ); } - flushed_during_dep_loop = TRUE; + } else if ( ! ( entry_ptr->is_pinned ) ) { + + /* Test to see if we are can flush the entry now. + * If we can, go ahead and flush. + */ + if(entry_ptr->flush_dep_height == curr_flush_dep_height ){ + status = H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + NULL, + entry_ptr->addr, + (cooked_flags | H5C__FLUSH_INVALIDATE_FLAG), + &first_flush, + TRUE); + if ( status < 0 ) { + + /* This shouldn't happen -- if it does, we are toast so + * just scream and die. + */ + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Entry flush destroy failed.") + } + flushed_during_dep_loop = TRUE; + } /* end if */ + else if(entry_ptr->flush_dep_height < curr_flush_dep_height) + /* This shouldn't happen -- if it does, just scream and die. */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry below current flush dep. height.") } /* end if */ - else if(entry_ptr->flush_dep_height < curr_flush_dep_height) - /* This shouldn't happen -- if it does, just scream and die. */ - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry below current flush dep. height.") } /* end if */ /* We can't do anything if the entry is pinned. The * hope is that the entry will be unpinned as the diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index 06eeb48..1d3bc60 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -282,6 +282,16 @@ * don't use this at present, I hope that this will allow * some optimizations when I get to it. * + * num_last_entries: The number of entries in the cache that can only be + * flushed after all other entries in the cache have + * been flushed. At this time, this will only ever be + * one entry (the superblock), and the code has been + * protected with HDasserts to enforce this. This restraint + * can certainly be relaxed in the future if the need for + * multiple entries being flushed last arises, though + * explicit tests for that case should be added when said + * HDasserts are removed. + * * With the addition of the fractal heap, the cache must now deal with * the case in which entries may be dirtied, moved, or have their sizes * changed during a flush. To allow sanity checks in this situation, the @@ -878,6 +888,7 @@ struct H5C_t int32_t slist_len; size_t slist_size; H5SL_t * slist_ptr; + int32_t num_last_entries; #if H5C_DO_SANITY_CHECKS int64_t slist_len_increase; int64_t slist_size_increase; @@ -1964,6 +1975,10 @@ if ( (cache_ptr)->index_size != \ } else { \ (cache_ptr)->clean_index_size += (entry_ptr)->size; \ } \ + if ((entry_ptr)->flush_me_last) { \ + (cache_ptr)->num_last_entries++; \ + HDassert((cache_ptr)->num_last_entries == 1); \ + } \ H5C__UPDATE_STATS_FOR_HT_INSERTION(cache_ptr) \ } @@ -1993,6 +2008,10 @@ if ( (cache_ptr)->index_size != \ } else { \ (cache_ptr)->clean_index_size -= (entry_ptr)->size; \ } \ + if ((entry_ptr)->flush_me_last) { \ + (cache_ptr)->num_last_entries--; \ + HDassert((cache_ptr)->num_last_entries == 0); \ + } \ H5C__UPDATE_STATS_FOR_HT_DELETION(cache_ptr) \ } diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 8eb7113..0de9c5b 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -387,6 +387,23 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr, * H5C__FLUSH_MARKED_ENTRIES_FLAG. The flag is reset when * the entry is flushed for whatever reason. * + * flush_me_last: Boolean flag indicating that this entry should not be + * flushed from the cache until all other entries without + * the flush_me_last flag set have been flushed. + * + * flush_me_collectively: Boolean flag indicating that this entry needs + * to be flushed collectively when in a parallel + * situation. + * + * Note: At this time, the flush_me_last and flush_me_collectively + * flags will only be applied to one entry, the superblock, + * and the code utilizing these flags is protected with HDasserts + * to enforce this. This restraint can certainly be relaxed in + * the future if the the need for multiple entries getting flushed + * last or collectively arises, though the code allowing for that + * will need to be expanded and tested appropriately if that + * functionality is desired. + * * clear_on_unprotect: Boolean flag used only in PHDF5. When H5C is used * to implement the metadata cache In the parallel case, only * the cache with mpi rank 0 is allowed to actually write to @@ -594,7 +611,7 @@ typedef struct H5C_cache_entry_t haddr_t addr; size_t size; const H5C_class_t * type; - haddr_t tag; + haddr_t tag; int globality; hbool_t is_dirty; hbool_t dirtied; @@ -604,13 +621,15 @@ typedef struct H5C_cache_entry_t hbool_t is_pinned; hbool_t in_slist; hbool_t flush_marker; + hbool_t flush_me_last; #ifdef H5_HAVE_PARALLEL + hbool_t flush_me_collectively; hbool_t clear_on_unprotect; - hbool_t flush_immediately; + hbool_t flush_immediately; #endif /* H5_HAVE_PARALLEL */ hbool_t flush_in_progress; hbool_t destroy_in_progress; - hbool_t free_file_space_on_destroy; + hbool_t free_file_space_on_destroy; /* fields supporting the 'flush dependency' feature: */ @@ -1059,6 +1078,8 @@ typedef struct H5C_auto_size_ctl_t #define H5C__READ_ONLY_FLAG 0x0200 #define H5C__FREE_FILE_SPACE_FLAG 0x0800 #define H5C__TAKE_OWNERSHIP_FLAG 0x1000 +#define H5C__FLUSH_LAST_FLAG 0x2000 +#define H5C__FLUSH_COLLECTIVELY_FLAG 0x4000 #ifdef H5_HAVE_PARALLEL H5_DLL herr_t H5C_apply_candidate_list(H5F_t * f, diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index 9e79f82..0471ccd 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -4448,7 +4448,9 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) /* * Determine the chunks which need to be filled or removed */ - for(op_dim=0; op_dim<space_ndims; op_dim++) { + HDmemset(min_mod_chunk_off, 0, sizeof(min_mod_chunk_off)); + HDmemset(max_mod_chunk_off, 0, sizeof(max_mod_chunk_off)); + for(op_dim = 0; op_dim < space_ndims; op_dim++) { /* Calculate the largest offset of chunks that might need to be * modified in this dimension */ max_mod_chunk_off[op_dim] = chunk_dim[op_dim] * ((old_dim[op_dim] - 1) diff --git a/src/H5Doh.c b/src/H5Doh.c index 5de3ca8..df4eed2 100644 --- a/src/H5Doh.c +++ b/src/H5Doh.c @@ -459,7 +459,7 @@ done: static herr_t H5O__dset_flush(H5G_loc_t *obj_loc, hid_t dxpl_id) { - H5D_t *dset; /* Dataset opened */ + H5D_t *dset = NULL; /* Dataset opened */ H5O_type_t obj_type; /* Type of object at location */ herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5Eint.c b/src/H5Eint.c index 594a69a..76eaaf5 100644 --- a/src/H5Eint.c +++ b/src/H5Eint.c @@ -264,7 +264,10 @@ H5E_walk1_cb(int n, H5E_error1_t *err_desc, void *client_data) if(cls_ptr->lib_vers) eprint->cls.lib_vers = cls_ptr->lib_vers; - fprintf(stream, "%s-DIAG: Error detected in %s (%s) ", cls_ptr->cls_name, cls_ptr->lib_name, cls_ptr->lib_vers); + fprintf(stream, "%s-DIAG: Error detected in %s (%s) ", + (cls_ptr->cls_name ? cls_ptr->cls_name : "(null)"), + (cls_ptr->lib_name ? cls_ptr->lib_name : "(null)"), + (cls_ptr->lib_vers ? cls_ptr->lib_vers : "(null)")); /* try show the process or thread id in multiple processes cases*/ #ifdef H5_HAVE_PARALLEL @@ -387,7 +390,10 @@ H5E_walk2_cb(unsigned n, const H5E_error2_t *err_desc, void *client_data) if(cls_ptr->lib_vers) eprint->cls.lib_vers = cls_ptr->lib_vers; - fprintf(stream, "%s-DIAG: Error detected in %s (%s) ", cls_ptr->cls_name, cls_ptr->lib_name, cls_ptr->lib_vers); + fprintf(stream, "%s-DIAG: Error detected in %s (%s) ", + (cls_ptr->cls_name ? cls_ptr->cls_name : "(null)"), + (cls_ptr->lib_name ? cls_ptr->lib_name : "(null)"), + (cls_ptr->lib_vers ? cls_ptr->lib_vers : "(null)")); /* try show the process or thread id in multiple processes cases*/ #ifdef H5_HAVE_PARALLEL @@ -1051,13 +1051,15 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush) * Only try to flush the file if it was opened with write access, and if * the caller requested a flush. */ - if((f->shared->flags & H5F_ACC_RDWR) && flush) + if((H5F_ACC_RDWR & H5F_INTENT(f)) && flush) if(H5F_flush(f, dxpl_id, TRUE) < 0) + /* Push error, but keep going*/ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") /* Release the external file cache */ if(f->shared->efc) { if(H5F_efc_destroy(f->shared->efc) < 0) + /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't destroy external file cache") f->shared->efc = NULL; } /* end if */ @@ -1075,6 +1077,14 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush) if(H5MF_close(f, dxpl_id) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info") + + /* Flush the file again (if requested), as shutting down the + * free space manager may dirty some data structures again. + */ + if(flush) + if(H5F_flush(f, dxpl_id, TRUE) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") } /* end if */ /* Unpin the superblock, since we're about to destroy the cache */ diff --git a/src/H5FDcore.c b/src/H5FDcore.c index cc48e51..bb23d2d 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -430,8 +430,9 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL, "maxaddr overflow") HDassert(H5P_DEFAULT != fapl_id); if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") - fa = (H5FD_core_fapl_t *)H5P_get_driver_info(plist); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") + if(NULL == (fa = (H5FD_core_fapl_t *)H5P_get_driver_info(plist))) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info") /* Build the open flags */ o_flags = (H5F_ACC_RDWR & flags) ? O_RDWR : O_RDONLY; @@ -446,6 +447,7 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, /* If the file image exists and this is an open, make sure the file doesn't exist */ HDassert(((file_image_info.buffer != NULL) && (file_image_info.size > 0)) || ((file_image_info.buffer == NULL) && (file_image_info.size == 0))); + HDmemset(&sb, 0, sizeof(sb)); if((file_image_info.buffer != NULL) && !(H5F_ACC_CREAT & flags)) { if(HDopen(name, o_flags, 0666) >= 0) HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file already exists") @@ -465,7 +467,7 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, * store is off is when the backing_store flag is off and H5F_ACC_CREAT is * on. */ else if(fa->backing_store || !(H5F_ACC_CREAT & flags)) { - if(fa && (fd = HDopen(name, o_flags, 0666)) < 0) + if((fd = HDopen(name, o_flags, 0666)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file") if(HDfstat(fd, &sb) < 0) HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, NULL, "unable to fstat file") @@ -482,7 +484,7 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, * default value. But if the file access property list was zero then use * the default value instead. */ - file->increment = (fa && fa->increment>0) ? fa->increment : H5FD_CORE_INCREMENT; + file->increment = (fa->increment>0) ? fa->increment : H5FD_CORE_INCREMENT; /* If save data in backing store. */ file->backing_store = fa->backing_store; diff --git a/src/H5FDmpi.c b/src/H5FDmpi.c index 01c28e6..866a2cf 100644 --- a/src/H5FDmpi.c +++ b/src/H5FDmpi.c @@ -56,12 +56,15 @@ char H5FD_mpi_native_g[] = "native"; int H5FD_mpi_get_rank(const H5FD_t *file) { - const H5FD_class_mpi_t *cls=(const H5FD_class_mpi_t *)(file->cls); + const H5FD_class_mpi_t *cls; + int ret_value; FUNC_ENTER_NOAPI(FAIL) - assert(file && cls); + assert(file); + cls = (const H5FD_class_mpi_t *)(file->cls); + assert(cls); assert(cls->get_rank); /* All MPI drivers must implement this */ /* Dispatch to driver */ @@ -92,12 +95,14 @@ done: int H5FD_mpi_get_size(const H5FD_t *file) { - const H5FD_class_mpi_t *cls=(const H5FD_class_mpi_t *)(file->cls); + const H5FD_class_mpi_t *cls; int ret_value; FUNC_ENTER_NOAPI(FAIL) - assert(file && cls); + assert(file); + cls = (const H5FD_class_mpi_t *)(file->cls); + assert(cls); assert(cls->get_size); /* All MPI drivers must implement this */ /* Dispatch to driver */ @@ -128,12 +133,14 @@ done: MPI_Comm H5FD_mpi_get_comm(const H5FD_t *file) { - const H5FD_class_mpi_t *cls=(const H5FD_class_mpi_t *)(file->cls); + const H5FD_class_mpi_t *cls; MPI_Comm ret_value; FUNC_ENTER_NOAPI(MPI_COMM_NULL) - assert(file && cls); + assert(file); + cls = (const H5FD_class_mpi_t *)(file->cls); + assert(cls); assert(cls->get_comm); /* All MPI drivers must implement this */ /* Dispatch to driver */ diff --git a/src/H5FDmpiposix.c b/src/H5FDmpiposix.c index c91f176..ecf6e0f 100644 --- a/src/H5FDmpiposix.c +++ b/src/H5FDmpiposix.c @@ -89,12 +89,12 @@ typedef struct H5FD_mpiposix_t { MPI_Comm comm; /*communicator */ int mpi_rank; /* This process's rank */ int mpi_size; /* Total number of processes */ - haddr_t eof; /*end-of-file marker */ - haddr_t eoa; /*end-of-address marker */ - haddr_t last_eoa; /* Last known end-of-address marker */ - haddr_t pos; /* Current file I/O position */ - int op; /* Last file I/O operation */ - hsize_t naccess; /* Number of (write) accesses to file */ + haddr_t eof; /*end-of-file marker */ + haddr_t eoa; /*end-of-address marker */ + haddr_t last_eoa; /* Last known end-of-address marker */ + haddr_t pos; /* Current file I/O position */ + int op; /* Last file I/O operation */ + hsize_t naccess; /* Number of (write) accesses to file */ #ifdef H5_HAVE_GPFS size_t blksize; /* Block size of file system */ #endif @@ -233,13 +233,13 @@ static const H5FD_class_mpi_t H5FD_mpiposix_g = { H5FD_mpiposix_set_eoa, /*set_eoa */ H5FD_mpiposix_get_eof, /*get_eof */ H5FD_mpiposix_get_handle, /*get_handle */ - H5FD_mpiposix_read, /*read */ - H5FD_mpiposix_write, /*write */ + H5FD_mpiposix_read, /*read */ + H5FD_mpiposix_write, /*write */ NULL, /*flush */ - H5FD_mpiposix_truncate, /*truncate */ + H5FD_mpiposix_truncate, /*truncate */ NULL, /*lock */ NULL, /*unlock */ - H5FD_FLMAP_SINGLE /*fl_map */ + H5FD_FLMAP_SINGLE /*fl_map */ }, /* End of superclass information */ H5FD_mpiposix_mpi_rank, /*get_rank */ H5FD_mpiposix_mpi_size, /*get_size */ @@ -284,6 +284,50 @@ HDfprintf(stderr, "%s: Deleting free space manager, fs_addr = %a\n", FUNC, fs_ad cache_udata.cls_init_udata = NULL; cache_udata.addr = fs_addr; +#ifdef H5FS_DEBUG +{ + unsigned fspace_status = 0; /* Free space section info's status in the metadata cache */ + + /* Sanity check */ + HDassert(H5F_addr_defined(fs_addr)); + + /* Check the free space section info's status in the metadata cache */ + if(H5AC_get_entry_status(f, fs_addr, &fspace_status) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to check metadata cache status for free space section info") + + HDfprintf(stderr, "%s: fspace_status = %0x: ", FUNC, fspace_status); + if(fspace_status) { + hbool_t printed = FALSE; + + if(fspace_status & H5AC_ES__IN_CACHE) { + HDfprintf(stderr, "H5AC_ES__IN_CACHE"); + printed = TRUE; + } /* end if */ + if(fspace_status & H5AC_ES__IS_DIRTY) { + HDfprintf(stderr, "%sH5AC_ES__IS_DIRTY", (printed ? " | " : "")); + printed = TRUE; + } /* end if */ + if(fspace_status & H5AC_ES__IS_PROTECTED) { + HDfprintf(stderr, "%sH5AC_ES__IS_PROTECTED", (printed ? " | " : "")); + printed = TRUE; + } /* end if */ + if(fspace_status & H5AC_ES__IS_PINNED) { + HDfprintf(stderr, "%sH5AC_ES__IS_PINNED", (printed ? " | " : "")); + printed = TRUE; + } /* end if */ + if(fspace_status & H5AC_ES__IS_FLUSH_DEP_PARENT) { + HDfprintf(stderr, "%sH5AC_ES__IS_FLUSH_DEP_PARENT", (printed ? " | " : "")); + printed = TRUE; + } /* end if */ + if(fspace_status & H5AC_ES__IS_FLUSH_DEP_CHILD) { + HDfprintf(stderr, "%sH5AC_ES__IS_FLUSH_DEP_CHILD", (printed ? " | " : "")); + printed = TRUE; + } /* end if */ + } /* end if */ + HDfprintf(stderr, "\n"); +} +#endif /* H5FS_DEBUG */ + /* Protect the free space header */ if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &cache_udata, H5AC_WRITE))) HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to protect free space header") @@ -324,9 +368,14 @@ HDfprintf(stderr, "%s: Done expunging free space section info from cache\n", FUN #endif /* H5FS_DEBUG */ } /* end if */ else { +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Deleting free space section info from file\n", FUNC); +#endif /* H5FS_DEBUG */ /* Release the space in the file */ - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections") + if(!H5F_IS_TMP_ADDR(f, fspace->sect_addr)) { + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections") + } /* end if */ } /* end else */ } /* end if */ @@ -387,8 +436,14 @@ HDfprintf(stderr, "%s: Real sections to store in file\n", FUNC); HDassert(fspace->sect_size > 0); /* Allocate space for the section info in file */ - if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size))) - HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") + if(H5F_USE_TMP_SPACE(f)) { + if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc_tmp(f, fspace->sect_size))) + HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") + } /* end if */ + else { + if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size))) + HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") + } /* end if */ fspace->alloc_sect_size = (size_t)fspace->sect_size; /* Mark free space header as dirty */ @@ -430,19 +485,9 @@ HDfprintf(stderr, "%s: Section info allocated though\n", FUNC); HDfprintf(stderr, "%s: Section info is for file free space\n", FUNC); #endif /* H5FS_DEBUG */ /* Try to shrink the file or absorb the section info into a block aggregator */ - if((status = H5MF_try_shrink(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size)) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for absorbing section info") - else if(status == FALSE) { - /* Section info can't "go away", but it's free. Allow - * header to record it - */ -#ifdef H5FS_DEBUG -HDfprintf(stderr, "%s: Section info can't 'go away', header will own it\n", FUNC); -#endif /* H5FS_DEBUG */ - } /* end if */ - else { + if(H5F_IS_TMP_ADDR(f, fspace->sect_addr)) { #ifdef H5FS_DEBUG -HDfprintf(stderr, "%s: Section info went 'go away'\n", FUNC); +HDfprintf(stderr, "%s: Section info in temp. address space went 'go away'\n", FUNC); #endif /* H5FS_DEBUG */ /* Reset section info in header */ fspace->sect_addr = HADDR_UNDEF; @@ -451,6 +496,30 @@ HDfprintf(stderr, "%s: Section info went 'go away'\n", FUNC); /* Mark free space header as dirty */ if(H5AC_mark_entry_dirty(fspace) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") + } /* end if */ + else { + if((status = H5MF_try_shrink(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size)) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for absorbing section info") + else if(status == FALSE) { + /* Section info can't "go away", but it's free. Allow + * header to record it + */ +#ifdef H5FS_DEBUG + HDfprintf(stderr, "%s: Section info can't 'go away', header will own it\n", FUNC); +#endif /* H5FS_DEBUG */ + } /* end if */ + else { +#ifdef H5FS_DEBUG + HDfprintf(stderr, "%s: Section info went 'go away'\n", FUNC); +#endif /* H5FS_DEBUG */ + /* Reset section info in header */ + fspace->sect_addr = HADDR_UNDEF; + fspace->alloc_sect_size = 0; + + /* Mark free space header as dirty */ + if(H5AC_mark_entry_dirty(fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") + } /* end else */ } /* end else */ } /* end if */ else { @@ -469,10 +538,12 @@ HDfprintf(stderr, "%s: Section info is NOT for file free space\n", FUNC); HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") /* Free previous serialized sections disk space */ - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_sect_addr, old_alloc_sect_size) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections") - } /* end if */ - } /* end else */ + if(!H5F_IS_TMP_ADDR(f, old_sect_addr)) { + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_sect_addr, old_alloc_sect_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections") + } /* end if */ + } /* end else */ + } /* end if */ /* Destroy section info */ if(H5FS_sinfo_dest(fspace->sinfo) < 0) @@ -802,11 +873,11 @@ H5FS_alloc_sect(H5F_t *f, H5FS_t *fspace, hid_t dxpl_id) HDassert(fspace); if(!H5F_addr_defined(fspace->sect_addr) && fspace->sinfo && fspace->serial_sect_count > 0) { - /* Allocate space for section info from aggregator/vfd */ - /* (The original version called H5MF_alloc(), but that may cause sect_size to change again) */ - if(HADDR_UNDEF == (fspace->sect_addr = H5MF_aggr_vfd_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size))) - HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for section info") - + /* Allocate space for section info from aggregator/vfd (or temp. address space) */ + /* (The original version called H5MF_alloc(), but that may cause sect_size to change again) */ + /* (This routine is only called during file close operations, so don't allocate from temp. address space) */ + if(HADDR_UNDEF == (fspace->sect_addr = H5MF_aggr_vfd_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size))) + HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for section info") fspace->alloc_sect_size = fspace->sect_size; /* Mark free-space header as dirty */ @@ -882,8 +953,10 @@ H5FS_free(H5F_t *f, H5FS_t *fspace, hid_t dxpl_id) fspace->alloc_sect_size = 0; /* Free space for the free-space manager section info */ - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, saved_addr, saved_size) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections") + if(!H5F_IS_TMP_ADDR(f, saved_addr)) { + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, saved_addr, saved_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections") + } /* end if */ /* Mark free-space manager header as dirty */ if(H5FS_dirty(fspace) < 0) @@ -1120,7 +1193,7 @@ herr_t H5FS_assert(const H5FS_t *fspace) { FUNC_ENTER_NOAPI_NOINIT_NOERR -#ifndef QAK +#ifdef QAK HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", "H5FS_assert", fspace->tot_sect_count); #endif /* QAK */ diff --git a/src/H5FScache.c b/src/H5FScache.c index d186404..e441398 100644 --- a/src/H5FScache.c +++ b/src/H5FScache.c @@ -306,7 +306,7 @@ H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5F if(fspace->sinfo->dirty) { if(fspace->serial_sect_count > 0) { /* Check if we need to allocate space for section info */ - if(!H5F_addr_defined(fspace->sect_addr)) { + if(H5F_IS_TMP_ADDR(f, fspace->sect_addr) || !H5F_addr_defined(fspace->sect_addr)) { /* Sanity check */ HDassert(fspace->sect_size > 0); @@ -884,6 +884,32 @@ H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H HDassert((size_t)(p - buf) == sinfo->fspace->sect_size); HDassert(sinfo->fspace->sect_size <= sinfo->fspace->alloc_sect_size); + /* Check for section info at temporary address */ + if(H5F_IS_TMP_ADDR(f, sinfo->fspace->sect_addr)) { + /* Sanity check */ + HDassert(sinfo->fspace->sect_size > 0); + HDassert(H5F_addr_eq(sinfo->fspace->sect_addr, addr)); + + /* Allocate space for the section info in file */ + if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, sinfo->fspace->sect_size))) + HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") + sinfo->fspace->alloc_sect_size = (size_t)sinfo->fspace->sect_size; + + /* Sanity check */ + HDassert(!H5F_addr_eq(sinfo->fspace->sect_addr, addr)); + + /* Let the metadata cache know the section info moved */ + if(H5AC_move_entry(f, H5AC_FSPACE_SINFO, sinfo->fspace->sect_addr, addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move indirect block") + + /* Update the internal address for the section info */ + sinfo->fspace->sect_addr = addr; + + /* Mark free space header as dirty */ + if(H5AC_mark_entry_dirty(sinfo->fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") + } /* end if */ + /* Write buffer to disk */ if(H5F_block_write(f, H5FD_MEM_FSPACE_SINFO, sinfo->fspace->sect_addr, (size_t)sinfo->fspace->sect_size, dxpl_id, buf) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space sections to disk") @@ -936,8 +962,9 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo) /* Release the space on disk */ /* (XXX: Nasty usage of internal DXPL value! -QAK) */ - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, H5AC_dxpl_id, sinfo->cache_info.addr, (hsize_t)sinfo->fspace->alloc_sect_size) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space section info") + if(!H5F_IS_TMP_ADDR(f, sinfo->cache_info.addr)) + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, H5AC_dxpl_id, sinfo->cache_info.addr, (hsize_t)sinfo->fspace->alloc_sect_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space section info") } /* end if */ /* Destroy free space info */ diff --git a/src/H5FSsection.c b/src/H5FSsection.c index 0f126c2..581d3dc 100644 --- a/src/H5FSsection.c +++ b/src/H5FSsection.c @@ -445,8 +445,10 @@ HDfprintf(stderr, "%s: Relinquishing section info ownership\n", FUNC); HDfprintf(stderr, "%s: Freeing section info on disk, old_sect_addr = %a, old_alloc_sect_size = %Hu\n", FUNC, old_sect_addr, old_alloc_sect_size); #endif /* H5FS_SINFO_DEBUG */ /* Release space for section info in file */ - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_sect_addr, old_alloc_sect_size) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections") + if(!H5F_IS_TMP_ADDR(f, old_sect_addr)) { + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_sect_addr, old_alloc_sect_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections") + } /* end if */ } /* end if */ } /* end if */ diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index 8bf4405..8205392 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -516,7 +516,7 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set EOA value for superblock") /* Insert superblock into cache, pinned */ - if(H5AC_insert_entry(f, dxpl_id, H5AC_SUPERBLOCK, (haddr_t)0, sblock, H5AC__PIN_ENTRY_FLAG) < 0) + if(H5AC_insert_entry(f, dxpl_id, H5AC_SUPERBLOCK, (haddr_t)0, sblock, H5AC__PIN_ENTRY_FLAG | H5AC__FLUSH_LAST_FLAG | H5AC__FLUSH_COLLECTIVELY_FLAG) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "can't add superblock to cache") sblock_in_cache = TRUE; diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c index 29139d5..af4e886 100644 --- a/src/H5Fsuper_cache.c +++ b/src/H5Fsuper_cache.c @@ -153,6 +153,12 @@ H5F_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, void *_udata) if(NULL == (sblock = H5FL_CALLOC(H5F_super_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + /* The superblock must be flushed last (and collectively in parallel) */ + sblock->cache_info.flush_me_last = TRUE; +#ifdef H5_HAVE_PARALLEL + sblock->cache_info.flush_me_collectively = TRUE; +#endif + /* Read fixed-size portion of the superblock */ p = sbuf; H5_CHECK_OVERFLOW(fixed_size, size_t, haddr_t); @@ -644,6 +650,15 @@ H5F_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, HDassert(f); HDassert(H5F_addr_eq(addr, 0)); HDassert(sblock); + + /* Assert that the superblock is marked as being flushed last (and + collectively in parallel) */ + /* (We'll rely on the cache to make sure it actually *is* flushed + last (and collectively in parallel), but this check doesn't hurt) */ + HDassert(sblock->cache_info.flush_me_last); +#ifdef H5_HAVE_PARALLEL + HDassert(sblock->cache_info.flush_me_collectively); +#endif if(sblock->cache_info.is_dirty) { uint8_t buf[H5F_MAX_SUPERBLOCK_SIZE + H5F_MAX_DRVINFOBLOCK_SIZE]; /* Superblock & driver info blockencoding buffer */ @@ -683,10 +698,15 @@ H5F_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, *p++ = 0; /*reserved */ } /* end if */ + /* Encode the base address */ H5F_addr_encode(f, &p, sblock->base_addr); + + /* Encode the address of global free-space index */ H5F_addr_encode(f, &p, sblock->ext_addr); rel_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER); H5F_addr_encode(f, &p, (rel_eoa + sblock->base_addr)); + + /* Encode the driver informaton block address */ H5F_addr_encode(f, &p, sblock->driver_addr); /* Encode the root group object entry, including the cached stab info */ @@ -737,9 +757,12 @@ H5F_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, *p++ = (uint8_t)H5F_SIZEOF_SIZE(f); *p++ = sblock->status_flags; - /* Base, superblock extension & end of file addresses */ + /* Encode the base address */ H5F_addr_encode(f, &p, sblock->base_addr); + + /* Encode the address of the superblock extension */ H5F_addr_encode(f, &p, sblock->ext_addr); + rel_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER); H5F_addr_encode(f, &p, (rel_eoa + sblock->base_addr)); @@ -773,13 +796,18 @@ H5F_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, /* Check for newer version of superblock format & superblock extension */ if(sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2 && H5F_addr_defined(sblock->ext_addr)) { + H5O_loc_t ext_loc; /* "Object location" for superblock extension */ + + /* Open the superblock extension's object header */ + if(H5F_super_ext_open(f, sblock->ext_addr, &ext_loc) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, FAIL, "unable to open file's superblock extension") + /* Check for ignoring the driver info for this file */ if(!H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO)) { /* Check for driver info message */ H5_ASSIGN_OVERFLOW(driver_size, H5FD_sb_size(f->shared->lf), hsize_t, size_t); if(driver_size > 0) { H5O_drvinfo_t drvinfo; /* Driver info */ - H5O_loc_t ext_loc; /* "Object location" for superblock extension */ uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Driver info block encoding buffer */ /* Sanity check */ @@ -789,21 +817,19 @@ H5F_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, if(H5FD_sb_encode(f->shared->lf, drvinfo.name, dbuf) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information") - /* Open the superblock extension's object header */ - if(H5F_super_ext_open(f, sblock->ext_addr, &ext_loc) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, FAIL, "unable to open file's superblock extension") - /* Write driver info information to the superblock extension */ drvinfo.len = driver_size; drvinfo.buf = dbuf; if(H5O_msg_write(&ext_loc, H5O_DRVINFO_ID, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &drvinfo, dxpl_id) < 0) HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "unable to update driver info header message") - /* Close the superblock extension object header */ - if(H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close file's superblock extension") } /* end if */ + } /* end if */ + + /* Close the superblock extension object header */ + if(H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close file's superblock extension") } /* end if */ /* Reset the dirty flag. */ diff --git a/src/H5HFsection.c b/src/H5HFsection.c index e9ea7e0..72ea100 100644 --- a/src/H5HFsection.c +++ b/src/H5HFsection.c @@ -2398,7 +2398,10 @@ H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id, HDassert(sect->u.indirect.span_size > 0); /* Reset reference count for indirect section */ + /* (Also reset the direct & indirect row pointers */ sect->u.indirect.rc = 0; + sect->u.indirect.dir_rows = NULL; + sect->u.indirect.indir_ents = NULL; /* Set up direct block information, if necessary */ if(start_row < hdr->man_dtable.max_direct_rows) { @@ -2424,7 +2427,6 @@ H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id, /* No rows of direct blocks covered, reset direct row information */ dir_nrows = 0; sect->u.indirect.dir_nrows = 0; - sect->u.indirect.dir_rows = NULL; } /* end else */ /* Set up indirect block information, if necessary */ @@ -2459,7 +2461,6 @@ H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id, else { /* No indirect block entries covered, reset indirect row information */ sect->u.indirect.indir_nents = 0; - sect->u.indirect.indir_ents = NULL; } /* end else */ /* Set up initial row information */ @@ -2598,6 +2599,13 @@ H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id, (sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows)); done: + if(ret_value < 0) { + if(sect->u.indirect.indir_ents) + H5MM_xfree(sect->u.indirect.indir_ents); + if(sect->u.indirect.dir_rows) + H5MM_xfree(sect->u.indirect.dir_rows); + } /* end if */ + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_sect_indirect_init_rows() */ @@ -136,7 +136,7 @@ H5HG_create(H5F_t *f, hid_t dxpl_id, size_t size) { H5HG_heap_t *heap = NULL; uint8_t *p = NULL; - haddr_t addr; + haddr_t addr = HADDR_UNDEF; size_t n; haddr_t ret_value = HADDR_UNDEF; /* Return value */ @@ -245,6 +245,7 @@ H5MF_alloc_open(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type) */ HDassert(f); HDassert(f->shared); + HDassert(type != H5FD_MEM_NOLIST); HDassert(H5F_addr_defined(f->shared->fs_addr[type])); HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED); @@ -292,6 +293,7 @@ H5MF_alloc_create(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type) */ HDassert(f); HDassert(f->shared); + HDassert(type != H5FD_MEM_NOLIST); HDassert(!H5F_addr_defined(f->shared->fs_addr[type])); HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED); @@ -342,6 +344,7 @@ H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type) */ HDassert(f); HDassert(f->shared); + HDassert(type != H5FD_MEM_NOLIST); /* Check if the free space manager exists already */ if(H5F_addr_defined(f->shared->fs_addr[type])) { @@ -384,6 +387,7 @@ H5MF_alloc_close(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type) */ HDassert(f); HDassert(f->shared); + HDassert(type != H5FD_MEM_NOLIST); HDassert(f->shared->fs_man[type]); HDassert(f->shared->fs_state[type] != H5F_FS_STATE_CLOSED); diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index 1d1aa90..ceb6563 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -1066,11 +1066,15 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, FUNC_ENTER_NOAPI_NOINIT + /* Sanity check */ HDassert(oloc_src); HDassert(oloc_src->file); HDassert(H5F_addr_defined(oloc_src->addr)); HDassert(oloc_dst->file); + /* Intialize copy info before errors can be thrown */ + HDmemset(&cpy_info, 0, sizeof(H5O_copy_t)); + /* Get the copy property list */ if(NULL == (ocpy_plist = (H5P_genplist_t *)H5I_object(ocpypl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") @@ -1088,7 +1092,6 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get callback info") /* Convert copy flags into copy struct */ - HDmemset(&cpy_info, 0, sizeof(H5O_copy_t)); if((cpy_option & H5O_COPY_SHALLOW_HIERARCHY_FLAG) > 0) { cpy_info.copy_shallow = TRUE; cpy_info.max_depth = 1; diff --git a/src/H5Otest.c b/src/H5Otest.c index b526b30..21e4ca8 100644 --- a/src/H5Otest.c +++ b/src/H5Otest.c @@ -520,7 +520,7 @@ H5O_expunge_chunks_test(const H5O_loc_t *loc, hid_t dxpl_id) /* Safety check */ nchunks = oh->nchunks; - HDassert(nchunks < NELMTS(chk_addr)); + HDassert(0 < nchunks && nchunks < NELMTS(chk_addr)); /* Iterate over all the chunks, saving the chunk addresses */ for(u = 0; u < oh->nchunks; u++) diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c index f2af61b..9b5d1b0 100644 --- a/src/H5Pfapl.c +++ b/src/H5Pfapl.c @@ -2494,12 +2494,13 @@ done: herr_t H5P_file_image_info_copy(const char UNUSED *name, size_t UNUSED size, void *value) { - H5FD_file_image_info_t *info; /* Image info struct */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT if(value) { + H5FD_file_image_info_t *info; /* Image info struct */ + info = (H5FD_file_image_info_t *)value; /* verify file image field consistancy */ @@ -2533,16 +2534,17 @@ H5P_file_image_info_copy(const char UNUSED *name, size_t UNUSED size, void *valu else HDmemcpy(info->buffer, old_buffer, info->size); } /* end if */ - } /* end if */ - /* Copy udata if it exists */ - if(info->callbacks.udata) { - void *old_udata = info->callbacks.udata; + /* Copy udata if it exists */ + if(info->callbacks.udata) { + void *old_udata = info->callbacks.udata; + + if(NULL == info->callbacks.udata_copy) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_copy not defined") - if(NULL == info->callbacks.udata_copy) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_copy not defined") + info->callbacks.udata = info->callbacks.udata_copy(old_udata); + } /* end if */ - info->callbacks.udata = info->callbacks.udata_copy(old_udata); } /* end if */ done: @@ -2567,32 +2569,33 @@ done: herr_t H5P_file_image_info_close(const char UNUSED *name, size_t UNUSED size, void *value) { - H5FD_file_image_info_t info; /* Image info struct */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT if(value) { - info = *(H5FD_file_image_info_t *)value; + H5FD_file_image_info_t *info; /* Image info struct */ + + info = (H5FD_file_image_info_t *)value; - if(info.buffer != NULL && info.size > 0) { + if(info->buffer != NULL && info->size > 0) { /* Free buffer */ - if(info.callbacks.image_free) { - if(info.callbacks.image_free(info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, - info.callbacks.udata) < 0) + if(info->callbacks.image_free) { + if(info->callbacks.image_free(info->buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, + info->callbacks.udata) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed") } /* end if */ else - H5MM_xfree(info.buffer); + H5MM_xfree(info->buffer); } /* end if */ - } /* end if */ - /* Free udata if it exists */ - if(info.callbacks.udata) { - if(NULL == info.callbacks.udata_free) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_free not defined") - if(info.callbacks.udata_free(info.callbacks.udata) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed") + /* Free udata if it exists */ + if(info->callbacks.udata) { + if(NULL == info->callbacks.udata_free) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_free not defined") + if(info->callbacks.udata_free(info->callbacks.udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed") + } /* end if */ } /* end if */ done: diff --git a/src/H5Shyper.c b/src/H5Shyper.c index d9b306d..d88ac35 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -2784,7 +2784,7 @@ H5S_hyper_offset(const H5S_t *space, hsize_t *offset) FUNC_ENTER_NOAPI(FAIL) - HDassert(space); + HDassert(space && space->extent.rank>0); HDassert(offset); /* Start at linear offset 0 */ diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 817b2f2..b758a92 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -643,7 +643,7 @@ H5S_point_copy(H5S_t *dst, const H5S_t *src, hbool_t UNUSED share_selection) } /* end while */ done: - if(ret_value < 0) { + if(ret_value < 0 && dst->select.sel_info.pnt_lst) { /* Traverse the (incomplete?) dst list, freeing all memory */ curr = dst->select.sel_info.pnt_lst->head; while(curr) { diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 91aed1e..9a993a5 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -67,7 +67,7 @@ H5S_select_offset(H5S_t *space, const hssize_t *offset) /* Check args */ HDassert(space); - HDassert(space->extent.rank); + HDassert(0 < space->extent.rank && space->extent.rank <= H5S_MAX_RANK); HDassert(offset); /* Copy the offset over */ diff --git a/src/H5Tarray.c b/src/H5Tarray.c index 9986631..c73b934 100644 --- a/src/H5Tarray.c +++ b/src/H5Tarray.c @@ -194,7 +194,8 @@ H5T__array_create(H5T_t *base, unsigned ndims, const hsize_t dim[/* ndims */]) ret_value->shared->type = H5T_ARRAY; /* Copy the base type of the array */ - ret_value->shared->parent = H5T_copy(base, H5T_COPY_ALL); + if(NULL == (ret_value->shared->parent = H5T_copy(base, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to copy base datatype") /* Set the array parameters */ ret_value->shared->u.array.ndims = ndims; diff --git a/src/H5trace.c b/src/H5trace.c index b711f40..b559669 100644 --- a/src/H5trace.c +++ b/src/H5trace.c @@ -212,6 +212,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...) if('[' == *type) { if('a' == type[1]) { asize_idx = (int)HDstrtol(type + 2, &rest, 10); + HDassert(0 <= asize_idx && asize_idx < (int) NELMTS(asize)); HDassert(']'==*rest); type = rest + 1; } else { |