From 097d2de6f8d8790596bbd189a8e01929e353bdd8 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 29 Aug 2015 00:00:07 -0500 Subject: [svn-r27615] Description: Protect dataset that's closing from being flushed again, if it's the last one holding a file open. Tested on: MacOSX/64 10.10.5 (amazon) w/serial & parallel (h5committest forthcoming) --- src/H5Dint.c | 87 ++++++++++++++++++++++++++++++++---------------------------- src/H5Dpkg.h | 1 + 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/H5Dint.c b/src/H5Dint.c index b41e5a8..20817c3 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -1486,7 +1486,7 @@ done: herr_t H5D_close(H5D_t *dataset) { - unsigned free_failed = FALSE; + hbool_t free_failed = FALSE; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1506,16 +1506,18 @@ H5D_close(H5D_t *dataset) if(H5D__flush_real(dataset, H5AC_dxpl_id) < 0) HDONE_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to flush cached dataset info") - /* Free the data sieve buffer, if it's been allocated */ - if(dataset->shared->cache.contig.sieve_buf) { - HDassert(dataset->shared->layout.type != H5D_COMPACT); /* We should never have a sieve buffer for compact storage */ - - dataset->shared->cache.contig.sieve_buf = (unsigned char *)H5FL_BLK_FREE(sieve_buf,dataset->shared->cache.contig.sieve_buf); - } /* end if */ + /* Set a flag to indicate the dataset is closing, before we start freeing things */ + /* (Avoids problems with flushing datasets twice, when one is holding + * the file open and it iterates through dataset to flush them -QAK) + */ + dataset->shared->closing = TRUE; /* Free cached information for each kind of dataset */ switch(dataset->shared->layout.type) { case H5D_CONTIGUOUS: + /* Free the data sieve buffer, if it's been allocated */ + if(dataset->shared->cache.contig.sieve_buf) + dataset->shared->cache.contig.sieve_buf = (unsigned char *)H5FL_BLK_FREE(sieve_buf,dataset->shared->cache.contig.sieve_buf); break; case H5D_CHUNKED: @@ -1562,8 +1564,9 @@ H5D_close(H5D_t *dataset) * Release datatype, dataspace and creation property list -- there isn't * much we can do if one of these fails, so we just continue. */ - free_failed = (unsigned)(H5I_dec_ref(dataset->shared->type_id) < 0 || H5S_close(dataset->shared->space) < 0 || - H5I_dec_ref(dataset->shared->dcpl_id) < 0); + free_failed = (H5I_dec_ref(dataset->shared->type_id) < 0) || + (H5S_close(dataset->shared->space) < 0) || + (H5I_dec_ref(dataset->shared->dcpl_id) < 0); /* Remove the dataset from the list of opened objects in the file */ if(H5FO_top_decr(dataset->oloc.file, dataset->oloc.addr) < 0) @@ -2459,44 +2462,48 @@ H5D__flush_real(H5D_t *dataset, hid_t dxpl_id) /* Check args */ HDassert(dataset); + HDassert(dataset->shared); + + /* Avoid flushing the dataset (again) if it's closing */ + if(!dataset->shared->closing) { + /* Check for metadata changes that will require updating the object's modification time */ + if(dataset->shared->layout_dirty || dataset->shared->space_dirty) { + unsigned update_flags = H5O_UPDATE_TIME; /* Modification time flag */ + + /* Pin the object header */ + if(NULL == (oh = H5O_pin(&dataset->oloc, dxpl_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header") + + /* Update the layout on disk, if it's been changed */ + if(dataset->shared->layout_dirty) { + if(H5D__layout_oh_write(dataset, dxpl_id, oh, update_flags) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update layout/pline/efl info") + dataset->shared->layout_dirty = FALSE; + + /* Reset the "update the modification time" flag, so we only do it once */ + update_flags = 0; + } /* end if */ - /* Check for metadata changes that will require updating the object's modification time */ - if(dataset->shared->layout_dirty || dataset->shared->space_dirty) { - unsigned update_flags = H5O_UPDATE_TIME; /* Modification time flag */ - - /* Pin the object header */ - if(NULL == (oh = H5O_pin(&dataset->oloc, dxpl_id))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header") - - /* Update the layout on disk, if it's been changed */ - if(dataset->shared->layout_dirty) { - if(H5D__layout_oh_write(dataset, dxpl_id, oh, update_flags) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update layout/pline/efl info") - dataset->shared->layout_dirty = FALSE; - - /* Reset the "update the modification time" flag, so we only do it once */ - update_flags = 0; - } /* end if */ + /* Update the dataspace on disk, if it's been changed */ + if(dataset->shared->space_dirty) { + if(H5S_write(dataset->oloc.file, dxpl_id, oh, update_flags, dataset->shared->space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace") + dataset->shared->space_dirty = FALSE; - /* Update the dataspace on disk, if it's been changed */ - if(dataset->shared->space_dirty) { - if(H5S_write(dataset->oloc.file, dxpl_id, oh, update_flags, dataset->shared->space) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace") - dataset->shared->space_dirty = FALSE; + /* Reset the "update the modification time" flag, so we only do it once */ + update_flags = 0; + } /* end if */ - /* Reset the "update the modification time" flag, so we only do it once */ - update_flags = 0; + /* _Somebody_ should have update the modification time! */ + HDassert(update_flags == 0); } /* end if */ - /* _Somebody_ should have update the modification time! */ - HDassert(update_flags == 0); + /* Flush cached raw data for each kind of dataset layout */ + if(dataset->shared->layout.ops->flush && + (dataset->shared->layout.ops->flush)(dataset, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to flush raw data") } /* end if */ - /* Flush cached raw data for each kind of dataset layout */ - if(dataset->shared->layout.ops->flush && - (dataset->shared->layout.ops->flush)(dataset, dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to flush raw data") - done: /* Release pointer to object header */ if(oh != NULL) diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 6e9a6a7..11f8918 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -408,6 +408,7 @@ typedef struct H5D_rdcdc_t { */ typedef struct H5D_shared_t { size_t fo_count; /* Reference count */ + hbool_t closing; /* Flag to indicate dataset is closing */ hid_t type_id; /* ID for dataset's datatype */ H5T_t *type; /* Datatype for this dataset */ H5S_t *space; /* Dataspace of this dataset */ -- cgit v0.12