コード例 #1
0
ファイル: auth-cache.c プロジェクト: kotreshhr/glusterfs
/**
 * auth_cache_lookup -- Lookup an item from the cache
 *
 * @cache: cache to lookup from
 * @fh   : FH to use in lookup
 * @host_addr: Address to use in lookup
 * @timestamp: The timestamp to set when lookup succeeds
 * @can_write: Is the host authorized to write to the filehandle?
 *
 * If the current time - entry time of the cache entry > ttl_sec,
 * we remove the element from the dict and return ENTRY_EXPIRED.
 *
 * @return: ENTRY_EXPIRED if entry expired
 *          ENTRY_NOT_FOUND if entry not found in dict
 *          0 if found
 */
enum auth_cache_lookup_results
auth_cache_lookup (struct auth_cache *cache, struct nfs3_fh *fh,
                   const char *host_addr, time_t *timestamp,
                   gf_boolean_t *can_write)
{
        char                    *hashkey    = NULL;
        data_t                  *entry_data = NULL;
        struct auth_cache_entry *lookup_res = NULL;
        int                      ret        = ENTRY_NOT_FOUND;

        GF_VALIDATE_OR_GOTO (GF_NFS, cache, out);
        GF_VALIDATE_OR_GOTO (GF_NFS, cache->cache_dict, out);
        GF_VALIDATE_OR_GOTO (GF_NFS, fh, out);
        GF_VALIDATE_OR_GOTO (GF_NFS, host_addr, out);
        GF_VALIDATE_OR_GOTO (GF_NFS, timestamp, out);
        GF_VALIDATE_OR_GOTO (GF_NFS, can_write, out);

        hashkey = make_hashkey (fh, host_addr);
        if (!hashkey) {
                ret = -ENOMEM;
                goto out;
        }

        entry_data = dict_get (cache->cache_dict, hashkey);
        if (!entry_data) {
                gf_msg_debug (GF_NFS, 0, "could not find entry for %s",
                              host_addr);
                goto out;
        }

        lookup_res = (struct auth_cache_entry *)(entry_data->data);

        if ((time (NULL) - lookup_res->timestamp) > cache->ttl_sec) {
                gf_msg_debug (GF_NFS, 0, "entry for host %s has expired",
                              host_addr);
                GF_FREE (lookup_res);
                entry_data->data = NULL;
                /* Remove from the cache */
                dict_del (cache->cache_dict, hashkey);

                ret = ENTRY_EXPIRED;
                goto out;
        }

        *timestamp = lookup_res->timestamp;
        *can_write = lookup_res->item->opts->rw;

        ret = ENTRY_FOUND;
out:
        GF_FREE (hashkey);

        return ret;
}
コード例 #2
0
ファイル: exports.c プロジェクト: gluster/glusterfs
/**
 * exp_dir_get_host -- Given a host string and an exports directory structure,
 *                     find and return an struct export_item structure that
 *                     represents the requested host.
 *
 * @expdir: Export directory to lookup from
 * @host  : Host string to lookup
 *
 * @return: success: Pointer to a export item structure
 *          failure: NULL
 */
struct export_item *
exp_dir_get_host(const struct export_dir *expdir, const char *host)
{
    struct export_item *lookup_res = NULL;
    data_t *dict_res = NULL;

    GF_VALIDATE_OR_GOTO(GF_EXP, expdir, out);
    GF_VALIDATE_OR_GOTO(GF_EXP, host, out);

    if (!expdir->hosts)
        goto out;

    dict_res = dict_get(expdir->hosts, (char *)host);
    if (!dict_res) {
        gf_msg_debug(GF_EXP, 0, "%s not found for %s", host, expdir->dir_name);

        /* Check if wildcards are allowed for the host */
        dict_res = dict_get(expdir->hosts, "*");
        if (!dict_res) {
            goto out;
        }
    }

    lookup_res = (struct export_item *)dict_res->data;
out:
    return lookup_res;
}
コード例 #3
0
ファイル: exports.c プロジェクト: gluster/glusterfs
/**
 * exp_file_get_dir -- Return an export dir given a directory name
 *                     Does a lookup from the dict in the file structure.
 *
 * @file : Exports file structure to lookup from
 * @dir  : Directory name to lookup
 *
 * @return : success: Pointer to an export directory structure
 *           failure: NULL
 */
