예제 #1
0
파일: path.c 프로젝트: anandhis/ompi
int
pmix_path_df(const char *path,
             uint64_t *out_avail)
{
    int rc = -1;
    int trials = 5;
    int err = 0;
#if defined(USE_STATFS)
    struct statfs buf;
#elif defined(HAVE_STATVFS)
    struct statvfs buf;
#endif

    if (NULL == path || NULL == out_avail) {
        return PMIX_ERROR;
    }
    *out_avail = 0;

    do {
#if defined(USE_STATFS)
        rc = statfs(path, &buf);
#elif defined(HAVE_STATVFS)
        rc = statvfs(path, &buf);
#endif
        err = errno;
    } while (-1 == rc && ESTALE == err && (--trials > 0));

    if (-1 == rc) {
        PMIX_OUTPUT_VERBOSE((10, 2, "pmix_path_df: stat(v)fs on "
                             "path: %s failed with errno: %d (%s)\n",
                             path, err, strerror(err)));
        return PMIX_ERROR;
    }

    /* now set the amount of free space available on path */
                               /* sometimes buf.f_bavail is negative */
    *out_avail = buf.f_bsize * ((int)buf.f_bavail < 0 ? 0 : buf.f_bavail);

    PMIX_OUTPUT_VERBOSE((10, 2, "pmix_path_df: stat(v)fs states "
                         "path: %s has %"PRIu64 " B of free space.",
                         path, *out_avail));

    return PMIX_SUCCESS;
}
예제 #2
0
/*
 * Parse one or more ranges in a set
 *
 * @param base     The base text of the value name
 * @param *ranges  A pointer to a range. This can contain multiple ranges
 *                 (i.e. "1-3,10" or "5" or "9,0100-0130,250")
 * @param ***names An argv array to add the newly discovered values to
 */
