From 5e98b5bb36c9e0b1078e56d9b734657fcfe7a03d Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 16 Jul 2005 11:33:15 -0500 Subject: [svn-r11077] Purpose: Bug fix Description: Further progress on fixing file mounting to work properly. Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4 Too minor to require h5committest --- release_docs/RELEASE.txt | 2 + src/H5Fmount.c | 17 ++++-- src/H5G.c | 3 +- src/H5O.c | 20 +++++- test/mount.c | 154 +++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 183 insertions(+), 13 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 0af4f73..b6fea3f 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -305,6 +305,8 @@ Bug Fixes since HDF5-1.6.0 release Library ------- + - More bug fixes on holding open files that are mounted and have + IDs open. QAK - 2005/07/14 - Don't unmount child files until the parent file actually closes. (Previously, if an object is holding open a file, the child files would get unmounted too early). QAK - 2005/07/05 diff --git a/src/H5Fmount.c b/src/H5Fmount.c index 73a450d..c67f40d 100644 --- a/src/H5Fmount.c +++ b/src/H5Fmount.c @@ -78,9 +78,14 @@ H5F_close_mounts(H5F_t *f) /* Unmount all child files */ for (u = 0; u < f->mtab.nmounts; u++) { + /* Detach the child file from the parent file */ f->mtab.child[u].file->mtab.parent = NULL; + + /* Close the internal group maintaining the mount point */ if(H5G_close(f->mtab.child[u].group) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close child group") + + /* Close the child file */ if(H5F_close(f->mtab.child[u].file) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close child file") } /* end if */ @@ -633,13 +638,13 @@ done: static hbool_t H5F_check_mounts_recurse(H5F_t *f) { - hbool_t ret_value; /* Return value */ + hbool_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_check_mounts_recurse) /* Check if this file is closing and if the only objects left open are * the mount points */ - if(f->closing && f->nopen_objs == f->mtab.nmounts) { + if((f->closing || (f->nrefs == 1 && f->mtab.parent)) && f->nopen_objs == f->mtab.nmounts) { unsigned u; /* Iterate over files mounted in this file and check if all can be closed */ @@ -648,9 +653,10 @@ H5F_check_mounts_recurse(H5F_t *f) || !H5F_check_mounts_recurse(f->mtab.child[u].file)) HGOTO_DONE(FALSE) } /* end for */ - } /* end if */ - ret_value = TRUE; + /* Set return value */ + ret_value = TRUE; + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -703,7 +709,8 @@ H5F_check_mounts(H5F_t *f) if(H5F_close_mounts(top) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child file") - H5I_dec_ref(top->closing); + if(H5I_dec_ref(top->closing) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't decrement file closing ID") } /* end if */ } /* end if */ diff --git a/src/H5G.c b/src/H5G.c index 1f8a2ac..ec17d28 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -2257,7 +2257,8 @@ H5G_close(H5G_t *grp) /* Check if this group was the last object holding open a mounted file * hierarchy and close down the file hierarchy if so */ if(grp->shared->fo_count == 1) - H5F_check_mounts(grp->ent.file); + if(H5F_check_mounts(grp->ent.file) < 0) + HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy"); if(H5G_free_ent_name(&(grp->ent))<0) { diff --git a/src/H5O.c b/src/H5O.c index e341335..8dfd922 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -428,8 +428,24 @@ H5O_close(H5G_entry_t *obj_ent) * pending then close the file and remove it from the H5I_FILE_CLOSING ID * group. */ - if (obj_ent->file->mtab.nmounts==obj_ent->file->nopen_objs && obj_ent->file->closing) - H5I_dec_ref(obj_ent->file->closing); + /* Check for just mount points holding file open */ + if(obj_ent->file->mtab.nmounts == obj_ent->file->nopen_objs && obj_ent->file->closing) { + unsigned u; /* Local index variable */ + hbool_t really_close; /* Whether to delay the file close by going to a "closing" state */ + + /* Check for open groups on mount points */ + really_close = TRUE; + for(u = 0; u < obj_ent->file->mtab.nmounts; u++) { + if(H5G_get_shared_count(obj_ent->file->mtab.child[u].group) > 1) { + really_close = FALSE; + break; + } /* end if */ + } /* end for */ + + /* If we really want to close this file now */ + if(really_close) + H5I_dec_ref(obj_ent->file->closing); + } /* end if */ /* Free the ID to name buffers */ H5G_free_ent_name(obj_ent); diff --git a/test/mount.c b/test/mount.c index 71d8c5a..dd798a6 100644 --- a/test/mount.c +++ b/test/mount.c @@ -1680,7 +1680,7 @@ error: /*------------------------------------------------------------------------- - * Function: test_hold_open + * Function: test_hold_open_file * * Purpose: Test that the library correctly holds open files when they * have child files that have not been unmounted. @@ -1697,14 +1697,14 @@ error: *------------------------------------------------------------------------- */ static int -test_hold_open(hid_t fapl) +test_hold_open_file(hid_t fapl) { hid_t fid1 = -1, fid2 = -1; /* File IDs */ hid_t gidA = -1, gidM = -1, gidAM = -1; /* Group IDs */ char filename1[1024], filename2[1024]; /* Name of files to mount */ - TESTING("hold open"); + TESTING("hold open w/file"); h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1); h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2); @@ -1791,6 +1791,148 @@ test_hold_open(hid_t fapl) if(H5Gclose(gidA) < 0) TEST_ERROR + /* Check that all file IDs have been closed */ + if(H5I_nmembers(H5I_FILE) != 0) + TEST_ERROR + + /* Check that all "file closing" IDs have been closed */ + if(H5I_nmembers(H5I_FILE_CLOSING) != 0) + TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gidM); + H5Gclose(gidAM); + H5Gclose(gidA); + H5Fclose(fid2); + H5Fclose(fid1); + } H5E_END_TRY; + return 1; +} /* end test_hold_open_file() */ + + +/*------------------------------------------------------------------------- + * Function: test_hold_open_group + * + * Purpose: Test that the library correctly holds open file mount + * hierarchies when they have objects open. + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Thursday, July 14, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_hold_open_group(hid_t fapl) +{ + hid_t fid1 = -1, fid2 = -1; /* File IDs */ + hid_t gidA = -1, gidM = -1, gidAM = -1, gidAM2 = -1; /* Group IDs */ + char filename1[1024], + filename2[1024]; /* Name of files to mount */ + + TESTING("hold open w/group"); + + h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2); + + /* Create file #1 */ + if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidA) < 0) + TEST_ERROR + + if(H5Fclose(fid1) < 0) + TEST_ERROR + + + /* Create file #2 */ + if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidM = H5Gcreate(fid2, "M", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidM) < 0) + TEST_ERROR + + if(H5Fclose(fid2) < 0) + TEST_ERROR + + + /* Re-open files and mount file #2 in file #1 */ + if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidA = H5Gopen(fid1, "A")) < 0) + TEST_ERROR + + if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + + if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0) + TEST_ERROR + + if((gidAM = H5Gopen(fid1, "A/M")) < 0) + TEST_ERROR + + /* Close file #2 */ + if(H5Fclose(fid2) < 0) + TEST_ERROR + + /* Close group in parent file */ + if(H5Gclose(gidA) < 0) + TEST_ERROR + + /* Keep fid1 & gidAM open, everything else closed */ + + /* Retry to opening group in mounted file */ + /* (Should work because file is still mounted) */ + if((gidAM2 = H5Gopen(fid1, "A/M")) < 0) + TEST_ERROR + + /* Close group in mounted file */ + if(H5Gclose(gidAM2) < 0) + TEST_ERROR + + /* Close original group in mount file */ + if(H5Gclose(gidAM) < 0) + TEST_ERROR + + /* Attempt to open group in mounted file */ + /* (Should work because file is still mounted) */ + if((gidAM2 = H5Gopen(fid1, "/A/M")) < 0) + TEST_ERROR + + /* Close group in mounted file */ + if(H5Gclose(gidAM2) < 0) + TEST_ERROR + + /* Close file #1 */ + /* (should unmount file #2 also) */ + if(H5Fclose(fid1) < 0) + TEST_ERROR + + /* Check that all file IDs have been closed */ + if(H5I_nmembers(H5I_FILE) != 0) + TEST_ERROR + + /* Check that all "file closing" IDs have been closed */ + if(H5I_nmembers(H5I_FILE_CLOSING) != 0) + TEST_ERROR + PASSED(); return 0; @@ -1798,12 +1940,13 @@ error: H5E_BEGIN_TRY { H5Gclose(gidM); H5Gclose(gidAM); + H5Gclose(gidAM2); H5Gclose(gidA); H5Fclose(fid2); H5Fclose(fid1); } H5E_END_TRY; return 1; -} /* end test_hold_open() */ +} /* end test_hold_open_group() */ /*------------------------------------------------------------------------- @@ -1848,7 +1991,8 @@ main(void) nerrors += test_mount_after_close(fapl); nerrors += test_mount_after_unmount(fapl); nerrors += test_missing_unmount(fapl); - nerrors += test_hold_open(fapl); + nerrors += test_hold_open_file(fapl); + nerrors += test_hold_open_group(fapl); if (nerrors) goto error; puts("All mount tests passed."); -- cgit v0.12