diff options
author | Raymond Lu <songyulu@hdfgroup.org> | 2013-04-29 19:23:04 (GMT) |
---|---|---|
committer | Raymond Lu <songyulu@hdfgroup.org> | 2013-04-29 19:23:04 (GMT) |
commit | bada3f7a86cb30b24fad3a24f88114861527ed58 (patch) | |
tree | 3f351f78649e966c2521c606082ad63e860e81c1 /src | |
parent | 029e143471397de6ddc204be0c21f0c04ee5f2e2 (diff) | |
download | hdf5-bada3f7a86cb30b24fad3a24f88114861527ed58.zip hdf5-bada3f7a86cb30b24fad3a24f88114861527ed58.tar.gz hdf5-bada3f7a86cb30b24fad3a24f88114861527ed58.tar.bz2 |
[svn-r23656] Issue 8380 H5Zunregister caused seg fault: I added some protection measures:
1. If any opened object uses the filter, let it fail.
2. Flush all opened files to push any cached data to files.
Tested with h5committest.
Diffstat (limited to 'src')
-rw-r--r-- | src/H5D.c | 47 | ||||
-rw-r--r-- | src/H5Dprivate.h | 1 | ||||
-rw-r--r-- | src/H5G.c | 46 | ||||
-rw-r--r-- | src/H5Gprivate.h | 1 | ||||
-rw-r--r-- | src/H5I.c | 42 | ||||
-rw-r--r-- | src/H5Iprivate.h | 1 | ||||
-rw-r--r-- | src/H5Pocpl.c | 37 | ||||
-rw-r--r-- | src/H5Pprivate.h | 1 | ||||
-rw-r--r-- | src/H5Z.c | 163 | ||||
-rw-r--r-- | src/H5Zprivate.h | 1 |
10 files changed, 319 insertions, 21 deletions
@@ -572,19 +572,56 @@ done: hid_t H5Dget_create_plist(hid_t dset_id) { - H5D_t *dset; /* Dataset structure */ + H5D_t *dataset; /* Dataset structure */ H5P_genplist_t *dcpl_plist; /* Dataset's DCPL */ H5P_genplist_t *new_plist; /* Copy of dataset's DCPL */ H5O_fill_t copied_fill; /* Fill value to tweak */ hid_t new_dcpl_id = FAIL; - hid_t ret_value; /* Return value */ + hid_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE1("i", "i", dset_id); /* Check args */ - if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) + if(NULL == (dataset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + + if((ret_value = H5D_get_create_plist(dataset)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dget_create_plist() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_get_create_plist + * + * Purpose: Private function for H5Dget_create_plist + * + * Return: Success: ID for a copy of the dataset creation + * property list. The template should be + * released by calling H5P_close(). + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, February 3, 1998 + * + *------------------------------------------------------------------------- + */ +hid_t +H5D_get_create_plist(H5D_t *dset) +{ + H5P_genplist_t *dcpl_plist; /* Dataset's DCPL */ + H5P_genplist_t *new_plist; /* Copy of dataset's DCPL */ + H5O_fill_t copied_fill; /* Fill value to tweak */ + hid_t new_dcpl_id = FAIL; + hid_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Check args */ if(NULL == (dcpl_plist = (H5P_genplist_t *)H5I_object(dset->shared->dcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") @@ -670,8 +707,8 @@ done: if(H5I_dec_app_ref(new_dcpl_id) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object") - FUNC_LEAVE_API(ret_value) -} /* end H5Dget_create_plist() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_get_create_plist() */ /*------------------------------------------------------------------------- diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index 1e2b91d..7adc231 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -162,6 +162,7 @@ H5_DLL H5O_loc_t *H5D_oloc(H5D_t *dataset); H5_DLL H5G_name_t *H5D_nameof(H5D_t *dataset); H5_DLL H5T_t *H5D_typeof(const H5D_t *dset); H5_DLL herr_t H5D_flush(const H5F_t *f, hid_t dxpl_id); +H5_DLL hid_t H5D_get_create_plist(H5D_t *dset); /* Functions that operate on vlen data */ H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id, @@ -499,7 +499,7 @@ H5Gget_create_plist(hid_t group_id) htri_t ginfo_exists; htri_t linfo_exists; htri_t pline_exists; - H5G_t *grp = NULL; + H5G_t *group = NULL; H5P_genplist_t *gcpl_plist; H5P_genplist_t *new_plist; hid_t new_gcpl_id = FAIL; @@ -509,9 +509,47 @@ H5Gget_create_plist(hid_t group_id) H5TRACE1("i", "i", group_id); /* Check args */ - if(NULL == (grp = (H5G_t *)H5I_object_verify(group_id, H5I_GROUP))) + if(NULL == (group = (H5G_t *)H5I_object_verify(group_id, H5I_GROUP))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + if((ret_value = H5G_get_create_plist(group)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_create_plist() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_get_create_plist + * + * Purpose: Private function for H5Gget_create_plist + * + * Return: Success: ID for a copy of the group creation + * property list. The property list ID should be + * released by calling H5Pclose(). + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Tuesday, October 25, 2005 + * + *------------------------------------------------------------------------- + */ +hid_t +H5G_get_create_plist(H5G_t *grp) +{ + H5O_linfo_t linfo; /* Link info message */ + htri_t ginfo_exists; + htri_t linfo_exists; + htri_t pline_exists; + H5P_genplist_t *gcpl_plist; + H5P_genplist_t *new_plist; + hid_t new_gcpl_id = FAIL; + hid_t ret_value = FAIL; + + FUNC_ENTER_NOAPI(FAIL) + /* Copy the default group creation property list */ if(NULL == (gcpl_plist = (H5P_genplist_t *)H5I_object(H5P_LST_GROUP_CREATE_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get default group creation property list") @@ -573,8 +611,8 @@ done: HDONE_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "can't free") } /* end if */ - FUNC_LEAVE_API(ret_value) -} /* end H5Gget_create_plist() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_get_create_plist() */ /*------------------------------------------------------------------------- diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index f765b52..50f8bda 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -243,6 +243,7 @@ H5_DLL herr_t H5G_obj_remove_by_idx(const struct H5O_loc_t *grp_oloc, H5RS_str_t H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t dxpl_id); H5_DLL herr_t H5G_obj_lookup_by_idx(const struct H5O_loc_t *grp_oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, struct H5O_link_t *lnk, hid_t dxpl_id); +H5_DLL hid_t H5G_get_create_plist(H5G_t *grp); /* * These functions operate on symbol table nodes. @@ -2002,21 +2002,55 @@ H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key) if(H5I_IS_LIB_TYPE(type)) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type") + if((ret_value = H5I_search(type, func, key)) == NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Isearch() */ + + +/*------------------------------------------------------------------------- + * Function: H5I_search + * + * Purpose: Private function for H5Isearch + * + * Return: Success: The first object in the type for which FUNC + * returns non-zero. NULL if FUNC returned zero + * for every object in the type. + * + * Failure: NULL + * + * Programmer: James Laird + * Nathaniel Furrer + * Friday, April 23, 2004 + * + *------------------------------------------------------------------------- + */ +void * +H5I_search(H5I_type_t _type, H5I_search_func_t _func, void *_key) +{ + H5I_search_ud_t udata; /* Context for iteration */ + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(NULL) + /* Set up udata struct */ - udata.app_cb = func; - udata.app_key = key; + udata.app_cb = _func; + udata.app_key = _key; udata.ret_obj = NULL; /* Note that H5I_iterate returns an error code. We ignore it * here, as we can't do anything with it without revising the API. */ - H5I_iterate(type, H5I_search_cb, &udata, TRUE); + if(H5I_iterate(_type, H5I_search_cb, &udata, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type") /* Set return value */ ret_value = udata.ret_obj; done: - FUNC_LEAVE_API(ret_value) + FUNC_LEAVE_NOAPI(ret_value) } /* end H5Isearch() */ diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index ff1463d..28b6327 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -78,6 +78,7 @@ H5_DLL H5I_type_t H5I_get_type(hid_t id); H5_DLL hid_t H5I_get_file_id(hid_t obj_id, hbool_t app_ref); H5_DLL void *H5I_remove(hid_t id); H5_DLL void *H5I_remove_verify(hid_t id, H5I_type_t id_type); +H5_DLL void *H5I_search(H5I_type_t _type, H5I_search_func_t _func, void *_key); H5_DLL herr_t H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref); H5_DLL int H5I_get_ref(hid_t id, hbool_t app_ref); H5_DLL int H5I_inc_ref(hid_t id, hbool_t app_ref); diff --git a/src/H5Pocpl.c b/src/H5Pocpl.c index 880b46a..f80e4e7 100644 --- a/src/H5Pocpl.c +++ b/src/H5Pocpl.c @@ -1177,6 +1177,43 @@ done: /*------------------------------------------------------------------------- + * Function: H5P_filter_in_pline + * + * Purpose: Check whether the filter is in the pipeline of the object + * creation property list. + * + * Return: TRUE: found + * FALSE: not found + * FAIL: error + * + * Programmer: Raymond Lu + * 26 April 2013 + * + *------------------------------------------------------------------------- + */ +htri_t +H5P_filter_in_pline(H5P_genplist_t *plist, H5Z_filter_t id) +{ + H5O_pline_t pline; /* Filter pipeline */ + H5Z_filter_info_t *filter; /* Pointer to filter information */ + htri_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Get pipeline info */ + if(H5P_get(plist, H5O_CRT_PIPELINE_NAME, &pline) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get pipeline") + + /* Check if the file is in the pipeline */ + if((ret_value = H5Z_filter_in_pline(&pline, id)) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTCOMPARE, FAIL, "can't find filter") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_get_filter_by_id() */ + + +/*------------------------------------------------------------------------- * Function: H5Premove_filter * * Purpose: Deletes a filter from the dataset creation property list; diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h index 6560064..083619b 100644 --- a/src/H5Pprivate.h +++ b/src/H5Pprivate.h @@ -108,6 +108,7 @@ H5_DLL herr_t H5P_modify_filter(H5P_genplist_t *plist, H5Z_filter_t filter, H5_DLL herr_t H5P_get_filter_by_id(H5P_genplist_t *plist, H5Z_filter_t id, unsigned int *flags, size_t *cd_nelmts, unsigned cd_values[], size_t namelen, char name[], unsigned *filter_config); +H5_DLL htri_t H5P_filter_in_pline(H5P_genplist_t *plist, H5Z_filter_t id); /* *SPECIAL* Don't make more of these! -QAK */ H5_DLL htri_t H5P_isa_class(hid_t plist_id, hid_t pclass_id); @@ -22,6 +22,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Dprivate.h" /* Dataset functions */ #include "H5Eprivate.h" /* Error handling */ +#include "H5Fprivate.h" /* File */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Oprivate.h" /* Object headers */ @@ -51,6 +52,9 @@ typedef enum { H5Z_PRELUDE_SET_LOCAL /* Call "set local" callback */ } H5Z_prelude_type_t; +/* Maximal number of the list of opened objects (2^16) */ +#define NUM_OBJS 65536 + /* Local variables */ static size_t H5Z_table_alloc_g = 0; static size_t H5Z_table_used_g = 0; @@ -403,33 +407,133 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Z_unregister (H5Z_filter_t id) +H5Z_unregister (H5Z_filter_t filter_id) { - size_t i; /* Local index variable */ + hid_t *file_list = NULL; + hid_t *obj_id_list = NULL; + size_t num_obj_id = 0; + size_t num_file_id = 0; + H5F_t *f = NULL; /* File to query */ + H5I_type_t id_type; + hid_t ocpl_id; + H5P_genplist_t *plist; /* Property list */ + size_t filter_index; /* Local index variable for filter */ + int i; + htri_t filter_in_pline = FALSE; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - assert (id>=0 && id<=H5Z_FILTER_MAX); + assert (filter_id>=0 && filter_id<=H5Z_FILTER_MAX); /* Is the filter already registered? */ - for (i=0; i<H5Z_table_used_g; i++) - if (H5Z_table_g[i].id==id) + for (filter_index=0; filter_index<H5Z_table_used_g; filter_index++) + if (H5Z_table_g[filter_index].id==filter_id) break; /* Fail if filter not found */ - if (i>=H5Z_table_used_g) + if (filter_index>=H5Z_table_used_g) HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, FAIL, "filter is not registered") + /* Count the number of opened datasets and groups among all opened files */ + if(H5F_get_obj_count(NULL, H5F_OBJ_DATASET | H5F_OBJ_GROUP, FALSE, &num_obj_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get object number") + + if(num_obj_id) { + if(NULL == (obj_id_list = (hid_t *)H5MM_malloc(num_obj_id*sizeof(hid_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "failed to allocate space") + + /* Find all opened objects that may use the filter (datasets and groups). Passing NULL as a pointer to + * file structure indicates searching among all opened files */ + if(H5F_get_obj_ids(NULL, H5F_OBJ_DATASET | H5F_OBJ_GROUP, num_obj_id, obj_id_list, FALSE, &num_obj_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get object IDs") + } + + /* Check if any opened object (dataset or group) uses the filter. If so, fail with a message */ + for(i=0; i<num_obj_id; i++) { + if((id_type = H5I_get_type(obj_id_list[i])) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "bad object id"); + + switch(id_type) { + case H5I_GROUP: + { + H5G_t *group = NULL; + + if(NULL == (group = (H5G_t *)H5I_object_verify(obj_id_list[i], H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + + if((ocpl_id = H5G_get_create_plist(group)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get group creation property list") + + } + break; + + case H5I_DATASET: + { + H5D_t *dataset = NULL; + + if(NULL == (dataset = (H5D_t *)H5I_object_verify(obj_id_list[i], H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + + if((ocpl_id = H5D_get_create_plist(dataset)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get dataset creation property list") + } + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object") + } /* end switch */ + + /* Get the plist structure of object creation */ + if(NULL == (plist = H5P_object_verify(ocpl_id, H5P_OBJECT_CREATE))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Check if the object creation property list uses the filter */ + if((filter_in_pline = H5P_filter_in_pline(plist, filter_id)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't check filter in pipeline") + + if(filter_in_pline) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't unregister filter because some object is still using it") + } + + /* Count the number of opened files */ + if(H5F_get_obj_count(NULL, H5F_OBJ_FILE, FALSE, &num_file_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file number") + + /* Get the list of IDs for all opened files */ + if(num_file_id) { + if(NULL == (file_list = (hid_t *)H5MM_malloc(num_file_id*sizeof(hid_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "failed to allocate space") + + if(H5F_get_obj_ids(NULL, H5F_OBJ_FILE, num_file_id, file_list, FALSE, &num_file_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file IDs") + } + + /* Flush all opened files in case any file uses the filter */ + for(i=0; i<num_file_id; i++) { + if(NULL == (f = (H5F_t *)H5I_object_verify(file_list[i], H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") + + /* Call the flush routine for mounted file hierarchies. Do a global flush + * if the file is opened for write */ + if(H5F_ACC_RDWR & H5F_INTENT(f)) { + if(H5F_flush_mounts(f, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file hierarchy") + } /* end if */ + } + /* Remove filter from table */ /* Don't worry about shrinking table size (for now) */ - HDmemmove(&H5Z_table_g[i],&H5Z_table_g[i+1],sizeof(H5Z_class2_t)*((H5Z_table_used_g-1)-i)); + HDmemmove(&H5Z_table_g[filter_index],&H5Z_table_g[filter_index+1],sizeof(H5Z_class2_t)*((H5Z_table_used_g-1)-filter_index)); #ifdef H5Z_DEBUG - HDmemmove(&H5Z_stat_table_g[i],&H5Z_stat_table_g[i+1],sizeof(H5Z_stats_t)*((H5Z_table_used_g-1)-i)); + HDmemmove(&H5Z_stat_table_g[filter_index],&H5Z_stat_table_g[filter_index+1],sizeof(H5Z_stats_t)*((H5Z_table_used_g-1)-filter_index)); #endif /* H5Z_DEBUG */ H5Z_table_used_g--; done: + if(file_list) H5MM_free(file_list); + if(obj_id_list) H5MM_free(obj_id_list); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5Z_unregister() */ @@ -1275,6 +1379,49 @@ done: /*------------------------------------------------------------------------- + * Function: H5Z_filter_in_pline + * + * Purpose: Check wheter a filter is in the filter pipeline using the + * filter ID. This function is very similar to H5Z_filter_info + * + * Return: TRUE - found filter + * FALSE - not found + * FAIL - error + * + * Programmer: Raymond Lu + * 26 April 2013 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5Z_filter_in_pline(const H5O_pline_t *pline, H5Z_filter_t filter) +{ + size_t idx; /* Index of filter in pipeline */ + htri_t ret_value = TRUE; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + assert(pline); + assert(filter>=0 && filter<=H5Z_FILTER_MAX); + + /* Locate the filter in the pipeline */ + for(idx=0; idx<pline->nused; idx++) + if(pline->filter[idx].id==filter) + break; + + /* Check if the filter was not already in the pipeline */ + if(idx>=pline->nused) + ret_value = FALSE; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Z_filter_in_pline() */ + + + +/*------------------------------------------------------------------------- * Function: H5Z_all_filters_avail * * Purpose: Verify that all the filters in a pipeline are currently diff --git a/src/H5Zprivate.h b/src/H5Zprivate.h index f53b50c..6c0a46f 100644 --- a/src/H5Zprivate.h +++ b/src/H5Zprivate.h @@ -91,6 +91,7 @@ H5_DLL herr_t H5Z_can_apply_direct(const struct H5O_pline_t *pline); H5_DLL herr_t H5Z_set_local_direct(const struct H5O_pline_t *pline); H5_DLL H5Z_filter_info_t *H5Z_filter_info(const struct H5O_pline_t *pline, H5Z_filter_t filter); +H5_DLL htri_t H5Z_filter_in_pline(const struct H5O_pline_t *pline, H5Z_filter_t filter); H5_DLL htri_t H5Z_all_filters_avail(const struct H5O_pline_t *pline); H5_DLL htri_t H5Z_filter_avail(H5Z_filter_t id); H5_DLL herr_t H5Z_delete(struct H5O_pline_t *pline, H5Z_filter_t filter); |