static pmix_status_t regex_parse_value_ranges(char *base, char *ranges,
                                              int num_digits, char *suffix,
                                              char ***names)
{
    int i, len;
    pmix_status_t ret;
    char *start, *orig;

    /* Look for commas, the separator between ranges */

    len = strlen(ranges);
    for (orig = start = ranges, i = 0; i < len; ++i) {
        if (',' == ranges[i]) {
            ranges[i] = '\0';
            ret = regex_parse_value_range(base, start, num_digits, suffix, names);
            if (PMIX_SUCCESS != ret) {
                PMIX_ERROR_LOG(ret);
                return ret;
            }
            start = ranges + i + 1;
        }
    }

    /* Pick up the last range, if it exists */

    if (start < orig + len) {

        PMIX_OUTPUT_VERBOSE((1, pmix_globals.debug_output,
                             "regex:parse:ranges: parse range %s (2)", start));

        ret = regex_parse_value_range(base, start, num_digits, suffix, names);
        if (PMIX_SUCCESS != ret) {
            PMIX_ERROR_LOG(ret);
            return ret;
        }
    }

    /* All done */
    return PMIX_SUCCESS;
}
예제 #3
0
static pmix_status_t pmix_regex_extract_nodes(char *regexp, char ***names)
{
    int i, j, k, len;
    pmix_status_t ret;
    char *base;
    char *orig, *suffix;
    bool found_range = false;
    bool more_to_come = false;
    int num_digits;

    /* set the default */
    *names = NULL;

    if (NULL == regexp) {
        return PMIX_SUCCESS;
    }

    orig = base = strdup(regexp);
    if (NULL == base) {
        PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
        return PMIX_ERR_OUT_OF_RESOURCE;
    }

    PMIX_OUTPUT_VERBOSE((1, pmix_globals.debug_output,
                         "pmix:extract:nodes: checking list: %s", regexp));

    do {
        /* Find the base */
        len = strlen(base);
        for (i = 0; i <= len; ++i) {
            if (base[i] == '[') {
                /* we found a range. this gets dealt with below */
                base[i] = '\0';
                found_range = true;
                break;
            }
            if (base[i] == ',') {
                /* we found a singleton value, and there are more to come */
                base[i] = '\0';
                found_range = false;
                more_to_come = true;
                break;
            }
            if (base[i] == '\0') {
                /* we found a singleton value */
                found_range = false;
                more_to_come = false;
                break;
            }
        }
        if (i == 0 && !found_range) {
            /* we found a special character at the beginning of the string */
            free(orig);
            return PMIX_ERR_BAD_PARAM;
        }

        if (found_range) {
            /* If we found a range, get the number of digits in the numbers */
            i++;  /* step over the [ */
            for (j=i; j < len; j++) {
                if (base[j] == ':') {
                    base[j] = '\0';
                    break;
                }
            }
            if (j >= len) {
                /* we didn't find the number of digits */
                free(orig);
                return PMIX_ERR_BAD_PARAM;
            }
            num_digits = strtol(&base[i], NULL, 10);
            i = j + 1;  /* step over the : */
            /* now find the end of the range */
            for (j = i; j < len; ++j) {
                if (base[j] == ']') {
                    base[j] = '\0';
                    break;
                }
            }
            if (j >= len) {
                /* we didn't find the end of the range */
                free(orig);
                return PMIX_ERR_BAD_PARAM;
            }
            /* check for a suffix */
            if (j+1 < len && base[j+1] != ',') {
                /* find the next comma, if present */
                for (k=j+1; k < len && base[k] != ','; k++);
                if (k < len) {
                    base[k] = '\0';
                }
                suffix = strdup(&base[j+1]);
                if (k < len) {
                    base[k] = ',';
                }
                j = k-1;
            } else {
                suffix = NULL;
            }
            PMIX_OUTPUT_VERBOSE((1, pmix_globals.debug_output,
                                 "regex:extract:nodes: parsing range %s %s %s",
                                 base, base + i, suffix));

            ret = regex_parse_value_ranges(base, base + i, num_digits, suffix, names);
            if (NULL != suffix) {
                free(suffix);
            }
            if (PMIX_SUCCESS != ret) {
                free(orig);
                return ret;
            }
            if (j+1 < len && base[j + 1] == ',') {
                more_to_come = true;
                base = &base[j + 2];
            } else {
                more_to_come = false;
            }
        } else {
            /* If we didn't find a range, just add the value */
            if(PMIX_SUCCESS != (ret = pmix_argv_append_nosize(names, base))) {
                PMIX_ERROR_LOG(ret);
                free(orig);
                return ret;
            }
            /* step over the comma */
            i++;
            /* set base equal to the (possible) next base to look at */
            base = &base[i];
        }
    } while(more_to_come);

    free(orig);

    /* All done */
    return ret;
}
예제 #4
0
pmix_status_t pmix_gds_ds12_lock_init(pmix_common_dstor_lock_ctx_t *ctx, const char *base_path,
                                      const char * name, uint32_t local_size, uid_t uid, bool setuid)
{
    size_t size = pmix_common_dstor_getpagesize();
    pmix_status_t rc = PMIX_SUCCESS;
    pthread_rwlockattr_t attr;
    ds12_lock_pthread_ctx_t *lock_ctx = (ds12_lock_pthread_ctx_t*)ctx;

    if (*ctx != NULL) {
        return PMIX_SUCCESS;
    }

    lock_ctx = (ds12_lock_pthread_ctx_t*)malloc(sizeof(ds12_lock_pthread_ctx_t));
    if (NULL == lock_ctx) {
        rc = PMIX_ERR_INIT;
        PMIX_ERROR_LOG(rc);
        goto error;
    }
    memset(lock_ctx, 0, sizeof(ds12_lock_pthread_ctx_t));
    *ctx = (pmix_common_dstor_lock_ctx_t*)lock_ctx;

    lock_ctx->segment = (pmix_pshmem_seg_t *)malloc(sizeof(pmix_pshmem_seg_t));
    if (NULL == lock_ctx->segment) {
        rc = PMIX_ERR_OUT_OF_RESOURCE;
        PMIX_ERROR_LOG(rc);
        goto error;
    }

    /* create a lock file to prevent clients from reading while server is writing
     * to the shared memory. This situation is quite often, especially in case of
     * direct modex when clients might ask for data simultaneously. */
    if(0 > asprintf(&lock_ctx->lockfile, "%s/dstore_sm.lock", base_path)) {
        rc = PMIX_ERR_OUT_OF_RESOURCE;
        PMIX_ERROR_LOG(rc);
        goto error;
    }
    PMIX_OUTPUT_VERBOSE((10, pmix_gds_base_framework.framework_output,
        "%s:%d:%s _lockfile_name: %s", __FILE__, __LINE__, __func__, lock_ctx->lockfile));

    if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) {
        if (PMIX_SUCCESS != (rc = pmix_pshmem.segment_create(lock_ctx->segment,
                                            lock_ctx->lockfile, size))) {
            PMIX_ERROR_LOG(rc);
            goto error;
        }
        memset(lock_ctx->segment->seg_base_addr, 0, size);
        if (0 != setuid) {
            if (0 > chown(lock_ctx->lockfile, (uid_t) uid, (gid_t) -1)){
                rc = PMIX_ERROR;
                PMIX_ERROR_LOG(rc);
                goto error;
            }
            /* set the mode as required */
            if (0 > chmod(lock_ctx->lockfile, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP )) {
                rc = PMIX_ERROR;
                PMIX_ERROR_LOG(rc);
                goto error;
            }
        }
        lock_ctx->rwlock = (pthread_rwlock_t *)lock_ctx->segment->seg_base_addr;

        if (0 != pthread_rwlockattr_init(&attr)) {
            rc = PMIX_ERROR;
            PMIX_ERROR_LOG(rc);
            goto error;
        }
        if (0 != pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
            pthread_rwlockattr_destroy(&attr);
            rc = PMIX_ERR_INIT;
            PMIX_ERROR_LOG(rc);
            goto error;
        }
#ifdef HAVE_PTHREAD_SETKIND
        if (0 != pthread_rwlockattr_setkind_np(&attr,
                                PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)) {
            pthread_rwlockattr_destroy(&attr);
            PMIX_ERROR_LOG(PMIX_ERR_INIT);
            goto error;
        }
#endif
        if (0 != pthread_rwlock_init(lock_ctx->rwlock, &attr)) {
            pthread_rwlockattr_destroy(&attr);
            PMIX_ERROR_LOG(PMIX_ERR_INIT);
            goto error;
        }
        if (0 != pthread_rwlockattr_destroy(&attr)) {
            PMIX_ERROR_LOG(PMIX_ERR_INIT);
            goto error;
        }

    }
    else {
        lock_ctx->segment->seg_size = size;
        snprintf(lock_ctx->segment->seg_name, PMIX_PATH_MAX, "%s", lock_ctx->lockfile);
        if (PMIX_SUCCESS != (rc = pmix_pshmem.segment_attach(lock_ctx->segment,
                                                             PMIX_PSHMEM_RW))) {
            PMIX_ERROR_LOG(rc);
            goto error;
        }
        lock_ctx->rwlock = (pthread_rwlock_t *)lock_ctx->segment->seg_base_addr;
    }

    return PMIX_SUCCESS;

