diff options
-rw-r--r-- | release_docs/RELEASE.txt | 6 | ||||
-rw-r--r-- | src/H5F.c | 18 | ||||
-rw-r--r-- | src/H5Fmount.c | 146 | ||||
-rw-r--r-- | src/H5Fpkg.h | 37 | ||||
-rw-r--r-- | src/H5G.c | 4 | ||||
-rw-r--r-- | src/H5Gname.c | 12 | ||||
-rw-r--r-- | src/H5Gtraverse.c | 40 | ||||
-rw-r--r-- | src/H5O.c | 2 | ||||
-rw-r--r-- | test/mount.c | 299 |
9 files changed, 426 insertions, 138 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index a68b88b..69c37f3 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -88,6 +88,12 @@ Bug Fixes since HDF5-1.8.0 release 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) - when an attribute was opened twice and data was written with one of the handles, the file didn't have the data. It happened because each handle had its own object structure, and the empty one overwrote the data with fill value. This is @@ -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 */ }; /*****************************/ @@ -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 185da21..c5fc2c1 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: @@ -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."); |