root/ompi/mca/fs/pvfs2/fs_pvfs2_file_open.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mca_fs_pvfs2_file_open
  2. fake_an_open

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2017 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2008-2014 University of Houston. All rights reserved.
  13  * Copyright (c) 2015-2018 Research Organization for Information Science
  14  *                         and Technology (RIST). All rights reserved.
  15  * Copyright (c) 2016-2017 IBM Corporation. All rights reserved.
  16  * $COPYRIGHT$
  17  *
  18  * Additional copyrights may follow
  19  *
  20  * $HEADER$
  21  */
  22 
  23 /* This code is based on the PVFS2 ADIO module in ROMIO
  24  *   Copyright (C) 1997 University of Chicago.
  25  *   See COPYRIGHT notice in top-level directory.
  26  */
  27 
  28 #include "ompi_config.h"
  29 #include "fs_pvfs2.h"
  30 
  31 #include "mpi.h"
  32 #include "ompi/constants.h"
  33 #include "ompi/mca/fs/fs.h"
  34 #include "ompi/communicator/communicator.h"
  35 #include "ompi/info/info.h"
  36 #include "opal/datatype/opal_convertor.h"
  37 #include "opal/datatype/opal_datatype.h"
  38 #include "ompi/datatype/ompi_datatype.h"
  39 
  40 struct open_status_s {
  41     int error;
  42     PVFS_object_ref object_ref;
  43 };
  44 typedef struct open_status_s open_status;
  45 
  46 static void fake_an_open(PVFS_fs_id id,
  47                          const char *pvfs2_name,
  48                          int access_mode,
  49                          int stripe_width,
  50                          PVFS_size stripe_size,
  51                          mca_fs_pvfs2 *pvfs2_fs,
  52                          open_status *o_status);
  53 /*
  54  *      file_open_pvfs2: This is the same strategy as ROMIO's pvfs2 open
  55  *
  56  *      Function:       - opens a new file
  57  *      Accepts:        - same arguments as MPI_File_open()
  58  *      Returns:        - Success if new file handle
  59  */
  60 int
  61 mca_fs_pvfs2_file_open (struct ompi_communicator_t *comm,
  62                         const char* filename,
  63                         int access_mode,
  64                         struct opal_info_t *info,
  65                         ompio_file_t *fh)
  66 {
  67     int ret;
  68     mca_fs_pvfs2 *pvfs2_fs;
  69     PVFS_fs_id pvfs2_id;
  70     char pvfs2_path[OMPIO_PVFS2_MAX_NAME] = {0};
  71     char * ncache_timeout;
  72     open_status o_status = {0, {0, 0}};
  73     struct ompi_datatype_t *open_status_type;
  74     struct ompi_datatype_t *types[2] = {&ompi_mpi_int.dt, &ompi_mpi_byte.dt};
  75     int lens[2] = {1, sizeof(PVFS_object_ref)};
  76     ptrdiff_t offsets[2];
  77     char char_stripe[MPI_MAX_INFO_KEY];
  78     int flag;
  79     int fs_pvfs2_stripe_size = -1;
  80     int fs_pvfs2_stripe_width = -1;
  81 
  82     /* We are going to do what ROMIO does with one process resolving
  83      * the name and broadcasting to others */
  84 
  85     pvfs2_fs = (mca_fs_pvfs2 *) malloc(sizeof(mca_fs_pvfs2));
  86     if (NULL == pvfs2_fs) {
  87         opal_output (1, "OUT OF MEMORY\n");
  88         return OMPI_ERR_OUT_OF_RESOURCE;
  89     }
  90 
  91     if (!mca_fs_pvfs2_IS_INITIALIZED) {
  92         /* disable the pvfs2 ncache */
  93         ncache_timeout = getenv("PVFS2_NCACHE_TIMEOUT");
  94         if (ncache_timeout == NULL ) {
  95             setenv("PVFS2_NCACHE_TIMEOUT", "0", 1);
  96         }
  97         ret = PVFS_util_init_defaults();
  98         if (ret < 0) {
  99             PVFS_perror("PVFS_util_init_defaults", ret);
 100             return OMPI_ERROR;
 101         }
 102         mca_fs_pvfs2_IS_INITIALIZED = 1;
 103     }
 104 
 105     memset(&(pvfs2_fs->credentials), 0, sizeof(PVFS_credentials));
 106     PVFS_util_gen_credentials(&(pvfs2_fs->credentials));
 107 
 108     /* check for stripe size and stripe depth in the info object and
 109        update mca_fs_pvfs2_stripe_width and mca_fs_pvfs2_stripe_size
 110        before calling fake_an_open() */
 111 
 112     opal_info_get (info, "stripe_size", MPI_MAX_INFO_VAL, char_stripe, &flag);
 113     if ( flag ) {
 114         sscanf ( char_stripe, "%d", &fs_pvfs2_stripe_size );
 115     }
 116 
 117     opal_info_get (info, "stripe_width", MPI_MAX_INFO_VAL, char_stripe, &flag);
 118     if ( flag ) {
 119         sscanf ( char_stripe, "%d", &fs_pvfs2_stripe_width );
 120     }
 121 
 122     if (fs_pvfs2_stripe_size < 0) {
 123         fs_pvfs2_stripe_size = mca_fs_pvfs2_stripe_size;
 124     }
 125 
 126     if (fs_pvfs2_stripe_width < 0) {
 127         fs_pvfs2_stripe_width = mca_fs_pvfs2_stripe_width;
 128     }
 129 
 130 
 131     if (OMPIO_ROOT == fh->f_rank) {
 132         ret = PVFS_util_resolve(filename, &pvfs2_id, pvfs2_path, OMPIO_PVFS2_MAX_NAME);
 133         if (ret < 0 ) {
 134             PVFS_perror("PVFS_util_resolve", ret);
 135             o_status.error = -1;
 136         }
 137         else {
 138             fake_an_open (pvfs2_id,
 139                           pvfs2_path,
 140                           access_mode,
 141                           fs_pvfs2_stripe_width,
 142                           (PVFS_size)fs_pvfs2_stripe_size,
 143                           pvfs2_fs,
 144                           &o_status);
 145         }
 146         pvfs2_fs->object_ref = o_status.object_ref;
 147         fh->f_fs_ptr = pvfs2_fs;
 148     }
 149 
 150     /* broadcast status and (possibly valid) object reference */
 151     offsets[0] = (MPI_Aint)(&o_status.error);
 152     offsets[1] = (MPI_Aint)(&o_status.object_ref);
 153 
 154     ompi_datatype_create_struct (2, lens, offsets, types, &open_status_type);
 155     ompi_datatype_commit (&open_status_type);
 156 
 157     fh->f_comm->c_coll->coll_bcast (MPI_BOTTOM,
 158                                    1,
 159                                    open_status_type,
 160                                    OMPIO_ROOT,
 161                                    fh->f_comm,
 162                                    fh->f_comm->c_coll->coll_bcast_module);
 163 
 164     ompi_datatype_destroy (&open_status_type);
 165 
 166     if (o_status.error != 0) {
 167         /* No need to free the pvfs2_fs structure, since it will
 168            be deallocated in file_close in case of an error */
 169         fh->f_fs_ptr = NULL;
 170         return OMPI_ERROR;
 171     }
 172 
 173     pvfs2_fs->object_ref = o_status.object_ref;
 174     fh->f_fs_ptr = pvfs2_fs;
 175 
 176     /* update the internal ompio structure to store stripe
 177        size and stripe depth correctly.
 178        Hadi(to be done): For this read the stripe size and stripe depth from
 179        the file itself
 180     */
 181 
 182     if (fs_pvfs2_stripe_size > 0 && fs_pvfs2_stripe_width > 0) {
 183         fh->f_stripe_size = fs_pvfs2_stripe_size;
 184         fh->f_stripe_count = fs_pvfs2_stripe_width;
 185     }
 186 
 187     return OMPI_SUCCESS;
 188 }
 189 
 190 static void fake_an_open(PVFS_fs_id id,
 191                          const char *pvfs2_name,
 192                          int access_mode,
 193                          int stripe_width,
 194                          PVFS_size stripe_size,
 195                          mca_fs_pvfs2 *pvfs2_fs,
 196                          open_status *o_status)
 197 {
 198     int ret;
 199     PVFS_sysresp_lookup resp_lookup;
 200     PVFS_sysresp_getparent resp_getparent;
 201     PVFS_sysresp_create resp_create;
 202     PVFS_sys_attr attribs;
 203     PVFS_sys_dist *dist;
 204 
 205     memset(&attribs, 0, sizeof(PVFS_sys_attr));
 206 
 207     attribs.owner = geteuid();
 208     attribs.group = getegid();
 209     attribs.perms = 0644;
 210     attribs.mask =  PVFS_ATTR_SYS_ALL_SETABLE;
 211     attribs.atime = time(NULL);
 212     attribs.mtime = attribs.atime;
 213     attribs.ctime = attribs.atime;
 214 
 215     if (stripe_width > 0 ) {
 216         attribs.dfile_count = stripe_width;
 217         attribs.mask |= PVFS_ATTR_SYS_DFILE_COUNT;
 218     }
 219 
 220     dist = NULL;
 221 
 222     memset(&resp_lookup, 0, sizeof(resp_lookup));
 223     memset(&resp_getparent, 0, sizeof(resp_getparent));
 224     memset(&resp_create, 0, sizeof(resp_create));
 225 
 226     ret = PVFS_sys_lookup(id,
 227                           pvfs2_name,
 228                           &(pvfs2_fs->credentials),
 229                           &resp_lookup,
 230                           PVFS2_LOOKUP_LINK_FOLLOW);
 231 
 232     if ( ret == (-PVFS_ENOENT)) {
 233         if (access_mode & MPI_MODE_CREATE)  {
 234             ret = PVFS_sys_getparent(id,
 235                                      pvfs2_name,
 236                                      &(pvfs2_fs->credentials),
 237                                      &resp_getparent);
 238             if (ret < 0) {
 239                 opal_output (1, "pvfs_sys_getparent returns with %d\n", ret);
 240                 o_status->error = ret;
 241                 return;
 242             }
 243 
 244             /* Set the distribution stripe size if specified */
 245             if (0 < stripe_size) {
 246                 /* Note that the distribution is hardcoded here */
 247                 dist = PVFS_sys_dist_lookup ("simple_stripe");
 248                 ret = PVFS_sys_dist_setparam (dist,
 249                                               "strip_size",
 250                                               &stripe_size);
 251                 if (ret < 0)  {
 252                     opal_output (1,
 253                             "pvfs_sys_dist_setparam returns with %d\n", ret);
 254                     o_status->error = ret;
 255                 }
 256             }
 257 
 258             /* Perform file creation */
 259             ret = PVFS_sys_create(resp_getparent.basename,
 260                                   resp_getparent.parent_ref,
 261                                   attribs,
 262                                   &(pvfs2_fs->credentials),
 263                                   dist,
 264                                   &resp_create);
 265             /*
 266 #ifdef HAVE_PVFS2_CREATE_WITHOUT_LAYOUT
 267             ret = PVFS_sys_create(resp_getparent.basename,
 268                                   resp_getparent.parent_ref,
 269                                   attribs,
 270                                   &(pvfs2_fs->credentials),
 271                                   dist,
 272                                   &resp_create);
 273                                   #else
 274             ret = PVFS_sys_create(resp_getparent.basename,
 275                                   resp_getparent.parent_ref,
 276                                   attribs,
 277                                   &(pvfs2_fs->credentials),
 278                                   dist,
 279                                   NULL,
 280                                   &resp_create);
 281             #endif
 282             */
 283 
 284             /* if many creates are happening in this directory, the earlier
 285              * sys_lookup may have returned ENOENT, but the sys_create could
 286              * return EEXISTS.  That means the file has been created anyway, so
 287              * less work for us and we can just open it up and return the
 288              * handle */
 289             if (ret == (-PVFS_EEXIST)) {
 290                 ret = PVFS_sys_lookup(id,
 291                                       pvfs2_name,
 292                                       &(pvfs2_fs->credentials),
 293                                       &resp_lookup,
 294                                       PVFS2_LOOKUP_LINK_FOLLOW);
 295                 if ( ret < 0 ) {
 296                     o_status->error = ret;
 297                     return;
 298                 }
 299                 o_status->error = ret;
 300                 o_status->object_ref = resp_lookup.ref;
 301                 return;
 302             }
 303             o_status->object_ref = resp_create.ref;
 304         }
 305         else {
 306             opal_output (10, "cannot create file without MPI_MODE_CREATE\n");
 307             o_status->error = ret;
 308             return;
 309         }
 310     }
 311     else if (access_mode & MPI_MODE_EXCL) {
 312         /* lookup should not succeed if opened with EXCL */
 313         o_status->error = -PVFS_EEXIST;
 314         return;
 315     }
 316     else {
 317         o_status->object_ref = resp_lookup.ref;
 318     }
 319     o_status->error = ret;
 320     return;
 321 }

/* [<][>][^][v][top][bottom][index][help] */