error:
    if (NULL != lock_ctx) {
        if (lock_ctx->segment) {
            /* detach & unlink from current desc */
            if (lock_ctx->segment->seg_cpid == getpid()) {
                pmix_pshmem.segment_unlink(lock_ctx->segment);
            }
            pmix_pshmem.segment_detach(lock_ctx->segment);
            lock_ctx->rwlock = NULL;
        }
        if (NULL != lock_ctx->lockfile) {
            free(lock_ctx->lockfile);
        }
        free(lock_ctx);
        *ctx = (pmix_common_dstor_lock_ctx_t*)NULL;
    }

    return rc;
}
예제 #5
0
pmix_status_t pmix_gds_ds21_lock_init(pmix_common_dstor_lock_ctx_t *ctx, const char *base_path, const char * name,
                                      uint32_t local_size, uid_t uid, bool setuid)
{
    pthread_mutexattr_t attr;
    size_t size;
    uint32_t i;
    int page_size = pmix_common_dstor_getpagesize();
    segment_hdr_t *seg_hdr;
    lock_item_t *lock_item = NULL;
    lock_ctx_t *lock_ctx = (lock_ctx_t*)*ctx;
    pmix_list_t *lock_tracker;
    pmix_status_t rc = PMIX_SUCCESS;

    if (NULL == *ctx) {
        lock_ctx = (lock_ctx_t*)malloc(sizeof(lock_ctx_t));
        if (NULL == lock_ctx) {
            rc = PMIX_ERR_INIT;
            PMIX_ERROR_LOG(rc);
            goto error;
        }
        memset(lock_ctx, 0, sizeof(lock_ctx_t));
        PMIX_CONSTRUCT(&lock_ctx->lock_traker, pmix_list_t);
        *ctx = lock_ctx;
    }

    lock_tracker = &lock_ctx->lock_traker;
    lock_item = PMIX_NEW(lock_item_t);

    if (NULL == lock_item) {
        rc = PMIX_ERR_INIT;
        PMIX_ERROR_LOG(rc);
        goto error;
    }
    pmix_list_append(lock_tracker, &lock_item->super);

    PMIX_OUTPUT_VERBOSE((10, pmix_gds_base_framework.framework_output,
        "%s:%d:%s local_size %d", __FILE__, __LINE__, __func__, local_size));

    if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) {
        size_t seg_align_size;
        size_t seg_hdr_size;

        if (0 != (seg_align_size = pmix_common_dstor_getcacheblocksize())) {
            seg_align_size = (sizeof(pthread_mutex_t) / seg_align_size + 1)
                    * seg_align_size;
        } else {
            seg_align_size = sizeof(pthread_mutex_t);
        }

        seg_hdr_size = ((sizeof(segment_hdr_t)
                        + sizeof(int32_t) * local_size)
                        / seg_align_size + 1) * seg_align_size;

        size = ((seg_hdr_size
                + 2 * local_size * seg_align_size) /* array of mutexes */
                / page_size + 1) * page_size;

        lock_item->seg_desc = pmix_common_dstor_create_new_lock_seg(base_path,
                                    size, name, 0, uid, setuid);
        if (NULL == lock_item->seg_desc) {
            rc = PMIX_ERR_OUT_OF_RESOURCE;
            PMIX_ERROR_LOG(rc);
            goto error;
        }

        if (0 != pthread_mutexattr_init(&attr)) {
            rc = PMIX_ERR_INIT;
            PMIX_ERROR_LOG(rc);
            goto error;
        }
        if (0 != pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
            pthread_mutexattr_destroy(&attr);
            rc = PMIX_ERR_INIT;
            PMIX_ERROR_LOG(rc);
            goto error;
        }

        segment_hdr_t *seg_hdr = (segment_hdr_t*)lock_item->seg_desc->seg_info.seg_base_addr;
        seg_hdr->num_locks = local_size;
        seg_hdr->seg_size = size;
        seg_hdr->align_size = seg_align_size;
        seg_hdr->mutex_offs = seg_hdr_size;

        lock_item->lockfile = strdup(lock_item->seg_desc->seg_info.seg_name);
        lock_item->num_locks = local_size;
        lock_item->mutex = _GET_MUTEX_ARR_PTR(seg_hdr);

        for(i = 0; i < local_size * 2; i++) {
            pthread_mutex_t *mutex = _GET_MUTEX_PTR(seg_hdr, i);
            if (0 != pthread_mutex_init(mutex, &attr)) {
                pthread_mutexattr_destroy(&attr);
                rc = PMIX_ERR_INIT;
                PMIX_ERROR_LOG(rc);
                goto error;
            }
        }
        if (0 != pthread_mutexattr_destroy(&attr)) {
            rc = PMIX_ERR_INIT;
            PMIX_ERROR_LOG(PMIX_ERR_INIT);
            goto error;
        }
    }
    else {
        int32_t *lock_idx_ptr;
        bool idx_found = false;

        size = pmix_common_dstor_getpagesize();
        lock_item->seg_desc = pmix_common_dstor_attach_new_lock_seg(base_path, size, name, 0);
        if (NULL == lock_item->seg_desc) {
            rc = PMIX_ERR_NOT_FOUND;
            goto error;
        }
        seg_hdr = (segment_hdr_t*)lock_item->seg_desc->seg_info.seg_base_addr;

        if (seg_hdr->seg_size > size) {
            size = seg_hdr->seg_size;
            pmix_common_dstor_delete_sm_desc(lock_item->seg_desc);
            lock_item->seg_desc = pmix_common_dstor_attach_new_lock_seg(base_path, size, name, 0);
            if (NULL == lock_item->seg_desc) {
                rc = PMIX_ERR_NOT_FOUND;
                goto error;
            }
        }

        lock_item->num_locks = seg_hdr->num_locks;
        lock_idx_ptr = _GET_IDX_ARR_PTR(seg_hdr);
        lock_item->mutex = _GET_MUTEX_ARR_PTR(seg_hdr);

        for (i = 0; i < lock_item->num_locks; i++) {
            int32_t expected = 0;
            if (pmix_atomic_compare_exchange_strong_32(&lock_idx_ptr[i], &expected, 1)) {
                lock_item->lock_idx = i;
                lock_item->lockfile = strdup(lock_item->seg_desc->seg_info.seg_name);
                idx_found = true;
                break;
            }
        }

        if (false == idx_found) {
            rc = PMIX_ERR_NOT_FOUND;
            goto error;
        }
    }

    return rc;

