[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; unsigned mesgno = 0;
haddr_t addr_new = HADDR_UNDEF; haddr_t addr_new = HADDR_UNDEF;
hbool_t *deleted = NULL; /* Array of flags indicating whether messages should be copied */ 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 null_msgs; /* Number of NULL messages found in each loop */
size_t orig_dst_msgs; /* Original # of messages in dest. object */ size_t orig_dst_msgs; /* Original # of messages in dest. object */
H5O_mesg_t *mesg_src; /* Message in source object header */ 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 /* Allocate memory for "deleted" array. This array marks the message in
* the source that shouldn't be copied to the destination. * 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") 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 /* "pre copy" pass over messages, to gather information for actual message copy operation
* (for messages which depend on information from other messages) * (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. */ * 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) 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") HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header")
inserted = TRUE;
/* Reset metadata tag */ /* Reset metadata tag */
H5_END_TAG(FAIL); 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 */ /* Unpin oh_dst */
if(H5AC_unpin_entry(oh_dst) < 0) 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; oh_dst = NULL;
/* Retag all copied metadata to apply the destination object's tag */ /* 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) 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") HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
/* Release pointer to destination object header */ /* Free destination object header on failure */
if(ret_value < 0 && oh_dst && H5O_free(oh_dst) < 0) if(ret_value < 0 && oh_dst) {
HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data") 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) FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
} /* end H5O_copy_header_real() */ } /* end H5O_copy_header_real() */