struct export_dir *
exp_file_get_dir(const struct exports_file *file, const char *dir)
{
    struct export_dir *lookup_res = NULL;
    data_t *dict_res = NULL;
    char *dirdup = NULL;
    size_t dirlen = 0;

    GF_VALIDATE_OR_GOTO(GF_EXP, file, out);
    GF_VALIDATE_OR_GOTO(GF_EXP, dir, out);

    dirlen = strlen(dir);
    if (dirlen <= 0)
        goto out;

    dirdup = (char *)dir; /* Point at the directory */

    /* If directories don't contain a leading slash */
    if (*dir != '/') {
        dirdup = alloca(dirlen + 2); /* Leading slash & null byte */
        snprintf(dirdup, dirlen + 2, "/%s", dir);
    }

    dict_res = dict_get(file->exports_dict, dirdup);
    if (!dict_res) {
        gf_msg_debug(GF_EXP, 0, "%s not found in %s", dirdup, file->filename);
        goto out;
    }

    lookup_res = (struct export_dir *)dict_res->data;
out:
    return lookup_res;
}
コード例 #4
0
static int
glusterd_mgmt_v3_unlock_send_resp (rpcsvc_request_t *req, int32_t status)
{

        gd1_mgmt_v3_unlock_rsp          rsp   = {{0},};
        int                             ret   = -1;
        xlator_t                       *this  = NULL;

        this = THIS;
        GF_ASSERT (this);
        GF_ASSERT (req);

        rsp.op_ret = status;
        if (rsp.op_ret)
                rsp.op_errno = errno;

        glusterd_get_uuid (&rsp.uuid);

        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL,
                                     (xdrproc_t)xdr_gd1_mgmt_v3_unlock_rsp);

        gf_msg_debug (this->name, 0,
                "Responded to mgmt_v3 unlock, ret: %d", ret);

        return ret;
}
コード例 #5
0
ファイル: options.c プロジェクト: lkzhd/glusterfs-annotation
/*  Parses the string to be of the form <key1>:<value1>,<key2>:<value2>...  *
 *  takes two optional validaters key_validator and value_validator         */
