summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--release_docs/RELEASE.txt2
-rw-r--r--src/H5Fmount.c17
-rw-r--r--src/H5G.c3
-rw-r--r--src/H5O.c20
-rw-r--r--test/mount.c154
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.");