[svn-r21610] Purpose: Fix bug 7776

Description:
When H5Ocopy failed due to attempting to expand an invalid reference in an
attribute (or at any point after the destination object header was inserted
into the cache), it failed to clean up correctly.  Modified
H5O_copy_header_real to keep track of whether the object header was inserted
and take appropriate action on failure.

Tested: fedora (too minor for full commit test)
This commit is contained in:
Neil Fortner 2011-10-19 15:39:55 -05:00
parent 395c1c7db5
commit 8ce6f57fed

View File

@ -293,6 +293,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
unsigned mesgno = 0;
haddr_t addr_new = HADDR_UNDEF;
hbool_t *deleted = NULL; /* Array of flags indicating whether messages should be copied */
hbool_t inserted = FALSE; /* Whether the destination object header has been inserted into the cache */
size_t null_msgs; /* Number of NULL messages found in each loop */
size_t orig_dst_msgs; /* Original # of messages in dest. object */
H5O_mesg_t *mesg_src; /* Message in source object header */
@ -370,9 +371,9 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
/* Allocate memory for "deleted" array. This array marks the message in
* the source that shouldn't be copied to the destination.
*/
if(NULL == (deleted = (hbool_t *)HDmalloc(sizeof(hbool_t) * oh_src->nmesgs)))
if(NULL == (deleted = (hbool_t *)HDmalloc(sizeof(hbool_t) * oh_src->nmesgs)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
HDmemset(deleted, FALSE, sizeof(hbool_t) * oh_src->nmesgs);
HDmemset(deleted, FALSE, sizeof(hbool_t) * oh_src->nmesgs);
/* "pre copy" pass over messages, to gather information for actual message copy operation
* (for messages which depend on information from other messages)
@ -696,6 +697,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
* pinned so we can continue using oh_dst. */
if(H5AC_insert_entry(oloc_dst->file, dxpl_id, H5AC_OHDR, oloc_dst->addr, oh_dst, H5AC__PIN_ENTRY_FLAG) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header")
inserted = TRUE;
/* Reset metadata tag */
H5_END_TAG(FAIL);
@ -752,7 +754,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
/* Unpin oh_dst */
if(H5AC_unpin_entry(oh_dst) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "can't unpin object header")
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "can't unpin object header")
oh_dst = NULL;
/* Retag all copied metadata to apply the destination object's tag */
@ -775,9 +777,19 @@ done:
if(oh_src && H5O_unprotect(oloc_src, dxpl_id, oh_src, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
/* Release pointer to destination object header */
if(ret_value < 0 && oh_dst && H5O_free(oh_dst) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
/* Free destination object header on failure */
if(ret_value < 0 && oh_dst) {
if(inserted) {
if(H5AC_unpin_entry(oh_dst) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "can't unpin object header")
} /* end if */
else {
if(H5O_free(oh_dst) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
if(H5O_loc_reset(oloc_dst) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
} /* end else */
} /* end if */
FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
} /* end H5O_copy_header_real() */