1
1
openmpi/ompi/mca/sharedfp/sm/sharedfp_sm_file_open.c
Edgar Gabriel 9b65ec9445 sharedfp/sm and lockedfile: fix naming bug
If an application opens a file for reading from multiple processes
using MPI_COMM_SELF (or another communicator that has distinct
process groups but the same comm-id, as can happen as the result
of comm_split), the naming chosen for the lockedfile or the mmapped
file used by the sharedfp/sm component would collide. This patch
ensures that the filename is different by integrating the process id
of rank 0 for each sub-communicator.

This fixes one aspect of the problem reported in github issue 5593

Signed-off-by: Edgar Gabriel <egabriel@central.uh.edu>
2018-08-27 12:40:49 -05:00

284 строки
9.5 KiB
C

/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2017 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2013-2018 University of Houston. All rights reserved.
* Copyright (c) 2013 Intel, Inc. All rights reserved.
* Copyright (c) 2015-2018 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2016-2017 IBM Corporation. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#if HAVE_LIBGEN_H
#include <libgen.h>
#endif
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#include "sharedfp_sm.h"
#include "mpi.h"
#include "ompi/constants.h"
#include "ompi/group/group.h"
#include "ompi/proc/proc.h"
#include "ompi/mca/sharedfp/sharedfp.h"
#include "ompi/mca/sharedfp/base/base.h"
#include <semaphore.h>
#include <sys/mman.h>
#include <libgen.h>
#include <unistd.h>
int mca_sharedfp_sm_file_open (struct ompi_communicator_t *comm,
const char* filename,
int amode,
struct opal_info_t *info,
ompio_file_t *fh)
{
int err = OMPI_SUCCESS;
struct mca_sharedfp_base_data_t* sh;
struct mca_sharedfp_sm_data * sm_data = NULL;
char * filename_basename;
char * sm_filename;
int sm_filename_length;
struct mca_sharedfp_sm_offset * sm_offset_ptr;
struct mca_sharedfp_sm_offset sm_offset;
int sm_fd;
uint32_t comm_cid;
int int_pid;
pid_t my_pid;
/*Memory is allocated here for the sh structure*/
if ( mca_sharedfp_sm_verbose ) {
opal_output(ompi_sharedfp_base_framework.framework_output,
"mca_sharedfp_sm_file_open: malloc f_sharedfp_ptr struct\n");
}
sh = (struct mca_sharedfp_base_data_t*)malloc(sizeof(struct mca_sharedfp_base_data_t));
if ( NULL == sh ) {
opal_output(0, "mca_sharedfp_sm_file_open: Error, unable to malloc f_sharedfp struct\n");
return OMPI_ERR_OUT_OF_RESOURCE;
}
/*Populate the sh file structure based on the implementation*/
sh->global_offset = 0; /* Global Offset*/
sh->selected_module_data = NULL;
/*Open a shared memory segment which will hold the shared file pointer*/
if ( mca_sharedfp_sm_verbose ) {
opal_output(ompi_sharedfp_base_framework.framework_output,
"mca_sharedfp_sm_file_open: allocatge shared memory segment.\n");
}
sm_data = (struct mca_sharedfp_sm_data*) malloc ( sizeof(struct mca_sharedfp_sm_data));
if ( NULL == sm_data ){
opal_output(0, "mca_sharedfp_sm_file_open: Error, unable to malloc sm_data struct\n");
free(sh);
return OMPI_ERR_OUT_OF_RESOURCE;
}
sm_data->sm_filename=NULL;
/* the shared memory segment is identified opening a file
** and then mapping it to memory
** For sharedfp we also want to put the file backed shared memory into the tmp directory
*/
filename_basename = basename((char*)filename);
/* format is "%s/%s_cid-%d-%d.sm", see below */
sm_filename_length = strlen(ompi_process_info.job_session_dir) + 1 + strlen(filename_basename) + 5 + (3*sizeof(uint32_t)+1) + 4;
sm_filename = (char*) malloc( sizeof(char) * sm_filename_length);
if (NULL == sm_filename) {
opal_output(0, "mca_sharedfp_sm_file_open: Error, unable to malloc sm_filename\n");
free(sm_data);
free(sh);
return OMPI_ERR_OUT_OF_RESOURCE;
}
comm_cid = ompi_comm_get_cid(comm);
if ( 0 == fh->f_rank ) {
my_pid = getpid();
int_pid = (int) my_pid;
}
err = comm->c_coll->coll_bcast (&int_pid, 1, MPI_INT, 0, comm, comm->c_coll->coll_bcast_module );
if ( OMPI_SUCCESS != err ) {
opal_output(0,"mca_sharedfp_sm_file_open: Error in bcast operation \n");
free(sm_filename);
free(sm_data);
free(sh);
return err;
}
snprintf(sm_filename, sm_filename_length, "%s/%s_cid-%d-%d.sm", ompi_process_info.job_session_dir,
filename_basename, comm_cid, int_pid);
/* open shared memory file, initialize to 0, map into memory */
sm_fd = open(sm_filename, O_RDWR | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if ( sm_fd == -1){
/*error opening file*/
opal_output(0,"mca_sharedfp_sm_file_open: Error, unable to open file for mmap: %s\n",sm_filename);
free(sm_filename);
free(sm_data);
free(sh);
return OMPI_ERROR;
}
sm_data->sm_filename = sm_filename;
/* TODO: is it necessary to write to the file first? */
if( 0 == fh->f_rank ){
memset ( &sm_offset, 0, sizeof (struct mca_sharedfp_sm_offset ));
write ( sm_fd, &sm_offset, sizeof(struct mca_sharedfp_sm_offset));
}
err = comm->c_coll->coll_barrier (comm, comm->c_coll->coll_barrier_module );
if ( OMPI_SUCCESS != err ) {
opal_output(0,"mca_sharedfp_sm_file_open: Error in barrier operation \n");
free(sm_filename);
free(sm_data);
free(sh);
close (sm_fd);
return err;
}
/*the file has been written to, now we can map*/
sm_offset_ptr = mmap(NULL, sizeof(struct mca_sharedfp_sm_offset), PROT_READ | PROT_WRITE,
MAP_SHARED, sm_fd, 0);
close(sm_fd);
if ( sm_offset_ptr==MAP_FAILED){
err = OMPI_ERROR;
opal_output(0, "mca_sharedfp_sm_file_open: Error, unable to mmap file: %s\n",sm_filename);
opal_output(0, "%s\n", strerror(errno));
free(sm_filename);
free(sm_data);
free(sh);
return OMPI_ERROR;
}
/* Initialize semaphore so that is shared between processes. */
/* the semaphore is shared by keeping it in the shared memory segment */
#if defined(HAVE_SEM_OPEN)
#if defined (__APPLE__)
sm_data->sem_name = (char*) malloc( sizeof(char) * 32);
snprintf(sm_data->sem_name,31,"OMPIO_%s",filename_basename);
#else
sm_data->sem_name = (char*) malloc( sizeof(char) * 253);
snprintf(sm_data->sem_name,252,"OMPIO_%s",filename_basename);
#endif
if( (sm_data->mutex = sem_open(sm_data->sem_name, O_CREAT, 0644, 1)) != SEM_FAILED ) {
#elif defined(HAVE_SEM_INIT)
sm_data->mutex = &sm_offset_ptr->mutex;
if(sem_init(&sm_offset_ptr->mutex, 1, 1) != -1){
#endif
/*If opening was successful*/
/*Store the new file handle*/
sm_data->sm_offset_ptr = sm_offset_ptr;
/* Assign the sm_data to sh->selected_module_data*/
sh->selected_module_data = sm_data;
/*remember the shared file handle*/
fh->f_sharedfp_data = sh;
/*write initial zero*/
if(fh->f_rank==0){
MPI_Offset position=0;
sem_wait(sm_data->mutex);
sm_offset_ptr->offset=position;
sem_post(sm_data->mutex);
}
}else{
free(sm_filename);
free(sm_data);
free(sh);
munmap(sm_offset_ptr, sizeof(struct mca_sharedfp_sm_offset));
return OMPI_ERROR;
}
err = comm->c_coll->coll_barrier (comm, comm->c_coll->coll_barrier_module );
if ( OMPI_SUCCESS != err ) {
opal_output(0,"mca_sharedfp_sm_file_open: Error in barrier operation \n");
free(sm_filename);
free(sm_data);
free(sh);
munmap(sm_offset_ptr, sizeof(struct mca_sharedfp_sm_offset));
return err;
}
#if defined(HAVE_SEM_OPEN)
if ( 0 == fh->f_rank ) {
sem_unlink ( sm_data->sem_name);
}
#endif
return OMPI_SUCCESS;
}
int mca_sharedfp_sm_file_close (ompio_file_t *fh)
{
int err = OMPI_SUCCESS;
/*sharedfp data structure*/
struct mca_sharedfp_base_data_t *sh=NULL;
/*sharedfp sm module data structure*/
struct mca_sharedfp_sm_data * file_data=NULL;
if( NULL == fh->f_sharedfp_data ){
return OMPI_SUCCESS;
}
sh = fh->f_sharedfp_data;
/* Use an MPI Barrier in order to make sure that
* all processes are ready to release the
* shared file pointer resources
*/
fh->f_comm->c_coll->coll_barrier (fh->f_comm, fh->f_comm->c_coll->coll_barrier_module );
file_data = (sm_data*)(sh->selected_module_data);
if (file_data) {
/*Close sm handle*/
if (file_data->sm_offset_ptr) {
/* destroy semaphore */
#if defined(HAVE_SEM_OPEN)
sem_close ( file_data->mutex);
free (file_data->sem_name);
#elif defined(HAVE_SEM_INIT)
sem_destroy(&file_data->sm_offset_ptr->mutex);
#endif
/*Release the shared memory segment.*/
munmap(file_data->sm_offset_ptr,sizeof(struct mca_sharedfp_sm_offset));
/*Q: Do we need to delete the file? */
remove(file_data->sm_filename);
}
/*free our sm data structure*/
if(file_data->sm_filename){
free(file_data->sm_filename);
}
free(file_data);
}
/*free shared file pointer data struct*/
free(sh);
return err;
}