static int
validate_list_elements (const char *string, volume_option_t *opt,
                        int (key_validator)( const char *),
                        int (value_validator)( const char *, volume_option_t *))
{

        char                    *dup_string = NULL;
        char                    *str_sav = NULL;
        char                    *substr_sav = NULL;
        char                    *str_ptr = NULL;
        char                    *key = NULL;
        char                    *value = NULL;
        int                     ret = 0;

        GF_ASSERT (string);

        dup_string = gf_strdup (string);
        if (NULL == dup_string)
                goto out;

        str_ptr = strtok_r (dup_string, ",", &str_sav);
        if (str_ptr == NULL) {
                ret = -1;
                goto out;
        }
        while (str_ptr) {

                key = strtok_r (str_ptr, ":", &substr_sav);
                if (!key ||
                    (key_validator && key_validator(key))) {
                        ret = -1;
                        gf_msg (THIS->name, GF_LOG_WARNING, 0,
                                LG_MSG_INVALID_ENTRY, "invalid list '%s', key "
                                "'%s' not valid.", string, key);
                        goto out;
                }

                value = strtok_r (NULL, ":", &substr_sav);
                if (!value ||
                    (value_validator && value_validator(value, opt))) {
                        ret = -1;
                        gf_msg (THIS->name, GF_LOG_WARNING, 0,
                                LG_MSG_INVALID_ENTRY, "invalid list '%s', "
                                "value '%s' not valid.", string, key);
                        goto out;
                }

                str_ptr = strtok_r (NULL, ",", &str_sav);
                substr_sav = NULL;
        }

 out:
        GF_FREE (dup_string);
        gf_msg_debug (THIS->name, 0, "Returning %d", ret);
        return ret;
}
コード例 #6
0
void
cb_buffer_show (buffer_t *buffer)
{
        pthread_mutex_lock (&buffer->lock);
        {
                gf_msg_debug ("circ-buff", 0, "w_index: %d, size: %"
                              GF_PRI_SIZET" used_buffer: %d", buffer->w_index,
                              buffer->size_buffer, buffer->used_len);
        }
        pthread_mutex_unlock (&buffer->lock);
}
コード例 #7
0
int
gf_changelog_done (char *file)
{
        int                     ret    = -1;
        char                   *buffer = NULL;
        xlator_t               *this   = NULL;
        gf_changelog_journal_t *jnl    = NULL;
        char to_path[PATH_MAX]         = {0,};

        errno = EINVAL;

        this = THIS;
        if (!this)
                goto out;

        jnl = (gf_changelog_journal_t *) GF_CHANGELOG_GET_API_PTR (this);
        if (!jnl)
                goto out;

        if (!file || !strlen (file))
                goto out;

        /* make sure 'file' is inside ->jnl_working_dir */
        buffer = realpath (file, NULL);
        if (!buffer)
                goto out;

        if (strncmp (jnl->jnl_working_dir,
                     buffer, strlen (jnl->jnl_working_dir)))
                goto out;

        (void) snprintf (to_path, PATH_MAX, "%s%s",
                         jnl->jnl_processed_dir, basename (buffer));
        gf_msg_debug (this->name, 0,
                      "moving %s to processed directory", file);
        ret = sys_rename (buffer, to_path);
        if (ret) {
                gf_smsg (this->name, GF_LOG_ERROR, errno,
                         CHANGELOG_LIB_MSG_RENAME_FAILED,
                         "cannot move changelog file",
                         "from=%s", file,
                         "to=%s", to_path,
                         NULL);
                goto out;
        }

        ret = 0;

 out:
        if (buffer)
                free (buffer); /* allocated by realpath() */
        return ret;
}
コード例 #8
0
ファイル: compat.c プロジェクト: lkzhd/glusterfs-annotation
int
solaris_xattr_resolve_path (const char *real_path, char **path)
{
        int                    ret  = -1;
        char                   *export_path = NULL;
        char                   xattr_path[PATH_MAX] = {0, };
        struct stat            lstatbuf = {0, };
        struct iatt            stbuf = {0, };
        struct stat            statbuf = {0, };

        ret = lstat (real_path, &lstatbuf);
        if (ret != 0 )
                return ret;
        iatt_from_stat (&stbuf, &lstatbuf);
        if (IA_ISREG(stbuf.ia_type) || IA_ISDIR(stbuf.ia_type))
                return -1;

        ret = make_export_path (real_path, &export_path);
        if (!ret && export_path) {
                strcat (export_path, "/"GF_SOLARIS_XATTR_DIR);
                if (lstat (export_path, &statbuf)) {
                        ret = mkdir (export_path, 0777);
                        if (ret && (errno != EEXIST)) {
                                gf_msg_debug (THIS->name, 0, "mkdir failed,"
                                        " errno: %d", errno);
                                goto out;
                        }
                }

                snprintf(xattr_path, PATH_MAX, "%s%s%lu", export_path,
                         "/", stbuf.ia_ino);

                ret = lstat (xattr_path, &statbuf);

                if (ret) {
                        ret = mknod (xattr_path, S_IFREG|O_WRONLY, 0);
                        if (ret && (errno != EEXIST)) {
                                gf_msg (THIS->name, GF_LOG_WARNING, errno,
                                        LG_MSG_FILE_OP_FAILED, "Failed to "
                                        "create mapped file %s", xattr_path);
                                goto out;
                        }
                }
                *path = gf_strdup (xattr_path);
        }
out:
        GF_FREE (export_path);
        if (*path)
                return 0;
        else
                return -1;
}
コード例 #9
0
ファイル: xlator.c プロジェクト: rlugojr/glusterfs
int
xlator_volopt_dynload (char *xlator_type, void **dl_handle,
                       volume_opt_list_t *opt_list)
{
        int                     ret = -1;
        char                    *name = NULL;
        void                    *handle = NULL;

        GF_VALIDATE_OR_GOTO ("xlator", xlator_type, out);

        /* socket.so doesn't fall under the default xlator directory, hence we
         * need this check */
        if (!strstr(xlator_type, "rpc-transport"))
                ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xlator_type);
        else
                ret = gf_asprintf (&name, "%s/%s.so", XLATORPARENTDIR, xlator_type);
        if (-1 == ret) {
                goto out;
        }

        ret = -1;

        gf_msg_trace ("xlator", 0, "attempt to load file %s", name);

        handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL);
        if (!handle) {
                gf_msg ("xlator", GF_LOG_WARNING, 0, LG_MSG_DLOPEN_FAILED,
                        "%s", dlerror ());
                goto out;
        }

        if (!(opt_list->given_opt = dlsym (handle, "options"))) {
                dlerror ();
                gf_msg ("xlator", GF_LOG_ERROR, 0, LG_MSG_LOAD_FAILED,
                        "Failed to load xlator opt table");
                goto out;
        }

        *dl_handle = handle;
        handle = NULL;

        ret = 0;
 out:
        GF_FREE (name);
        if (handle)
                dlclose (handle);

        gf_msg_debug ("xlator", 0, "Returning %d", ret);
        return ret;

}
コード例 #10
0
void
eh_dump (eh_t *history, void *data,
         int (dump_fn) (circular_buffer_t *buffer, void *data))
{
        if (!history) {
                gf_msg_debug ("event-history", 0, "history is NULL");
                goto out;
        }

        cb_buffer_dump (history->buffer, data, dump_fn);

out:
        return;
}
コード例 #11
0
ファイル: xlator.c プロジェクト: lkzhd/glusterfs-annotation
int
xlator_volopt_dynload (char *xlator_type, void **dl_handle,
                       volume_opt_list_t *opt_list)
{
        int                     ret = -1;
        char                    *name = NULL;
        void                    *handle = NULL;

        GF_VALIDATE_OR_GOTO ("xlator", xlator_type, out);

        ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xlator_type);
        if (-1 == ret) {
                goto out;
        }

        ret = -1;

        gf_msg_trace ("xlator", 0, "attempt to load file %s", name);

        handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL);
        if (!handle) {
                gf_msg ("xlator", GF_LOG_WARNING, 0, LG_MSG_DLOPEN_FAILED,
                        "%s", dlerror ());
                goto out;
        }

        if (!(opt_list->given_opt = dlsym (handle, "options"))) {
                dlerror ();
                gf_msg ("xlator", GF_LOG_ERROR, 0, LG_MSG_LOAD_FAILED,
                        "Failed to load xlator opt table");
                goto out;
        }

        *dl_handle = handle;
        handle = NULL;

        ret = 0;
 out:
        GF_FREE (name);
        if (handle)
                dlclose (handle);

        gf_msg_debug ("xlator", 0, "Returning %d", ret);
        return ret;

}
コード例 #12
0
ファイル: options.c プロジェクト: lkzhd/glusterfs-annotation
/*XXX: the rules to validate are as per block-size required for stripe xlator */
static int
gf_validate_size (const char *sizestr, volume_option_t *opt)
{
        size_t                value = 0;
        int                     ret = 0;

        GF_ASSERT (opt);

        if (gf_string2bytesize_size (sizestr, &value) != 0 ||
            value < opt->min ||
            value % 512) {
                ret = -1;
                goto out;
        }

 out:
        gf_msg_debug (THIS->name, 0, "Returning %d", ret);
        return ret;
}
コード例 #13
0
static int
glusterd_mgmt_v3_post_validate_send_resp (rpcsvc_request_t   *req,
                                         int32_t op, int32_t status,
                                         char *op_errstr, dict_t *rsp_dict)
{
        gd1_mgmt_v3_post_val_rsp         rsp      = {{0},};
        int                             ret      = -1;
        xlator_t                       *this     = NULL;

        this = THIS;
        GF_ASSERT (this);
        GF_ASSERT (req);

        rsp.op_ret = status;
        glusterd_get_uuid (&rsp.uuid);
        rsp.op = op;
        if (op_errstr)
                rsp.op_errstr = op_errstr;
        else
                rsp.op_errstr = "";

        ret = dict_allocate_and_serialize (rsp_dict, &rsp.dict.dict_val,
                                           &rsp.dict.dict_len);
        if (ret < 0) {
                gf_msg (this->name, GF_LOG_ERROR, 0,
                        GD_MSG_DICT_SERL_LENGTH_GET_FAIL,
                        "failed to get serialized length of dict");
                goto out;
        }

        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL,
                                     (xdrproc_t)xdr_gd1_mgmt_v3_post_val_rsp);

        GF_FREE (rsp.dict.dict_val);
