From 46f7aa75fd09b5a61ea62e917634abe45ec41476 Mon Sep 17 00:00:00 2001 From: jhendersonHDF Date: Thu, 22 Feb 2024 14:52:36 -0600 Subject: Fix H5F_get_access_plist to copy file locking settings (#4030) H5F_get_access_plist previously did not copy over the file locking settings from a file into the new File Access Property List that it creates. This would make it difficult to match the file locking settings between an external file and its parent file. --- release_docs/RELEASE.txt | 27 +++++++ src/H5Fint.c | 103 +++++++++++++++++-------- src/H5Fpkg.h | 27 ++++--- src/H5Ftest.c | 2 +- src/H5Pfapl.c | 4 +- test/links.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 313 insertions(+), 46 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index bc4ff92..4d1aabb 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -481,6 +481,33 @@ Bug Fixes since HDF5-1.14.0 release =================================== Library ------- + - Fixed H5Fget_access_plist so that it returns the file locking + settings for a file + + When H5Fget_access_plist (and the internal H5F_get_access_plist) + is called on a file, the returned File Access Property List has + the library's default file locking settings rather than any + settings set for the file. This causes two problems: + + - Opening an HDF5 file through an external link using H5Gopen, + H5Dopen, etc. with H5P_DEFAULT for the Dataset/Group/etc. + Access Property List will cause the external file to be opened + with the library's default file locking settings rather than + inheriting them from the parent file. This can be surprising + when a file is opened with file locking disabled, but its + external files are opened with file locking enabled. + + - An application cannot make use of the H5Pset_elink_fapl + function to match file locking settings between an external + file and its parent file without knowing the correct setting + ahead of time, as calling H5Fget_access_plist on the parent + file will not return the correct settings. + + This has been fixed by copying a file's file locking settings + into the newly-created File Access Property List in H5F_get_access_plist. + + This fix partially addresses GitHub issue #4011 + - Memory usage growth issue Starting with the HDF5 1.12.1 release, an issue (GitHub issue #1256) diff --git a/src/H5Fint.c b/src/H5Fint.c index 1feada6..7b5aeb4 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -79,7 +79,8 @@ static int H5F__get_objects_cb(void *obj_ptr, hid_t obj_id, void *key); static herr_t H5F__build_name(const char *prefix, const char *file_name, char **full_name /*out*/); static char *H5F__getenv_prefix_name(char **env_prefix /*in,out*/); static H5F_t *H5F__new(H5F_shared_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf); -static herr_t H5F__check_if_using_file_locks(H5P_genplist_t *fapl, bool *use_file_locking); +static herr_t H5F__check_if_using_file_locks(H5P_genplist_t *fapl, bool *use_file_locking, + bool *ignore_disabled_locks); static herr_t H5F__dest(H5F_t *f, bool flush, bool free_on_failure); static herr_t H5F__build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name, char ** /*out*/ actual_name); @@ -94,7 +95,8 @@ static herr_t H5F__flush_phase2(H5F_t *f, bool closing); * true/false have obvious meanings. FAIL means the environment variable was * not set, so the code should ignore it and use the fapl value instead. */ -htri_t use_locks_env_g = FAIL; +htri_t use_locks_env_g = FAIL; +htri_t ignore_disabled_locks_g = FAIL; /*****************************/ /* Library Private Variables */ @@ -140,7 +142,7 @@ H5F_init(void) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to initialize interface"); /* Check the file locking environment variable */ - if (H5F__parse_file_lock_env_var(&use_locks_env_g) < 0) + if (H5F__parse_file_lock_env_var(&use_locks_env_g, &ignore_disabled_locks_g) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to parse file locking environment variable"); done: @@ -237,7 +239,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5F__parse_file_lock_env_var(htri_t *use_locks) +H5F__parse_file_lock_env_var(htri_t *use_locks, htri_t *ignore_disabled_locks) { char *lock_env_var = NULL; /* Environment variable pointer */ @@ -245,13 +247,23 @@ H5F__parse_file_lock_env_var(htri_t *use_locks) /* Check the file locking environment variable */ lock_env_var = getenv(HDF5_USE_FILE_LOCKING); - if (lock_env_var && (!strcmp(lock_env_var, "FALSE") || !strcmp(lock_env_var, "0"))) - *use_locks = false; /* Override: Never use locks */ - else if (lock_env_var && (!strcmp(lock_env_var, "TRUE") || !strcmp(lock_env_var, "BEST_EFFORT") || - !strcmp(lock_env_var, "1"))) - *use_locks = true; /* Override: Always use locks */ - else - *use_locks = FAIL; /* Environment variable not set, or not set correctly */ + if (lock_env_var && (!strcmp(lock_env_var, "FALSE") || !strcmp(lock_env_var, "0"))) { + *use_locks = false; /* Override: Never use locks */ + *ignore_disabled_locks = FAIL; + } + else if (lock_env_var && !strcmp(lock_env_var, "BEST_EFFORT")) { + *use_locks = true; /* Override: Always use locks */ + *ignore_disabled_locks = true; /* Override: Ignore disabled locks */ + } + else if (lock_env_var && (!strcmp(lock_env_var, "TRUE") || !strcmp(lock_env_var, "1"))) { + *use_locks = true; /* Override: Always use locks */ + *ignore_disabled_locks = false; /* Override: Don't ignore disabled locks */ + } + else { + /* Environment variable not set, or not set correctly */ + *use_locks = FAIL; + *ignore_disabled_locks = FAIL; + } FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5F__parse_file_lock_env_var() */ @@ -374,8 +386,13 @@ H5F_get_access_plist(H5F_t *f, bool app_ref) if (H5P_set(new_plist, H5F_ACS_LIBVER_HIGH_BOUND_NAME, &f->shared->high_bound) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set 'high' bound for library format versions"); + if (H5P_set(new_plist, H5F_ACS_USE_FILE_LOCKING_NAME, &f->shared->use_file_locking) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set file locking property"); + if (H5P_set(new_plist, H5F_ACS_IGNORE_DISABLED_FILE_LOCKS_NAME, &f->shared->ignore_disabled_locks) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, + "can't set 'ignore disabled file locks' property"); if (H5P_set(new_plist, H5F_ACS_METADATA_READ_ATTEMPTS_NAME, &(f->shared->read_attempts)) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set 'read attempts ' flag"); + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set 'read attempts' flag"); if (H5P_set(new_plist, H5F_ACS_OBJECT_FLUSH_CB_NAME, &(f->shared->object_flush)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set object flush callback"); @@ -1644,7 +1661,9 @@ H5F__dest(H5F_t *f, bool flush, bool free_on_failure) /*------------------------------------------------------------------------- * Function: H5F__check_if_using_file_locks * - * Purpose: Determines if this file will use file locks. + * Purpose: Determines if this file will use file locks and whether or + * not to ignore the case where file locking is disabled on + * the file system. * * There are three ways that file locking can be controlled: * @@ -1665,22 +1684,35 @@ H5F__dest(H5F_t *f, bool flush, bool free_on_failure) *------------------------------------------------------------------------- */ static herr_t -H5F__check_if_using_file_locks(H5P_genplist_t *fapl, bool *use_file_locking) +H5F__check_if_using_file_locks(H5P_genplist_t *fapl, bool *use_file_locking, bool *ignore_disabled_locks) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE - /* Make sure the out parameter has a value */ - *use_file_locking = true; + /* Make sure the out parameters have a value */ + *use_file_locking = true; + *ignore_disabled_locks = false; - /* Check the fapl property */ - if (H5P_get(fapl, H5F_ACS_USE_FILE_LOCKING_NAME, use_file_locking) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get use file locking flag"); + /* Check file locking environment variable first */ + if (use_locks_env_g != FAIL) { + *use_file_locking = (use_locks_env_g == true); + } + else { + /* Check the file locking fapl property */ + if (H5P_get(fapl, H5F_ACS_USE_FILE_LOCKING_NAME, use_file_locking) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get use file locking flag"); + } - /* Check the environment variable */ - if (use_locks_env_g != FAIL) - *use_file_locking = (use_locks_env_g == true) ? true : false; + /* Check "ignore disabled file locks" environment variable first */ + if (ignore_disabled_locks_g != FAIL) { + *ignore_disabled_locks = (ignore_disabled_locks_g == true); + } + else { + /* Check the "ignore disabled file locks" fapl property */ + if (H5P_get(fapl, H5F_ACS_IGNORE_DISABLED_FILE_LOCKS_NAME, ignore_disabled_locks) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get ignore disabled file locks property"); + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -1775,10 +1807,11 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) bool set_flag = false; /*set the status_flags in the superblock */ bool clear = false; /*clear the status_flags */ bool evict_on_close; /* evict on close value from plist */ - bool use_file_locking = true; /* Using file locks? */ - bool ci_load = false; /* whether MDC ci load requested */ - bool ci_write = false; /* whether MDC CI write requested */ - H5F_t *ret_value = NULL; /*actual return value */ + bool use_file_locking = true; /* Using file locks? */ + bool ignore_disabled_locks = false; /* Ignore disabled file locks? */ + bool ci_load = false; /* whether MDC ci load requested */ + bool ci_write = false; /* whether MDC CI write requested */ + H5F_t *ret_value = NULL; /*actual return value */ FUNC_ENTER_NOAPI(NULL) @@ -1798,8 +1831,8 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list"); /* Check if we are using file locking */ - if (H5F__check_if_using_file_locks(a_plist, &use_file_locking) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to get file locking flag"); + if (H5F__check_if_using_file_locks(a_plist, &use_file_locking, &ignore_disabled_locks) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to get file locking flags"); /* * Opening a file is a two step process. First we try to open the @@ -1951,14 +1984,20 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) shared = file->shared; lf = shared->lf; - /* Set the file locking flag. If the file is already open, the file + /* Set the file locking flags. If the file is already open, the file * requested file locking flag must match that of the open file. */ - if (shared->nrefs == 1) - file->shared->use_file_locking = use_file_locking; - else if (shared->nrefs > 1) + if (shared->nrefs == 1) { + file->shared->use_file_locking = use_file_locking; + file->shared->ignore_disabled_locks = ignore_disabled_locks; + } + else if (shared->nrefs > 1) { if (file->shared->use_file_locking != use_file_locking) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file locking flag values don't match"); + if (file->shared->use_file_locking && (file->shared->ignore_disabled_locks != ignore_disabled_locks)) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, + "file locking 'ignore disabled locks' flag values don't match"); + } /* Check if page buffering is enabled */ if (H5P_get(a_plist, H5F_ACS_PAGE_BUFFER_SIZE_NAME, &page_buf_size) < 0) diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index bc5c90b..60de31e 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -293,16 +293,17 @@ struct H5F_shared_t { hsize_t threshold; /* Threshold for alignment */ hsize_t alignment; /* Alignment */ unsigned gc_ref; /* Garbage-collect references? */ - H5F_libver_t low_bound; /* The 'low' bound of library format versions */ - H5F_libver_t high_bound; /* The 'high' bound of library format versions */ - bool store_msg_crt_idx; /* Store creation index for object header messages? */ - unsigned ncwfs; /* Num entries on cwfs list */ - struct H5HG_heap_t **cwfs; /* Global heap cache */ - struct H5G_t *root_grp; /* Open root group */ - H5FO_t *open_objs; /* Open objects in file */ - H5UC_t *grp_btree_shared; /* Ref-counted group B-tree node info */ - bool use_file_locking; /* Whether or not to use file locking */ - bool closing; /* File is in the process of being closed */ + H5F_libver_t low_bound; /* The 'low' bound of library format versions */ + H5F_libver_t high_bound; /* The 'high' bound of library format versions */ + bool store_msg_crt_idx; /* Store creation index for object header messages? */ + unsigned ncwfs; /* Num entries on cwfs list */ + struct H5HG_heap_t **cwfs; /* Global heap cache */ + struct H5G_t *root_grp; /* Open root group */ + H5FO_t *open_objs; /* Open objects in file */ + H5UC_t *grp_btree_shared; /* Ref-counted group B-tree node info */ + bool use_file_locking; /* Whether or not to use file locking */ + bool ignore_disabled_locks; /* Whether or not to ignore disabled file locking */ + bool closing; /* File is in the process of being closed */ /* Cached VOL connector ID & info */ hid_t vol_id; /* ID of VOL connector for the container */ @@ -391,9 +392,11 @@ H5FL_EXTERN(H5F_t); H5FL_EXTERN(H5F_shared_t); /* Whether or not to use file locking (based on the environment variable) - * FAIL means ignore the environment variable. + * and whether or not to ignore disabled file locking. FAIL means ignore + * the environment variable. */ H5_DLLVAR htri_t use_locks_env_g; +H5_DLLVAR htri_t ignore_disabled_locks_g; /******************************/ /* Package Private Prototypes */ @@ -411,7 +414,7 @@ H5_DLL herr_t H5F__start_swmr_write(H5F_t *f); H5_DLL herr_t H5F__close(H5F_t *f); H5_DLL herr_t H5F__set_libver_bounds(H5F_t *f, H5F_libver_t low, H5F_libver_t high); H5_DLL herr_t H5F__get_cont_info(const H5F_t *f, H5VL_file_cont_info_t *info); -H5_DLL herr_t H5F__parse_file_lock_env_var(htri_t *use_locks); +H5_DLL herr_t H5F__parse_file_lock_env_var(htri_t *use_locks, htri_t *ignore_disabled_locks); H5_DLL herr_t H5F__delete(const char *filename, hid_t fapl_id); /* File mount related routines */ diff --git a/src/H5Ftest.c b/src/H5Ftest.c index 081fbda..7e34e0a 100644 --- a/src/H5Ftest.c +++ b/src/H5Ftest.c @@ -258,7 +258,7 @@ H5F__reparse_file_lock_variable_test(void) FUNC_ENTER_PACKAGE /* Check the file locking environment variable */ - if (H5F__parse_file_lock_env_var(&use_locks_env_g) < 0) + if (H5F__parse_file_lock_env_var(&use_locks_env_g, &ignore_disabled_locks_g) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to parse file locking environment variable"); done: diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c index e7c1fb3..e9496bf 100644 --- a/src/H5Pfapl.c +++ b/src/H5Pfapl.c @@ -4978,7 +4978,9 @@ H5Pget_file_locking(hid_t fapl_id, hbool_t *use_file_locking /*out*/, hbool_t *i H5TRACE3("e", "ixx", fapl_id, use_file_locking, ignore_when_disabled); /* Make sure this is a fapl */ - if (true != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) + if (H5P_DEFAULT == fapl_id) + fapl_id = H5P_FILE_ACCESS_DEFAULT; + else if (true != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "property list is not an access plist"); /* Get the plist structure */ diff --git a/test/links.c b/test/links.c index e068d71..827f1da 100644 --- a/test/links.c +++ b/test/links.c @@ -100,6 +100,8 @@ static const char *FILENAME[] = {"links0", TMPDIR "extlinks21D", /* 49: */ TMPDIR "extlinks21E", /* 50: */ "extlinks21E", /* 51: (same as #50, only without the TMPDIR prefix) */ + "extlinks22", /* 52: */ + "extlinks22A", /* 53: */ NULL}; #define FAMILY_SIZE 1024 @@ -9821,6 +9823,199 @@ error: } /* end external_set_elink_acc_flags() */ /*------------------------------------------------------------------------- + * Function: external_link_inherit_locking + * + * Purpose: Test that opening a file through an external link using a + * default FAPL will cause that file to inherit the parent + * file's file locking settings. + * + * Return: Success: 0 + * Failure: 1 + * + *------------------------------------------------------------------------- + */ +static int +external_link_inherit_locking(hid_t fapl_id, bool new_format) +{ + hid_t fid = H5I_INVALID_HID; + hid_t tmp_fid = H5I_INVALID_HID; + hid_t gid = H5I_INVALID_HID; + hid_t ext_fid = H5I_INVALID_HID; + hid_t file_fapl = H5I_INVALID_HID; + hid_t tmp_fapl = H5I_INVALID_HID; + bool use_locking = true; + bool ignore_disabled_locking = false; + char *filename = NULL; + char *ext_filename = NULL; + + if (new_format) + TESTING("inheriting of file locking settings (w/new group format)"); + else + TESTING("inheriting of file locking settings"); + + if (HDsetenv(HDF5_USE_FILE_LOCKING, "", 1) < 0) + TEST_ERROR; + + /* Check that external links are registered with the library */ + if (H5Lis_registered(H5L_TYPE_EXTERNAL) != true) + TEST_ERROR; + + if (NULL == (filename = malloc(NAME_BUF_SIZE))) + TEST_ERROR; + if (NULL == (ext_filename = malloc(NAME_BUF_SIZE))) + TEST_ERROR; + + if ((file_fapl = H5Pcopy(fapl_id)) < 0) + TEST_ERROR; + + /* Create external file */ + h5_fixname(FILENAME[53], file_fapl, ext_filename, NAME_BUF_SIZE); + if ((ext_fid = H5Fcreate(ext_filename, H5F_ACC_TRUNC, H5P_DEFAULT, file_fapl)) < 0) + TEST_ERROR; + if (H5Fclose(ext_fid) < 0) + TEST_ERROR; + + /* Create main file and link to external file */ + h5_fixname(FILENAME[52], file_fapl, filename, NAME_BUF_SIZE); + if ((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, file_fapl)) < 0) + TEST_ERROR; + if (H5Lcreate_external(ext_filename, "/", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) + TEST_ERROR; + if (H5Fclose(fid) < 0) + TEST_ERROR; + + /* Set file locking on */ + if (H5Pset_file_locking(file_fapl, true, true) < 0) + TEST_ERROR; + + /* Open main file */ + if ((fid = H5Fopen(filename, H5F_ACC_RDWR, file_fapl)) < 0) + TEST_ERROR; + + /* Make sure that locking setting retrieved from access plist + * matches what we set. + */ + if ((tmp_fapl = H5Fget_access_plist(fid)) < 0) + TEST_ERROR; + if (H5Pget_file_locking(tmp_fapl, &use_locking, &ignore_disabled_locking) < 0) + TEST_ERROR; + if (use_locking != true || ignore_disabled_locking != true) + TEST_ERROR; + if (H5Pclose(tmp_fapl) < 0) + TEST_ERROR; + + /* Open external file through link */ + if ((gid = H5Gopen2(fid, "ext_link", H5P_DEFAULT)) < 0) + TEST_ERROR; + + /* Get file ID for external file */ + if ((tmp_fid = H5Iget_file_id(gid)) < 0) + TEST_ERROR; + + /* Make sure that locking setting retrieved from external file's + * access plist matches what we set. + */ + if ((tmp_fapl = H5Fget_access_plist(tmp_fid)) < 0) + TEST_ERROR; + if (H5Pget_file_locking(tmp_fapl, &use_locking, &ignore_disabled_locking) < 0) + TEST_ERROR; + if (use_locking != true || ignore_disabled_locking != true) + TEST_ERROR; + if (H5Pclose(tmp_fapl) < 0) + TEST_ERROR; + + if (H5Gclose(gid) < 0) + TEST_ERROR; + if (H5Fclose(tmp_fid) < 0) + TEST_ERROR; + if (H5Fclose(fid) < 0) + TEST_ERROR; + + /* Repeat with file locking off */ + + /* Set file locking off */ + if (H5Pset_file_locking(file_fapl, false, false) < 0) + TEST_ERROR; + + /* Open main file */ + if ((fid = H5Fopen(filename, H5F_ACC_RDWR, file_fapl)) < 0) + TEST_ERROR; + + /* Make sure that locking setting retrieved from access plist + * matches what we set. + */ + if ((tmp_fapl = H5Fget_access_plist(fid)) < 0) + TEST_ERROR; + if (H5Pget_file_locking(tmp_fapl, &use_locking, &ignore_disabled_locking) < 0) + TEST_ERROR; + if (use_locking != false || ignore_disabled_locking != false) + TEST_ERROR; + if (H5Pclose(tmp_fapl) < 0) + TEST_ERROR; + + /* Open external file through link */ + if ((gid = H5Gopen2(fid, "ext_link", H5P_DEFAULT)) < 0) + TEST_ERROR; + + /* Get file ID for external file */ + if ((tmp_fid = H5Iget_file_id(gid)) < 0) + TEST_ERROR; + + /* Make sure that locking setting retrieved from external file's + * access plist matches what we set. + */ + if ((tmp_fapl = H5Fget_access_plist(tmp_fid)) < 0) + TEST_ERROR; + if (H5Pget_file_locking(tmp_fapl, &use_locking, &ignore_disabled_locking) < 0) + TEST_ERROR; + if (use_locking != false || ignore_disabled_locking != false) + TEST_ERROR; + if (H5Pclose(tmp_fapl) < 0) + TEST_ERROR; + + if (H5Gclose(gid) < 0) + TEST_ERROR; + if (H5Fclose(tmp_fid) < 0) + TEST_ERROR; + if (H5Fclose(fid) < 0) + TEST_ERROR; + + if (H5Fdelete(ext_filename, file_fapl) < 0) + TEST_ERROR; + if (H5Fdelete(filename, file_fapl) < 0) + TEST_ERROR; + + if (H5Pclose(file_fapl) < 0) + TEST_ERROR; + + free(ext_filename); + ext_filename = NULL; + free(filename); + filename = NULL; + + PASSED(); + + return SUCCEED; + +error: + H5E_BEGIN_TRY + { + H5Pclose(tmp_fapl); + H5Pclose(file_fapl); + H5Fclose(ext_fid); + H5Gclose(gid); + H5Fclose(tmp_fid); + H5Fclose(fid); + } + H5E_END_TRY + + free(ext_filename); + free(filename); + + return FAIL; +} + +/*------------------------------------------------------------------------- * Function: external_set_elink_cb * * Purpose: Verify functionality of H5P_set/get_elink_cb @@ -23034,6 +23229,7 @@ main(void) nerrors += external_set_elink_fapl2(my_fapl, new_format) < 0 ? 1 : 0; nerrors += external_set_elink_fapl3(new_format) < 0 ? 1 : 0; + nerrors += external_link_inherit_locking(my_fapl, new_format) < 0 ? 1 : 0; nerrors += external_set_elink_cb(my_fapl, new_format) < 0 ? 1 : 0; #ifdef H5_HAVE_WINDOW_PATH nerrors += external_link_win1(my_fapl, new_format) < 0 ? 1 : 0; -- cgit v0.12