From 8360fc1b7d7879d6ccbd4525e140bfa6346d64d2 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 14 Jul 2005 21:44:26 -0500 Subject: [svn-r11074] 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 | 26 ++++++-- src/H5G.c | 3 +- src/H5O.c | 20 +++++- test/mount.c | 154 +++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 192 insertions(+), 13 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 5706e91..3f8e6b7 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -72,6 +72,8 @@ Bug Fixes since HDF5-1.6.4 release Library ------- + - More bug fixes on holding open files that are mounted and have + IDs open. QAK - 2005/07/14 - Dataset sieve buffer cache was inadvertantly disabled - re-enable it. QAK - 2005/07/08 - Don't unmount child files until the parent file actually closes. diff --git a/src/H5Fmount.c b/src/H5Fmount.c index 73a450d..5714415 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) @@ -682,6 +688,15 @@ H5F_check_mounts(H5F_t *f) herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_check_mounts, FAIL) +#ifdef QAK +HDfprintf(stderr, "%s: f->name=%s\n", FUNC, f->name); +HDfprintf(stderr, "%s: f->nrefs=%u\n", FUNC, f->nrefs); +HDfprintf(stderr, "%s: f->shared->nrefs=%u\n", FUNC, f->shared->nrefs); +HDfprintf(stderr, "%s: f->mtab.parent=%p\n", FUNC, f->mtab.parent); +HDfprintf(stderr, "%s: f->mtab.nmounts=%u\n", FUNC, f->mtab.nmounts); +HDfprintf(stderr, "%s: f->nopen_objs=%u\n", FUNC, f->nopen_objs); +HDfprintf(stderr, "%s: f->closing=%x\n", FUNC, f->closing); +#endif /* QAK */ /* Only try to close files for files involved in a mounting hierarchy */ if(f->mtab.parent || f->mtab.nmounts) { @@ -703,7 +718,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 ea53380..76c024f 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -2161,7 +2161,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 e4553ed..c721596 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -421,8 +421,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 d4fc819..8df2b21 100644 --- a/test/mount.c +++ b/test/mount.c @@ -1682,7 +1682,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. @@ -1699,14 +1699,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); @@ -1793,6 +1793,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; @@ -1800,12 +1942,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() */ /*------------------------------------------------------------------------- @@ -1850,7 +1993,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