out:
        gf_msg_debug (this->name, 0,
                "Responded to post validation, ret: %d", ret);
        return ret;
}
コード例 #14
0
ファイル: exports.c プロジェクト: gluster/glusterfs
struct export_item *
exp_dir_get_netgroup(const struct export_dir *expdir, const char *netgroup)
{
    struct export_item *lookup_res = NULL;
    data_t *dict_res = NULL;

    GF_VALIDATE_OR_GOTO(GF_EXP, expdir, out);
    GF_VALIDATE_OR_GOTO(GF_EXP, netgroup, out);

    if (!expdir->netgroups)
        goto out;

    dict_res = dict_get(expdir->netgroups, (char *)netgroup);
    if (!dict_res) {
        gf_msg_debug(GF_EXP, 0, "%s not found for %s", netgroup,
                     expdir->dir_name);
        goto out;
    }

    lookup_res = (struct export_item *)dict_res->data;
out:
    return lookup_res;
}
コード例 #15
0
ファイル: exports.c プロジェクト: gluster/glusterfs
/**
 * exp_file_parse -- Parse an exports file into a structure
 *                   that can be looked up through simple
 *                   function calls.
 *
 * @filepath: Path to the exports file
 * @ms      : Current mount state (useful to match with gluster vol files)
 *
 * @return  : success: 0
 *            failure: -1 on parsing failure, -EINVAL on bad arguments,
 *                     -ENOMEM on allocation failures.
 *
 * The caller is responsible for freeing memory allocated by this function.
 * The caller should free this memory using the exp_file_deinit () function.
 * Calling GF_FREE ( ) on the pointer will NOT free all the allocated memory.
 *
 * Externally usable.
 */