error:
    if (NULL != lock_item) {
        pmix_list_remove_item(lock_tracker, &lock_item->super);
        PMIX_RELEASE(lock_item);
        lock_item = NULL;
    }
    *ctx = NULL;

    return rc;
}
예제 #6
0
파일: path.c 프로젝트: anandhis/ompi
bool pmix_path_nfs(char *fname, char **ret_fstype)
{
    int i;
    int fsrc = -1;
    int vfsrc = -1;
    int trials;
    char * file = strdup (fname);
#if defined(USE_STATFS)
    struct statfs fsbuf;
#endif
#if defined(HAVE_STATVFS)
    struct statvfs vfsbuf;
#endif
    /*
     * Be sure to update the test (test/util/pmix_path_nfs.c)
     * while adding a new Network/Cluster Filesystem here
     */
    static struct fs_types_t {
        unsigned long long f_fsid;
        unsigned long long f_mask;
        const char * f_fsname;
    } fs_types[] = {
        {LL_SUPER_MAGIC,                   MASK4, "lustre"},
        {NFS_SUPER_MAGIC,                  MASK2, "nfs"},
        {AUTOFS_SUPER_MAGIC,               MASK2, "autofs"},
        {PAN_KERNEL_FS_CLIENT_SUPER_MAGIC, MASK4, "panfs"},
        {GPFS_SUPER_MAGIC,                 MASK4, "gpfs"},
        {PVFS2_SUPER_MAGIC,                MASK4, "pvfs2"}
    };
#define FS_TYPES_NUM (int)(sizeof (fs_types)/sizeof (fs_types[0]))

    /*
     * First, get the OS-dependent struct stat(v)fs buf.  This may
     * return the ESTALE error on NFS, if the underlying file/path has
     * changed.
     */
again:
#if defined(USE_STATFS)
    trials = 5;
    do {
        fsrc = statfs(file, &fsbuf);
    } while (-1 == fsrc && ESTALE == errno && (0 < --trials));
#endif
#if defined(HAVE_STATVFS)
    trials = 5;
    do {
        vfsrc = statvfs(file, &vfsbuf);
    } while (-1 == vfsrc && ESTALE == errno && (0 < --trials));
#endif

    /* In case some error with the current filename, try the parent
       directory */
    if (-1 == fsrc && -1 == vfsrc) {
        char * last_sep;

        PMIX_OUTPUT_VERBOSE((10, 0, "pmix_path_nfs: stat(v)fs on file:%s failed errno:%d directory:%s\n",
                             fname, errno, file));
        if (EPERM == errno) {
            free(file);
            if ( NULL != ret_fstype ) {
                *ret_fstype = NULL;
            }
            return false;
        }

        last_sep = strrchr(file, PMIX_PATH_SEP[0]);
        /* Stop the search, when we have searched past root '/' */
        if (NULL == last_sep || (1 == strlen(last_sep) &&
            PMIX_PATH_SEP[0] == *last_sep)) {
            free (file);
            if ( NULL != ret_fstype ) {
                *ret_fstype=NULL;
            }
            return false;
        }
        *last_sep = '\0';

        goto again;
    }

    /* Next, extract the magic value */
    for (i = 0; i < FS_TYPES_NUM; i++) {
#if defined(USE_STATFS)
        /* These are uses of struct statfs */
#    if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME)
        if (0 == fsrc &&
            0 == strncasecmp(fs_types[i].f_fsname, fsbuf.f_fstypename,
                             sizeof(fsbuf.f_fstypename))) {
            goto found;
        }
#    endif
#    if defined(HAVE_STRUCT_STATFS_F_TYPE)
        if (0 == fsrc &&
            fs_types[i].f_fsid == (fsbuf.f_type & fs_types[i].f_mask)) {
            goto found;
        }
#    endif
#endif

#if defined(HAVE_STATVFS)
        /* These are uses of struct statvfs */
#    if defined(HAVE_STRUCT_STATVFS_F_BASETYPE)
        if (0 == vfsrc &&
            0 == strncasecmp(fs_types[i].f_fsname, vfsbuf.f_basetype,
                             sizeof(vfsbuf.f_basetype))) {
            goto found;
        }
#    endif
#    if defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
        if (0 == vfsrc &&
            0 == strncasecmp(fs_types[i].f_fsname, vfsbuf.f_fstypename,
                             sizeof(vfsbuf.f_fstypename))) {
            goto found;
        }
#    endif
#endif
    }

    free (file);
    if ( NULL != ret_fstype ) {
        *ret_fstype=NULL;
    }
    return false;

#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) || \
    defined(HAVE_STRUCT_STATFS_F_TYPE) || \
    defined(HAVE_STRUCT_STATVFS_F_BASETYPE) || \
    defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
  found:
#endif

    free (file);
    if (AUTOFS_SUPER_MAGIC == fs_types[i].f_fsid) {
        char *fs_type = pmix_check_mtab(fname);
        int x;
        if (NULL != fs_type) {
            for (x = 0; x < FS_TYPES_NUM; x++) {
                if (AUTOFS_SUPER_MAGIC == fs_types[x].f_fsid) {
                    continue;
                }
                if (0 == strcasecmp(fs_types[x].f_fsname, fs_type)) {
                    PMIX_OUTPUT_VERBOSE((10, 0, "pmix_path_nfs: file:%s on fs:%s\n", fname, fs_type));
                    free(fs_type);
                    if ( NULL != ret_fstype ) {
                        *ret_fstype = strdup(fs_types[x].f_fsname);
                    }
                    return true;
                }
            }
            free(fs_type);
            if ( NULL != ret_fstype ) {
                *ret_fstype=NULL;
            }
            return false;
        }
    }

    PMIX_OUTPUT_VERBOSE((10, 0, "pmix_path_nfs: file:%s on fs:%s\n",
                fname, fs_types[i].f_fsname));
    if ( NULL != ret_fstype ) {
        *ret_fstype = strdup (fs_types[i].f_fsname);
    }
    return true;

#undef FS_TYPES_NUM
}