diff --git a/ompi/mca/io/ompio/io_ompio_file_open.c b/ompi/mca/io/ompio/io_ompio_file_open.c index 37bc8fea57..dbb62d718c 100644 --- a/ompi/mca/io/ompio/io_ompio_file_open.c +++ b/ompi/mca/io/ompio/io_ompio_file_open.c @@ -385,6 +385,45 @@ int mca_io_ompio_file_sync (ompi_file_t *fh) return ret; } +static void mca_io_ompio_file_get_eof_offset (ompio_file_t *fh, + OMPI_MPI_OFFSET_TYPE in_offset, + OMPI_MPI_OFFSET_TYPE *out_offset) +{ + /* a file_seek with SEEK_END might require an actual offset that is + not lined up with the end of the file, depending on the file view. + This routine determines the closest (smaller or equal) offset to + the provided in_offset value, avoiding gaps in the file view and avoiding to + break up an etype. + */ + OMPI_MPI_OFFSET_TYPE offset=0, prev_offset=0, start_offset=0; + size_t k=0, blocklen=0; + size_t index_in_file_view=0; + + in_offset -= fh->f_disp; + if ( fh->f_view_size > 0 ) { + /* starting offset of the current copy of the filew view */ + start_offset = in_offset / fh->f_view_extent; + + index_in_file_view = 0; + /* determine block id that the offset is located in and + the starting offset of that block */ + while ( offset <= in_offset && index_in_file_view < fh->f_iov_count) { + prev_offset = offset; + offset = start_offset + (OMPI_MPI_OFFSET_TYPE)(intptr_t) fh->f_decoded_iov[index_in_file_view++].iov_base; + } + + offset = prev_offset; + blocklen = fh->f_decoded_iov[index_in_file_view-1].iov_len; + while ( offset <= in_offset && k <= blocklen ) { + prev_offset = offset; + offset += fh->f_etype_size; + k += fh->f_etype_size; + } + + *out_offset = prev_offset; + } + return; +} int mca_io_ompio_file_seek (ompi_file_t *fh, OMPI_MPI_OFFSET_TYPE off, @@ -392,7 +431,7 @@ int mca_io_ompio_file_seek (ompi_file_t *fh, { int ret = OMPI_SUCCESS; mca_common_ompio_data_t *data; - OMPI_MPI_OFFSET_TYPE offset, temp_offset; + OMPI_MPI_OFFSET_TYPE offset, temp_offset, temp_offset2; data = (mca_common_ompio_data_t *) fh->f_io_selected_data; @@ -409,7 +448,7 @@ int mca_io_ompio_file_seek (ompi_file_t *fh, case MPI_SEEK_CUR: ret = mca_common_ompio_file_get_position (&data->ompio_fh, &temp_offset); - offset += temp_offset; + offset += temp_offset * data->ompio_fh.f_etype_size; if (offset < 0) { OPAL_THREAD_UNLOCK(&fh->f_lock); return OMPI_ERROR; @@ -417,7 +456,9 @@ int mca_io_ompio_file_seek (ompi_file_t *fh, break; case MPI_SEEK_END: ret = data->ompio_fh.f_fs->fs_file_get_size (&data->ompio_fh, - &temp_offset); + &temp_offset2); + mca_io_ompio_file_get_eof_offset (&data->ompio_fh, + temp_offset2, &temp_offset); offset += temp_offset; if (offset < 0 || OMPI_SUCCESS != ret) { OPAL_THREAD_UNLOCK(&fh->f_lock); @@ -436,6 +477,7 @@ int mca_io_ompio_file_seek (ompi_file_t *fh, return ret; } + int mca_io_ompio_file_get_position (ompi_file_t *fd, OMPI_MPI_OFFSET_TYPE *offset) {