int
exp_file_parse(const char *filepath, struct exports_file **expfile,
               struct mount3_state *ms)
{
    FILE *fp = NULL;
    struct exports_file *file = NULL;
    size_t len = 0;
    int ret = -EINVAL;
    unsigned long line_number = 0;
    char *line = NULL;
    struct export_dir *expdir = NULL;

    /* Sets whether we we should parse the entire file or just that which
     * is present in the mount state */
    gf_boolean_t parse_complete_file = _gf_false;

    GF_VALIDATE_OR_GOTO(GF_EXP, expfile, parse_done);

    if (!ms) {
        /* If mount state is null that means that we
         * should go through and parse the whole file
         * since we don't have anything to compare against.
         */
        parse_complete_file = _gf_true;
    }

    fp = fopen(filepath, "r");
    if (!fp) {
        ret = -errno;
        goto parse_done;
    }

    ret = _exp_init_parsers();
    if (ret < 0)
        goto parse_done;

    /* Process the file line by line, with each line being parsed into
     * an struct export_dir struct. If 'parse_complete_file' is set to TRUE
     * then
     */
    while (getline(&line, &len, fp) != -1) {
        line_number++;      /* Keeping track of line number allows us to
                             * to log which line numbers were wrong
                             */
        strtok(line, "\n"); /* removes the newline character from
                             * the line
                             */

        /* Parse the line from the file into an struct export_dir
         * structure. The process is as follows:
         * Given a line like :
         * "/vol @test(sec=sys,rw,anonuid=0) 10.35.11.31(sec=sys,rw)"
         *
         * This function will allocate an export dir and set its name
         * to '/vol', using the function _exp_line_dir_parse ().
         *
         * Then it will extract the netgroups from the line, in this
         * case it would be '@test(sec=sys,rw,anonuid=0)', and set the
         * item structure's name to '@test'.
         * It will also extract the options from that string and parse
         * them into an struct export_options which will be pointed
         * to by the item structure. This will be put into a dict
         * which will be pointed to by the export directory structure.
         *
         * The same process happens above for the host string
         * '10.35.11.32(sec=sys,rw)'
         */
        ret = _exp_line_parse(line, &expdir, parse_complete_file, ms);
        if (ret == -ENOMEM) {
            /* If we get memory allocation errors, we really should
             * not continue parsing, so just free the allocated
             * memory and exit.
             */
            goto free_and_done;
        }

        if (ret < 0) {
            gf_msg(GF_EXP, GF_LOG_ERROR, -ret, NFS_MSG_PARSE_FAIL,
                   "Failed to parse line #%lu", line_number);
            continue; /* Skip entering this line and continue */
        }

        if (ret == GF_EXP_PARSE_LINE_IGNORING) {
            /* This just means the line was empty or started with a
             * '#' or a ' ' and we are ignoring it.
             */
            gf_msg_debug(GF_EXP, 0,
                         "Ignoring line #%lu because it started "
                         "with a %c",
                         line_number, *line);
            continue;
        }

        if (!file) {
            file = _exports_file_init();
            GF_CHECK_ALLOC_AND_LOG(GF_EXP, file, ret,
                                   "Allocation error while "
                                   "allocating file struct",
                                   parse_done);

            file->filename = gf_strdup(filepath);
            GF_CHECK_ALLOC_AND_LOG(GF_EXP, file, ret,
                                   "Allocation error while "
                                   "duping filepath",
                                   free_and_done);
        }

        /* If the parsing is successful store the export directory
         * in the file structure.
         */
        _exp_file_insert(file, expdir);
    }

