root/opal/mca/pmix/pmix4x/pmix/src/mca/gds/ds12/gds_ds12_lock_fcntl.c

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

DEFINITIONS

This source file includes following definitions.
  1. pmix_gds_ds12_lock_init
  2. pmix_ds12_lock_finalize
  3. pmix_ds12_lock_rd_get
  4. pmix_ds12_lock_wr_get
  5. pmix_ds12_lock_rw_rel

   1 /*
   2  * Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
   3  * Copyright (c) 2016      IBM Corporation.  All rights reserved.
   4  * Copyright (c) 2016-2018 Mellanox Technologies, Inc.
   5  *                         All rights reserved.
   6  * Copyright (c) 2018      Research Organization for Information Science
   7  *                         and Technology (RIST).  All rights reserved.
   8  *
   9  * $COPYRIGHT$
  10  *
  11  * Additional copyrights may follow
  12  *
  13  * $HEADER$
  14  */
  15 
  16 #include <src/include/pmix_config.h>
  17 
  18 #ifdef HAVE_UNISTD_H
  19 #include <unistd.h>
  20 #endif
  21 #ifdef HAVE_SYS_TYPES_H
  22 #include <sys/types.h>
  23 #endif
  24 #ifdef HAVE_SYS_STAT_H
  25 #include <sys/stat.h>
  26 #endif
  27 #ifdef HAVE_FCNTL_H
  28 #include <fcntl.h>
  29 #endif
  30 
  31 #include <pmix_common.h>
  32 
  33 #include "src/mca/common/dstore/dstore_common.h"
  34 #include "src/mca/gds/base/base.h"
  35 
  36 #include "src/util/error.h"
  37 #include "src/util/output.h"
  38 
  39 #include "gds_ds12_lock.h"
  40 
  41 #define _ESH_12_FCNTL_LOCK(lockfd, operation)               \
  42 __pmix_attribute_extension__ ({                             \
  43     pmix_status_t ret = PMIX_SUCCESS;                       \
  44     int i;                                                  \
  45     struct flock fl = {0};                                  \
  46     fl.l_type = operation;                                  \
  47     fl.l_whence = SEEK_SET;                                 \
  48     for(i = 0; i < 10; i++) {                               \
  49         if( 0 > fcntl(lockfd, F_SETLKW, &fl) ) {            \
  50             switch( errno ){                                \
  51                 case EINTR:                                 \
  52                     continue;                               \
  53                 case ENOENT:                                \
  54                 case EINVAL:                                \
  55                     ret = PMIX_ERR_NOT_FOUND;               \
  56                     break;                                  \
  57                 case EBADF:                                 \
  58                     ret = PMIX_ERR_BAD_PARAM;               \
  59                     break;                                  \
  60                 case EDEADLK:                               \
  61                 case EFAULT:                                \
  62                 case ENOLCK:                                \
  63                     ret = PMIX_ERR_RESOURCE_BUSY;           \
  64                     break;                                  \
  65                 default:                                    \
  66                     ret = PMIX_ERROR;                       \
  67                     break;                                  \
  68             }                                               \
  69         }                                                   \
  70         break;                                              \
  71     }                                                       \
  72     if (ret) {                                              \
  73         pmix_output(0, "%s %d:%s lock failed: %s",          \
  74             __FILE__, __LINE__, __func__, strerror(errno)); \
  75     }                                                       \
  76     ret;                                                    \
  77 })
  78 
  79 typedef struct {
  80     char *lockfile;
  81     int lockfd;
  82 } ds12_lock_fcntl_ctx_t;
  83 
  84 pmix_status_t pmix_gds_ds12_lock_init(pmix_common_dstor_lock_ctx_t *ctx, const char *base_path,
  85                                       const char *name, uint32_t local_size, uid_t uid, bool setuid)
  86 {
  87     pmix_status_t rc = PMIX_SUCCESS;
  88     ds12_lock_fcntl_ctx_t *lock_ctx;
  89 
  90     if (*ctx != NULL) {
  91         return PMIX_SUCCESS;
  92     }
  93 
  94     lock_ctx = (ds12_lock_fcntl_ctx_t*)malloc(sizeof(ds12_lock_fcntl_ctx_t));
  95     if (NULL == lock_ctx) {
  96         rc = PMIX_ERR_INIT;
  97         PMIX_ERROR_LOG(rc);
  98         goto error;
  99     }
 100     *ctx = lock_ctx;
 101     memset(lock_ctx, 0, sizeof(ds12_lock_fcntl_ctx_t));
 102     lock_ctx->lockfd = -1;
 103 
 104     /* create a lock file to prevent clients from reading while server is writing
 105      * to the shared memory. This situation is quite often, especially in case of
 106      * direct modex when clients might ask for data simultaneously. */
 107     if(0 > asprintf(&lock_ctx->lockfile, "%s/dstore_sm.lock", base_path)) {
 108         rc = PMIX_ERR_OUT_OF_RESOURCE;
 109         PMIX_ERROR_LOG(rc);
 110         goto error;
 111     }
 112     PMIX_OUTPUT_VERBOSE((10, pmix_gds_base_framework.framework_output,
 113         "%s:%d:%s _lockfile_name: %s", __FILE__, __LINE__, __func__, lock_ctx->lockfile));
 114 
 115     if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) {
 116         lock_ctx->lockfd = open(lock_ctx->lockfile, O_CREAT | O_RDWR | O_EXCL, 0600);
 117 
 118         /* if previous launch was crashed, the lockfile might not be deleted and unlocked,
 119          * so we delete it and create a new one. */
 120         if (lock_ctx->lockfd < 0) {
 121             unlink(lock_ctx->lockfile);
 122             lock_ctx->lockfd = open(lock_ctx->lockfile, O_CREAT | O_RDWR, 0600);
 123             if (lock_ctx->lockfd < 0) {
 124                 rc = PMIX_ERROR;
 125                 PMIX_ERROR_LOG(rc);
 126                 goto error;
 127             }
 128         }
 129         if (0 != setuid) {
 130             if (0 > chown(lock_ctx->lockfile, uid, (gid_t) -1)) {
 131                 rc = PMIX_ERROR;
 132                 PMIX_ERROR_LOG(rc);
 133                 goto error;
 134             }
 135             if (0 > chmod(lock_ctx->lockfile, S_IRUSR | S_IWGRP | S_IRGRP)) {
 136                 rc = PMIX_ERROR;
 137                 PMIX_ERROR_LOG(rc);
 138                 goto error;
 139             }
 140         }
 141     }
 142     else {
 143         lock_ctx->lockfd = open(lock_ctx->lockfile, O_RDONLY);
 144         if (0 > lock_ctx->lockfd) {
 145             rc = PMIX_ERROR;
 146             PMIX_ERROR_LOG(rc);
 147             goto error;
 148         }
 149     }
 150 
 151     return rc;
 152 
 153 error:
 154     if (NULL != lock_ctx) {
 155         if (NULL != lock_ctx->lockfile) {
 156             free(lock_ctx->lockfile);
 157         }
 158         if (0 > lock_ctx->lockfd) {
 159             close(lock_ctx->lockfd);
 160             if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) {
 161                 unlink(lock_ctx->lockfile);
 162             }
 163         }
 164         free(lock_ctx);
 165         lock_ctx = NULL;
 166     }
 167     *ctx = NULL;
 168 
 169     return rc;
 170 }
 171 
 172 void pmix_ds12_lock_finalize(pmix_common_dstor_lock_ctx_t *lock_ctx)
 173 {
 174     ds12_lock_fcntl_ctx_t *fcntl_lock = (ds12_lock_fcntl_ctx_t*)*lock_ctx;
 175 
 176     if (NULL == fcntl_lock) {
 177         PMIX_ERROR_LOG(PMIX_ERR_NOT_FOUND);
 178         return;
 179     }
 180 
 181     close(fcntl_lock->lockfd);
 182 
 183     if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) {
 184         unlink(fcntl_lock->lockfile);
 185     }
 186     free(fcntl_lock);
 187     *lock_ctx = NULL;
 188 }
 189 
 190 pmix_status_t pmix_ds12_lock_rd_get(pmix_common_dstor_lock_ctx_t lock_ctx)
 191 {    ds12_lock_fcntl_ctx_t *fcntl_lock = (ds12_lock_fcntl_ctx_t*)lock_ctx;
 192      pmix_status_t rc;
 193 
 194      if (NULL == fcntl_lock) {
 195          rc = PMIX_ERR_NOT_FOUND;
 196          PMIX_ERROR_LOG(rc);
 197          return rc;
 198      }
 199      rc = _ESH_12_FCNTL_LOCK(fcntl_lock->lockfd, F_RDLCK);
 200 
 201      return rc;
 202 
 203 }
 204 
 205 pmix_status_t pmix_ds12_lock_wr_get(pmix_common_dstor_lock_ctx_t lock_ctx)
 206 {    ds12_lock_fcntl_ctx_t *fcntl_lock = (ds12_lock_fcntl_ctx_t*)lock_ctx;
 207      pmix_status_t rc;
 208 
 209      if (NULL == fcntl_lock) {
 210          rc = PMIX_ERR_NOT_FOUND;
 211          PMIX_ERROR_LOG(rc);
 212          return rc;
 213      }
 214      rc = _ESH_12_FCNTL_LOCK(fcntl_lock->lockfd, F_WRLCK);
 215 
 216      return rc;
 217 
 218 }
 219 
 220 pmix_status_t pmix_ds12_lock_rw_rel(pmix_common_dstor_lock_ctx_t lock_ctx)
 221 {    ds12_lock_fcntl_ctx_t *fcntl_lock = (ds12_lock_fcntl_ctx_t*)lock_ctx;
 222      pmix_status_t rc;
 223 
 224      if (NULL == fcntl_lock) {
 225          rc = PMIX_ERR_NOT_FOUND;
 226          PMIX_ERROR_LOG(rc);
 227          return rc;
 228      }
 229      rc = _ESH_12_FCNTL_LOCK(fcntl_lock->lockfd, F_UNLCK);
 230 
 231      return rc;
 232 
 233 }

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