summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--release_docs/RELEASE.txt6
-rw-r--r--src/H5F.c18
-rw-r--r--src/H5Fmount.c146
-rw-r--r--src/H5Fpkg.h37
-rw-r--r--src/H5G.c4
-rw-r--r--src/H5Gname.c12
-rw-r--r--src/H5Gtraverse.c40
-rw-r--r--src/H5O.c2
-rw-r--r--test/mount.c299
9 files changed, 426 insertions, 138 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 0b28276..c434ef5 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -99,6 +99,12 @@ Bug Fixes since HDF5-1.8.1
Library
-------
+ - Fixed an issue where mount point traversal would fail when using
+ multiple handles for the child. (NAF - 2008/08/07)
+ - Fixed an issue where mount points were inaccessible when using multiple
+ file handles for the parent. The mount table is now in the shared
+ file structure (the parent pointer is still in the top structure).
+ (NAF - 2008/08/07)
- Fixed issue where a group could have a file mounted on it twice.
(QAK - 2008/07/15)
- when an attribute was opened twice and data was written with one of the handles,
diff --git a/src/H5F.c b/src/H5F.c
index 80c28bc..a5427db 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1058,6 +1058,10 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file")
+ /* Free mount table */
+ f->shared->mtab.child = H5MM_xfree(f->shared->mtab.child);
+ f->shared->mtab.nalloc = 0;
+
/* Destroy shared file struct */
f->shared = H5FL_FREE(H5F_file_t,f->shared);
@@ -1072,8 +1076,6 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
/* Free the non-shared part of the file */
f->name = H5MM_xfree(f->name);
f->extpath = H5MM_xfree(f->extpath);
- f->mtab.child = H5MM_xfree(f->mtab.child);
- f->mtab.nalloc = 0;
if(H5FO_top_dest(f) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file")
f->shared = NULL;
@@ -1701,14 +1703,14 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags)
/* Flush other files, depending on scope */
if(H5F_SCOPE_GLOBAL == scope) {
- while(f->mtab.parent)
- f = f->mtab.parent;
+ while(f->parent)
+ f = f->parent;
scope = H5F_SCOPE_DOWN;
} /* end while */
if(H5F_SCOPE_DOWN == scope)
- for(i = 0; i < f->mtab.nmounts; i++)
- if(H5F_flush(f->mtab.child[i].file, dxpl_id, scope, flags) < 0)
+ for(i = 0; i < f->shared->mtab.nmounts; i++)
+ if(H5F_flush(f->shared->mtab.child[i].file, dxpl_id, scope, flags) < 0)
nerrors++;
/* Flush any cached dataset storage raw data */
@@ -1938,8 +1940,8 @@ H5F_try_close(H5F_t *f)
/* Check if this is a child file in a mounting hierarchy & proceed up the
* hierarchy if so.
*/
- if(f->mtab.parent)
- if(H5F_try_close(f->mtab.parent) < 0)
+ if(f->parent)
+ if(H5F_try_close(f->parent) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close parent file")
/* Unmount and close each child before closing the current file. */
diff --git a/src/H5Fmount.c b/src/H5Fmount.c
index c96c920..b922446 100644
--- a/src/H5Fmount.c
+++ b/src/H5Fmount.c
@@ -80,19 +80,23 @@ H5F_close_mounts(H5F_t *f)
HDassert(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)
+ for (u = 0; u < f->shared->mtab.nmounts; u++) {
+ /* Only unmount children mounted to this top level file structure */
+ if(f->shared->mtab.child[u].file->parent == f) {
+ /* Detach the child file from the parent file */
+ f->shared->mtab.child[u].file->parent = NULL;
+
+ /* Close the internal group maintaining the mount point */
+ if(H5G_close(f->shared->mtab.child[u].group) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close child group")
- /* Close the child file */
- if(H5F_try_close(f->mtab.child[u].file) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close child file")
+ /* Close the child file */
+ if(H5F_try_close(f->shared->mtab.child[u].file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close child file")
+ }
} /* end if */
- f->mtab.nmounts = 0;
+ f->shared->mtab.nmounts -= f->nmounts;
+ f->nmounts = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -146,7 +150,7 @@ H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child,
* the parent & child files have the same file close degree, and
* that the mount wouldn't introduce a cycle in the mount tree.
*/
- if(child->mtab.parent)
+ if(child->parent)
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "file is already mounted")
if(H5G_loc_find(loc, name, &mp_loc/*out*/, H5P_DEFAULT, dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found")
@@ -175,8 +179,8 @@ H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child,
HDassert(mp_loc.oloc);
mp_loc.path = H5G_nameof(mount_point);
HDassert(mp_loc.path);
- for(ancestor = parent; ancestor; ancestor = ancestor->mtab.parent) {
- if(ancestor == child)
+ for(ancestor = parent; ancestor; ancestor = ancestor->parent) {
+ if(ancestor->shared == child->shared)
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount would introduce a cycle")
} /* end for */
@@ -190,13 +194,13 @@ H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child,
* `md' will be the index where the child should be inserted.
*/
lt = md = 0;
- rt = parent->mtab.nmounts;
+ rt = parent->shared->mtab.nmounts;
cmp = -1;
while(lt < rt && cmp) {
H5O_loc_t *oloc; /*temporary symbol table entry */
md = (lt + rt) / 2;
- oloc = H5G_oloc(parent->mtab.child[md].group);
+ oloc = H5G_oloc(parent->shared->mtab.child[md].group);
cmp = H5F_addr_cmp(mp_loc.oloc->addr, oloc->addr);
if(cmp < 0)
rt = md;
@@ -209,26 +213,27 @@ H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child,
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point is already in use")
/* Make room in the table */
- if(parent->mtab.nmounts >= parent->mtab.nalloc) {
- unsigned n = MAX(16, 2 * parent->mtab.nalloc);
- H5F_mount_t *x = H5MM_realloc(parent->mtab.child,
- n * sizeof(parent->mtab.child[0]));
+ if(parent->shared->mtab.nmounts >= parent->shared->mtab.nalloc) {
+ unsigned n = MAX(16, 2 * parent->shared->mtab.nalloc);
+ H5F_mount_t *x = H5MM_realloc(parent->shared->mtab.child,
+ n * sizeof(parent->shared->mtab.child[0]));
if(!x)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for mount table")
- parent->mtab.child = x;
- parent->mtab.nalloc = n;
+ parent->shared->mtab.child = x;
+ parent->shared->mtab.nalloc = n;
} /* end if */
/* Insert into table */
- HDmemmove(parent->mtab.child + md + 1, parent->mtab.child + md,
- (parent->mtab.nmounts-md) * sizeof(parent->mtab.child[0]));
- parent->mtab.nmounts++;
- parent->mtab.child[md].group = mount_point;
- parent->mtab.child[md].file = child;
- child->mtab.parent = parent;
+ HDmemmove(parent->shared->mtab.child + md + 1, parent->shared->mtab.child + md,
+ (parent->shared->mtab.nmounts-md) * sizeof(parent->shared->mtab.child[0]));
+ parent->shared->mtab.nmounts++;
+ parent->nmounts++;
+ parent->shared->mtab.child[md].group = mount_point;
+ parent->shared->mtab.child[md].file = child;
+ child->parent = parent;
/* Set the group's mountpoint flag */
- if(H5G_mount(parent->mtab.child[md].group) < 0)
+ if(H5G_mount(parent->shared->mtab.child[md].group) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to set group mounted flag")
/* Get the group location for the root group in the file to unmount */
@@ -315,16 +320,16 @@ H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id)
mnt_oloc = H5G_oloc(child->shared->root_grp);
child_idx = -1;
- if(child->mtab.parent && H5F_addr_eq(mp_oloc.addr, mnt_oloc->addr)) {
+ if(child->parent && H5F_addr_eq(mp_oloc.addr, mnt_oloc->addr)) {
unsigned u; /*counters */
/*
* We've been given the root group of the child. We do a reverse
* lookup in the parent's mount table to find the correct entry.
*/
- parent = child->mtab.parent;
- for(u = 0; u < parent->mtab.nmounts; u++) {
- if(parent->mtab.child[u].file == child) {
+ parent = child->parent;
+ for(u = 0; u < parent->shared->mtab.nmounts; u++) {
+ if(parent->shared->mtab.child[u].file->shared == child->shared) {
/* Found the correct index */
child_idx = u;
break;
@@ -340,11 +345,11 @@ H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id)
*/
parent = child; /*we guessed wrong*/
lt = 0;
- rt = parent->mtab.nmounts;
+ rt = parent->shared->mtab.nmounts;
cmp = -1;
while(lt < rt && cmp) {
md = (lt + rt) / 2;
- mnt_oloc = H5G_oloc(parent->mtab.child[md].group);
+ mnt_oloc = H5G_oloc(parent->shared->mtab.child[md].group);
cmp = H5F_addr_cmp(mp_oloc.addr, mnt_oloc->addr);
if (cmp<0)
rt = md;
@@ -359,13 +364,17 @@ H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id)
H5G_loc_free(&mp_loc);
mp_loc_setup = FALSE;
mp_loc.oloc = mnt_oloc;
- mp_loc.path = H5G_nameof(parent->mtab.child[md].group);
- child = parent->mtab.child[child_idx].file;
+ mp_loc.path = H5G_nameof(parent->shared->mtab.child[md].group);
+ child = parent->shared->mtab.child[child_idx].file;
+
+ /* Set the parent to be the actual parent of the discovered child.
+ * Could be different due to the shared mount table. */
+ parent = child->parent;
} /* end else */
HDassert(child_idx >= 0);
/* Save the information about the child from the mount table */
- child_group = parent->mtab.child[child_idx].group;
+ child_group = parent->shared->mtab.child[child_idx].group;
/* Get the group location for the root group in the file to unmount */
if(NULL == (root_loc.oloc = H5G_oloc(child->shared->root_grp)))
@@ -380,9 +389,10 @@ H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name")
/* Eliminate the mount point from the table */
- HDmemmove(parent->mtab.child + child_idx, parent->mtab.child + child_idx + 1,
- (parent->mtab.nmounts-child_idx) * sizeof(parent->mtab.child[0]));
- parent->mtab.nmounts -= 1;
+ HDmemmove(parent->shared->mtab.child + child_idx, parent->shared->mtab.child + child_idx + 1,
+ (parent->shared->mtab.nmounts-child_idx) * sizeof(parent->shared->mtab.child[0]));
+ parent->shared->mtab.nmounts -= 1;
+ parent->nmounts -= 1;
/* Unmount the child file from the parent file */
if(H5G_unmount(child_group) < 0)
@@ -391,7 +401,7 @@ H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group")
/* Detach child file from parent & see if it should close */
- child->mtab.parent = NULL;
+ child->parent = NULL;
if(H5F_try_close(child) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file")
@@ -405,37 +415,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_has_mount
- *
- * Purpose: Check if a file has mounted files within it.
- *
- * Return: Success: TRUE/FALSE
- * Failure: (can't happen)
- *
- * Programmer: Quincey Koziol
- * Thursday, January 2, 2002
- *
- *-------------------------------------------------------------------------
- */
-hbool_t
-H5F_has_mount(const H5F_t *file)
-{
- hbool_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_has_mount)
-
- HDassert(file);
-
- if(file->mtab.nmounts > 0)
- ret_value = TRUE;
- else
- ret_value = FALSE;
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_has_mount() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5F_is_mount
*
* Purpose: Check if a file is mounted within another file.
@@ -457,7 +436,7 @@ H5F_is_mount(const H5F_t *file)
HDassert(file);
- if(file->mtab.parent != NULL)
+ if(file->parent != NULL)
ret_value = TRUE;
else
ret_value = FALSE;
@@ -587,15 +566,18 @@ H5F_mount_count_ids_recurse(H5F_t *f, unsigned *nopen_files, unsigned *nopen_obj
* (Reduced by number of mounted files, we'll add back in the mount point's
* groups later, if they are open)
*/
- *nopen_objs += (f->nopen_objs - f->mtab.nmounts);
+ *nopen_objs += (f->nopen_objs - f->nmounts);
/* Iterate over files mounted in this file and add in their open ID counts also */
- for(u = 0; u < f->mtab.nmounts; u++) {
- /* Increment the open object count if the mount point group has an open ID */
- if(H5G_get_shared_count(f->mtab.child[u].group) > 1)
- *nopen_objs += 1;
-
- H5F_mount_count_ids_recurse(f->mtab.child[u].file, nopen_files, nopen_objs);
+ for(u = 0; u < f->shared->mtab.nmounts; u++) {
+ /* Only recurse on children mounted to this top level file structure */
+ if(f->shared->mtab.child[u].file->parent == f) {
+ /* Increment the open object count if the mount point group has an open ID */
+ if(H5G_get_shared_count(f->shared->mtab.child[u].group) > 1)
+ *nopen_objs += 1;
+
+ H5F_mount_count_ids_recurse(f->shared->mtab.child[u].file, nopen_files, nopen_objs);
+ }
} /* end for */
FUNC_LEAVE_NOAPI_VOID
@@ -627,8 +609,8 @@ H5F_mount_count_ids(H5F_t *f, unsigned *nopen_files, unsigned *nopen_objs)
HDassert(nopen_objs);
/* Find the top file in the mounting hierarchy */
- while(f->mtab.parent)
- f = f->mtab.parent;
+ while(f->parent)
+ f = f->parent;
/* Count open IDs in the hierarchy */
H5F_mount_count_ids_recurse(f, nopen_files, nopen_objs);
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 288ef8a..594ed50 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -62,6 +62,22 @@
/* Mask for removing private file access flags */
#define H5F_ACC_PUBLIC_FLAGS 0x00ffu
+/* A record of the mount table */
+typedef struct H5F_mount_t {
+ struct H5G_t *group; /* Mount point group held open */
+ struct H5F_t *file; /* File mounted at that point */
+} H5F_mount_t;
+
+/*
+ * The mount table describes what files are attached to (mounted on) the file
+ * to which this table belongs.
+ */
+typedef struct H5F_mtab_t {
+ unsigned nmounts;/* Number of children which are mounted */
+ unsigned nalloc; /* Number of mount slots allocated */
+ H5F_mount_t *child; /* An array of mount records */
+} H5F_mtab_t;
+
/*
* Define the structure to store the file information for HDF5 files. One of
* these structures is allocated per file, not per H5Fopen(). That is, set of
@@ -74,6 +90,7 @@ typedef struct H5F_file_t {
unsigned nrefs; /* Ref count for times file is opened */
uint8_t status_flags; /* File status flags */
unsigned flags; /* Access Permissions for file */
+ H5F_mtab_t mtab; /* File mount table */
/* Cached values from FCPL/superblock */
unsigned sym_leaf_k; /* Size of leaves in symbol tables */
@@ -114,23 +131,6 @@ typedef struct H5F_file_t {
H5RC_t *grp_btree_shared; /* Ref-counted group B-tree node info */
} H5F_file_t;
-/* A record of the mount table */
-typedef struct H5F_mount_t {
- struct H5G_t *group; /* Mount point group held open */
- struct H5F_t *file; /* File mounted at that point */
-} H5F_mount_t;
-
-/*
- * The mount table describes what files are attached to (mounted on) the file
- * to which this table belongs.
- */
-typedef struct H5F_mtab_t {
- struct H5F_t *parent;/* Parent file */
- unsigned nmounts;/* Number of children which are mounted */
- unsigned nalloc; /* Number of mount slots allocated */
- H5F_mount_t *child; /* An array of mount records */
-} H5F_mtab_t;
-
/*
* This is the top-level file descriptor. One of these structures is
* allocated every time H5Fopen() is called although they may contain pointers
@@ -148,7 +148,8 @@ struct H5F_t {
H5FO_t *obj_count; /* # of time each object is opened through top file structure */
hid_t file_id; /* ID of this file */
hbool_t closing; /* File is in the process of being closed */
- H5F_mtab_t mtab; /* File mount table */
+ struct H5F_t *parent; /* Parent file that this file is mounted to */
+ unsigned nmounts; /* Number of children mounted to this file */
};
/*****************************/
diff --git a/src/H5G.c b/src/H5G.c
index e04402e..3a57fa7 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -1360,8 +1360,8 @@ H5G_rootof(H5F_t *f)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_rootof)
- while(f->mtab.parent)
- f = f->mtab.parent;
+ while(f->parent)
+ f = f->parent;
FUNC_LEAVE_NOAPI(f->shared->root_grp)
} /* end H5G_rootof() */
diff --git a/src/H5Gname.c b/src/H5Gname.c
index 1efb91e..072673a 100644
--- a/src/H5Gname.c
+++ b/src/H5Gname.c
@@ -700,19 +700,19 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key)
HGOTO_DONE(SUCCEED) /* No need to look at object, it's path is already invalid */
/* Find the top file in object's mount hier. */
- if(oloc->file->mtab.parent) {
+ if(oloc->file->parent) {
/* Check if object is in child file (for mount & unmount operations) */
if(names->dst_file && oloc->file->shared == names->dst_file->shared)
obj_in_child = TRUE;
/* Find the "top" file in the chain of mounted files */
- top_obj_file = oloc->file->mtab.parent;
- while(top_obj_file->mtab.parent != NULL) {
+ top_obj_file = oloc->file->parent;
+ while(top_obj_file->parent != NULL) {
/* Check if object is in child mount hier. (for mount & unmount operations) */
if(names->dst_file && top_obj_file->shared == names->dst_file->shared)
obj_in_child = TRUE;
- top_obj_file = top_obj_file->mtab.parent;
+ top_obj_file = top_obj_file->parent;
} /* end while */
} /* end if */
else
@@ -997,8 +997,8 @@ H5G_name_replace(const H5O_link_t *lnk, H5G_names_op_t op, H5F_t *src_file,
H5G_names_t names; /* Structure to hold operation information for callback */
/* Find top file in src location's mount hierarchy */
- while(src_file->mtab.parent)
- src_file = src_file->mtab.parent;
+ while(src_file->parent)
+ src_file = src_file->parent;
/* Set up common information for callback */
names.src_file = src_file;
diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c
index 4fc345c..dcc77c2 100644
--- a/src/H5Gtraverse.c
+++ b/src/H5Gtraverse.c
@@ -384,7 +384,8 @@ done:
static herr_t
H5G_traverse_mount(H5G_loc_t *obj_loc/*in,out*/)
{
- H5F_t *parent = obj_loc->oloc->file; /* File of object */
+ H5F_t *parent = obj_loc->oloc->file, /* File of object */
+ *child = NULL; /* Child file */
unsigned lt, rt, md = 0; /* Binary search indices */
int cmp;
H5O_loc_t *oloc = NULL; /* Object location for mount points */
@@ -405,11 +406,11 @@ H5G_traverse_mount(H5G_loc_t *obj_loc/*in,out*/)
* table for the parent
*/
lt = 0;
- rt = parent->mtab.nmounts;
+ rt = parent->shared->mtab.nmounts;
cmp = -1;
while(lt < rt && cmp) {
md = (lt + rt) / 2;
- oloc = H5G_oloc(parent->mtab.child[md].group);
+ oloc = H5G_oloc(parent->shared->mtab.child[md].group);
cmp = H5F_addr_cmp(obj_loc->oloc->addr, oloc->addr);
if(cmp < 0)
rt = md;
@@ -418,17 +419,28 @@ H5G_traverse_mount(H5G_loc_t *obj_loc/*in,out*/)
} /* end while */
/* Copy root info over to ENT */
- if(0 == cmp) {
- /* Get the location for the root group in the child's file */
- oloc = H5G_oloc(parent->mtab.child[md].file->shared->root_grp);
-
- /* Copy the entry for the root group */
- if(H5O_loc_copy(obj_loc->oloc, oloc, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object location")
-
- /* Switch to child's file */
- parent = oloc->file;
- } /* end if */
+ if(0 == cmp) {
+ /* Get the child file */
+ child = parent->shared->mtab.child[md].file;
+
+ /* Get the location for the root group in the child's file */
+ oloc = H5G_oloc(child->shared->root_grp);
+
+ /* Release the mount point */
+ if(H5O_loc_free(obj_loc->oloc) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "unable to free object location")
+
+ /* Copy the entry for the root group */
+ if(H5O_loc_copy(obj_loc->oloc, oloc, H5_COPY_DEEP) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object location")
+
+ /* In case the shared root group info points to a different file handle
+ * than the child, modify obj_loc */
+ obj_loc->oloc->file = child;
+
+ /* Switch to child's file */
+ parent = child;
+ } /* end if */
} while(!cmp);
done:
diff --git a/src/H5O.c b/src/H5O.c
index b5c74ff..d090df0 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -1375,7 +1375,7 @@ H5O_close(H5O_loc_t *loc)
* If the file open object count has reached the number of open mount points
* (each of which has a group open in the file) attempt to close the file.
*/
- if(loc->file->nopen_objs == loc->file->mtab.nmounts)
+ if(loc->file->nopen_objs == loc->file->nmounts)
/* Attempt to close down the file hierarchy */
if(H5F_try_close(loc->file) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCLOSEFILE, FAIL, "problem attempting file close")
diff --git a/test/mount.c b/test/mount.c
index 1898a36..c86c56b 100644
--- a/test/mount.c
+++ b/test/mount.c
@@ -168,7 +168,7 @@ test_basic(hid_t fapl)
static int
test_illegal(hid_t fapl)
{
- hid_t file1 = -1, file2 = -1, file3 = -1, file4 = -1, mnt = -1;
+ hid_t file1 = -1, file1b = -1, file2 = -1, file3 = -1, file3b = -1, mnt = -1;
char filename1[1024], filename2[1024], filename3[1024];
herr_t status;
@@ -183,7 +183,9 @@ test_illegal(hid_t fapl)
(file2 = H5Fopen(filename2, H5F_ACC_RDONLY, fapl)) < 0 ||
(file3 = H5Fopen(filename3, H5F_ACC_RDONLY, fapl)) < 0)
FAIL_STACK_ERROR
- if((file4 = H5Fopen(filename3, H5F_ACC_RDONLY, fapl)) < 0)
+ if((file1b = H5Fopen(filename1, H5F_ACC_RDONLY, fapl)) < 0)
+ FAIL_STACK_ERROR
+ if((file3b = H5Fopen(filename3, H5F_ACC_RDONLY, fapl)) < 0)
FAIL_STACK_ERROR
/* Try mounting a file on itself */
@@ -218,12 +220,12 @@ test_illegal(hid_t fapl)
* Try mounting the same file opened twice at the same place.
*
* We have to open the mount point before we mount the first file or we'll
- * end up mounting file4 at the root of file3 and the mount will succeed.
+ * end up mounting file3b at the root of file3 and the mount will succeed.
*/
if((mnt = H5Gopen2(file1, "/mnt1", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
if(H5Fmount(mnt, ".", file3, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
H5E_BEGIN_TRY {
- status = H5Fmount(mnt, ".", file4, H5P_DEFAULT);
+ status = H5Fmount(mnt, ".", file3b, H5P_DEFAULT);
} H5E_END_TRY;
if(status >= 0) {
H5_FAILED();
@@ -233,13 +235,24 @@ test_illegal(hid_t fapl)
if(H5Funmount(mnt, ".") < 0) FAIL_STACK_ERROR
if(H5Gclose(mnt) < 0) FAIL_STACK_ERROR
-
+ /* Try to create a "weak" cycle */
+ if(H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
+ H5E_BEGIN_TRY {
+ status = H5Fmount(file2, "/mnt1/file2", file1b, H5P_DEFAULT);
+ } H5E_END_TRY;
+ if(status >= 0) {
+ H5_FAILED();
+ puts(" Creating a cycle with mount points should have failed.");
+ TEST_ERROR
+ } /* end if */
+ if(H5Funmount(file1, "/mnt1") < 0) FAIL_STACK_ERROR
/* Close everything and return */
if(H5Fclose(file1) < 0) FAIL_STACK_ERROR
+ if(H5Fclose(file1b) < 0) FAIL_STACK_ERROR
if(H5Fclose(file2) < 0) FAIL_STACK_ERROR
if(H5Fclose(file3) < 0) FAIL_STACK_ERROR
- if(H5Fclose(file4) < 0) FAIL_STACK_ERROR
+ if(H5Fclose(file3b) < 0) FAIL_STACK_ERROR
PASSED();
return 0;
@@ -248,9 +261,10 @@ error:
H5E_BEGIN_TRY {
H5Gclose(mnt);
H5Fclose(file1);
+ H5Fclose(file1b);
H5Fclose(file2);
H5Fclose(file3);
- H5Fclose(file4);
+ H5Fclose(file3b);
} H5E_END_TRY;
return 1;
} /* end test_illegal() */
@@ -3919,6 +3933,275 @@ error:
/*-------------------------------------------------------------------------
+ * Function: test_sharedacc
+ *
+ * Purpose: Test shared access to a file's mount table.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Neil Fortner
+ * Friday, August 1, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+ static int
+test_sharedacc(hid_t fapl)
+{
+ hid_t fid1[2] = {-1, -1}, fid2[2] = {-1, -1}; /* File IDs */
+ hid_t gid = -1;
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ filename3[NAME_BUF_SIZE]; /* Name of files to mount */
+ int i, j, k; /* Counters */
+
+ TESTING("shared mount access");
+
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+ h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3);
+
+ /* Create file #1 & its group */
+ if((fid1[0] = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((gid = H5Gcreate2(fid1[0], "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gid) < 0)
+ TEST_ERROR
+
+ /* Create file #2 & its group */
+ if((fid2[0] = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((gid = H5Gcreate2(fid2[0], "B", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gid) < 0)
+ TEST_ERROR
+
+ /* Test mount before reopen, then using reopened handle for access */
+ if(H5Fmount(fid1[0], "/A", fid2[0], H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if((fid1[1] = H5Freopen(fid1[0])) < 0)
+ TEST_ERROR
+ if((fid2[1] = H5Freopen(fid2[0])) < 0)
+ TEST_ERROR
+ if((gid = H5Gopen2(fid1[1], "/A/B", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gid) < 0)
+ TEST_ERROR
+ if(H5Funmount(fid1[1], "/A") < 0)
+ TEST_ERROR
+
+ /* "Brute force" test of all possible ways of mounting, accessing, and
+ * unmounting files with multiple handles (mount after reopen) */
+ for(i=0; i<2; i++)
+ for(j=0; j<2; j++)
+ for(k=0; k<2; k++) {
+ if(H5Fmount(fid1[i], "/A", fid2[j], H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if((gid = H5Gopen2(fid1[k], "/A/B", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gid) < 0)
+ TEST_ERROR
+ if(H5Funmount(fid1[k], "/A") < 0)
+ TEST_ERROR
+ }
+
+ /* Close file IDs */
+ for(i=0; i<2; i++) {
+ if(H5Fclose(fid1[i]) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid2[i]) < 0)
+ TEST_ERROR
+ }
+
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Gclose(gid);
+ for(i=0; i<2; i++) {
+ H5Fclose(fid1[i]);
+ H5Fclose(fid2[i]);
+ }
+ } H5E_END_TRY;
+ return 1;
+} /* end test_sharedacc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_sharedclose
+ *
+ * Purpose: Test that files within a shared mount structure are properly
+ * closed.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Neil Fortner
+ * Friday, August 6, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+ static int
+test_sharedclose(hid_t fapl)
+{
+ hid_t fid1a = -1, fid1b = -1, fid2 = -1, fid3 = -2; /* File IDs */
+ hid_t gid1 = -1, gid2 = -1, gid3 = -1;
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ filename3[NAME_BUF_SIZE]; /* Name of files to mount */
+
+ TESTING("closing shared mounts");
+
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+ h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3);
+
+ /* Create file #1a & its group */
+ if((fid1a = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((gid1 = H5Gcreate2(fid1a, "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create file #1b & its groups */
+ if((fid1b = H5Freopen(fid1a)) < 0)
+ TEST_ERROR
+ if((gid2 = H5Gcreate2(fid1b, "B", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((gid3 = H5Gcreate2(fid1b, "B/C", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create file #2 */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create file #3 */
+ if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Mount file #2 to file #1a */
+ if(H5Fmount(gid1, ".", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Mount file #3 to file #1b */
+ if(H5Fmount(gid2, ".", fid3, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Close file #1b. It should be held open by the groups in it. */
+ if(H5Fclose(fid1b) < 0)
+ TEST_ERROR
+
+ /* Close file #3. It should be held open by the groups in its parent. */
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+ /* Close group B in file #1b. This should not close file #1b and #3. */
+ if(H5Gclose(gid2) < 0)
+ TEST_ERROR
+
+ /* Check that file #3 is still open */
+ if(H5F_sfile_assert_num(3) != 0)
+ TEST_ERROR
+
+ /* Close group B/C in file #1b. This should close file #1b and #3. */
+ if(H5Gclose(gid3) < 0)
+ TEST_ERROR
+
+ /* Check that file #3 has been closed */
+ if(H5F_sfile_assert_num(2) != 0)
+ TEST_ERROR
+
+ /* Unmount file 2 and close the rest of the handles */
+ if(H5Funmount(fid1a, "A") < 0)
+ TEST_ERROR
+ if(H5Gclose(gid1) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid1a) < 0)
+ TEST_ERROR
+
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
+
+ /* Create file #1 & its group */
+ if((fid1a = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((gid1 = H5Gcreate2(fid1a, "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create file #1b & its group */
+ if((fid1b = H5Freopen(fid1a)) < 0)
+ TEST_ERROR
+ if((gid2 = H5Gcreate2(fid1b, "B", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create file #2 */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Mount file #2 to file #1 */
+ if(H5Fmount(fid1a, "A", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Close file #1b. It should be held open by the group in it. */
+ if(H5Fclose(fid1b) < 0)
+ TEST_ERROR
+
+ /* Close the group in file #1b. This should close file # 1b. */
+ if(H5Gclose(gid2) < 0)
+ TEST_ERROR
+
+ /* Unmount file 2 and close the rest of the handles */
+ if(H5Funmount(fid1a, "A") < 0)
+ TEST_ERROR
+ if(H5Gclose(gid1) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid1a) < 0)
+ TEST_ERROR
+
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Gclose(gid1);
+ H5Gclose(gid2);
+ H5Gclose(gid3);
+ H5Fclose(fid1a);
+ H5Fclose(fid1b);
+ H5Fclose(fid2);
+ H5Fclose(fid3);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_sharedclose() */
+
+
+/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Test file mounting
@@ -3977,6 +4260,8 @@ main(void)
nerrors += test_close_parent(fapl);
nerrors += test_cut_graph(fapl);
nerrors += test_symlink(fapl);
+ nerrors += test_sharedacc(fapl);
+ nerrors += test_sharedclose(fapl);
if (nerrors) goto error;
puts("All mount tests passed.");