    /* line got allocated through getline(), don't use GF_FREE() for it */
    free(line);

    *expfile = file;
    goto parse_done;

free_and_done:
    exp_file_deinit(file);
    _export_dir_deinit(expdir);

parse_done:
    if (fp)
        fclose(fp);
    _exp_deinit_parsers();
    return ret;
}
コード例 #16
0
static int
glusterd_handle_mgmt_v3_unlock_fn (rpcsvc_request_t *req)
{
        gd1_mgmt_v3_unlock_req  lock_req        = {{0},};
        int32_t                 ret             = -1;
        glusterd_op_lock_ctx_t *ctx             = NULL;
        xlator_t               *this            = NULL;
        gf_boolean_t            is_synctasked   = _gf_false;
        gf_boolean_t            free_ctx        = _gf_false;

        this = THIS;
        GF_ASSERT (this);
        GF_ASSERT (req);

        ret = xdr_to_generic (req->msg[0], &lock_req,
                              (xdrproc_t)xdr_gd1_mgmt_v3_unlock_req);
        if (ret < 0) {
                gf_msg (this->name, GF_LOG_ERROR, 0,
                        GD_MSG_REQ_DECODE_FAIL, "Failed to decode unlock "
                        "request received from peer");
                req->rpc_err = GARBAGE_ARGS;
                goto out;
        }

        gf_msg_debug (this->name, 0, "Received volume unlock req "
                "from uuid: %s", uuid_utoa (lock_req.uuid));

        if (glusterd_peerinfo_find_by_uuid (lock_req.uuid) == NULL) {
                gf_msg (this->name, GF_LOG_WARNING, 0,
                        GD_MSG_PEER_NOT_FOUND, "%s doesn't "
                        "belong to the cluster. Ignoring request.",
                        uuid_utoa (lock_req.uuid));
                ret = -1;
                goto out;
        }

        ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_op_lock_ctx_t);
        if (!ctx) {
                ret = -1;
                goto out;
        }

        gf_uuid_copy (ctx->uuid, lock_req.uuid);
        ctx->req = req;

        ctx->dict = dict_new ();
        if (!ctx->dict) {
                ret = -1;
                goto out;
        }

        ret = dict_unserialize (lock_req.dict.dict_val,
                                lock_req.dict.dict_len, &ctx->dict);
        if (ret) {
                gf_msg (this->name, GF_LOG_WARNING, 0,
                        GD_MSG_DICT_UNSERIALIZE_FAIL,
                        "failed to unserialize the dictionary");
                goto out;
        }

        is_synctasked = dict_get_str_boolean (ctx->dict,
                                              "is_synctasked", _gf_false);
        if (is_synctasked) {
                ret = glusterd_syctasked_mgmt_v3_unlock (req, &lock_req, ctx);
                if (ret) {
                        gf_msg (this->name, GF_LOG_ERROR, 0,
                                GD_MSG_MGMTV3_UNLOCK_FAIL,
                                "Failed to release mgmt_v3_locks");
                        /* Ignore the return code, as it shouldn't be propagated
                         * from the handler function so as to avoid double
                         * deletion of the req
                         */
                        ret = 0;
                }

                /* The above function does not take ownership of ctx.
                 * Therefore we need to free the ctx explicitly. */
                free_ctx = _gf_true;
        }
        else {
                /* Shouldn't ignore the return code here, and it should
                 * be propagated from the handler function as in failure
                 * case it doesn't delete the req object
                 */
                ret = glusterd_op_state_machine_mgmt_v3_unlock (req, &lock_req,
                                                                ctx);
                if (ret)
                        gf_msg (this->name, GF_LOG_ERROR, 0,
                                GD_MSG_MGMTV3_UNLOCK_FAIL,
                                "Failed to release mgmt_v3_locks");
        }

