diff options
Diffstat (limited to 'xlators/encryption/crypt/src/atom.c')
| -rw-r--r-- | xlators/encryption/crypt/src/atom.c | 861 | 
1 files changed, 0 insertions, 861 deletions
diff --git a/xlators/encryption/crypt/src/atom.c b/xlators/encryption/crypt/src/atom.c deleted file mode 100644 index bdc37c500a3..00000000000 --- a/xlators/encryption/crypt/src/atom.c +++ /dev/null @@ -1,861 +0,0 @@ -/* -  Copyright (c) 2008-2013 Red Hat, Inc. <http://www.redhat.com> -  This file is part of GlusterFS. - -  This file is licensed to you under your choice of the GNU Lesser -  General Public License, version 3 or any later version (LGPLv3 or -  later), or the GNU General Public License, version 2 (GPLv2), in all -  cases as published by the Free Software Foundation. -*/ - -#include <glusterfs/defaults.h> -#include "crypt-common.h" -#include "crypt.h" - -/* - *                              Glossary - * - * - * cblock            (or cipher block). A logical unit in a file. - *                   cblock size is defined as the number of bits - *                   in an input (or output) block of the block - *                   cipher (*). Cipher block size is a property of - *                   cipher algorithm. E.g. cblock size is 64 bits - *                   for DES, 128 bits for AES, etc. - * - * atomic cipher     A cipher algorithm, which requires some chunks of - * algorithm         text to be padded at left and(or) right sides before - *                   cipher transaform. - * - * - * block (atom)      Minimal chunk of file's data, which doesn't require - *                   padding. We'll consider logical units in a file of - *                   block size (atom size). - * - * cipher algorithm  Atomic cipher algorithm, which requires the last - * with EOF issue    incomplete cblock in a file to be padded with some - *                   data (usually zeros). - * - * - * operation, which  reading/writing from offset, which is not aligned to - * forms a gap at    to atom size - * the beginning - * - * - * operation, which  reading/writing count bytes starting from offset off, - * forms a gap at    so that off+count is not aligned to atom_size - * the end - * - * head block        the first atom affected by an operation, which forms - *                   a gap at the beginning, or(and) at the end. - *                   Сomment. Head block has at least one gap (either at - *                   the beginning, or at the end) - * - * - * tail block        the last atom different from head, affected by an - *                   operation, which forms a gap at the end. - *                   Сomment: Tail block has exactly one gap (at the end). - * - * - * partial block     head or tail block - * - * - * full block        block without gaps. - * - * - * (*) Recommendation for Block Cipher Modes of Operation - *     Methods and Techniques - *     NIST Special Publication 800-38A Edition 2001 - */ - -/* - * atom->offset_at() - */ -static off_t -offset_at_head(struct avec_config *conf) -{ -    return conf->aligned_offset; -} - -static off_t -offset_at_hole_head(call_frame_t *frame, struct object_cipher_info *object) -{ -    return offset_at_head(get_hole_conf(frame)); -} - -static off_t -offset_at_data_head(call_frame_t *frame, struct object_cipher_info *object) -{ -    return offset_at_head(get_data_conf(frame)); -} - -static off_t -offset_at_tail(struct avec_config *conf, struct object_cipher_info *object) -{ -    return conf->aligned_offset + -           (conf->off_in_head ? get_atom_size(object) : 0) + -           (conf->nr_full_blocks << get_atom_bits(object)); -} - -static off_t -offset_at_hole_tail(call_frame_t *frame, struct object_cipher_info *object) -{ -    return offset_at_tail(get_hole_conf(frame), object); -} - -static off_t -offset_at_data_tail(call_frame_t *frame, struct object_cipher_info *object) -{ -    return offset_at_tail(get_data_conf(frame), object); -} - -static off_t -offset_at_full(struct avec_config *conf, struct object_cipher_info *object) -{ -    return conf->aligned_offset + -           (conf->off_in_head ? get_atom_size(object) : 0); -} - -static off_t -offset_at_data_full(call_frame_t *frame, struct object_cipher_info *object) -{ -    return offset_at_full(get_data_conf(frame), object); -} - -static off_t -offset_at_hole_full(call_frame_t *frame, struct object_cipher_info *object) -{ -    return offset_at_full(get_hole_conf(frame), object); -} - -/* - * atom->io_size_nopad() - */ - -static uint32_t -io_size_nopad_head(struct avec_config *conf, struct object_cipher_info *object) -{ -    uint32_t gap_at_beg; -    uint32_t gap_at_end; - -    check_head_block(conf); - -    gap_at_beg = conf->off_in_head; - -    if (has_tail_block(conf) || has_full_blocks(conf) || conf->off_in_tail == 0) -        gap_at_end = 0; -    else -        gap_at_end = get_atom_size(object) - conf->off_in_tail; - -    return get_atom_size(object) - (gap_at_beg + gap_at_end); -} - -static uint32_t -io_size_nopad_tail(struct avec_config *conf, struct object_cipher_info *object) -{ -    check_tail_block(conf); -    return conf->off_in_tail; -} - -static uint32_t -io_size_nopad_full(struct avec_config *conf, struct object_cipher_info *object) -{ -    check_full_block(conf); -    return get_atom_size(object); -} - -static uint32_t -io_size_nopad_data_head(call_frame_t *frame, struct object_cipher_info *object) -{ -    return io_size_nopad_head(get_data_conf(frame), object); -} - -static uint32_t -io_size_nopad_hole_head(call_frame_t *frame, struct object_cipher_info *object) -{ -    return io_size_nopad_head(get_hole_conf(frame), object); -} - -static uint32_t -io_size_nopad_data_tail(call_frame_t *frame, struct object_cipher_info *object) -{ -    return io_size_nopad_tail(get_data_conf(frame), object); -} - -static uint32_t -io_size_nopad_hole_tail(call_frame_t *frame, struct object_cipher_info *object) -{ -    return io_size_nopad_tail(get_hole_conf(frame), object); -} - -static uint32_t -io_size_nopad_data_full(call_frame_t *frame, struct object_cipher_info *object) -{ -    return io_size_nopad_full(get_data_conf(frame), object); -} - -static uint32_t -io_size_nopad_hole_full(call_frame_t *frame, struct object_cipher_info *object) -{ -    return io_size_nopad_full(get_hole_conf(frame), object); -} - -static uint32_t -offset_in_head(struct avec_config *conf) -{ -    check_cursor_head(conf); - -    return conf->off_in_head; -} - -static uint32_t -offset_in_tail(call_frame_t *frame, struct object_cipher_info *object) -{ -    return 0; -} - -static uint32_t -offset_in_full(struct avec_config *conf, struct object_cipher_info *object) -{ -    check_cursor_full(conf); - -    if (has_head_block(conf)) -        return (conf->cursor - 1) << get_atom_bits(object); -    else -        return conf->cursor << get_atom_bits(object); -} - -static uint32_t -offset_in_data_head(call_frame_t *frame, struct object_cipher_info *object) -{ -    return offset_in_head(get_data_conf(frame)); -} - -static uint32_t -offset_in_hole_head(call_frame_t *frame, struct object_cipher_info *object) -{ -    return offset_in_head(get_hole_conf(frame)); -} - -static uint32_t -offset_in_data_full(call_frame_t *frame, struct object_cipher_info *object) -{ -    return offset_in_full(get_data_conf(frame), object); -} - -static uint32_t -offset_in_hole_full(call_frame_t *frame, struct object_cipher_info *object) -{ -    return offset_in_full(get_hole_conf(frame), object); -} - -/* - * atom->rmw() - */ -/* - * Pre-conditions: - * @vec contains plain text of the latest - * version. - * - * Uptodate gaps of the @partial block with - * this plain text, encrypt the whole block - * and write the result to disk. - */ -static int32_t -rmw_partial_block(call_frame_t *frame, void *cookie, xlator_t *this, -                  int32_t op_ret, int32_t op_errno, struct iovec *vec, -                  int32_t count, struct iatt *stbuf, struct iobref *iobref, -                  struct rmw_atom *atom) -{ -    size_t was_read = 0; -    uint64_t file_size; -    crypt_local_t *local = frame->local; -    struct object_cipher_info *object = &local->info->cinfo; - -    struct iovec *partial = atom->get_iovec(frame, 0); -    struct avec_config *conf = atom->get_config(frame); -    end_writeback_handler_t end_writeback_partial_block; -#if DEBUG_CRYPT -    gf_boolean_t check_last_cblock = _gf_false; -#endif -    local->op_ret = op_ret; -    local->op_errno = op_errno; - -    if (op_ret < 0) -        goto exit; - -    file_size = local->cur_file_size; -    was_read = op_ret; - -    if (atom->locality == HEAD_ATOM && conf->off_in_head) { -        /* -         * head atom with a non-uptodate gap -         * at the beginning -         * -         * fill the gap with plain text of the -         * latest version. Convert a part of hole -         * (if any) to zeros. -         */ -        int32_t i; -        int32_t copied = 0; -        int32_t to_gap; /* amount of data needed to uptodate -                           the gap at the beginning */ -#if 0 -		int32_t hole = 0; /* The part of the hole which -				   * got in the head block */ -#endif /* 0 */ -        to_gap = conf->off_in_head; - -        if (was_read < to_gap) { -            if (file_size > offset_at_head(conf) + was_read) { -                /* -                 * It is impossible to uptodate -                 * head block: too few bytes have -                 * been read from disk, so that -                 * partial write is impossible. -                 * -                 * It could happen because of many -                 * reasons: IO errors, (meta)data -                 * corruption in the local file system, -                 * etc. -                 */ -                gf_log(this->name, GF_LOG_WARNING, -                       "Can not uptodate a gap at the beginning"); -                local->op_ret = -1; -                local->op_errno = EIO; -                goto exit; -            } -#if 0 -			hole = to_gap - was_read; -#endif /* 0 */ -            to_gap = was_read; -        } -        /* -         * uptodate the gap at the beginning -         */ -        for (i = 0; i < count && copied < to_gap; i++) { -            int32_t to_copy; - -            to_copy = vec[i].iov_len; -            if (to_copy > to_gap - copied) -                to_copy = to_gap - copied; - -            memcpy(partial->iov_base, vec[i].iov_base, to_copy); -            copied += to_copy; -        } -#if 0 -		/* -		 * If possible, convert part of the -		 * hole, which got in the head block -		 */ -		ret = TRY_LOCK(&local->hole_lock); -		if (!ret) { -			if (local->hole_handled) -				/* -				 * already converted by -				 * crypt_writev_cbk() -				 */ -				UNLOCK(&local->hole_lock); -			else { -				/* -				 * convert the part of the hole -				 * which got in the head block -				 * to zeros. -				 * -				 * Update the orig_offset to make -				 * sure writev_cbk() won't care -				 * about this part of the hole. -				 * -				 */ -				memset(partial->iov_base + to_gap, 0, hole); - -				conf->orig_offset -= hole; -				conf->orig_size += hole; -				UNLOCK(&local->hole_lock); -			} -		} -		else /* -		      * conversion is being performed -		      * by crypt_writev_cbk() -		      */ -			; -#endif /* 0 */ -    } -    if (atom->locality == TAIL_ATOM || -        (!has_tail_block(conf) && conf->off_in_tail)) { -        /* -         * tail atom, or head atom with a non-uptodate -         * gap at the end. -         * -         * fill the gap at the end of the block -         * with plain text of the latest version. -         * Pad the result, (if needed) -         */ -        int32_t i; -        int32_t to_gap; -        int copied; -        off_t off_in_tail; -        int32_t to_copy; - -        off_in_tail = conf->off_in_tail; -        to_gap = conf->gap_in_tail; - -        if (to_gap && was_read < off_in_tail + to_gap) { -            /* -             * It is impossible to uptodate -             * the gap at the end: too few bytes -             * have been read from disk, so that -             * partial write is impossible. -             * -             * It could happen because of many -             * reasons: IO errors, (meta)data -             * corruption in the local file system, -             * etc. -             */ -            gf_log(this->name, GF_LOG_WARNING, -                   "Can not uptodate a gap at the end"); -            local->op_ret = -1; -            local->op_errno = EIO; -            goto exit; -        } -        /* -         * uptodate the gap at the end -         */ -        copied = 0; -        to_copy = to_gap; -        for (i = count - 1; i >= 0 && to_copy > 0; i--) { -            uint32_t from_vec, off_in_vec; - -            off_in_vec = 0; -            from_vec = vec[i].iov_len; -            if (from_vec > to_copy) { -                off_in_vec = from_vec - to_copy; -                from_vec = to_copy; -            } -            memcpy(partial->iov_base + off_in_tail + to_gap - copied - from_vec, -                   vec[i].iov_base + off_in_vec, from_vec); - -            gf_log( -                this->name, GF_LOG_DEBUG, -                "uptodate %d bytes at tail. Offset at target(source): %d(%d)", -                (int)from_vec, (int)off_in_tail + to_gap - copied - from_vec, -                (int)off_in_vec); - -            copied += from_vec; -            to_copy -= from_vec; -        } -        partial->iov_len = off_in_tail + to_gap; - -        if (object_alg_should_pad(object)) { -            int32_t resid = 0; -            resid = partial->iov_len & (object_alg_blksize(object) - 1); -            if (resid) { -                /* -                 * append a new EOF padding -                 */ -                local->eof_padding_size = object_alg_blksize(object) - resid; - -                gf_log(this->name, GF_LOG_DEBUG, "set padding size %d", -                       local->eof_padding_size); - -                memset(partial->iov_base + partial->iov_len, 1, -                       local->eof_padding_size); -                partial->iov_len += local->eof_padding_size; -#if DEBUG_CRYPT -                gf_log(this->name, GF_LOG_DEBUG, -                       "pad cblock with %d zeros:", local->eof_padding_size); -                dump_cblock(this, (unsigned char *)partial->iov_base + -                                      partial->iov_len - -                                      object_alg_blksize(object)); -                check_last_cblock = _gf_true; -#endif -            } -        } -    } -    /* -     * encrypt the whole block -     */ -    encrypt_aligned_iov(object, partial, 1, atom->offset_at(frame, object)); -#if DEBUG_CRYPT -    if (check_last_cblock == _gf_true) { -        gf_log(this->name, GF_LOG_DEBUG, "encrypt last cblock with offset %llu", -               (unsigned long long)atom->offset_at(frame, object)); -        dump_cblock(this, (unsigned char *)partial->iov_base + -                              partial->iov_len - object_alg_blksize(object)); -    } -#endif -    set_local_io_params_writev(frame, object, atom, -                               atom->offset_at(frame, object), -                               iov_length(partial, 1)); -    /* -     * write the whole block to disk -     */ -    end_writeback_partial_block = dispatch_end_writeback(local->fop); -    conf->cursor++; -    STACK_WIND(frame, end_writeback_partial_block, FIRST_CHILD(this), -               FIRST_CHILD(this)->fops->writev, local->fd, partial, 1, -               atom->offset_at(frame, object), local->flags, local->iobref_data, -               local->xdata); - -    gf_log("crypt", GF_LOG_DEBUG, -           "submit partial block: %d bytes from %d offset", -           (int)iov_length(partial, 1), (int)atom->offset_at(frame, object)); -exit: -    return 0; -} - -/* - * Perform a (read-)modify-write sequence. - * This should be performed only after approval - * of upper server-side manager, i.e. the caller - * needs to make sure this is his turn to rmw. - */ -void -submit_partial(call_frame_t *frame, xlator_t *this, fd_t *fd, -               atom_locality_type ltype) -{ -    int32_t ret; -    dict_t *dict; -    struct rmw_atom *atom; -    crypt_local_t *local = frame->local; -    struct object_cipher_info *object = &local->info->cinfo; - -    atom = atom_by_types(local->active_setup, ltype); -    /* -     * To perform the "read" component of the read-modify-write -     * sequence the crypt translator does stack_wind to itself. -     * -     * Pass current file size to crypt_readv() -     */ -    dict = dict_new(); -    if (!dict) { -        /* -         * FIXME: Handle the error -         */ -        gf_log("crypt", GF_LOG_WARNING, "Can not alloc dict"); -        return; -    } -    ret = dict_set(dict, FSIZE_XATTR_PREFIX, -                   data_from_uint64(local->cur_file_size)); -    if (ret) { -        /* -         * FIXME: Handle the error -         */ -        dict_unref(dict); -        gf_log("crypt", GF_LOG_WARNING, "Can not set dict"); -        goto exit; -    } -    STACK_WIND(frame, atom->rmw, this, this->fops->readv,  /* crypt_readv */ -               fd, atom->count_to_uptodate(frame, object), /* count */ -               atom->offset_at(frame, object), /* offset to read from */ -               0, dict); -exit: -    dict_unref(dict); -} - -/* - * submit blocks of FULL_ATOM type - */ -void -submit_full(call_frame_t *frame, xlator_t *this) -{ -    crypt_local_t *local = frame->local; -    struct object_cipher_info *object = &local->info->cinfo; -    struct rmw_atom *atom = atom_by_types(local->active_setup, FULL_ATOM); -    uint32_t count;       /* total number of full blocks to submit */ -    uint32_t granularity; /* number of blocks to submit in one iteration */ - -    uint64_t off_in_file;        /* start offset in the file, bytes */ -    uint32_t off_in_atom;        /* start offset in the atom, blocks */ -    uint32_t blocks_written = 0; /* blocks written for this submit */ - -    struct avec_config *conf = atom->get_config(frame); -    end_writeback_handler_t end_writeback_full_block; -    /* -     * Write full blocks by groups of granularity size. -     */ -    end_writeback_full_block = dispatch_end_writeback(local->fop); - -    if (is_ordered_mode(frame)) { -        uint32_t skip = has_head_block(conf) ? 1 : 0; -        count = 1; -        granularity = 1; -        /* -         * calculate start offset using cursor value; -         * here we should take into account head block, -         * which corresponds to cursor value 0. -         */ -        off_in_file = atom->offset_at(frame, object) + -                      ((conf->cursor - skip) << get_atom_bits(object)); -        off_in_atom = conf->cursor - skip; -    } else { -        /* -         * in parallel mode -         */ -        count = conf->nr_full_blocks; -        granularity = MAX_IOVEC; -        off_in_file = atom->offset_at(frame, object); -        off_in_atom = 0; -    } -    while (count) { -        uint32_t blocks_to_write = count; - -        if (blocks_to_write > granularity) -            blocks_to_write = granularity; -        if (conf->type == HOLE_ATOM) -            /* -             * reset iovec before encryption -             */ -            memset(atom->get_iovec(frame, 0)->iov_base, 0, -                   get_atom_size(object)); -        /* -         * encrypt the group -         */ -        encrypt_aligned_iov( -            object, atom->get_iovec(frame, off_in_atom + blocks_written), -            blocks_to_write, -            off_in_file + (blocks_written << get_atom_bits(object))); - -        set_local_io_params_writev( -            frame, object, atom, -            off_in_file + (blocks_written << get_atom_bits(object)), -            blocks_to_write << get_atom_bits(object)); - -        conf->cursor += blocks_to_write; - -        STACK_WIND(frame, end_writeback_full_block, FIRST_CHILD(this), -                   FIRST_CHILD(this)->fops->writev, local->fd, -                   atom->get_iovec(frame, off_in_atom + blocks_written), -                   blocks_to_write, -                   off_in_file + (blocks_written << get_atom_bits(object)), -                   local->flags, -                   local->iobref_data ? local->iobref_data : local->iobref, -                   local->xdata); - -        gf_log("crypt", GF_LOG_DEBUG, "submit %d full blocks from %d offset", -               blocks_to_write, -               (int)(off_in_file + (blocks_written << get_atom_bits(object)))); - -        count -= blocks_to_write; -        blocks_written += blocks_to_write; -    } -    return; -} - -static int32_t -rmw_data_head(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, -              int32_t op_errno, struct iovec *vec, int32_t count, -              struct iatt *stbuf, struct iobref *iobref, dict_t *xdata) -{ -    return rmw_partial_block(frame, cookie, this, op_ret, op_errno, vec, count, -                             stbuf, iobref, -                             atom_by_types(DATA_ATOM, HEAD_ATOM)); -} - -static int32_t -rmw_data_tail(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, -              int32_t op_errno, struct iovec *vec, int32_t count, -              struct iatt *stbuf, struct iobref *iobref, dict_t *xdata) -{ -    return rmw_partial_block(frame, cookie, this, op_ret, op_errno, vec, count, -                             stbuf, iobref, -                             atom_by_types(DATA_ATOM, TAIL_ATOM)); -} - -static int32_t -rmw_hole_head(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, -              int32_t op_errno, struct iovec *vec, int32_t count, -              struct iatt *stbuf, struct iobref *iobref, dict_t *xdata) -{ -    return rmw_partial_block(frame, cookie, this, op_ret, op_errno, vec, count, -                             stbuf, iobref, -                             atom_by_types(HOLE_ATOM, HEAD_ATOM)); -} - -static int32_t -rmw_hole_tail(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, -              int32_t op_errno, struct iovec *vec, int32_t count, -              struct iatt *stbuf, struct iobref *iobref, dict_t *xdata) -{ -    return rmw_partial_block(frame, cookie, this, op_ret, op_errno, vec, count, -                             stbuf, iobref, -                             atom_by_types(HOLE_ATOM, TAIL_ATOM)); -} - -/* - * atom->count_to_uptodate() - */ -static uint32_t -count_to_uptodate_head(struct avec_config *conf, -                       struct object_cipher_info *object) -{ -    if (conf->acount == 1 && conf->off_in_tail) -        return get_atom_size(object); -    else -        /* there is no need to read the whole head block */ -        return conf->off_in_head; -} - -static uint32_t -count_to_uptodate_tail(struct avec_config *conf, -                       struct object_cipher_info *object) -{ -    /* we need to read the whole tail block */ -    return get_atom_size(object); -} - -static uint32_t -count_to_uptodate_data_head(call_frame_t *frame, -                            struct object_cipher_info *object) -{ -    return count_to_uptodate_head(get_data_conf(frame), object); -} - -static uint32_t -count_to_uptodate_data_tail(call_frame_t *frame, -                            struct object_cipher_info *object) -{ -    return count_to_uptodate_tail(get_data_conf(frame), object); -} - -static uint32_t -count_to_uptodate_hole_head(call_frame_t *frame, -                            struct object_cipher_info *object) -{ -    return count_to_uptodate_head(get_hole_conf(frame), object); -} - -static uint32_t -count_to_uptodate_hole_tail(call_frame_t *frame, -                            struct object_cipher_info *object) -{ -    return count_to_uptodate_tail(get_hole_conf(frame), object); -} - -/* atom->get_config() */ - -static struct avec_config * -get_config_data(call_frame_t *frame) -{ -    return &((crypt_local_t *)frame->local)->data_conf; -} - -static struct avec_config * -get_config_hole(call_frame_t *frame) -{ -    return &((crypt_local_t *)frame->local)->hole_conf; -} - -/* - * atom->get_iovec() - */ -static struct iovec * -get_iovec_hole_head(call_frame_t *frame, uint32_t count) -{ -    struct avec_config *conf = get_hole_conf(frame); - -    return conf->avec; -} - -static struct iovec * -get_iovec_hole_full(call_frame_t *frame, uint32_t count) -{ -    struct avec_config *conf = get_hole_conf(frame); - -    return conf->avec + (conf->off_in_head ? 1 : 0); -} - -static struct iovec * -get_iovec_hole_tail(call_frame_t *frame, uint32_t count) -{ -    struct avec_config *conf = get_hole_conf(frame); - -    return conf->avec + (conf->blocks_in_pool - 1); -} - -static struct iovec * -get_iovec_data_head(call_frame_t *frame, uint32_t count) -{ -    struct avec_config *conf = get_data_conf(frame); - -    return conf->avec; -} - -static struct iovec * -get_iovec_data_full(call_frame_t *frame, uint32_t count) -{ -    struct avec_config *conf = get_data_conf(frame); - -    return conf->avec + (conf->off_in_head ? 1 : 0) + count; -} - -static struct iovec * -get_iovec_data_tail(call_frame_t *frame, uint32_t count) -{ -    struct avec_config *conf = get_data_conf(frame); - -    return conf->avec + (conf->off_in_head ? 1 : 0) + conf->nr_full_blocks; -} - -static struct rmw_atom atoms[LAST_DATA_TYPE][LAST_LOCALITY_TYPE] = { -    [DATA_ATOM][HEAD_ATOM] = {.locality = HEAD_ATOM, -                              .rmw = rmw_data_head, -                              .offset_at = offset_at_data_head, -                              .offset_in = offset_in_data_head, -                              .get_iovec = get_iovec_data_head, -                              .io_size_nopad = io_size_nopad_data_head, -                              .count_to_uptodate = count_to_uptodate_data_head, -                              .get_config = get_config_data}, -    [DATA_ATOM][TAIL_ATOM] = {.locality = TAIL_ATOM, -                              .rmw = rmw_data_tail, -                              .offset_at = offset_at_data_tail, -                              .offset_in = offset_in_tail, -                              .get_iovec = get_iovec_data_tail, -                              .io_size_nopad = io_size_nopad_data_tail, -                              .count_to_uptodate = count_to_uptodate_data_tail, -                              .get_config = get_config_data}, -    [DATA_ATOM][FULL_ATOM] = {.locality = FULL_ATOM, -                              .offset_at = offset_at_data_full, -                              .offset_in = offset_in_data_full, -                              .get_iovec = get_iovec_data_full, -                              .io_size_nopad = io_size_nopad_data_full, -                              .get_config = get_config_data}, -    [HOLE_ATOM][HEAD_ATOM] = {.locality = HEAD_ATOM, -                              .rmw = rmw_hole_head, -                              .offset_at = offset_at_hole_head, -                              .offset_in = offset_in_hole_head, -                              .get_iovec = get_iovec_hole_head, -                              .io_size_nopad = io_size_nopad_hole_head, -                              .count_to_uptodate = count_to_uptodate_hole_head, -                              .get_config = get_config_hole}, -    [HOLE_ATOM][TAIL_ATOM] = {.locality = TAIL_ATOM, -                              .rmw = rmw_hole_tail, -                              .offset_at = offset_at_hole_tail, -                              .offset_in = offset_in_tail, -                              .get_iovec = get_iovec_hole_tail, -                              .io_size_nopad = io_size_nopad_hole_tail, -                              .count_to_uptodate = count_to_uptodate_hole_tail, -                              .get_config = get_config_hole}, -    [HOLE_ATOM][FULL_ATOM] = {.locality = FULL_ATOM, -                              .offset_at = offset_at_hole_full, -                              .offset_in = offset_in_hole_full, -                              .get_iovec = get_iovec_hole_full, -                              .io_size_nopad = io_size_nopad_hole_full, -                              .get_config = get_config_hole}}; - -struct rmw_atom * -atom_by_types(atom_data_type data, atom_locality_type locality) -{ -    return &atoms[data][locality]; -} - -/* -  Local variables: -  c-indentation-style: "K&R" -  mode-name: "LC" -  c-basic-offset: 8 -  tab-width: 8 -  fill-column: 80 -  scroll-step: 1 -  End: -*/  | 