out:

        if (ctx && (ret || free_ctx)) {
                if (ctx->dict)
                        dict_unref (ctx->dict);

                GF_FREE (ctx);
        }

        free (lock_req.dict.dict_val);

        gf_msg_trace (this->name, 0, "Returning %d", ret);
        return ret;
}
コード例 #17
0
ファイル: exports.c プロジェクト: gluster/glusterfs
/**
 * __exp_line_dir_parse -- Extract directory name from a line in the exports
 *                         file.
 *
 * @line    : The line to parse
 * @dirname : Double pointer to the string we need to hold the directory name.
 *            If the parsing failed, the string will point to NULL, otherwise
 *            it will point to a valid memory region that is allocated by
 *            this function.
 * @check_ms: If this variable is set then we cross check the directory line
 *            with what's in gluster's vol files and reject them if they don't
 *            match.
 *
 * @return : success: GF_EXP_PARSE_SUCCESS
 *           failure: GF_EXP_PARSE_ITEM_FAILURE on parse failure,
 *           -EINVAL on bad arguments, -ENOMEM on allocation failures,
 *           GF_EXP_PARSE_ITEM_NOT_IN_MOUNT_STATE if we failed to match
 *           with gluster's mountstate.
 *
 * The caller is responsible for freeing memory allocated by this function
 *
 * Not for external use.
 */
static int
__exp_line_dir_parse(const char *line, char **dirname, struct mount3_state *ms)
{
    char *dir = NULL;
    char *delim = NULL;
    int ret = -EINVAL;
    char *linedup = NULL;
    struct mnt3_export *mnt3export = NULL;
    size_t dirlen = 0;

    GF_VALIDATE_OR_GOTO(GF_EXP, line, out);
    GF_VALIDATE_OR_GOTO(GF_EXP, dirname, out);

    /* Duplicate the line because we don't
     * want to modify the original string.
     */
    linedup = strdupa(line);

    /* We use strtok_r () here to split the string by space/tab and get the
     * the result. We only need the first result of the split.
     * a simple task. It is worth noting that dirnames always have to be
     * validated against gluster's vol files so if they don't
     * match it will be rejected.
     */
    dir = linedup;
    delim = linedup + strcspn(linedup, " \t");
    *delim = 0;

    if (ms) {
        /* Match the directory name with an existing
         * export in the mount state.
         */
        mnt3export = mnt3_mntpath_to_export(ms, dir, _gf_true);
        if (!mnt3export) {
            gf_msg_debug(GF_EXP, 0,
                         "%s not in mount state, "
                         "ignoring!",
                         dir);
            ret = GF_EXP_PARSE_ITEM_NOT_IN_MOUNT_STATE;
            goto out;
        }
    }

    /* Directories can be 1024 bytes in length, check
     * that the argument provided adheres to
     * that restriction.
     */
    if (strlen(dir) > DIR_MAX_LEN) {
        ret = -EINVAL;
        goto out;
    }

    /* Copy the result of the split */
    dir = gf_strdup(dir);
    GF_CHECK_ALLOC(dir, ret, out);

    /* Ensure that trailing slashes are stripped before storing the name */
    dirlen = strlen(dir);
    if (dirlen > 0 && dir[dirlen - 1] == '/')
        dir[dirlen - 1] = '\0';

    /* Set the argument to point to the allocated string */
    *dirname = dir;
    ret = GF_EXP_PARSE_SUCCESS;
out:
    return ret;
}
コード例 #18
0
static int
event_dispatch_epoll_handler (struct event_pool *event_pool,
                              struct epoll_event *event)
{
        struct event_data  *ev_data = NULL;
	struct event_slot_epoll *slot = NULL;
        event_handler_t     handler = NULL;
        void               *data = NULL;
        int                 idx = -1;
	int                 gen = -1;
        int                 ret = -1;
	int                 fd = -1;

	ev_data = (void *)&event->data;
        handler = NULL;
        data = NULL;

	idx = ev_data->idx;
	gen = ev_data->gen;

	slot = event_slot_get (event_pool, idx);

	LOCK (&slot->lock);
	{
		fd = slot->fd;
		if (fd == -1) {
			gf_msg ("epoll", GF_LOG_ERROR, 0,
                                LG_MSG_STALE_FD_FOUND, "stale fd found on "
                                "idx=%d, gen=%d, events=%d, slot->gen=%d",
				idx, gen, event->events, slot->gen);
			/* fd got unregistered in another thread */
			goto pre_unlock;
		}

		if (gen != slot->gen) {
			gf_msg ("epoll", GF_LOG_ERROR, 0,
                                LG_MSG_GENERATION_MISMATCH, "generation "
                                "mismatch on idx=%d, gen=%d, slot->gen=%d, "
                                "slot->fd=%d", idx, gen, slot->gen, slot->fd);
			/* slot was re-used and therefore is another fd! */
			goto pre_unlock;
		}

		handler = slot->handler;
		data = slot->data;

		slot->in_handler++;
	}
pre_unlock:
	UNLOCK (&slot->lock);

        if (!handler)
		goto out;

	ret = handler (fd, idx, data,
		       (event->events & (EPOLLIN|EPOLLPRI)),
		       (event->events & (EPOLLOUT)),
		       (event->events & (EPOLLERR|EPOLLHUP)));

	LOCK (&slot->lock);
	{
		slot->in_handler--;

		if (gen != slot->gen) {
			/* event_unregister() happened while we were
			   in handler()
			*/
			gf_msg_debug ("epoll", 0, "generation bumped on idx=%d"
                                      " from gen=%d to slot->gen=%d, fd=%d, "
				      "slot->fd=%d", idx, gen, slot->gen, fd,
                                      slot->fd);
			goto post_unlock;
		}

		/* This call also picks up the changes made by another
		   thread calling event_select_on_epoll() while this
		   thread was busy in handler()
		*/
                if (slot->in_handler == 0) {
                        event->events = slot->events;
                        ret = epoll_ctl (event_pool->fd, EPOLL_CTL_MOD,
                                         fd, event);
                }
	}
post_unlock:
	UNLOCK (&slot->lock);
out:
	event_slot_unref (event_pool, slot, idx);

        return ret;
}