diff options
| author | Xavier Hernandez <xhernandez@datalab.es> | 2014-05-05 12:57:34 +0200 | 
|---|---|---|
| committer | Vijay Bellur <vbellur@redhat.com> | 2014-07-11 10:33:40 -0700 | 
| commit | ad112305a1c7452b13c92238b40ded80361838f3 (patch) | |
| tree | 82dbf9aa0b77eb76d43c8b1ccb3ba58e61bc4e2a | |
| parent | 6b4702897bd56e29db4db06f8cf896f89df1133c (diff) | |
cluster/ec: Added erasure code translator
Change-Id: I293917501d5c2ca4cdc6303df30cf0b568cea361
BUG: 1118629
Signed-off-by: Xavier Hernandez <xhernandez@datalab.es>
Reviewed-on: http://review.gluster.org/7749
Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com>
Reviewed-by: Jeff Darcy <jdarcy@redhat.com>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
27 files changed, 26034 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index 8ea92b988b4..d7350912fd9 100644 --- a/configure.ac +++ b/configure.ac @@ -72,6 +72,8 @@ AC_CONFIG_FILES([Makefile                  xlators/cluster/stripe/src/Makefile                  xlators/cluster/dht/Makefile                  xlators/cluster/dht/src/Makefile +                xlators/cluster/ec/Makefile +                xlators/cluster/ec/src/Makefile                  xlators/performance/Makefile                  xlators/performance/write-behind/Makefile                  xlators/performance/write-behind/src/Makefile diff --git a/xlators/cluster/Makefile.am b/xlators/cluster/Makefile.am index 0990822a7d3..903fbb39f12 100644 --- a/xlators/cluster/Makefile.am +++ b/xlators/cluster/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = stripe afr dht +SUBDIRS = stripe afr dht ec  CLEANFILES =  diff --git a/xlators/cluster/ec/Makefile.am b/xlators/cluster/ec/Makefile.am new file mode 100644 index 00000000000..d471a3f9243 --- /dev/null +++ b/xlators/cluster/ec/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src + +CLEANFILES =  diff --git a/xlators/cluster/ec/src/Makefile.am b/xlators/cluster/ec/src/Makefile.am new file mode 100644 index 00000000000..e2a9330a944 --- /dev/null +++ b/xlators/cluster/ec/src/Makefile.am @@ -0,0 +1,49 @@ +xlator_LTLIBRARIES = ec.la +xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/cluster + +ec_sources := ec.c +ec_sources += ec-data.c +ec_sources += ec-helpers.c +ec_sources += ec-common.c +ec_sources += ec-generic.c +ec_sources += ec-locks.c +ec_sources += ec-dir-read.c +ec_sources += ec-dir-write.c +ec_sources += ec-inode-read.c +ec_sources += ec-inode-write.c +ec_sources += ec-combine.c +ec_sources += ec-gf.c +ec_sources += ec-method.c +ec_sources += ec-heal.c + +ec_headers := ec.h +ec_headers += ec-mem-types.h +ec_headers += ec-helpers.h +ec_headers += ec-data.h +ec_headers += ec-fops.h +ec_headers += ec-common.h +ec_headers += ec-combine.h +ec_headers += ec-gf.h +ec_headers += ec-method.h + +ec_ext_sources = $(top_builddir)/xlators/lib/src/libxlator.c + +ec_ext_headers = $(top_builddir)/xlators/lib/src/libxlator.h + +ec_la_LDFLAGS = -module -avoid-version +ec_la_SOURCES = $(ec_sources) $(ec_headers) $(ec_ext_sources) $(ec_ext_headers) +ec_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la + +AM_CPPFLAGS  = $(GF_CPPFLAGS) +AM_CPPFLAGS += -I$(top_srcdir)/libglusterfs/src +AM_CPPFLAGS += -I$(top_srcdir)/xlators/lib/src + +AM_CFLAGS = -Wall $(GF_CFLAGS) + +CLEANFILES = + +install-data-hook: +	ln -sf ec.so $(DESTDIR)$(xlatordir)/disperse.so + +uninstall-local: +	rm -f $(DESTDIR)$(xlatordir)/disperse.so diff --git a/xlators/cluster/ec/src/ec-combine.c b/xlators/cluster/ec/src/ec-combine.c new file mode 100644 index 00000000000..07d819a9a3d --- /dev/null +++ b/xlators/cluster/ec/src/ec-combine.c @@ -0,0 +1,787 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include <fnmatch.h> + +#include "libxlator.h" + +#include "ec-data.h" +#include "ec-helpers.h" +#include "ec-common.h" +#include "ec-combine.h" + +struct _ec_dict_info; +typedef struct _ec_dict_info ec_dict_info_t; + +struct _ec_dict_combine; +typedef struct _ec_dict_combine ec_dict_combine_t; + +struct _ec_dict_info +{ +    dict_t * dict; +    int32_t  count; +}; + +struct _ec_dict_combine +{ +    ec_cbk_data_t * cbk; +    int32_t         which; +}; + +void ec_iatt_time_merge(uint32_t * dst_sec, uint32_t * dst_nsec, +                        uint32_t src_sec, uint32_t src_nsec) +{ +    if ((*dst_sec < src_sec) || +        ((*dst_sec == src_sec) && (*dst_nsec < src_nsec))) +    { +        *dst_sec = src_sec; +        *dst_nsec = src_nsec; +    } +} + +int32_t ec_iatt_combine(struct iatt * dst, struct iatt * src, int32_t count) +{ +    int32_t i; + +    for (i = 0; i < count; i++) +    { +        if ((dst->ia_ino != src->ia_ino) || +            (dst->ia_uid != src->ia_uid) || +            (dst->ia_gid != src->ia_gid) || +            (((dst->ia_type == IA_IFBLK) || (dst->ia_type == IA_IFCHR)) && +             (dst->ia_rdev != src->ia_rdev)) || +            ((dst->ia_type == IA_IFREG) && (dst->ia_size != src->ia_size)) || +            (st_mode_from_ia(dst->ia_prot, dst->ia_type) != +             st_mode_from_ia(src->ia_prot, src->ia_type)) || +            (uuid_compare(dst->ia_gfid, src->ia_gfid) != 0)) +        { +            gf_log(THIS->name, GF_LOG_WARNING, +                   "Failed to combine iatt (inode: %lu-%lu, links: %u-%u, " +                   "uid: %u-%u, gid: %u-%u, rdev: %lu-%lu, size: %lu-%lu, " +                   "mode: %o-%o)", +                   dst->ia_ino, src->ia_ino, dst->ia_nlink, src->ia_nlink, +                   dst->ia_uid, src->ia_uid, dst->ia_gid, src->ia_gid, +                   dst->ia_rdev, src->ia_rdev, dst->ia_size, src->ia_size, +                   st_mode_from_ia(dst->ia_prot, dst->ia_type), +                   st_mode_from_ia(src->ia_prot, dst->ia_type)); + +            return 0; +        } +    } + +    while (count-- > 0) +    { +        dst->ia_blocks += src->ia_blocks; +        if (dst->ia_blksize < src->ia_blksize) +        { +            dst->ia_blksize = src->ia_blksize; +        } + +        ec_iatt_time_merge(&dst->ia_atime, &dst->ia_atime_nsec, src->ia_atime, +                           src->ia_atime_nsec); +        ec_iatt_time_merge(&dst->ia_mtime, &dst->ia_mtime_nsec, src->ia_mtime, +                           src->ia_mtime_nsec); +        ec_iatt_time_merge(&dst->ia_ctime, &dst->ia_ctime_nsec, src->ia_ctime, +                           src->ia_ctime_nsec); +    } + +    return 1; +} + +void ec_iatt_rebuild(ec_t * ec, struct iatt * iatt, int32_t count, +                     int32_t answers) +{ +    size_t blocks; + +    while (count-- > 0) +    { +        blocks = iatt[count].ia_blocks * ec->fragments + answers - 1; +        blocks /= answers; +        iatt[count].ia_blocks = blocks; +    } +} + +int32_t ec_dict_data_compare(dict_t * dict, char * key, data_t * value, +                             void * arg) +{ +    ec_dict_info_t * info = arg; +    data_t * data; + +    data = dict_get(info->dict, key); +    if (data == NULL) +    { +        gf_log("ec", GF_LOG_DEBUG, "key '%s' found only on one dict", key); + +        return -1; +    } + +    info->count--; + +    if ((strcmp(key, GF_CONTENT_KEY) == 0) || +        (strcmp(key, GF_XATTR_PATHINFO_KEY) == 0) || +        (strcmp(key, GF_XATTR_USER_PATHINFO_KEY) == 0) || +        (strcmp(key, GF_XATTR_LOCKINFO_KEY) == 0) || +        (strcmp(key, GF_XATTR_CLRLK_CMD) == 0) || +        (strcmp(key, GLUSTERFS_OPEN_FD_COUNT) == 0) || +        (fnmatch(GF_XATTR_STIME_PATTERN, key, 0) == 0) || +        (XATTR_IS_NODE_UUID(key))) +    { +        return 0; +    } + +    if ((data->len != value->len) || +        (memcmp(data->data, value->data, data->len) != 0)) +    { +        gf_log("ec", GF_LOG_DEBUG, "key '%s' is different (size: %u, %u)", +               key, data->len, value->len); + +        return -1; +    } + +    return 0; +} + +int32_t ec_dict_data_show(dict_t * dict, char * key, data_t * value, +                          void * arg) +{ +    if (dict_get(arg, key) == NULL) +    { +        gf_log("ec", GF_LOG_DEBUG, "key '%s' found only on one dict", key); +    } + +    return 0; +} + +int32_t ec_dict_compare(dict_t * dict1, dict_t * dict2) +{ +    ec_dict_info_t info; +    dict_t * dict; + +    if (dict1 != NULL) +    { +        info.dict = dict1; +        info.count = dict1->count; +        dict = dict2; +    } +    else if (dict2 != NULL) +    { +        info.dict = dict2; +        info.count = dict2->count; +        dict = dict1; +    } +    else +    { +        return 1; +    } + +    if (dict != NULL) +    { +        if (dict_foreach(dict, ec_dict_data_compare, &info) != 0) +        { +            return 0; +        } +    } + +    if (info.count != 0) +    { +        dict_foreach(info.dict, ec_dict_data_show, dict); +    } + +    return (info.count == 0); +} + +int32_t ec_dict_list(data_t ** list, int32_t * count, ec_cbk_data_t * cbk, +                     int32_t which, char * key) +{ +    ec_cbk_data_t * ans; +    dict_t * dict; +    int32_t i, max; + +    max = *count; +    i = 0; +    for (ans = cbk; ans != NULL; ans = ans->next) +    { +        if (i >= max) +        { +            gf_log(cbk->fop->xl->name, GF_LOG_ERROR, "Unexpected number of " +                                                     "dictionaries"); + +            return 0; +        } + +        dict = (which == EC_COMBINE_XDATA) ? ans->xdata : ans->dict; +        list[i] = dict_get(dict, key); +        if (list[i] == NULL) +        { +            gf_log(cbk->fop->xl->name, GF_LOG_ERROR, "Unexpected missing " +                                                     "dictionary entry"); + +            return 0; +        } + +        i++; +    } + +    *count = i; + +    return 1; +} + +char * ec_concat_prepare(xlator_t * xl, char ** sep, char ** post, +                         const char * fmt, va_list args) +{ +    char * str, * tmp; +    int32_t len; + +    len = gf_vasprintf(&str, fmt, args); +    if (len < 0) +    { +        return NULL; +    } + +    tmp = strchr(str, '{'); +    if (tmp == NULL) +    { +        goto out; +    } +    *tmp++ = 0; +    *sep = tmp; +    tmp = strchr(tmp, '}'); +    if (tmp == NULL) +    { +        goto out; +    } +    *tmp++ = 0; +    *post = tmp; + +    return str; + +out: +    gf_log(xl->name, GF_LOG_ERROR, "Invalid concat format"); + +    GF_FREE(str); + +    return NULL; +} + +int32_t ec_dict_data_concat(const char * fmt, ec_cbk_data_t * cbk, +                            int32_t which, char * key, ...) +{ +    data_t * data[cbk->count]; +    size_t len, tmp; +    char * str = NULL, * pre = NULL, * sep, * post; +    dict_t * dict; +    va_list args; +    int32_t i, num, prelen, postlen, seplen; +    int32_t ret = -1; + +    num = cbk->count; +    if (!ec_dict_list(data, &num, cbk, which, key)) +    { +        return -1; +    } + +    va_start(args, key); +    pre = ec_concat_prepare(cbk->fop->xl, &sep, &post, fmt, args); +    va_end(args); + +    if (pre == NULL) +    { +        return -1; +    } + +    prelen = strlen(pre); +    seplen = strlen(sep); +    postlen = strlen(post); + +    len = prelen + (num - 1) * seplen + postlen + 1; +    for (i = 0; i < num; i++) +    { +        len += data[i]->len - 1; +    } + +    str = GF_MALLOC(len, gf_common_mt_char); +    if (str == NULL) +    { +        goto out; +    } + +    memcpy(str, pre, prelen); +    len = prelen; +    for (i = 0; i < num; i++) +    { +        memcpy(str + len, sep, seplen); +        len += seplen; +        tmp = data[i]->len - 1; +        memcpy(str + len, data[i]->data, tmp); +        len += tmp; +    } +    memcpy(str + len, post, postlen + 1); + +    dict = (which == EC_COMBINE_XDATA) ? cbk->xdata : cbk->dict; +    if (dict_set_dynstr(dict, key, str) != 0) +    { +        goto out; +    } + +    str = NULL; + +    ret = 0; + +out: +    GF_FREE(str); +    GF_FREE(pre); + +    return ret; +} + +int32_t ec_dict_data_merge(ec_cbk_data_t * cbk, int32_t which, char * key) +{ +    data_t * data[cbk->count]; +    dict_t * dict, * lockinfo, * tmp; +    char * ptr = NULL; +    int32_t i, num, len; +    int32_t ret = -1; + +    num = cbk->count; +    if (!ec_dict_list(data, &num, cbk, which, key)) +    { +        return -1; +    } + +    if (dict_unserialize(data[0]->data, data[0]->len, &lockinfo) != 0) +    { +        return -1; +    } + +    for (i = 1; i < num; i++) +    { +        if (dict_unserialize(data[i]->data, data[i]->len, &tmp) != 0) +        { +            goto out; +        } +        if (dict_copy(tmp, lockinfo) == NULL) +        { +            dict_unref(tmp); + +            goto out; +        } + +        dict_unref(tmp); +    } + +    len = dict_serialized_length(lockinfo); +    if (len < 0) +    { +        goto out; +    } +    ptr = GF_MALLOC(len, gf_common_mt_char); +    if (ptr == NULL) +    { +        goto out; +    } +    if (dict_serialize(lockinfo, ptr) != 0) +    { +        goto out; +    } +    dict = (which == EC_COMBINE_XDATA) ? cbk->xdata : cbk->dict; +    if (dict_set_dynptr(dict, key, ptr, len) != 0) +    { +        goto out; +    } + +    ptr = NULL; + +    ret = 0; + +out: +    GF_FREE(ptr); +    dict_unref(lockinfo); + +    return ret; +} + +int32_t ec_dict_data_uuid(ec_cbk_data_t * cbk, int32_t which, char * key) +{ +    ec_cbk_data_t * ans, * min; +    dict_t * src, * dst; +    data_t * data; + +    min = cbk; +    for (ans = cbk->next; ans != NULL; ans = ans->next) +    { +        if (ans->idx < min->idx) +        { +            min = ans; +        } +    } + +    if (min != cbk) +    { +        src = (which == EC_COMBINE_XDATA) ? min->xdata : min->dict; +        dst = (which == EC_COMBINE_XDATA) ? cbk->xdata : cbk->dict; + +        data = dict_get(src, key); +        if (data == NULL) +        { +            return -1; +        } +        if (dict_set(dst, key, data) != 0) +        { +            return -1; +        } +    } + +    return 0; +} + +int32_t ec_dict_data_max(ec_cbk_data_t * cbk, int32_t which, char * key) +{ +    data_t * data[cbk->count]; +    dict_t * dict; +    int32_t i, num; +    uint32_t max, tmp; + +    num = cbk->count; +    if (!ec_dict_list(data, &num, cbk, which, key)) +    { +        return -1; +    } + +    if (num <= 1) +    { +        return 0; +    } + +    max = data_to_uint32(data[0]); +    for (i = 1; i < num; i++) +    { +        tmp = data_to_uint32(data[i]); +        if (max < tmp) +        { +            max = tmp; +        } +    } + +    dict = (which == EC_COMBINE_XDATA) ? cbk->xdata : cbk->dict; +    if (dict_set_uint32(dict, key, max) != 0) +    { +        return -1; +    } + +    return 0; +} + +int32_t ec_dict_data_stime(ec_cbk_data_t * cbk, int32_t which, char * key) +{ +    data_t * data[cbk->count]; +    dict_t * dict; +    int32_t i, num; + +    num = cbk->count; +    if (!ec_dict_list(data, &num, cbk, which, key)) +    { +        return -1; +    } + +    dict = (which == EC_COMBINE_XDATA) ? cbk->xdata : cbk->dict; +    for (i = 1; i < num; i++) +    { +        if (gf_get_max_stime(cbk->fop->xl, dict, key, data[i]) != 0) +        { +            gf_log(cbk->fop->xl->name, GF_LOG_ERROR, "STIME combination " +                                                     "failed"); + +            return -1; +        } +    } + +    return 0; +} + +int32_t ec_dict_data_combine(dict_t * dict, char * key, data_t * value, +                             void * arg) +{ +    ec_dict_combine_t * data = arg; + +    if ((strcmp(key, GF_XATTR_PATHINFO_KEY) == 0) || +        (strcmp(key, GF_XATTR_USER_PATHINFO_KEY) == 0)) +    { +        return ec_dict_data_concat("(<EC:%s> { })", data->cbk, data->which, +                                   key, data->cbk->fop->xl->name); +    } + +    if (strncmp(key, GF_XATTR_CLRLK_CMD, strlen(GF_XATTR_CLRLK_CMD)) == 0) +    { +        return ec_dict_data_concat("{\n}", data->cbk, data->which, key); +    } + +    if (strncmp(key, GF_XATTR_LOCKINFO_KEY, +                strlen(GF_XATTR_LOCKINFO_KEY)) == 0) +    { +        return ec_dict_data_merge(data->cbk, data->which, key); +    } + +    if (strcmp(key, GLUSTERFS_OPEN_FD_COUNT) == 0) +    { +        return ec_dict_data_max(data->cbk, data->which, key); +    } + +    if (XATTR_IS_NODE_UUID(key)) +    { +        return ec_dict_data_uuid(data->cbk, data->which, key); +    } + +    if (fnmatch(GF_XATTR_STIME_PATTERN, key, FNM_NOESCAPE) == 0) +    { +        return ec_dict_data_stime(data->cbk, data->which, key); +    } + +    return 0; +} + +int32_t ec_dict_combine(ec_cbk_data_t * cbk, int32_t which) +{ +    dict_t * dict; +    ec_dict_combine_t data; + +    data.cbk = cbk; +    data.which = which; + +    dict = (which == EC_COMBINE_XDATA) ? cbk->xdata : cbk->dict; +    if ((dict != NULL) && +        (dict_foreach(dict, ec_dict_data_combine, &data) != 0)) +    { +        gf_log(cbk->fop->xl->name, GF_LOG_ERROR, "Dictionary combination " +                                                 "failed"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_vector_compare(struct iovec * dst_vector, int32_t dst_count, +                          struct iovec * src_vector, int32_t src_count) +{ +    size_t dst_size = 0, src_size = 0; + +    if (dst_count > 0) +    { +        dst_size = iov_length(dst_vector, dst_count); +    } +    if (src_count > 0) +    { +        src_size = iov_length(src_vector, src_count); +    } + +    return (dst_size == src_size); +} + +int32_t ec_flock_compare(struct gf_flock * dst, struct gf_flock * src) +{ +    if ((dst->l_type != src->l_type) || +        (dst->l_whence != src->l_whence) || +        (dst->l_start != src->l_start) || +        (dst->l_len != src->l_len) || +        (dst->l_pid != src->l_pid) || +        !is_same_lkowner(&dst->l_owner, &src->l_owner)) +    { +        return 0; +    } + +    return 1; +} + +void ec_statvfs_combine(struct statvfs * dst, struct statvfs * src) +{ +    if (dst->f_bsize < src->f_bsize) +    { +        dst->f_bsize = src->f_bsize; +    } + +    if (dst->f_frsize < src->f_frsize) +    { +        dst->f_blocks *= dst->f_frsize; +        dst->f_blocks /= src->f_frsize; + +        dst->f_bfree *= dst->f_frsize; +        dst->f_bfree /= src->f_frsize; + +        dst->f_bavail *= dst->f_frsize; +        dst->f_bavail /= src->f_frsize; + +        dst->f_frsize = src->f_frsize; +    } +    else if (dst->f_frsize > src->f_frsize) +    { +        src->f_blocks *= src->f_frsize; +        src->f_blocks /= dst->f_frsize; + +        src->f_bfree *= src->f_frsize; +        src->f_bfree /= dst->f_frsize; + +        src->f_bavail *= src->f_frsize; +        src->f_bavail /= dst->f_frsize; +    } +    if (dst->f_blocks > src->f_blocks) +    { +        dst->f_blocks = src->f_blocks; +    } +    if (dst->f_bfree > src->f_bfree) +    { +        dst->f_bfree = src->f_bfree; +    } +    if (dst->f_bavail > src->f_bavail) +    { +        dst->f_bavail = src->f_bavail; +    } + +    if (dst->f_files < src->f_files) +    { +        dst->f_files = src->f_files; +    } +    if (dst->f_ffree > src->f_ffree) +    { +        dst->f_ffree = src->f_ffree; +    } +    if (dst->f_favail > src->f_favail) +    { +        dst->f_favail = src->f_favail; +    } +    if (dst->f_namemax > src->f_namemax) +    { +        dst->f_namemax = src->f_namemax; +    } + +    if (dst->f_flag != src->f_flag) +    { +        gf_log(THIS->name, GF_LOG_DEBUG, "Mismatching file system flags " +                                         "(%lX, %lX)", +               dst->f_flag, src->f_flag); +    } +    dst->f_flag &= src->f_flag; +} + +int32_t ec_combine_check(ec_cbk_data_t * dst, ec_cbk_data_t * src, +                         ec_combine_f combine) +{ +    ec_fop_data_t * fop = dst->fop; + +    if (dst->op_ret != src->op_ret) +    { +        gf_log(fop->xl->name, GF_LOG_DEBUG, "Mismatching return code in " +                                            "answers of '%s': %d <-> %d", +               ec_fop_name(fop->id), dst->op_ret, src->op_ret); + +        return 0; +    } +    if (dst->op_ret < 0) +    { +        if (dst->op_errno != src->op_errno) +        { +            gf_log(fop->xl->name, GF_LOG_DEBUG, "Mismatching errno code in " +                                                "answers of '%s': %d <-> %d", +                   ec_fop_name(fop->id), dst->op_errno, src->op_errno); + +            return 0; +        } +    } + +    if (!ec_dict_compare(dst->xdata, src->xdata)) +    { +        gf_log(fop->xl->name, GF_LOG_WARNING, "Mismatching xdata in answers " +                                              "of '%s'", +               ec_fop_name(fop->id)); + +        return 0; +    } + +    if ((dst->op_ret >= 0) && (combine != NULL)) +    { +        return combine(fop, dst, src); +    } + +    return 1; +} + +void ec_combine(ec_cbk_data_t * cbk, ec_combine_f combine) +{ +    ec_fop_data_t * fop = cbk->fop; +    ec_cbk_data_t * ans = NULL, * tmp = NULL; +    struct list_head * item = NULL; +    int32_t needed = 0, report = 0; +    char str[32]; + +    LOCK(&fop->lock); + +    item = fop->cbk_list.prev; +    list_for_each_entry(ans, &fop->cbk_list, list) +    { +        if (ec_combine_check(cbk, ans, combine)) +        { +            cbk->count += ans->count; +            cbk->mask |= ans->mask; + +            item = ans->list.prev; +            while (item != &fop->cbk_list) +            { +                tmp = list_entry(item, ec_cbk_data_t, list); +                if (tmp->count >= cbk->count) +                { +                    break; +                } +                item = item->prev; +            } +            list_del(&ans->list); + +            cbk->next = ans; + +            break; +        } +    } +    list_add(&cbk->list, item); + +    ec_trace("ANSWER", fop, "combine=%s[%d]", +             ec_bin(str, sizeof(str), cbk->mask, 0), cbk->count); + +    if ((cbk->count == fop->expected) && (fop->answer == NULL)) +    { +        fop->answer = cbk; + +        ec_update_bad(fop, cbk->mask); + +        report = 1; +    } + +    ans = list_entry(fop->cbk_list.next, ec_cbk_data_t, list); +    needed = fop->minimum - ans->count - fop->winds + 1; + +    UNLOCK(&fop->lock); + +    if (needed > 0) +    { +        ec_dispatch_next(fop, cbk->idx); +    } +    else if (report) +    { +        ec_report(fop, 0); +    } +} diff --git a/xlators/cluster/ec/src/ec-combine.h b/xlators/cluster/ec/src/ec-combine.h new file mode 100644 index 00000000000..0cf5a91dc03 --- /dev/null +++ b/xlators/cluster/ec/src/ec-combine.h @@ -0,0 +1,44 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef __EC_COMBINE_H__ +#define __EC_COMBINE_H__ + +#define EC_COMBINE_DICT  0 +#define EC_COMBINE_XDATA 1 + +typedef int32_t (* ec_combine_f)(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                                 ec_cbk_data_t * src); + +void ec_iatt_rebuild(ec_t * ec, struct iatt * iatt, int32_t count, +                     int32_t answers); + +int32_t ec_iatt_combine(struct iatt * dst, struct iatt * src, int32_t count); +int32_t ec_dict_compare(dict_t * dict1, dict_t * dict2); +int32_t ec_vector_compare(struct iovec * dst_vector, int32_t dst_count, +                          struct iovec * src_vector, int32_t src_count); +int32_t ec_flock_compare(struct gf_flock * dst, struct gf_flock * src); +void ec_statvfs_combine(struct statvfs * dst, struct statvfs * src); + +int32_t ec_dict_combine(ec_cbk_data_t * cbk, int32_t which); + +void ec_combine(ec_cbk_data_t * cbk, ec_combine_f combine); + +#endif /* __EC_COMBINE_H__ */ diff --git a/xlators/cluster/ec/src/ec-common.c b/xlators/cluster/ec/src/ec-common.c new file mode 100644 index 00000000000..a4423d94aa9 --- /dev/null +++ b/xlators/cluster/ec/src/ec-common.c @@ -0,0 +1,1109 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "byte-order.h" + +#include "ec-mem-types.h" +#include "ec-data.h" +#include "ec-helpers.h" +#include "ec-combine.h" +#include "ec-common.h" +#include "ec-fops.h" +#include "ec.h" + +int32_t ec_child_valid(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    return (idx < ec->nodes) && (((fop->remaining >> idx) & 1) == 1); +} + +int32_t ec_child_next(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    while (!ec_child_valid(ec, fop, idx)) +    { +        if (++idx >= ec->nodes) +        { +            idx = 0; +        } +        if (idx == fop->first) +        { +            return -1; +        } +    } + +    return idx; +} + +uintptr_t ec_inode_good(inode_t * inode, xlator_t * xl) +{ +    ec_inode_t * ctx; +    uintptr_t bad = 0; + +    ctx = ec_inode_get(inode, xl); +    if (ctx != NULL) +    { +        bad = ctx->bad; +    } + +    return ~bad; +} + +uintptr_t ec_fd_good(fd_t * fd, xlator_t * xl) +{ +    ec_fd_t * ctx; +    uintptr_t bad = 0; + +    ctx = ec_fd_get(fd, xl); +    if ((ctx != NULL) && (ctx->loc.inode != NULL)) +    { +        bad = ctx->bad; +    } + +    return ~bad; +} + +uintptr_t ec_update_inode(ec_fop_data_t * fop, inode_t * inode, uintptr_t good, +                          uintptr_t bad) +{ +    ec_inode_t * ctx = NULL; + +    if (inode != NULL) +    { +        LOCK(&inode->lock); + +        ctx = __ec_inode_get(inode, fop->xl); +        if (ctx != NULL) +        { +            ctx->bad &= ~good; +            bad |= ctx->bad; +            ctx->bad = bad; +        } + +        UNLOCK(&inode->lock); +    } + +    return bad; +} + +uintptr_t ec_update_fd(ec_fop_data_t * fop, fd_t * fd, uintptr_t good, +                       uintptr_t bad) +{ +    ec_fd_t * ctx = NULL; + +    LOCK(&fd->lock); + +    ctx = __ec_fd_get(fd, fop->xl); +    if ((ctx != NULL) && (ctx->loc.inode != NULL)) +    { +        ctx->bad &= ~good; +        bad |= ctx->bad; +        ctx->bad = bad; +    } + +    UNLOCK(&fd->lock); + +    return bad; +} + +int32_t ec_heal_report(call_frame_t * frame, void * cookie, xlator_t * this, +                       int32_t op_ret, int32_t op_errno, uintptr_t mask, +                       uintptr_t good, uintptr_t bad, dict_t * xdata) +{ +    if (op_ret < 0) +    { +        gf_log(this->name, GF_LOG_WARNING, "Heal failed (error %d)", op_errno); +    } +    else +    { +        gf_log(this->name, GF_LOG_INFO, "Heal succeeded on %d/%d subvolumes", +               ec_bits_count(mask & ~ (good | bad)), +               ec_bits_count(mask & ~good)); +    } + +    return 0; +} + +void ec_check_status(ec_fop_data_t * fop) +{ +    ec_t * ec = fop->xl->private; + +    if ((ec->xl_up & ~(fop->remaining | fop->good)) == 0) +    { +        return; +    } + +    gf_log(fop->xl->name, GF_LOG_WARNING, "Operation failed on some " +                                          "subvolumes (up=%lX, mask=%lX, " +                                          "remaining=%lX, good=%lX, bad=%lX)", +           ec->xl_up, fop->mask, fop->remaining, fop->good, fop->bad); + +    if (fop->fd != NULL) +    { +        ec_fheal(fop->frame, fop->xl, -1, EC_MINIMUM_ONE, ec_heal_report, NULL, +                 fop->fd, NULL); +    } +    else +    { +        ec_heal(fop->frame, fop->xl, -1, EC_MINIMUM_ONE, ec_heal_report, NULL, +                &fop->loc[0], NULL); + +        if (fop->loc[1].inode != NULL) +        { +            ec_heal(fop->frame, fop->xl, -1, EC_MINIMUM_ONE, ec_heal_report, +                    NULL, &fop->loc[1], NULL); +        } +    } +} + +void ec_update_bad(ec_fop_data_t * fop, uintptr_t good) +{ +    uintptr_t bad; +    int32_t update = 0; + +    bad = fop->mask & ~(fop->remaining | good); +    if ((fop->bad & bad) != bad) +    { +        fop->bad |= bad; +        update = 1; +    } +    if ((fop->good & good) != good) +    { +        fop->good |= good; +        update = 1; +    } + +    if (update && (fop->parent == NULL)) +    { +        if ((fop->flags & EC_FLAG_UPDATE_LOC_PARENT) != 0) +        { +            ec_update_inode(fop, fop->loc[0].parent, good, bad); +        } +        if ((fop->flags & EC_FLAG_UPDATE_LOC_INODE) != 0) +        { +            ec_update_inode(fop, fop->loc[0].inode, good, bad); +        } +        ec_update_inode(fop, fop->loc[1].inode, good, bad); +        if ((fop->flags & EC_FLAG_UPDATE_FD_INODE) != 0) +        { +            ec_update_inode(fop, fop->fd->inode, good, bad); +        } +        if ((fop->flags & EC_FLAG_UPDATE_FD) != 0) +        { +            ec_update_fd(fop, fop->fd, good, bad); +        } + +        ec_check_status(fop); +    } +} + + +void __ec_fop_set_error(ec_fop_data_t * fop, int32_t error) +{ +    if ((error != 0) && (fop->error == 0)) +    { +        fop->error = error; +    } +} + +void ec_fop_set_error(ec_fop_data_t * fop, int32_t error) +{ +    LOCK(&fop->lock); + +    __ec_fop_set_error(fop, error); + +    UNLOCK(&fop->lock); +} + +int32_t ec_check_complete(ec_fop_data_t * fop, ec_resume_f resume) +{ +    int32_t error = -1; + +    LOCK(&fop->lock); + +    GF_ASSERT(fop->resume == NULL); + +    if (fop->jobs != 0) +    { +        ec_trace("WAIT", fop, "resume=%p", resume); + +        fop->resume = resume; +    } +    else +    { +        error = fop->error; +        fop->error = 0; +    } + +    UNLOCK(&fop->lock); + +    return error; +} + +void ec_wait_winds(ec_fop_data_t * fop) +{ +    LOCK(&fop->lock); + +    if (fop->winds > 0) +    { +        fop->jobs++; +        fop->refs++; + +        fop->flags |= EC_FLAG_WAITING_WINDS; +    } + +    UNLOCK(&fop->lock); +} + +void ec_resume(ec_fop_data_t * fop, int32_t error) +{ +    ec_resume_f resume = NULL; + +    LOCK(&fop->lock); + +    __ec_fop_set_error(fop, error); + +    if (--fop->jobs == 0) +    { +        resume = fop->resume; +        fop->resume = NULL; +        if (resume != NULL) +        { +            ec_trace("RESUME", fop, "error=%d", error); + +            if (fop->error != 0) +            { +                error = fop->error; +            } +            fop->error = 0; +        } +    } + +    UNLOCK(&fop->lock); + +    if (resume != NULL) +    { +        resume(fop, error); +    } + +    ec_fop_data_release(fop); +} + +void ec_resume_parent(ec_fop_data_t * fop, int32_t error) +{ +    ec_fop_data_t * parent; + +    parent = fop->parent; +    if (parent != NULL) +    { +        fop->parent = NULL; +        ec_resume(parent, error); +    } +} + +void ec_report(ec_fop_data_t * fop, int32_t error) +{ +    if (!list_empty(&fop->lock_list)) +    { +        ec_owner_set(fop->frame, fop->frame->root); +    } + +    ec_resume(fop, error); +} + +void ec_complete(ec_fop_data_t * fop) +{ +    ec_cbk_data_t * cbk = NULL; +    int32_t ready = 0, report = 0; + +    LOCK(&fop->lock); + +    ec_trace("COMPLETE", fop, ""); + +    if (--fop->winds == 0) +    { +        if ((fop->answer == NULL) && (fop->expected != 1)) +        { +            if (!list_empty(&fop->cbk_list)) +            { +                cbk = list_entry(fop->cbk_list.next, ec_cbk_data_t, list); +                if ((cbk->count >= fop->minimum) && +                    ((cbk->op_ret >= 0) || (cbk->op_errno != ENOTCONN))) +                { +                    fop->answer = cbk; + +                    ec_update_bad(fop, cbk->mask); +                } +            } + +            report = 1; +        } +        else if ((fop->flags & EC_FLAG_WAITING_WINDS) != 0) +        { +            ready = 1; +        } +    } + +    UNLOCK(&fop->lock); + +    if (report) +    { +        ec_report(fop, 0); +    } +    if (ready) +    { +        ec_resume(fop, 0); +    } + +    ec_fop_data_release(fop); +} + +int32_t ec_child_select(ec_fop_data_t * fop) +{ +    ec_t * ec = fop->xl->private; +    uintptr_t mask = 0; +    int32_t first = 0, num = 0; + +    fop->mask &= ec->node_mask; + +    mask = ec->xl_up; +    if (fop->loc[0].inode != NULL) +    { +        mask |= ec_inode_good(fop->loc[0].inode, fop->xl); +    } +    if (fop->loc[1].inode != NULL) +    { +        mask |= ec_inode_good(fop->loc[1].inode, fop->xl); +    } +    if (fop->fd != NULL) +    { +        if (fop->fd->inode != NULL) +        { +            mask |= ec_inode_good(fop->fd->inode, fop->xl); +        } +        mask |= ec_fd_good(fop->fd, fop->xl); +    } +    if ((fop->mask & ~mask) != 0) +    { +        gf_log(fop->xl->name, GF_LOG_WARNING, "Executing operation with " +                                              "some subvolumes unavailable " +                                              "(%lX)", fop->mask & ~mask); + +        fop->mask &= mask; +    } + +    switch (fop->minimum) +    { +        case EC_MINIMUM_ALL: +            fop->minimum = ec_bits_count(fop->mask); +            if (fop->minimum >= ec->fragments) +            { +                break; +            } +        case EC_MINIMUM_MIN: +            fop->minimum = ec->fragments; +            break; +        case EC_MINIMUM_ONE: +            fop->minimum = 1; +    } + +    first = ec->idx; +    if (++first >= ec->nodes) +    { +        first = 0; +    } +    ec->idx = first; + +    fop->remaining = fop->mask; + +    ec_trace("SELECT", fop, ""); + +    num = ec_bits_count(fop->mask); +    if ((num < fop->minimum) && (num < ec->fragments)) +    { +        gf_log(ec->xl->name, GF_LOG_ERROR, "Insufficient available childs " +                                           "for this request (have %d, need " +                                           "%d)", num, fop->minimum); + +        return 0; +    } + +    LOCK(&fop->lock); + +    fop->jobs++; +    fop->refs++; + +    UNLOCK(&fop->lock); + +    return 1; +} + +int32_t ec_dispatch_next(ec_fop_data_t * fop, int32_t idx) +{ +    ec_t * ec = fop->xl->private; + +    LOCK(&fop->lock); + +    idx = ec_child_next(ec, fop, idx); +    if (idx >= 0) +    { +        fop->remaining ^= 1ULL << idx; + +        ec_trace("EXECUTE", fop, "idx=%d", idx); + +        fop->winds++; +        fop->refs++; +    } + +    UNLOCK(&fop->lock); + +    if (idx >= 0) +    { +        fop->wind(ec, fop, idx); +    } + +    return idx; +} + +void ec_dispatch_mask(ec_fop_data_t * fop, uintptr_t mask) +{ +    ec_t * ec = fop->xl->private; +    int32_t count, idx; + +    count = ec_bits_count(mask); + +    LOCK(&fop->lock); + +    ec_trace("EXECUTE", fop, "mask=%lX", mask); + +    fop->remaining ^= mask; + +    fop->winds += count; +    fop->refs += count; + +    UNLOCK(&fop->lock); + +    idx = 0; +    while (mask != 0) +    { +        if ((mask & 1) != 0) +        { +            fop->wind(ec, fop, idx); +        } +        idx++; +        mask >>= 1; +    } +} + +void ec_dispatch_start(ec_fop_data_t * fop) +{ +    fop->answer = NULL; +    fop->good = 0; +    fop->bad = 0; + +    INIT_LIST_HEAD(&fop->cbk_list); + +    if (!list_empty(&fop->lock_list)) +    { +        ec_owner_copy(fop->frame, &fop->req_frame->root->lk_owner); +    } +} + +void ec_dispatch_one(ec_fop_data_t * fop) +{ +    ec_t * ec = fop->xl->private; + +    ec_dispatch_start(fop); + +    if (ec_child_select(fop)) +    { +        fop->expected = 1; +        fop->first = ec->idx; + +        ec_dispatch_next(fop, fop->first); +    } +} + +int32_t ec_dispatch_one_retry(ec_fop_data_t * fop, int32_t idx, int32_t op_ret, +                              int32_t op_errno) +{ +    if ((op_ret < 0) && (op_errno == ENOTCONN)) +    { +        return (ec_dispatch_next(fop, idx) >= 0); +    } + +    return 0; +} + +void ec_dispatch_inc(ec_fop_data_t * fop) +{ +    ec_dispatch_start(fop); + +    if (ec_child_select(fop)) +    { +        fop->expected = ec_bits_count(fop->remaining); +        fop->first = 0; + +        ec_dispatch_next(fop, 0); +    } +} + +void ec_dispatch_all(ec_fop_data_t * fop) +{ +    ec_dispatch_start(fop); + +    if (ec_child_select(fop)) +    { +        fop->expected = ec_bits_count(fop->remaining); +        fop->first = 0; + +        ec_dispatch_mask(fop, fop->remaining); +    } +} + +void ec_dispatch_min(ec_fop_data_t * fop) +{ +    ec_t * ec = fop->xl->private; +    uintptr_t mask; +    int32_t idx, count; + +    ec_dispatch_start(fop); + +    if (ec_child_select(fop)) +    { +        fop->expected = count = ec->fragments; +        fop->first = ec->idx; +        idx = fop->first - 1; +        mask = 0; +        while (count-- > 0) +        { +            idx = ec_child_next(ec, fop, idx + 1); +            mask |= 1ULL << idx; +        } + +        ec_dispatch_mask(fop, mask); +    } +} + +ec_lock_t * ec_lock_allocate(xlator_t * xl, int32_t kind, loc_t * loc) +{ +    ec_lock_t * lock; + +    if ((loc->inode == NULL) || +        (uuid_is_null(loc->gfid) && uuid_is_null(loc->inode->gfid))) +    { +        gf_log(xl->name, GF_LOG_ERROR, "Trying to lock based on an invalid " +                                       "inode"); + +        return NULL; +    } + +    lock = GF_MALLOC(sizeof(*lock), ec_mt_ec_lock_t); +    if (lock != NULL) +    { +        memset(lock, 0, sizeof(*lock)); + +        lock->kind = kind; +        if (!ec_loc_from_loc(xl, &lock->loc, loc)) +        { +            GF_FREE(lock); +            lock = NULL; +        } +    } + +    return lock; +} + +void ec_lock_destroy(ec_lock_t * lock) +{ +    GF_FREE(lock->basename); +    loc_wipe(&lock->loc); + +    GF_FREE(lock); +} + +int32_t ec_locked(call_frame_t * frame, void * cookie, xlator_t * this, +                  int32_t op_ret, int32_t op_errno, dict_t * xdata) +{ +    ec_fop_data_t * fop = cookie; +    ec_lock_t * lock = NULL; + +    if (op_ret >= 0) +    { +        lock = fop->data; +        lock->mask = fop->good; +        fop->parent->mask &= fop->good; + +        ec_trace("LOCKED", fop->parent, "lock=%p", lock); +    } +    else +    { +        gf_log(this->name, GF_LOG_WARNING, "Failed to complete preop lock"); +    } + +    return 0; +} + +void ec_lock_entry(ec_fop_data_t * fop, loc_t * loc) +{ +    ec_lock_t * lock = NULL; +    char * name = NULL; +    loc_t tmp; +    int32_t error; + +    if ((fop->parent != NULL) || (fop->error != 0)) +    { +        return; +    } + +    error = ec_loc_parent(fop->xl, loc, &tmp, &name); +    if (error != 0) +    { +        ec_fop_set_error(fop, error); + +        return; +    } + +    LOCK(&fop->lock); + +    list_for_each_entry(lock, &fop->lock_list, list) +    { +        if ((lock->kind == EC_LOCK_ENTRY) && +            (lock->loc.inode == tmp.inode) && +            (strcmp(lock->basename, name) == 0)) +        { +            ec_trace("LOCK_ENTRYLK", fop, "lock=%p, parent=%p, path=%s, " +                                          "name=%s. Lock already acquired", +                     lock, loc->parent, loc->path, name); + +            lock = NULL; + +            goto unlock; +        } +    } + +    lock = ec_lock_allocate(fop->xl, EC_LOCK_ENTRY, &tmp); +    if (lock != NULL) +    { +        lock->type = ENTRYLK_WRLCK; +        lock->basename = name; + +        if (list_empty(&fop->lock_list)) +        { +            ec_owner_set(fop->frame, fop->frame->root); +        } +        list_add_tail(&lock->list, &fop->lock_list); +    } +    else +    { +        __ec_fop_set_error(fop, EIO); +    } + +unlock: +    UNLOCK(&fop->lock); + +    loc_wipe(&tmp); + +    if (lock != NULL) +    { +        ec_trace("LOCK_ENTRYLK", fop, "lock=%p, parent=%p, path=%s, " +                                      "basename=%s", lock, lock->loc.inode, +                 lock->loc.path, lock->basename); + +        ec_entrylk(fop->frame, fop->xl, -1, EC_MINIMUM_ALL, ec_locked, lock, +                   fop->xl->name, &lock->loc, lock->basename, ENTRYLK_LOCK, +                   lock->type, NULL); +    } +    else +    { +        GF_FREE(name); +    } +} + +void ec_lock_inode(ec_fop_data_t * fop, loc_t * loc) +{ +    ec_lock_t * lock; + +    if ((fop->parent != NULL) || (fop->error != 0) || (loc->inode == NULL)) +    { +        return; +    } + +    LOCK(&fop->lock); + +    list_for_each_entry(lock, &fop->lock_list, list) +    { +        if ((lock->kind == EC_LOCK_INODE) && (lock->loc.inode == loc->inode)) +        { +            UNLOCK(&fop->lock); + +            ec_trace("LOCK_INODELK", fop, "lock=%p, inode=%p. Lock already " +                                          "acquired", lock, loc->inode); + +            return; +        } +    } + +    lock = ec_lock_allocate(fop->xl, EC_LOCK_INODE, loc); +    if (lock != NULL) +    { +        lock->flock.l_type = F_WRLCK; +        lock->flock.l_whence = SEEK_SET; + +        if (list_empty(&fop->lock_list)) +        { +            ec_owner_set(fop->frame, fop->frame->root); +        } +        list_add_tail(&lock->list, &fop->lock_list); +    } +    else +    { +        __ec_fop_set_error(fop, EIO); +    } + +    UNLOCK(&fop->lock); + +    if (lock != NULL) +    { +        ec_trace("LOCK_INODELK", fop, "lock=%p, inode=%p, owner=%p", lock, +                 lock->loc.inode, fop->frame->root); + +        ec_inodelk(fop->frame, fop->xl, -1, EC_MINIMUM_ALL, ec_locked, lock, +                   fop->xl->name, &lock->loc, F_SETLKW, &lock->flock, NULL); +    } +} + +void ec_lock_fd(ec_fop_data_t * fop, fd_t * fd) +{ +    loc_t loc; + +    if ((fop->parent != NULL) || (fop->error != 0)) +    { +        return; +    } + +    if (ec_loc_from_fd(fop->xl, &loc, fd)) +    { +        ec_lock_inode(fop, &loc); + +        loc_wipe(&loc); +    } +    else +    { +        ec_fop_set_error(fop, EIO); +    } +} + +int32_t ec_unlocked(call_frame_t * frame, void * cookie, xlator_t * this, +                    int32_t op_ret, int32_t op_errno, dict_t * xdata) +{ +    ec_fop_data_t * fop = cookie; + +    if (op_ret < 0) +    { +        gf_log(this->name, GF_LOG_WARNING, "entry/inode unlocking failed (%s)", +               ec_fop_name(fop->parent->id)); +    } +    else +    { +        ec_trace("UNLOCKED", fop->parent, "lock=%p", fop->data); +    } + +    return 0; +} + +void ec_unlock(ec_fop_data_t * fop) +{ +    ec_lock_t * lock, * item; + +    ec_trace("UNLOCK", fop, ""); + +    list_for_each_entry_safe(lock, item, &fop->lock_list, list) +    { +        list_del(&lock->list); + +        if (lock->mask != 0) +        { +            switch (lock->kind) +            { +                case EC_LOCK_ENTRY: +                    ec_trace("UNLOCK_ENTRYLK", fop, "lock=%p, parent=%p, " +                                                    "path=%s, basename=%s", +                             lock, lock->loc.inode, lock->loc.path, +                             lock->basename); + +                    ec_entrylk(fop->frame, fop->xl, lock->mask, EC_MINIMUM_ALL, +                               ec_unlocked, lock, fop->xl->name, &lock->loc, +                               lock->basename, ENTRYLK_UNLOCK, lock->type, +                               NULL); + +                    break; + +                case EC_LOCK_INODE: +                    lock->flock.l_type = F_UNLCK; +                    ec_trace("UNLOCK_INODELK", fop, "lock=%p, inode=%p", lock, +                             lock->loc.inode); + +                    ec_inodelk(fop->frame, fop->xl, lock->mask, EC_MINIMUM_ALL, +                               ec_unlocked, lock, fop->xl->name, &lock->loc, +                               F_SETLK, &lock->flock, NULL); + +                    break; + +                default: +                    gf_log(fop->xl->name, GF_LOG_ERROR, "Invalid lock type"); +            } +        } + +        loc_wipe(&lock->loc); + +        GF_FREE(lock); +    } +} + +int32_t ec_get_size_version_set(call_frame_t * frame, void * cookie, +                                xlator_t * this, int32_t op_ret, +                                int32_t op_errno, inode_t * inode, +                                struct iatt * buf, dict_t * xdata, +                                struct iatt * postparent) +{ +    ec_fop_data_t * fop = cookie; + +    if (op_ret >= 0) +    { +        fop->parent->mask &= fop->good; +        fop->parent->pre_size = fop->parent->post_size = buf->ia_size; +    } +    else +    { +        gf_log(this->name, GF_LOG_WARNING, "Failed to get size and version " +                                           "(error %d)", op_errno); +        ec_fop_set_error(fop, op_errno); +    } + +    return 0; +} + +void ec_get_size_version(ec_fop_data_t * fop) +{ +    loc_t loc; +    dict_t * xdata; +    uid_t uid; +    gid_t gid; +    int32_t error = ENOMEM; + +    if (fop->parent != NULL) +    { +        fop->pre_size = fop->parent->pre_size; +        fop->post_size = fop->parent->post_size; + +        return; +    } + +    memset(&loc, 0, sizeof(loc)); + +    xdata = dict_new(); +    if (xdata == NULL) +    { +        goto out; +    } +    if ((dict_set_uint64(xdata, EC_XATTR_VERSION, 0) != 0) || +        (dict_set_uint64(xdata, EC_XATTR_SIZE, 0) != 0)) +    { +        goto out; +    } + +    uid = fop->frame->root->uid; +    gid = fop->frame->root->gid; + +    fop->frame->root->uid = 0; +    fop->frame->root->gid = 0; + +    error = EIO; + +    if (fop->fd == NULL) +    { +        if (!ec_loc_from_loc(fop->xl, &loc, &fop->loc[0])) +        { +            goto out; +        } +        if (uuid_is_null(loc.pargfid)) +        { +            if (loc.parent != NULL) +            { +                inode_unref(loc.parent); +                loc.parent = NULL; +            } +            GF_FREE((char *)loc.path); +            loc.path = NULL; +            loc.name = NULL; +        } +    } +    else if (!ec_loc_from_fd(fop->xl, &loc, fop->fd)) +    { +        goto out; +    } + +    ec_lookup(fop->frame, fop->xl, fop->mask, EC_MINIMUM_MIN, +              ec_get_size_version_set, NULL, &loc, xdata); + +    fop->frame->root->uid = uid; +    fop->frame->root->gid = gid; + +    error = 0; + +out: +    loc_wipe(&loc); + +    if (xdata != NULL) +    { +        dict_unref(xdata); +    } + +    ec_fop_set_error(fop, error); +} + +int32_t ec_update_size_version_done(call_frame_t * frame, void * cookie, +                                    xlator_t * this, int32_t op_ret, +                                    int32_t op_errno, dict_t * xattr, +                                    dict_t * xdata) +{ +    ec_fop_data_t * fop = cookie; + +    if (op_ret < 0) +    { +        gf_log(fop->xl->name, GF_LOG_ERROR, "Failed to update version and " +                                            "size (error %d)", op_errno); +    } +    else +    { +        fop->parent->mask &= fop->good; +    } + +    return 0; +} + +void ec_update_size_version(ec_fop_data_t * fop) +{ +    dict_t * dict; +    size_t size; +    uid_t uid; +    gid_t gid; + +    if (fop->parent != NULL) +    { +        fop->parent->post_size = fop->post_size; + +        return; +    } + +    dict = dict_new(); +    if (dict == NULL) +    { +        goto out; +    } + +    if (ec_dict_set_number(dict, EC_XATTR_VERSION, 1) != 0) +    { +        goto out; +    } +    size = fop->post_size; +    if (fop->pre_size != size) +    { +        size -= fop->pre_size; +        if (ec_dict_set_number(dict, EC_XATTR_SIZE, size) != 0) +        { +            goto out; +        } +    } + +    uid = fop->frame->root->uid; +    gid = fop->frame->root->gid; + +    fop->frame->root->uid = 0; +    fop->frame->root->gid = 0; + +    if (fop->fd == NULL) +    { +        ec_xattrop(fop->frame, fop->xl, fop->mask, EC_MINIMUM_MIN, +                   ec_update_size_version_done, NULL, &fop->loc[0], +                   GF_XATTROP_ADD_ARRAY64, dict, NULL); +    } +    else +    { +        ec_fxattrop(fop->frame, fop->xl, fop->mask, EC_MINIMUM_MIN, +                    ec_update_size_version_done, NULL, fop->fd, +                    GF_XATTROP_ADD_ARRAY64, dict, NULL); +    } + +    fop->frame->root->uid = uid; +    fop->frame->root->gid = gid; + +    dict_unref(dict); + +    return; + +out: +    if (dict != NULL) +    { +        dict_unref(dict); +    } + +    ec_fop_set_error(fop, EIO); + +    gf_log(fop->xl->name, GF_LOG_ERROR, "Unable to update version and size"); +} + +void __ec_manager(ec_fop_data_t * fop, int32_t error) +{ +    do +    { +        ec_trace("MANAGER", fop, "error=%d", error); + +        if (fop->state == EC_STATE_END) +        { +            ec_fop_data_release(fop); + +            break; +        } + +        if (error != 0) +        { +            fop->error = error; +            fop->state = -fop->state; +        } + +        fop->state = fop->handler(fop, fop->state); + +        error = ec_check_complete(fop, __ec_manager); +    } while (error >= 0); +} + +void ec_manager(ec_fop_data_t * fop, int32_t error) +{ +    GF_ASSERT(fop->jobs == 0); +    GF_ASSERT(fop->winds == 0); +    GF_ASSERT(fop->error == 0); + +    if (fop->state == EC_STATE_START) +    { +        fop->state = EC_STATE_INIT; +    } + +    __ec_manager(fop, error); +} diff --git a/xlators/cluster/ec/src/ec-common.h b/xlators/cluster/ec/src/ec-common.h new file mode 100644 index 00000000000..83f3ba9637e --- /dev/null +++ b/xlators/cluster/ec/src/ec-common.h @@ -0,0 +1,105 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef __EC_COMMON_H__ +#define __EC_COMMON_H__ + +#include "xlator.h" + +#include "ec-data.h" + +#define EC_FLAG_UPDATE_LOC_PARENT 0x0001 +#define EC_FLAG_UPDATE_LOC_INODE  0x0002 +#define EC_FLAG_UPDATE_FD         0x0004 +#define EC_FLAG_UPDATE_FD_INODE   0x0008 + +#define EC_FLAG_WAITING_WINDS     0x0010 + +#define EC_MINIMUM_ONE   -1 +#define EC_MINIMUM_MIN   -2 +#define EC_MINIMUM_ALL   -3 + +#define EC_LOCK_ENTRY   0 +#define EC_LOCK_INODE   1 + +#define EC_STATE_START                        0 +#define EC_STATE_END                          0 +#define EC_STATE_INIT                         1 +#define EC_STATE_LOCK                         2 +#define EC_STATE_GET_SIZE_AND_VERSION         3 +#define EC_STATE_DISPATCH                     4 +#define EC_STATE_PREPARE_ANSWER               5 +#define EC_STATE_REPORT                       6 +#define EC_STATE_UPDATE_SIZE_AND_VERSION      7 +#define EC_STATE_UNLOCK                       8 + +#define EC_STATE_WRITE_START                100 + +#define EC_STATE_HEAL_ENTRY_LOOKUP          200 +#define EC_STATE_HEAL_ENTRY_PREPARE         201 +#define EC_STATE_HEAL_PRE_INODELK_LOCK      202 +#define EC_STATE_HEAL_PRE_INODE_LOOKUP      203 +#define EC_STATE_HEAL_XATTRIBUTES_REMOVE    204 +#define EC_STATE_HEAL_XATTRIBUTES_SET       205 +#define EC_STATE_HEAL_ATTRIBUTES            206 +#define EC_STATE_HEAL_OPEN                  207 +#define EC_STATE_HEAL_REOPEN_FD             208 +#define EC_STATE_HEAL_UNLOCK                209 +#define EC_STATE_HEAL_DATA_LOCK             210 +#define EC_STATE_HEAL_DATA_COPY             211 +#define EC_STATE_HEAL_DATA_UNLOCK           212 +#define EC_STATE_HEAL_POST_INODELK_LOCK     213 +#define EC_STATE_HEAL_POST_INODE_LOOKUP     214 +#define EC_STATE_HEAL_SETATTR               215 +#define EC_STATE_HEAL_POST_INODELK_UNLOCK   216 +#define EC_STATE_HEAL_DISPATCH              217 + +int32_t ec_dispatch_one_retry(ec_fop_data_t * fop, int32_t idx, int32_t op_ret, +                              int32_t op_errno); +int32_t ec_dispatch_next(ec_fop_data_t * fop, int32_t idx); + +void ec_complete(ec_fop_data_t * fop); + +void ec_update_bad(ec_fop_data_t * fop, uintptr_t good); + +void ec_fop_set_error(ec_fop_data_t * fop, int32_t error); + +void ec_lock_inode(ec_fop_data_t * fop, loc_t * loc); +void ec_lock_entry(ec_fop_data_t * fop, loc_t * loc); +void ec_lock_fd(ec_fop_data_t * fop, fd_t * fd); + +void ec_unlock(ec_fop_data_t * fop); + +void ec_get_size_version(ec_fop_data_t * fop); +void ec_update_size_version(ec_fop_data_t * fop); + +void ec_dispatch_all(ec_fop_data_t * fop); +void ec_dispatch_inc(ec_fop_data_t * fop); +void ec_dispatch_min(ec_fop_data_t * fop); +void ec_dispatch_one(ec_fop_data_t * fop); + +void ec_wait_winds(ec_fop_data_t * fop); + +void ec_resume_parent(ec_fop_data_t * fop, int32_t error); +void ec_report(ec_fop_data_t * fop, int32_t error); + +void ec_manager(ec_fop_data_t * fop, int32_t error); + +#endif /* __EC_COMMON_H__ */ diff --git a/xlators/cluster/ec/src/ec-data.c b/xlators/cluster/ec/src/ec-data.c new file mode 100644 index 00000000000..0e72fbbd3b6 --- /dev/null +++ b/xlators/cluster/ec/src/ec-data.c @@ -0,0 +1,261 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "ec-mem-types.h" +#include "ec-helpers.h" +#include "ec-common.h" +#include "ec-data.h" + +ec_cbk_data_t * ec_cbk_data_allocate(call_frame_t * frame, xlator_t * this, +                                     ec_fop_data_t * fop, int32_t id, +                                     int32_t idx, int32_t op_ret, +                                     int32_t op_errno) +{ +    ec_cbk_data_t * cbk; +    ec_t * ec = this->private; + +    if (fop->xl != this) +    { +        gf_log(this->name, GF_LOG_ERROR, "Mismatching xlators between request " +                                         "and answer (req=%s, ans=%s).", +                                         fop->xl->name, this->name); + +        return NULL; +    } +    if (fop->frame != frame) +    { +        gf_log(this->name, GF_LOG_ERROR, "Mismatching frames between request " +                                         "and answer (req=%p, ans=%p).", +                                         fop->frame, frame); + +        return NULL; +    } +    if (fop->id != id) +    { +        gf_log(this->name, GF_LOG_ERROR, "Mismatching fops between request " +                                         "and answer (req=%d, ans=%d).", +                                         fop->id, id); + +        return NULL; +    } + +    cbk = mem_get0(ec->cbk_pool); +    if (cbk == NULL) +    { +        gf_log(this->name, GF_LOG_ERROR, "Failed to allocate memory for an " +                                         "answer."); +    } + +    cbk->fop = fop; +    cbk->idx = idx; +    cbk->mask = 1ULL << idx; +    cbk->count = 1; +    cbk->op_ret = op_ret; +    cbk->op_errno = op_errno; + +    LOCK(&fop->lock); + +    list_add_tail(&cbk->answer_list, &fop->answer_list); + +    UNLOCK(&fop->lock); + +    return cbk; +} + +void ec_cbk_data_destroy(ec_cbk_data_t * cbk) +{ +    if (cbk->xdata != NULL) +    { +        dict_unref(cbk->xdata); +    } +    if (cbk->dict != NULL) +    { +        dict_unref(cbk->dict); +    } +    if (cbk->inode != NULL) +    { +        inode_unref(cbk->inode); +    } +    if (cbk->fd != NULL) +    { +        fd_unref(cbk->fd); +    } +    if (cbk->buffers != NULL) +    { +        iobref_unref(cbk->buffers); +    } +    GF_FREE(cbk->vector); + +    mem_put(cbk); +} + +ec_fop_data_t * ec_fop_data_allocate(call_frame_t * frame, xlator_t * this, +                                     int32_t id, uint32_t flags, +                                     uintptr_t target, int32_t minimum, +                                     ec_wind_f wind, ec_handler_f handler, +                                     ec_cbk_t cbks, void * data) +{ +    ec_fop_data_t * fop, * parent; +    ec_t * ec = this->private; + +    fop = mem_get0(ec->fop_pool); +    if (fop == NULL) +    { +        gf_log(this->name, GF_LOG_ERROR, "Failed to allocate memory for a " +                                         "request."); + +        return NULL; +    } + +    fop->xl = this; +    fop->req_frame = frame; + +    /* fops need a private frame to be able to execute some postop operations +     * even if the original fop has completed and reported back to the upper +     * xlator and it has destroyed the base frame. +     * +     * TODO: minimize usage of private frames. Reuse req_frame as much as +     *       possible. +     */ +    if (frame != NULL) +    { +        fop->frame = copy_frame(frame); +    } +    else +    { +        fop->frame = create_frame(this, this->ctx->pool); +    } +    if (fop->frame == NULL) +    { +        gf_log(this->name, GF_LOG_ERROR, "Failed to create a private frame " +                                         "for a request"); + +        mem_put(fop); + +        return NULL; +    } +    fop->id = id; +    fop->refs = 1; + +    fop->flags = flags; +    fop->minimum = minimum; +    fop->mask = target; + +    INIT_LIST_HEAD(&fop->lock_list); +    INIT_LIST_HEAD(&fop->cbk_list); +    INIT_LIST_HEAD(&fop->answer_list); + +    fop->wind = wind; +    fop->handler = handler; +    fop->cbks = cbks; +    fop->data = data; + +    LOCK_INIT(&fop->lock); + +    fop->frame->local = fop; + +    if (frame != NULL) +    { +        parent = frame->local; +        if (parent != NULL) +        { +            LOCK(&parent->lock); + +            parent->jobs++; +            parent->refs++; + +            UNLOCK(&parent->lock); +        } + +        fop->parent = parent; +    } + +    return fop; +} + +void ec_fop_data_acquire(ec_fop_data_t * fop) +{ +    LOCK(&fop->lock); + +    ec_trace("ACQUIRE", fop, ""); + +    fop->refs++; + +    UNLOCK(&fop->lock); +} + +void ec_fop_data_release(ec_fop_data_t * fop) +{ +    ec_cbk_data_t * cbk, * tmp; +    int32_t refs; + +    LOCK(&fop->lock); + +    ec_trace("RELEASE", fop, ""); + +    refs = --fop->refs; + +    UNLOCK(&fop->lock); + +    if (refs == 0) +    { +        fop->frame->local = NULL; +        STACK_DESTROY(fop->frame->root); + +        LOCK_DESTROY(&fop->lock); + +        if (fop->xdata != NULL) +        { +            dict_unref(fop->xdata); +        } +        if (fop->dict != NULL) +        { +            dict_unref(fop->dict); +        } +        if (fop->inode != NULL) +        { +            inode_unref(fop->inode); +        } +        if (fop->fd != NULL) +        { +            fd_unref(fop->fd); +        } +        if (fop->buffers != NULL) +        { +            iobref_unref(fop->buffers); +        } +        GF_FREE(fop->vector); +        GF_FREE(fop->str[0]); +        GF_FREE(fop->str[1]); +        loc_wipe(&fop->loc[0]); +        loc_wipe(&fop->loc[1]); + +        ec_resume_parent(fop, fop->error); + +        list_for_each_entry_safe(cbk, tmp, &fop->answer_list, answer_list) +        { +            list_del_init(&cbk->answer_list); + +            ec_cbk_data_destroy(cbk); +        } + +        mem_put(fop); +    } +} diff --git a/xlators/cluster/ec/src/ec-data.h b/xlators/cluster/ec/src/ec-data.h new file mode 100644 index 00000000000..e83b6ad74eb --- /dev/null +++ b/xlators/cluster/ec/src/ec-data.h @@ -0,0 +1,260 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef __EC_DATA_H__ +#define __EC_DATA_H__ + +#include "xlator.h" + +#include "ec.h" + +struct _ec_fd; +typedef struct _ec_fd ec_fd_t; + +struct _ec_inode; +typedef struct _ec_inode ec_inode_t; + +union _ec_cbk; +typedef union _ec_cbk ec_cbk_t; + +struct _ec_lock; +typedef struct _ec_lock ec_lock_t; + +struct _ec_fop_data; +typedef struct _ec_fop_data ec_fop_data_t; + +struct _ec_cbk_data; +typedef struct _ec_cbk_data ec_cbk_data_t; + +struct _ec_heal; +typedef struct _ec_heal ec_heal_t; + +typedef void (* ec_wind_f)(ec_t *, ec_fop_data_t *, int32_t); +typedef int32_t (* ec_handler_f)(ec_fop_data_t *, int32_t); +typedef void (* ec_resume_f)(ec_fop_data_t *, int32_t); + +struct _ec_fd +{ +    uintptr_t bad; +    loc_t     loc; +    uintptr_t open; +    int32_t   flags; +}; + +struct _ec_inode +{ +    uintptr_t   bad; +    ec_heal_t * heal; +}; + +typedef int32_t (* fop_heal_cbk_t)(call_frame_t *, void * cookie, xlator_t *, +                                   int32_t, int32_t, uintptr_t, uintptr_t, +                                   uintptr_t, dict_t *); +typedef int32_t (* fop_fheal_cbk_t)(call_frame_t *, void * cookie, xlator_t *, +                                    int32_t, int32_t, uintptr_t, uintptr_t, +                                    uintptr_t, dict_t *); + + +union _ec_cbk +{ +    fop_access_cbk_t       access; +    fop_create_cbk_t       create; +    fop_discard_cbk_t      discard; +    fop_entrylk_cbk_t      entrylk; +    fop_fentrylk_cbk_t     fentrylk; +    fop_fallocate_cbk_t    fallocate; +    fop_flush_cbk_t        flush; +    fop_fsync_cbk_t        fsync; +    fop_fsyncdir_cbk_t     fsyncdir; +    fop_getxattr_cbk_t     getxattr; +    fop_fgetxattr_cbk_t    fgetxattr; +    fop_heal_cbk_t         heal; +    fop_fheal_cbk_t        fheal; +    fop_inodelk_cbk_t      inodelk; +    fop_finodelk_cbk_t     finodelk; +    fop_link_cbk_t         link; +    fop_lk_cbk_t           lk; +    fop_lookup_cbk_t       lookup; +    fop_mkdir_cbk_t        mkdir; +    fop_mknod_cbk_t        mknod; +    fop_open_cbk_t         open; +    fop_opendir_cbk_t      opendir; +    fop_readdir_cbk_t      readdir; +    fop_readdirp_cbk_t     readdirp; +    fop_readlink_cbk_t     readlink; +    fop_readv_cbk_t        readv; +    fop_removexattr_cbk_t  removexattr; +    fop_fremovexattr_cbk_t fremovexattr; +    fop_rename_cbk_t       rename; +    fop_rmdir_cbk_t        rmdir; +    fop_setattr_cbk_t      setattr; +    fop_fsetattr_cbk_t     fsetattr; +    fop_setxattr_cbk_t     setxattr; +    fop_fsetxattr_cbk_t    fsetxattr; +    fop_stat_cbk_t         stat; +    fop_fstat_cbk_t        fstat; +    fop_statfs_cbk_t       statfs; +    fop_symlink_cbk_t      symlink; +    fop_truncate_cbk_t     truncate; +    fop_ftruncate_cbk_t    ftruncate; +    fop_unlink_cbk_t       unlink; +    fop_writev_cbk_t       writev; +    fop_xattrop_cbk_t      xattrop; +    fop_fxattrop_cbk_t     fxattrop; +    fop_zerofill_cbk_t     zerofill; +}; + +struct _ec_lock +{ +    struct list_head     list; +    uintptr_t            mask; +    int32_t              kind; +    loc_t                loc; +    union +    { +        struct +        { +            entrylk_type type; +            char *       basename; +        }; +        struct gf_flock  flock; +    }; +}; + +struct _ec_fop_data +{ +    int32_t            id; +    int32_t            refs; +    int32_t            state; +    int32_t            minimum; +    int32_t            expected; +    int32_t            winds; +    int32_t            jobs; +    int32_t            error; +    ec_fop_data_t *    parent; +    xlator_t *         xl; +    call_frame_t *     req_frame;   // frame of the calling xlator +    call_frame_t *     frame;       // frame used by this fop +    struct list_head   lock_list;   // list locks held by this fop +    struct list_head   cbk_list;    // sorted list of groups of answers +    struct list_head   answer_list; // list of answers +    ec_cbk_data_t *    answer;      // accepted answer +    size_t             pre_size; +    size_t             post_size; +    gf_lock_t          lock; + +    uint32_t           flags; +    uint32_t           first; +    uintptr_t          mask; +    uintptr_t          remaining; +    uintptr_t          good; +    uintptr_t          bad; + +    ec_wind_f          wind; +    ec_handler_f       handler; +    ec_resume_f        resume; +    ec_cbk_t           cbks; +    void *             data; + +    size_t             user_size; +    size_t             head; + +    dict_t *           xdata; +    dict_t *           dict; +    int32_t            int32; +    uint32_t           uint32; +    size_t             size; +    off_t              offset; +    mode_t             mode[2]; +    entrylk_cmd        entrylk_cmd; +    entrylk_type       entrylk_type; +    gf_xattrop_flags_t xattrop_flags; +    dev_t              dev; +    inode_t *          inode; +    fd_t *             fd; +    struct iatt        iatt; +    char *             str[2]; +    loc_t              loc[2]; +    struct gf_flock    flock; +    struct iovec *     vector; +    struct iobref *    buffers; +}; + +struct _ec_cbk_data +{ +    struct list_head list;        // item in the sorted list of groups +    struct list_head answer_list; // item in the list of answers +    ec_fop_data_t *  fop; +    ec_cbk_data_t *  next;        // next answer in the same group +    int32_t          idx; +    int32_t          op_ret; +    int32_t          op_errno; +    int32_t          count; +    uintptr_t        mask; + +    dict_t *         xdata; +    dict_t *         dict; +    int32_t          int32; +    uintptr_t        uintptr[3]; +    size_t           size; +    uint64_t         version; +    inode_t *        inode; +    fd_t *           fd; +    struct statvfs   statvfs; +    struct iatt      iatt[5]; +    struct gf_flock  flock; +    struct iovec *   vector; +    struct iobref *  buffers; +}; + +struct _ec_heal +{ +    gf_lock_t       lock; +    xlator_t *      xl; +    ec_fop_data_t * fop; +    ec_fop_data_t * lookup; +    loc_t           loc; +    struct iatt     iatt; +    char *          symlink; +    fd_t *          fd; +    int32_t         done; +    uintptr_t       available; +    uintptr_t       good; +    uintptr_t       bad; +    uintptr_t       open; +    off_t           offset; +    size_t          size; +    uint64_t        version; +    size_t          raw_size; +}; + +ec_cbk_data_t * ec_cbk_data_allocate(call_frame_t * frame, xlator_t * this, +                                     ec_fop_data_t * fop, int32_t id, +                                     int32_t idx, int32_t op_ret, +                                     int32_t op_errno); +ec_fop_data_t * ec_fop_data_allocate(call_frame_t * frame, xlator_t * this, +                                     int32_t id, uint32_t flags, +                                     uintptr_t target, int32_t minimum, +                                     ec_wind_f wind, ec_handler_f handler, +                                     ec_cbk_t cbks, void * data); +void ec_fop_data_acquire(ec_fop_data_t * fop); +void ec_fop_data_release(ec_fop_data_t * fop); + +#endif /* __EC_DATA_H__ */ diff --git a/xlators/cluster/ec/src/ec-dir-read.c b/xlators/cluster/ec/src/ec-dir-read.c new file mode 100644 index 00000000000..1e7abc30d91 --- /dev/null +++ b/xlators/cluster/ec/src/ec-dir-read.c @@ -0,0 +1,571 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "xlator.h" +#include "defaults.h" + +#include "ec-helpers.h" +#include "ec-common.h" +#include "ec-combine.h" +#include "ec-method.h" +#include "ec-fops.h" + +/* FOP: opendir */ + +int32_t ec_combine_opendir(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                           ec_cbk_data_t * src) +{ +    if (dst->fd != src->fd) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching fd in answers " +                                             "of 'GF_FOP_OPENDIR': %p <-> %p", +               dst->fd, src->fd); + +        return 0; +    } + +    return 1; +} + +int32_t ec_opendir_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                       int32_t op_ret, int32_t op_errno, fd_t * fd, +                       dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_OPENDIR, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (fd != NULL) +            { +                cbk->fd = fd_ref(fd); +                if (cbk->fd == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                     "file descriptor."); + +                    goto out; +                } +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_opendir); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_opendir(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_opendir_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->opendir, +                      &fop->loc[0], fop->fd, fop->xdata); +} + +int32_t ec_manager_opendir(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.opendir != NULL) +            { +                fop->cbks.opendir(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                  cbk->op_errno, cbk->fd, cbk->xdata); +            } + +            return EC_STATE_END; + +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.opendir != NULL) +            { +                fop->cbks.opendir(fop->req_frame, fop, fop->xl, -1, fop->error, +                                  NULL, NULL); +            } + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_opendir(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_opendir_cbk_t func, void * data, +                loc_t * loc, fd_t * fd, dict_t * xdata) +{ +    ec_cbk_t callback = { .opendir = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(OPENDIR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_OPENDIR, EC_FLAG_UPDATE_FD, +                               target, minimum, ec_wind_opendir, +                               ec_manager_opendir, callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} + +/* FOP: readdir */ + +void ec_adjust_readdir(ec_t * ec, int32_t idx, gf_dirent_t * entries) +{ +    gf_dirent_t * entry; + +    list_for_each_entry(entry, &entries->list, list) +    { +        entry->d_off = ec_itransform(ec, idx, entry->d_off); + +        if (entry->d_stat.ia_type == IA_IFREG) +        { +            if ((entry->dict == NULL) || +                (ec_dict_del_number(entry->dict, EC_XATTR_SIZE, +                                    &entry->d_stat.ia_size) != 0)) +            { +                gf_log(ec->xl->name, GF_LOG_WARNING, "Unable to get exact " +                                                     "file size."); + +                entry->d_stat.ia_size *= ec->fragments; +            } + +            ec_iatt_rebuild(ec, &entry->d_stat, 1, 1); +        } +    } +} + +int32_t ec_readdir_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                       int32_t op_ret, int32_t op_errno, gf_dirent_t * entries, +                       dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    if (op_ret > 0) +    { +        ec_adjust_readdir(fop->xl->private, idx, entries); +    } + +    if (!ec_dispatch_one_retry(fop, idx, op_ret, op_errno)) +    { +        if (fop->cbks.readdir != NULL) +        { +            fop->cbks.readdir(fop->req_frame, fop, this, op_ret, op_errno, +                              entries, xdata); +        } +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_readdir(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_readdir_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->readdir, +                      fop->fd, fop->size, fop->offset, fop->xdata); +} + +int32_t ec_manager_readdir(ec_fop_data_t * fop, int32_t state) +{ +    switch (state) +    { +        case EC_STATE_INIT: +            if (fop->xdata == NULL) +            { +                fop->xdata = dict_new(); +                if (fop->xdata == NULL) +                { +                    gf_log(fop->xl->name, GF_LOG_ERROR, "Unable to prepare " +                                                        "readdirp request"); + +                    fop->error = EIO; + +                    return EC_STATE_REPORT; +                } +            } +            if (dict_set_uint64(fop->xdata, EC_XATTR_SIZE, 0) != 0) +            { +                gf_log(fop->xl->name, GF_LOG_ERROR, "Unable to prepare " +                                                    "readdirp request"); + +                fop->error = EIO; + +                return EC_STATE_REPORT; +            } + +            if (fop->offset != 0) +            { +                int32_t idx; + +                fop->offset = ec_deitransform(fop->xl->private, &idx, +                                              fop->offset); +                fop->mask &= 1ULL << idx; +            } + +        case EC_STATE_DISPATCH: +            ec_dispatch_one(fop); + +            return EC_STATE_REPORT; + +        case -EC_STATE_REPORT: +            if (fop->id == GF_FOP_READDIR) +            { +                if (fop->cbks.readdir != NULL) +                { +                    fop->cbks.readdir(fop->req_frame, fop, fop->xl, -1, +                                      fop->error, NULL, NULL); +                } +            } +            else +            { +                if (fop->cbks.readdirp != NULL) +                { +                    fop->cbks.readdirp(fop->req_frame, fop, fop->xl, -1, +                                       fop->error, NULL, NULL); +                } +            } + +        case EC_STATE_REPORT: +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_readdir(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_readdir_cbk_t func, void * data, +                fd_t * fd, size_t size, off_t offset, dict_t * xdata) +{ +    ec_cbk_t callback = { .readdir = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(READDIR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_READDIR, 0, target, minimum, +                               ec_wind_readdir, ec_manager_readdir, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->size = size; +    fop->offset = offset; + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} + +/* FOP: readdirp */ + +int32_t ec_readdirp_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                        int32_t op_ret, int32_t op_errno, +                        gf_dirent_t * entries, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    if (op_ret > 0) +    { +        ec_adjust_readdir(fop->xl->private, idx, entries); +    } + +    if (!ec_dispatch_one_retry(fop, idx, op_ret, op_errno)) +    { +        if (fop->cbks.readdirp != NULL) +        { +            fop->cbks.readdirp(fop->req_frame, fop, this, op_ret, op_errno, +                               entries, xdata); +        } +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_readdirp(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_readdirp_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->readdirp, +                      fop->fd, fop->size, fop->offset, fop->xdata); +} + +void ec_readdirp(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_readdirp_cbk_t func, void * data, +                 fd_t * fd, size_t size, off_t offset, dict_t * xdata) +{ +    ec_cbk_t callback = { .readdirp = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(READDIRP) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_READDIRP, 0, target, +                               minimum, ec_wind_readdirp, ec_manager_readdir, +                               callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->size = size; +    fop->offset = offset; + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} diff --git a/xlators/cluster/ec/src/ec-dir-write.c b/xlators/cluster/ec/src/ec-dir-write.c new file mode 100644 index 00000000000..da89e34ba25 --- /dev/null +++ b/xlators/cluster/ec/src/ec-dir-write.c @@ -0,0 +1,2102 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "xlator.h" +#include "defaults.h" + +#include "ec-helpers.h" +#include "ec-common.h" +#include "ec-combine.h" +#include "ec-method.h" +#include "ec-fops.h" + +/* FOP: create */ + +int32_t ec_combine_create(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                          ec_cbk_data_t * src) +{ +    if (dst->fd != src->fd) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching fd in answers " +                                             "of 'GF_FOP_CREATE': %p <-> %p", +               dst->fd, src->fd); + +        return 0; +    } + +    if (!ec_iatt_combine(dst->iatt, src->iatt, 3)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_CREATE'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_create_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                      int32_t op_ret, int32_t op_errno, fd_t * fd, +                      inode_t * inode, struct iatt * buf, +                      struct iatt * preparent, struct iatt * postparent, +                      dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_CREATE, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (fd != NULL) +            { +                cbk->fd = fd_ref(fd); +                if (cbk->fd == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                     "file descriptor."); + +                    goto out; +                } +            } +            if (inode != NULL) +            { +                cbk->inode = inode_ref(inode); +                if (cbk->inode == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, +                           "Failed to reference an inode."); + +                    goto out; +                } +            } +            if (buf != NULL) +            { +                cbk->iatt[0] = *buf; +            } +            if (preparent != NULL) +            { +                cbk->iatt[1] = *preparent; +            } +            if (postparent != NULL) +            { +                cbk->iatt[2] = *postparent; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_create); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_create(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_create_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->create, +                      &fop->loc[0], fop->int32, fop->mode[0], fop->mode[1], +                      fop->fd, fop->xdata); +} + +int32_t ec_manager_create(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; +    ec_fd_t * ctx; + +    switch (state) +    { +        case EC_STATE_INIT: +            LOCK(&fop->fd->lock); + +            ctx = __ec_fd_get(fop->fd, fop->xl); +            if ((ctx == NULL) || !ec_loc_from_loc(fop->xl, &ctx->loc, +                &fop->loc[0])) +            { +                UNLOCK(&fop->fd->lock); + +                fop->error = EIO; + +                return EC_STATE_REPORT; +            } + +            if (ctx->flags == 0) +            { +                ctx->flags = fop->int32; +            } + +            UNLOCK(&fop->fd->lock); + +            fop->int32 &= ~O_ACCMODE; +            fop->int32 |= O_RDWR; + +        case EC_STATE_LOCK: +            ec_lock_entry(fop, &fop->loc[0]); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 3, +                                    cbk->count); + +                    ec_loc_prepare(fop->xl, &fop->loc[0], cbk->inode, +                                   &cbk->iatt[0]); + +                    LOCK(&fop->fd->lock); + +                    ctx = __ec_fd_get(fop->fd, fop->xl); +                    if (ctx != NULL) +                    { +                        ctx->open |= cbk->mask; +                    } + +                    UNLOCK(&fop->fd->lock); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.create != NULL) +            { +                fop->cbks.create(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                 cbk->op_errno, cbk->fd, cbk->inode, +                                 &cbk->iatt[0], &cbk->iatt[1], &cbk->iatt[2], +                                 cbk->xdata); +            } + +            if (cbk->op_ret >= 0) +            { +                return EC_STATE_UPDATE_SIZE_AND_VERSION; +            } +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.create != NULL) +            { +                fop->cbks.create(fop->req_frame, fop, fop->xl, -1, fop->error, +                                 NULL, NULL, NULL, NULL, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case EC_STATE_UPDATE_SIZE_AND_VERSION: +            ec_update_size_version(fop); + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UPDATE_SIZE_AND_VERSION: +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_create(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_create_cbk_t func, void * data, +               loc_t * loc, int32_t flags, mode_t mode, mode_t umask, +               fd_t * fd, dict_t * xdata) +{ +    ec_cbk_t callback = { .create = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(CREATE) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_CREATE, +                               EC_FLAG_UPDATE_LOC_PARENT | +                               EC_FLAG_UPDATE_FD_INODE, target, minimum, +                               ec_wind_create, ec_manager_create, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = flags; +    fop->mode[0] = mode; +    fop->mode[1] = umask; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL, NULL, NULL, NULL); +    } +} + +/* FOP: link */ + +int32_t ec_combine_link(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                        ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 3)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_LINK'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_link_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                    int32_t op_ret, int32_t op_errno, inode_t * inode, +                    struct iatt * buf, struct iatt * preparent, +                    struct iatt * postparent, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_LINK, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (inode != NULL) +            { +                cbk->inode = inode_ref(inode); +                if (cbk->inode == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, +                           "Failed to reference an inode."); + +                    goto out; +                } +            } +            if (buf != NULL) +            { +                cbk->iatt[0] = *buf; +            } +            if (preparent != NULL) +            { +                cbk->iatt[1] = *preparent; +            } +            if (postparent != NULL) +            { +                cbk->iatt[2] = *postparent; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_link); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_link(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_link_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->link, +                      &fop->loc[0], &fop->loc[1], fop->xdata); +} + +int32_t ec_manager_link(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            // Parent entry of fop->loc[0] should be locked, but I don't +            // receive enough information to do it (fop->loc[0].parent is +            // NULL). +            ec_lock_entry(fop, &fop->loc[1]); + +            return EC_STATE_GET_SIZE_AND_VERSION; + +        case EC_STATE_GET_SIZE_AND_VERSION: +            ec_get_size_version(fop); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 3, +                                    cbk->count); + +                    ec_loc_prepare(fop->xl, &fop->loc[0], cbk->inode, +                                   &cbk->iatt[0]); + +                    if (cbk->iatt[0].ia_type == IA_IFREG) +                    { +                        cbk->iatt[0].ia_size = fop->pre_size; +                    } +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.link != NULL) +            { +                fop->cbks.link(fop->req_frame, fop, fop->xl, cbk->op_ret, +                               cbk->op_errno, cbk->inode, &cbk->iatt[0], +                               &cbk->iatt[1], &cbk->iatt[2], cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_GET_SIZE_AND_VERSION: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.link != NULL) +            { +                fop->cbks.link(fop->req_frame, fop, fop->xl, -1, fop->error, +                               NULL, NULL, NULL, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_link(call_frame_t * frame, xlator_t * this, uintptr_t target, +             int32_t minimum, fop_link_cbk_t func, void * data, loc_t * oldloc, +             loc_t * newloc, dict_t * xdata) +{ +    ec_cbk_t callback = { .link = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(LINK) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_LINK, 0, target, minimum, +                               ec_wind_link, ec_manager_link, callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (oldloc != NULL) +    { +        if (loc_copy(&fop->loc[0], oldloc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (newloc != NULL) +    { +        if (loc_copy(&fop->loc[1], newloc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL, NULL, NULL); +    } +} + +/* FOP: mkdir */ + +int32_t ec_combine_mkdir(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                         ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 3)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_MKDIR'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_mkdir_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                     int32_t op_ret, int32_t op_errno, inode_t * inode, +                     struct iatt * buf, struct iatt * preparent, +                     struct iatt * postparent, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_MKDIR, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (inode != NULL) +            { +                cbk->inode = inode_ref(inode); +                if (cbk->inode == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, +                           "Failed to reference an inode."); + +                    goto out; +                } +            } +            if (buf != NULL) +            { +                cbk->iatt[0] = *buf; +            } +            if (preparent != NULL) +            { +                cbk->iatt[1] = *preparent; +            } +            if (postparent != NULL) +            { +                cbk->iatt[2] = *postparent; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_mkdir); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_mkdir(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_mkdir_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->mkdir, +                      &fop->loc[0], fop->mode[0], fop->mode[1], fop->xdata); +} + +int32_t ec_manager_mkdir(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_entry(fop, &fop->loc[0]); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 3, +                                    cbk->count); + +                    ec_loc_prepare(fop->xl, &fop->loc[0], cbk->inode, +                                   &cbk->iatt[0]); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.mkdir != NULL) +            { +                fop->cbks.mkdir(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                cbk->op_errno, cbk->inode, &cbk->iatt[0], +                                &cbk->iatt[1], &cbk->iatt[2], cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.mkdir != NULL) +            { +                fop->cbks.mkdir(fop->req_frame, fop, fop->xl, -1, fop->error, +                                NULL, NULL, NULL, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_mkdir(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_mkdir_cbk_t func, void * data, loc_t * loc, +              mode_t mode, mode_t umask, dict_t * xdata) +{ +    ec_cbk_t callback = { .mkdir = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(MKDIR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_MKDIR, +                               EC_FLAG_UPDATE_LOC_PARENT, target, minimum, +                               ec_wind_mkdir, ec_manager_mkdir, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->mode[0] = mode; +    fop->mode[1] = umask; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL, NULL, NULL); +    } +} + +/* FOP: mknod */ + +int32_t ec_combine_mknod(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                         ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 3)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_MKNOD'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_mknod_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                     int32_t op_ret, int32_t op_errno, inode_t * inode, +                     struct iatt * buf, struct iatt * preparent, +                     struct iatt * postparent, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_MKNOD, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (inode != NULL) +            { +                cbk->inode = inode_ref(inode); +                if (cbk->inode == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, +                           "Failed to reference an inode."); + +                    goto out; +                } +            } +            if (buf != NULL) +            { +                cbk->iatt[0] = *buf; +            } +            if (preparent != NULL) +            { +                cbk->iatt[1] = *preparent; +            } +            if (postparent != NULL) +            { +                cbk->iatt[2] = *postparent; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_mknod); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_mknod(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_mknod_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->mknod, +                      &fop->loc[0], fop->mode[0], fop->dev, fop->mode[1], +                      fop->xdata); +} + +int32_t ec_manager_mknod(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_entry(fop, &fop->loc[0]); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 3, +                                    cbk->count); + +                    ec_loc_prepare(fop->xl, &fop->loc[0], cbk->inode, +                                   &cbk->iatt[0]); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.mknod != NULL) +            { +                fop->cbks.mknod(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                cbk->op_errno, cbk->inode, &cbk->iatt[0], +                                &cbk->iatt[1], &cbk->iatt[2], cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.mknod != NULL) +            { +                fop->cbks.mknod(fop->req_frame, fop, fop->xl, -1, fop->error, +                                NULL, NULL, NULL, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_mknod(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_mknod_cbk_t func, void * data, loc_t * loc, +              mode_t mode, dev_t rdev, mode_t umask, dict_t * xdata) +{ +    ec_cbk_t callback = { .mknod = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(MKNOD) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_MKNOD, +                               EC_FLAG_UPDATE_LOC_PARENT, target, minimum, +                               ec_wind_mknod, ec_manager_mknod, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->mode[0] = mode; +    fop->dev = rdev; +    fop->mode[1] = umask; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL, NULL, NULL); +    } +} + +/* FOP: rename */ + +int32_t ec_combine_rename(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                          ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 5)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_RENAME'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_rename_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                      int32_t op_ret, int32_t op_errno, struct iatt * buf, +                      struct iatt * preoldparent, struct iatt * postoldparent, +                      struct iatt * prenewparent, struct iatt * postnewparent, +                      dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_RENAME, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (buf != NULL) +            { +                cbk->iatt[0] = *buf; +            } +            if (preoldparent != NULL) +            { +                cbk->iatt[1] = *preoldparent; +            } +            if (postoldparent != NULL) +            { +                cbk->iatt[2] = *postoldparent; +            } +            if (prenewparent != NULL) +            { +                cbk->iatt[3] = *prenewparent; +            } +            if (postnewparent != NULL) +            { +                cbk->iatt[4] = *postnewparent; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_rename); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_rename(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_rename_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->rename, +                      &fop->loc[0], &fop->loc[1], fop->xdata); +} + +int32_t ec_manager_rename(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_entry(fop, &fop->loc[0]); +            ec_lock_entry(fop, &fop->loc[1]); + +            return EC_STATE_GET_SIZE_AND_VERSION; + +        case EC_STATE_GET_SIZE_AND_VERSION: +            ec_get_size_version(fop); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 5, +                                    cbk->count); + +                    if (cbk->iatt[0].ia_type == IA_IFREG) +                    { +                        cbk->iatt[0].ia_size = fop->pre_size; +                    } +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.rename != NULL) +            { +                fop->cbks.rename(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                 cbk->op_errno, &cbk->iatt[0], &cbk->iatt[1], +                                 &cbk->iatt[2], &cbk->iatt[3], &cbk->iatt[4], +                                 cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_GET_SIZE_AND_VERSION: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.rename != NULL) +            { +                fop->cbks.rename(fop->req_frame, fop, fop->xl, -1, fop->error, +                                 NULL, NULL, NULL, NULL, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_rename(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_rename_cbk_t func, void * data, +               loc_t * oldloc, loc_t * newloc, dict_t * xdata) +{ +    ec_cbk_t callback = { .rename = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(RENAME) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_RENAME, +                               EC_FLAG_UPDATE_LOC_PARENT, target, minimum, +                               ec_wind_rename, ec_manager_rename, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (oldloc != NULL) +    { +        if (loc_copy(&fop->loc[0], oldloc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (newloc != NULL) +    { +        if (loc_copy(&fop->loc[1], newloc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL, NULL, NULL, NULL); +    } +} + +/* FOP: rmdir */ + +int32_t ec_combine_rmdir(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                         ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 2)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_RMDIR'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_rmdir_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                     int32_t op_ret, int32_t op_errno, struct iatt * preparent, +                     struct iatt * postparent, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_RMDIR, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (preparent != NULL) +            { +                cbk->iatt[0] = *preparent; +            } +            if (postparent != NULL) +            { +                cbk->iatt[1] = *postparent; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_rmdir); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_rmdir(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_rmdir_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->rmdir, +                      &fop->loc[0], fop->int32, fop->xdata); +} + +int32_t ec_manager_rmdir(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_entry(fop, &fop->loc[0]); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.rmdir != NULL) +            { +                fop->cbks.rmdir(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                cbk->op_errno, &cbk->iatt[0], &cbk->iatt[1], +                                cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.rmdir != NULL) +            { +                fop->cbks.rmdir(fop->req_frame, fop, fop->xl, -1, fop->error, +                                NULL, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_rmdir(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_rmdir_cbk_t func, void * data, loc_t * loc, +              int xflags, dict_t * xdata) +{ +    ec_cbk_t callback = { .rmdir = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(RMDIR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_RMDIR, +                               EC_FLAG_UPDATE_LOC_PARENT, target, minimum, +                               ec_wind_rmdir, ec_manager_rmdir, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = xflags; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL); +    } +} + +/* FOP: symlink */ + +int32_t ec_combine_symlink(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                           ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 3)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_SYMLINK'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_symlink_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                       int32_t op_ret, int32_t op_errno, inode_t * inode, +                       struct iatt * buf, struct iatt * preparent, +                       struct iatt * postparent, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_SYMLINK, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (inode != NULL) +            { +                cbk->inode = inode_ref(inode); +                if (cbk->inode == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, +                           "Failed to reference an inode."); + +                    goto out; +                } +            } +            if (buf != NULL) +            { +                cbk->iatt[0] = *buf; +            } +            if (preparent != NULL) +            { +                cbk->iatt[1] = *preparent; +            } +            if (postparent != NULL) +            { +                cbk->iatt[2] = *postparent; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_symlink); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_symlink(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_symlink_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->symlink, +                      fop->str[0], &fop->loc[0], fop->mode[0], fop->xdata); +} + +int32_t ec_manager_symlink(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_entry(fop, &fop->loc[0]); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 3, +                                    cbk->count); + +                    ec_loc_prepare(fop->xl, &fop->loc[0], cbk->inode, +                                   &cbk->iatt[0]); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.symlink != NULL) +            { +                fop->cbks.symlink(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                  cbk->op_errno, cbk->inode, &cbk->iatt[0], +                                  &cbk->iatt[1], &cbk->iatt[2], cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.symlink != NULL) +            { +                fop->cbks.symlink(fop->req_frame, fop, fop->xl, -1, fop->error, +                                  NULL, NULL, NULL, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_symlink(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_symlink_cbk_t func, void * data, +                const char * linkname, loc_t * loc, mode_t umask, +                dict_t * xdata) +{ +    ec_cbk_t callback = { .symlink = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(SYMLINK) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_SYMLINK, +                               EC_FLAG_UPDATE_LOC_PARENT, target, minimum, +                               ec_wind_symlink, ec_manager_symlink, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->mode[0] = umask; + +    if (linkname != NULL) +    { +        fop->str[0] = gf_strdup(linkname); +        if (fop->str[0] == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a string."); + +            goto out; +        } +    } +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL, NULL, NULL); +    } +} + +/* FOP: unlink */ + +int32_t ec_combine_unlink(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                          ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 2)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_UNLINK'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_unlink_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                      int32_t op_ret, int32_t op_errno, +                      struct iatt * preparent, struct iatt * postparent, +                      dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_UNLINK, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (preparent != NULL) +            { +                cbk->iatt[0] = *preparent; +            } +            if (postparent != NULL) +            { +                cbk->iatt[1] = *postparent; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_unlink); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_unlink(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_unlink_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->unlink, +                      &fop->loc[0], fop->int32, fop->xdata); +} + +int32_t ec_manager_unlink(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_entry(fop, &fop->loc[0]); + +            return EC_STATE_GET_SIZE_AND_VERSION; + +        case EC_STATE_GET_SIZE_AND_VERSION: +            ec_get_size_version(fop); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.unlink != NULL) +            { +                fop->cbks.unlink(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                 cbk->op_errno, &cbk->iatt[0], &cbk->iatt[1], +                                 cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_GET_SIZE_AND_VERSION: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.unlink != NULL) +            { +                fop->cbks.unlink(fop->req_frame, fop, fop->xl, -1, fop->error, +                                 NULL, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_unlink(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_unlink_cbk_t func, void * data, +               loc_t * loc, int xflags, dict_t * xdata) +{ +    ec_cbk_t callback = { .unlink = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(UNLINK) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_UNLINK, +                               EC_FLAG_UPDATE_LOC_PARENT, target, minimum, +                               ec_wind_unlink, ec_manager_unlink, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = xflags; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL); +    } +} diff --git a/xlators/cluster/ec/src/ec-fops.h b/xlators/cluster/ec/src/ec-fops.h new file mode 100644 index 00000000000..2b6e03f723f --- /dev/null +++ b/xlators/cluster/ec/src/ec-fops.h @@ -0,0 +1,211 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef __EC_FOPS_H__ +#define __EC_FOPS_H__ + +#include "xlator.h" + +#include "ec-data.h" +#include "ec-common.h" + +#define EC_FOP_HEAL     -1 +#define EC_FOP_FHEAL    -2 + +void ec_access(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_access_cbk_t func, void *data, loc_t * loc, +               int32_t mask, dict_t * xdata); + +void ec_create(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_create_cbk_t func, void *data, loc_t * loc, +               int32_t flags, mode_t mode, mode_t umask, fd_t * fd, +               dict_t * xdata); + +void ec_entrylk(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_entrylk_cbk_t func, void *data, +                const char * volume, loc_t * loc, const char * basename, +                entrylk_cmd cmd, entrylk_type type, dict_t * xdata); + +void ec_fentrylk(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_fentrylk_cbk_t func, void *data, +                 const char * volume, fd_t * fd, const char * basename, +                 entrylk_cmd cmd, entrylk_type type, dict_t * xdata); + +void ec_flush(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_flush_cbk_t func, void *data, fd_t * fd, +              dict_t * xdata); + +void ec_fsync(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_fsync_cbk_t func, void *data, fd_t * fd, +              int32_t datasync, dict_t * xdata); + +void ec_fsyncdir(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_fsyncdir_cbk_t func, void *data, +                 fd_t * fd, int32_t datasync, dict_t * xdata); + +void ec_getxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_getxattr_cbk_t func, void *data, +                 loc_t * loc, const char * name, dict_t * xdata); + +void ec_fgetxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                  int32_t minimum, fop_fgetxattr_cbk_t func, void *data, +                  fd_t * fd, const char * name, dict_t * xdata); + +void ec_heal(call_frame_t * frame, xlator_t * this, uintptr_t target, +             int32_t minimum, fop_heal_cbk_t func, void *data, loc_t * loc, +             dict_t * xdata); + +void ec_fheal(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_fheal_cbk_t func, void *data, fd_t * fd, +              dict_t * xdata); + +void ec_inodelk(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_inodelk_cbk_t func, void *data, +                const char * volume, loc_t * loc, int32_t cmd, +                struct gf_flock * flock, dict_t * xdata); + +void ec_finodelk(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_finodelk_cbk_t func, void *data, +                 const char * volume, fd_t * fd, int32_t cmd, +                 struct gf_flock * flock, dict_t * xdata); + +void ec_link(call_frame_t * frame, xlator_t * this, uintptr_t target, +             int32_t minimum, fop_link_cbk_t func, void *data, loc_t * oldloc, +             loc_t * newloc, dict_t * xdata); + +void ec_lk(call_frame_t * frame, xlator_t * this, uintptr_t target, +           int32_t minimum, fop_lk_cbk_t func, void *data, fd_t * fd, +           int32_t cmd, struct gf_flock * flock, dict_t * xdata); + +void ec_lookup(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_lookup_cbk_t func, void *data, loc_t * loc, +               dict_t * xdata); + +void ec_mkdir(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_mkdir_cbk_t func, void *data, loc_t * loc, +              mode_t mode, mode_t umask, dict_t * xdata); + +void ec_mknod(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_mknod_cbk_t func, void *data, loc_t * loc, +              mode_t mode, dev_t rdev, mode_t umask, dict_t * xdata); + +void ec_open(call_frame_t * frame, xlator_t * this, uintptr_t target, +             int32_t minimum, fop_open_cbk_t func, void *data, loc_t * loc, +             int32_t flags, fd_t * fd, dict_t * xdata); + +void ec_opendir(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_opendir_cbk_t func, void *data, +                loc_t * loc, fd_t * fd, dict_t * xdata); + +void ec_readdir(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_readdir_cbk_t func, void *data, fd_t * fd, +                size_t size, off_t offset, dict_t * xdata); + +void ec_readdirp(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_readdirp_cbk_t func, void *data, +                 fd_t * fd, size_t size, off_t offset, dict_t * xdata); + +void ec_readlink(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_readlink_cbk_t func, void *data, +                 loc_t * loc, size_t size, dict_t * xdata); + +void ec_readv(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_readv_cbk_t func, void *data, fd_t * fd, +              size_t size, off_t offset, uint32_t flags, dict_t * xdata); + +void ec_removexattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                    int32_t minimum, fop_removexattr_cbk_t func, void *data, +                    loc_t * loc, const char * name, dict_t * xdata); + +void ec_fremovexattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                     int32_t minimum, fop_fremovexattr_cbk_t func, void *data, +                     fd_t * fd, const char * name, dict_t * xdata); + +void ec_rename(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_rename_cbk_t func, void *data, +               loc_t * oldloc, loc_t * newloc, dict_t * xdata); + +void ec_rmdir(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_rmdir_cbk_t func, void *data, loc_t * loc, +              int xflags, dict_t * xdata); + +void ec_setattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_setattr_cbk_t func, void *data, +                loc_t * loc, struct iatt * stbuf, int32_t valid, +                dict_t * xdata); + +void ec_fsetattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_fsetattr_cbk_t func, void *data, +                 fd_t * fd, struct iatt * stbuf, int32_t valid, +                 dict_t * xdata); + +void ec_setxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_setxattr_cbk_t func, void *data, +                 loc_t * loc, dict_t * dict, int32_t flags, dict_t * xdata); + +void ec_fsetxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                  int32_t minimum, fop_fsetxattr_cbk_t func, void *data, +                  fd_t * fd, dict_t * dict, int32_t flags, dict_t * xdata); + +void ec_stat(call_frame_t * frame, xlator_t * this, uintptr_t target, +             int32_t minimum, fop_stat_cbk_t func, void *data, loc_t * loc, +             dict_t * xdata); + +void ec_fstat(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_fstat_cbk_t func, void *data, fd_t * fd, +              dict_t * xdata); + +void ec_statfs(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_statfs_cbk_t func, void *data, loc_t * loc, +               dict_t * xdata); + +void ec_symlink(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_symlink_cbk_t func, void *data, +                const char * linkname, loc_t * loc, mode_t umask, +                dict_t * xdata); + +void ec_truncate(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_truncate_cbk_t func, void *data, +                 loc_t * loc, off_t offset, dict_t * xdata); + +void ec_ftruncate(call_frame_t * frame, xlator_t * this, uintptr_t target, +                  int32_t minimum, fop_ftruncate_cbk_t func, void *data, +                  fd_t * fd, off_t offset, dict_t * xdata); + +void ec_unlink(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_unlink_cbk_t func, void *data, loc_t * loc, +               int xflags, dict_t * xdata); + +void ec_writev(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_writev_cbk_t func, void *data, fd_t * fd, +               struct iovec * vector, int32_t count, off_t offset, +               uint32_t flags, struct iobref * iobref, dict_t * xdata); + +void ec_xattrop(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_xattrop_cbk_t func, void *data, +                loc_t * loc, gf_xattrop_flags_t optype, dict_t * xattr, +                dict_t * xdata); + +void ec_fxattrop(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_fxattrop_cbk_t func, void *data, +                 fd_t * fd, gf_xattrop_flags_t optype, dict_t * xattr, +                 dict_t * xdata); + +#endif /* __EC_FOPS_H__ */ diff --git a/xlators/cluster/ec/src/ec-generic.c b/xlators/cluster/ec/src/ec-generic.c new file mode 100644 index 00000000000..49343388934 --- /dev/null +++ b/xlators/cluster/ec/src/ec-generic.c @@ -0,0 +1,1660 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "xlator.h" +#include "defaults.h" + +#include "ec-helpers.h" +#include "ec-common.h" +#include "ec-combine.h" +#include "ec-method.h" +#include "ec-fops.h" + +/* FOP: flush */ + +int32_t ec_flush_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                     int32_t op_ret, int32_t op_errno, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FLUSH, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, NULL); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_flush(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_flush_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->flush, fop->fd, +                      fop->xdata); +} + +int32_t ec_manager_flush(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_fd(fop, fop->fd); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.flush != NULL) +            { +                fop->cbks.flush(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                cbk->op_errno, cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.flush != NULL) +            { +                fop->cbks.flush(fop->req_frame, fop, fop->xl, -1, fop->error, +                                NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_flush(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_flush_cbk_t func, void * data, fd_t * fd, +              dict_t * xdata) +{ +    ec_cbk_t callback = { .flush = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FLUSH) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FLUSH, EC_FLAG_UPDATE_FD, +                               target, minimum, ec_wind_flush, +                               ec_manager_flush, callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL); +    } +} + +/* FOP: fsync */ + +int32_t ec_combine_fsync(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                         ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 2)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_FSYNC'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_fsync_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                     int32_t op_ret, int32_t op_errno, struct iatt * prebuf, +                     struct iatt * postbuf, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FSYNC, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (prebuf != NULL) +            { +                cbk->iatt[0] = *prebuf; +            } +            if (postbuf != NULL) +            { +                cbk->iatt[1] = *postbuf; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_fsync); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_fsync(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_fsync_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->fsync, fop->fd, +                      fop->int32, fop->xdata); +} + +int32_t ec_manager_fsync(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_fd(fop, fop->fd); + +            return EC_STATE_GET_SIZE_AND_VERSION; + +        case EC_STATE_GET_SIZE_AND_VERSION: +            ec_get_size_version(fop); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 2, +                                    cbk->count); + +                    cbk->iatt[0].ia_size = fop->pre_size; +                    cbk->iatt[1].ia_size = fop->post_size; +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.fsync != NULL) +            { +                fop->cbks.fsync(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                cbk->op_errno, &cbk->iatt[0], &cbk->iatt[1], +                                cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_GET_SIZE_AND_VERSION: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.fsync != NULL) +            { +                fop->cbks.fsync(fop->req_frame, fop, fop->xl, -1, fop->error, +                                NULL, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_fsync(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_fsync_cbk_t func, void * data, fd_t * fd, +              int32_t datasync, dict_t * xdata) +{ +    ec_cbk_t callback = { .fsync = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FSYNC) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FSYNC, EC_FLAG_UPDATE_FD, +                               target, minimum, ec_wind_fsync, +                               ec_manager_fsync, callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = datasync; + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL); +    } +} + +/* FOP: fsyncdir */ + +int32_t ec_fsyncdir_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                        int32_t op_ret, int32_t op_errno, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FSYNCDIR, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, NULL); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_fsyncdir(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_fsyncdir_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->fsyncdir, +                      fop->fd, fop->int32, fop->xdata); +} + +int32_t ec_manager_fsyncdir(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_fd(fop, fop->fd); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.fsyncdir != NULL) +            { +                fop->cbks.fsyncdir(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                   cbk->op_errno, cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.fsyncdir != NULL) +            { +                fop->cbks.fsyncdir(fop->req_frame, fop, fop->xl, -1, +                                   fop->error, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_fsyncdir(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_fsyncdir_cbk_t func, void * data, +                 fd_t * fd, int32_t datasync, dict_t * xdata) +{ +    ec_cbk_t callback = { .fsyncdir = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FSYNCDIR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FSYNCDIR, EC_FLAG_UPDATE_FD, +                               target, minimum, ec_wind_fsyncdir, +                               ec_manager_fsyncdir, callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = datasync; + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL); +    } +} + +/* FOP: lookup */ + +void ec_lookup_rebuild(ec_t * ec, ec_fop_data_t * fop, ec_cbk_data_t * cbk) +{ +    ec_cbk_data_t * ans = NULL; +    data_t * data = NULL; +    uint8_t * ptr = NULL, * buff = NULL, * tmp = NULL; +    size_t size = 0; +    int32_t i = 0; + +    if (cbk->op_ret < 0) +    { +        return; +    } + +    ec_dict_del_number(cbk->xdata, EC_XATTR_VERSION, &cbk->version); + +    ec_loc_prepare(fop->xl, &fop->loc[0], cbk->inode, &cbk->iatt[0]); + +    if (cbk->iatt[0].ia_type == IA_IFREG) +    { +        uint8_t * blocks[cbk->count]; +        uint8_t * ptrs[cbk->count]; +        uint32_t values[cbk->count]; + +        cbk->size = cbk->iatt[0].ia_size; +        ec_dict_del_number(cbk->xdata, EC_XATTR_SIZE, &cbk->iatt[0].ia_size); + +        size = SIZE_MAX; +        for (i = 0, ans = cbk; (ans != NULL) && (i < ec->fragments); +             ans = ans->next) +        { +            data = dict_get(ans->xdata, GF_CONTENT_KEY); +            if (data != NULL) +            { +                values[i] = ans->idx; +                ptrs[i] = GF_MALLOC(data->len + EC_BUFFER_ALIGN_SIZE - 1, +                                    gf_common_mt_char); +                if (ptrs[i] == NULL) +                { +                    continue; +                } + +                if (size > data->len) +                { +                    size = data->len; +                } +                blocks[i] = GF_ALIGN_BUF(ptrs[i], EC_BUFFER_ALIGN_SIZE); +                memcpy(blocks[i], data->data, size); + +                i++; +            } +        } + +        dict_del(cbk->xdata, GF_CONTENT_KEY); + +        if (i >= ec->fragments) +        { +            size -= size % ec->fragment_size; +            if (size > 0) +            { +                ptr = GF_MALLOC(size * ec->fragments + +                                    EC_BUFFER_ALIGN_SIZE - 1, +                                gf_common_mt_char); +                if (ptr != NULL) +                { +                    buff = GF_ALIGN_BUF(ptr, EC_BUFFER_ALIGN_SIZE); + +                    size = ec_method_decode(size, ec->fragments, values, +                                            blocks, buff); +                    if (size > fop->size) +                    { +                        size = fop->size; +                    } +                    if (size > cbk->iatt[0].ia_size) +                    { +                        size = cbk->iatt[0].ia_size; +                    } + +                    tmp = GF_MALLOC(size, gf_common_mt_char); +                    if (tmp != NULL) +                    { +                        memcpy(tmp, buff, size); +                        if (dict_set_bin(cbk->xdata, GF_CONTENT_KEY, tmp, +                                         size) != 0) +                        { +                            GF_FREE(tmp); + +                            gf_log(fop->xl->name, GF_LOG_WARNING, "Lookup " +                                                                  "read-ahead " +                                                                  "failed"); +                        } +                    } + +                    GF_FREE(ptr); +                } +                else +                { +                    gf_log(fop->xl->name, GF_LOG_WARNING, "Lookup read-ahead " +                                                          "failed"); +                } +            } +        } +        while (--i > 0) +        { +            GF_FREE(ptrs[i]); +        } +    } +} + +int32_t ec_combine_lookup(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                          ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 2)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_LOOKUP'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_lookup_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                      int32_t op_ret, int32_t op_errno, inode_t * inode, +                      struct iatt * buf, dict_t * xdata, +                      struct iatt * postparent) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_LOOKUP, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (inode != NULL) +            { +                cbk->inode = inode_ref(inode); +                if (cbk->inode == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, +                           "Failed to reference an inode."); + +                    goto out; +                } +            } +            if (buf != NULL) +            { +                cbk->iatt[0] = *buf; +            } +            if (postparent != NULL) +            { +                cbk->iatt[1] = *postparent; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_lookup); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_lookup(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_lookup_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->lookup, +                      &fop->loc[0], fop->xdata); +} + +int32_t ec_manager_lookup(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +            if (fop->xdata == NULL) +            { +                fop->xdata = dict_new(); +                if (fop->xdata == NULL) +                { +                    gf_log(fop->xl->name, GF_LOG_ERROR, "Unable to prepare " +                                                        "lookup request"); + +                    fop->error = EIO; + +                    return EC_STATE_REPORT; +                } +            } +            else +            { +                uint64_t size; + +                if (dict_get_uint64(fop->xdata, GF_CONTENT_KEY, &size) == 0) +                { +                    fop->size = size; +                    size = ec_adjust_size(fop->xl->private, size, 1); +                    if (dict_set_uint64(fop->xdata, GF_CONTENT_KEY, size) != 0) +                    { +                        gf_log("ec", GF_LOG_DEBUG, "Unable to update lookup " +                                                   "content size"); +                    } +                } +            } +            if ((dict_set_uint64(fop->xdata, EC_XATTR_SIZE, 0) != 0) || +                (dict_set_uint64(fop->xdata, EC_XATTR_VERSION, 0) != 0)) +            { +                gf_log(fop->xl->name, GF_LOG_ERROR, "Unable to prepare lookup " +                                                    "request"); + +                fop->error = EIO; + +                return EC_STATE_REPORT; +            } + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 2, +                                    cbk->count); + +                    ec_lookup_rebuild(fop->xl->private, fop, cbk); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.lookup != NULL) +            { +                fop->cbks.lookup(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                 cbk->op_errno, cbk->inode, &cbk->iatt[0], +                                 cbk->xdata, &cbk->iatt[1]); +            } + +            return EC_STATE_END; + +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.lookup != NULL) +            { +                fop->cbks.lookup(fop->req_frame, fop, fop->xl, -1, fop->error, +                                 NULL, NULL, NULL, NULL); +            } + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_lookup(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_lookup_cbk_t func, void * data, +               loc_t * loc, dict_t * xdata) +{ +    ec_cbk_t callback = { .lookup = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(LOOKUP) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_LOOKUP, 0, target, minimum, +                               ec_wind_lookup, ec_manager_lookup, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL, NULL); +    } +} + +/* FOP: statfs */ + +int32_t ec_combine_statfs(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                          ec_cbk_data_t * src) +{ +    ec_statvfs_combine(&dst->statvfs, &src->statvfs); + +    return 1; +} + +int32_t ec_statfs_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                      int32_t op_ret, int32_t op_errno, struct statvfs * buf, +                      dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_STATFS, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (buf != NULL) +            { +                cbk->statvfs = *buf; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_statfs); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_statfs(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_statfs_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->statfs, +                      &fop->loc[0], fop->xdata); +} + +int32_t ec_manager_statfs(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_t * ec = fop->xl->private; + +                    cbk->statvfs.f_blocks *= ec->fragments; +                    cbk->statvfs.f_bfree *= ec->fragments; +                    cbk->statvfs.f_bavail *= ec->fragments; +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.statfs != NULL) +            { +                fop->cbks.statfs(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                 cbk->op_errno, &cbk->statvfs, cbk->xdata); +            } + +            return EC_STATE_END; + +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.statfs != NULL) +            { +                fop->cbks.statfs(fop->req_frame, fop, fop->xl, -1, fop->error, +                                 NULL, NULL); +            } + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_statfs(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_statfs_cbk_t func, void * data, +               loc_t * loc, dict_t * xdata) +{ +    ec_cbk_t callback = { .statfs = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(STATFS) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_STATFS, 0, target, minimum, +                               ec_wind_statfs, ec_manager_statfs, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} + +/* FOP: xattrop */ + +int32_t ec_combine_xattrop(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                           ec_cbk_data_t * src) +{ +    if (!ec_dict_compare(dst->dict, src->dict)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching dictionary in " +                                             "answers of 'GF_FOP_XATTROP'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_xattrop_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                       int32_t op_ret, int32_t op_errno, dict_t * xattr, +                       dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_XATTROP, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (xattr != NULL) +            { +                cbk->dict = dict_ref(xattr); +                if (cbk->dict == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                     "dictionary."); + +                    goto out; +                } +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_xattrop); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_xattrop(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_xattrop_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->xattrop, +                      &fop->loc[0], fop->xattrop_flags, fop->dict, fop->xdata); +} + +int32_t ec_manager_xattrop(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_inode(fop, &fop->loc[0]); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA) || +                    ((cbk->op_ret >= 0) && !ec_dict_combine(cbk, +                                                            EC_COMBINE_DICT))) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.xattrop != NULL) +                { +                    fop->cbks.xattrop(fop->req_frame, fop, fop->xl, +                                      cbk->op_ret, cbk->op_errno, cbk->dict, +                                      cbk->xdata); +                } +            } +            else +            { +                if (fop->cbks.fxattrop != NULL) +                { +                    fop->cbks.fxattrop(fop->req_frame, fop, fop->xl, +                                       cbk->op_ret, cbk->op_errno, cbk->dict, +                                       cbk->xdata); +                } +            } + +            if (cbk->op_ret >= 0) +            { +                return EC_STATE_UPDATE_SIZE_AND_VERSION; +            } +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.xattrop != NULL) +                { +                    fop->cbks.xattrop(fop->req_frame, fop, fop->xl, -1, +                                      fop->error, NULL, NULL); +                } +            } +            else +            { +                if (fop->cbks.fxattrop != NULL) +                { +                    fop->cbks.fxattrop(fop->req_frame, fop, fop->xl, -1, +                                       fop->error, NULL, NULL); +                } +            } + +            return EC_STATE_UNLOCK; + +        case EC_STATE_UPDATE_SIZE_AND_VERSION: +            ec_update_size_version(fop); + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UPDATE_SIZE_AND_VERSION: +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_xattrop(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_xattrop_cbk_t func, void * data, +                loc_t * loc, gf_xattrop_flags_t optype, dict_t * xattr, +                dict_t * xdata) +{ +    ec_cbk_t callback = { .xattrop = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(XATTROP) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_XATTROP, +                               EC_FLAG_UPDATE_LOC_INODE, target, minimum, +                               ec_wind_xattrop, ec_manager_xattrop, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->xattrop_flags = optype; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xattr != NULL) +    { +        fop->dict = dict_ref(xattr); +        if (fop->dict == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} + +/* FOP: fxattrop */ + +int32_t ec_fxattrop_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                        int32_t op_ret, int32_t op_errno, dict_t * xattr, +                        dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FXATTROP, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (xattr != NULL) +            { +                cbk->dict = dict_ref(xattr); +                if (cbk->dict == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                     "dictionary."); + +                    goto out; +                } +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_xattrop); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_fxattrop(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_fxattrop_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->fxattrop, +                      fop->fd, fop->xattrop_flags, fop->dict, fop->xdata); +} + +void ec_fxattrop(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_fxattrop_cbk_t func, void * data, +                 fd_t * fd, gf_xattrop_flags_t optype, dict_t * xattr, +                 dict_t * xdata) +{ +    ec_cbk_t callback = { .fxattrop = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FXATTROP) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FXATTROP, +                               EC_FLAG_UPDATE_FD_INODE, target, minimum, +                               ec_wind_fxattrop, ec_manager_xattrop, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->xattrop_flags = optype; + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xattr != NULL) +    { +        fop->dict = dict_ref(xattr); +        if (fop->dict == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} diff --git a/xlators/cluster/ec/src/ec-gf.c b/xlators/cluster/ec/src/ec-gf.c new file mode 100644 index 00000000000..03c4818c0cc --- /dev/null +++ b/xlators/cluster/ec/src/ec-gf.c @@ -0,0 +1,10120 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +/* + * File automatically generated on Thu Jan 26 12:08:19 2012 + * + * DO NOT MODIFY + * + * Multiplications in a GF(2^8) with modulus 0x11D using XOR's + * + * 7994 total xor's + * 31.3 average xor's per number + * 0 xor's for the best case (01) + * 43 xor's for the worst case (F4) + * + *  0 xor's: 01 + * 10 xor's: 03 + * 12 xor's: F5 + * 16 xor's: 04 05 + * 17 xor's: 9C A6 + * 18 xor's: 02 73 + * 19 xor's: 10 39 + * 20 xor's: 0B + * 21 xor's: 0D 59 D2 E9 EC + * 22 xor's: 12 28 61 + * 23 xor's: 08 09 44 + * 24 xor's: 0A 1D 25 55 B4 + * 25 xor's: 07 11 21 51 63 C4 + * 26 xor's: 0C 0F 13 45 54 5E 64 BD F2 + * 27 xor's: 06 1F 22 41 6B B9 C7 D1 F7 + * 28 xor's: 19 31 8C 95 B5 C1 F3 + * 29 xor's: 26 30 42 4A 4B 50 6A 88 90 A3 D8 E0 E8 F0 FD + * 30 xor's: 14 15 20 2E 34 5D 89 99 A2 A9 B0 E5 F9 + * 31 xor's: 16 17 18 1A 1B 24 29 2B 2D 3B 57 84 85 87 8F 97 A5 EB F1 FB + * 32 xor's: 33 36 43 47 65 67 72 75 78 79 81 83 8D 9B A8 AF B8 BB C5 CB CC CE E6 ED + * 33 xor's: 0E 35 3D 49 4C 4D 6E 70 94 98 A0 AB B1 B2 B6 C8 C9 CD D0 D6 DC DD E3 EA F8 + * 34 xor's: 1C 1E 23 27 2C 32 40 46 5C 60 68 6F 71 7F 8A 9A AA AC B3 C2 D3 FC FF + * 35 xor's: 3A 53 58 6D 74 7C 7D 8B 91 93 96 A1 AE C0 CA D5 DB E4 F6 + * 36 xor's: 2A 2F 38 48 4F 5B 66 6C 82 86 92 9F AD BC CF D4 DA DE E2 FA FE + * 37 xor's: 37 3E 52 69 7B 9D B7 BE C3 C6 EE + * 38 xor's: 3C 5A 7E 80 9E A7 BA BF D7 E7 EF + * 39 xor's: 3F 4E 77 8E A4 D9 E1 + * 40 xor's: 76 7A + * 41 xor's: 62 + * 42 xor's: 56 5F DF + * 43 xor's: F4 + * + */ + +#include <xmmintrin.h> + +#include "ec-gf.h" + +static void gf8mul_00000000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm0, %xmm0\n" +        "\tpxor    %xmm1, %xmm1\n" +        "\tpxor    %xmm2, %xmm2\n" +        "\tpxor    %xmm3, %xmm3\n" +        "\tpxor    %xmm4, %xmm4\n" +        "\tpxor    %xmm5, %xmm5\n" +        "\tpxor    %xmm6, %xmm6\n" +        "\tpxor    %xmm7, %xmm7\n" +    ); +} + +static void gf8mul_00000001(void) +{ +} + +static void gf8mul_00000010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00000011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00000100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_00000101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_00000110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00000111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00001000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_00001001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_00001010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00001011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00001100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00001101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_00001110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00001111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00010000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm4, %xmm0\n" +    ); +} + +static void gf8mul_00010001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +    ); +} + +static void gf8mul_00010010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00010011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00010100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_00010101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_00010110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00010111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00011000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_00011001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_00011010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00011011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00011100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_00011101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_00011110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00011111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00100000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm5, %xmm0\n" +    ); +} + +static void gf8mul_00100001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +    ); +} + +static void gf8mul_00100010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00100011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00100100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_00100101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_00100110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00100111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00101000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_00101001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00101010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00101011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00101100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_00101101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_00101110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00101111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00110000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00110001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +    ); +} + +static void gf8mul_00110010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00110011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00110100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_00110101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_00110110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00110111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00111000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_00111001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_00111010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_00111011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_00111100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_00111101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_00111110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +    ); +} + +static void gf8mul_00111111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01000000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm6, %xmm0\n" +    ); +} + +static void gf8mul_01000001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +    ); +} + +static void gf8mul_01000010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01000011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01000100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_01000101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_01000110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01000111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01001000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_01001001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_01001010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01001011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01001100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_01001101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_01001110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01001111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01010000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm4, %xmm0\n" +    ); +} + +static void gf8mul_01010001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +    ); +} + +static void gf8mul_01010010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01010011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01010100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_01010101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_01010110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01010111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01011000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_01011001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_01011010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01011011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01011100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_01011101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_01011110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01011111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_01100000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm5, %xmm0\n" +    ); +} + +static void gf8mul_01100001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +    ); +} + +static void gf8mul_01100010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01100011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01100100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_01100101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_01100110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_01100111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01101000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_01101001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_01101010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01101011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01101100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_01101101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_01101110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_01101111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01110000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm4, %xmm0\n" +    ); +} + +static void gf8mul_01110001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +    ); +} + +static void gf8mul_01110010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01110011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01110100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_01110101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_01110110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01110111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_01111000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_01111001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_01111010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01111011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_01111100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_01111101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_01111110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_01111111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10000000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm7, %xmm0\n" +    ); +} + +static void gf8mul_10000001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +    ); +} + +static void gf8mul_10000010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10000011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10000100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_10000101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_10000110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10000111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10001000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_10001001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_10001010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10001011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10001100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_10001101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_10001110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10001111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10010000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm4, %xmm0\n" +    ); +} + +static void gf8mul_10010001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +    ); +} + +static void gf8mul_10010010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10010011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10010100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_10010101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10010110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10010111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10011000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_10011001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_10011010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10011011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10011100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_10011101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_10011110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10011111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10100000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm5, %xmm0\n" +    ); +} + +static void gf8mul_10100001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +    ); +} + +static void gf8mul_10100010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10100011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10100100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10100101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_10100110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10100111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10101000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_10101001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10101010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10101011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10101100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_10101101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_10101110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10101111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10110000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm4, %xmm0\n" +    ); +} + +static void gf8mul_10110001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +    ); +} + +static void gf8mul_10110010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10110011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10110100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_10110101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_10110110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10110111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10111000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_10111001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10111010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10111011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_10111100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_10111101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_10111110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_10111111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_11000000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm6, %xmm0\n" +    ); +} + +static void gf8mul_11000001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +    ); +} + +static void gf8mul_11000010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11000011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11000100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_11000101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_11000110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11000111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11001000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_11001001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_11001010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11001011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11001100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_11001101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_11001110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11001111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11010000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm4, %xmm0\n" +    ); +} + +static void gf8mul_11010001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +    ); +} + +static void gf8mul_11010010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11010011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11010100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_11010101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_11010110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_11010111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11011000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_11011001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_11011010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11011011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11011100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_11011101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_11011110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11011111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11100000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm5, %xmm0\n" +    ); +} + +static void gf8mul_11100001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11100010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11100011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11100100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_11100101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_11100110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11100111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11101000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_11101001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_11101010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11101011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11101100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_11101101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_11101110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11101111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11110000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm4, %xmm0\n" +    ); +} + +static void gf8mul_11110001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +    ); +} + +static void gf8mul_11110010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11110011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_11110100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_11110101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_11110110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11110111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11111000(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm3, %xmm0\n" +    ); +} + +static void gf8mul_11111001(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +    ); +} + +static void gf8mul_11111010(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11111011(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm5, %xmm2\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +static void gf8mul_11111100(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm3, %xmm7\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm3, %xmm0\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm6\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm2, %xmm0\n" +    ); +} + +static void gf8mul_11111101(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm2\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm4\n" +        "\tpxor    %xmm5, %xmm0\n" +        "\tpxor    %xmm6, %xmm5\n" +        "\tpxor    %xmm4, %xmm7\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm3\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm5\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +    ); +} + +static void gf8mul_11111110(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm6\n" +        "\tpxor    %xmm7, %xmm5\n" +        "\tpxor    %xmm7, %xmm4\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm5, %xmm1\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm1\n" +        "\tpxor    %xmm4, %xmm0\n" +        "\tpxor    %xmm6, %xmm4\n" +        "\tpxor    %xmm3, %xmm6\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm2\n" +        "\tpxor    %xmm2, %xmm7\n" +        "\tpxor    %xmm2, %xmm6\n" +        "\tpxor    %xmm2, %xmm1\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm1, %xmm4\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm1, %xmm0\n" +        "\tpxor    %xmm0, %xmm7\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm5\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm3\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +        "\tpxor    %xmm1, %xmm0\n" +    ); +} + +static void gf8mul_11111111(void) +{ +    __asm__ __volatile__ +    ( +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm6, %xmm3\n" +        "\tpxor    %xmm6, %xmm2\n" +        "\tpxor    %xmm6, %xmm1\n" +        "\tpxor    %xmm6, %xmm0\n" +        "\tpxor    %xmm5, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm5, %xmm3\n" +        "\tpxor    %xmm4, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm4, %xmm2\n" +        "\tpxor    %xmm3, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm3, %xmm1\n" +        "\tpxor    %xmm2, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm2, %xmm0\n" +        "\tpxor    %xmm1, %xmm7\n" +        "\tpxor    %xmm1, %xmm5\n" +        "\tpxor    %xmm1, %xmm3\n" +        "\tpxor    %xmm0, %xmm6\n" +        "\tpxor    %xmm0, %xmm4\n" +        "\tpxor    %xmm0, %xmm2\n" +        "\tpxor    %xmm7, %xmm3\n" +        "\tpxor    %xmm7, %xmm1\n" +        "\tpxor    %xmm7, %xmm0\n" +        "\tpxor    %xmm6, %xmm7\n" +        "\tpxor    %xmm5, %xmm6\n" +        "\tpxor    %xmm4, %xmm5\n" +        "\tpxor    %xmm3, %xmm4\n" +        "\tpxor    %xmm2, %xmm3\n" +        "\tpxor    %xmm1, %xmm2\n" +        "\tpxor    %xmm0, %xmm1\n" +    ); +} + +void (* ec_gf_mul_table[256])(void) = +{ +    gf8mul_00000000, +    gf8mul_00000001, +    gf8mul_00000010, +    gf8mul_00000011, +    gf8mul_00000100, +    gf8mul_00000101, +    gf8mul_00000110, +    gf8mul_00000111, +    gf8mul_00001000, +    gf8mul_00001001, +    gf8mul_00001010, +    gf8mul_00001011, +    gf8mul_00001100, +    gf8mul_00001101, +    gf8mul_00001110, +    gf8mul_00001111, +    gf8mul_00010000, +    gf8mul_00010001, +    gf8mul_00010010, +    gf8mul_00010011, +    gf8mul_00010100, +    gf8mul_00010101, +    gf8mul_00010110, +    gf8mul_00010111, +    gf8mul_00011000, +    gf8mul_00011001, +    gf8mul_00011010, +    gf8mul_00011011, +    gf8mul_00011100, +    gf8mul_00011101, +    gf8mul_00011110, +    gf8mul_00011111, +    gf8mul_00100000, +    gf8mul_00100001, +    gf8mul_00100010, +    gf8mul_00100011, +    gf8mul_00100100, +    gf8mul_00100101, +    gf8mul_00100110, +    gf8mul_00100111, +    gf8mul_00101000, +    gf8mul_00101001, +    gf8mul_00101010, +    gf8mul_00101011, +    gf8mul_00101100, +    gf8mul_00101101, +    gf8mul_00101110, +    gf8mul_00101111, +    gf8mul_00110000, +    gf8mul_00110001, +    gf8mul_00110010, +    gf8mul_00110011, +    gf8mul_00110100, +    gf8mul_00110101, +    gf8mul_00110110, +    gf8mul_00110111, +    gf8mul_00111000, +    gf8mul_00111001, +    gf8mul_00111010, +    gf8mul_00111011, +    gf8mul_00111100, +    gf8mul_00111101, +    gf8mul_00111110, +    gf8mul_00111111, +    gf8mul_01000000, +    gf8mul_01000001, +    gf8mul_01000010, +    gf8mul_01000011, +    gf8mul_01000100, +    gf8mul_01000101, +    gf8mul_01000110, +    gf8mul_01000111, +    gf8mul_01001000, +    gf8mul_01001001, +    gf8mul_01001010, +    gf8mul_01001011, +    gf8mul_01001100, +    gf8mul_01001101, +    gf8mul_01001110, +    gf8mul_01001111, +    gf8mul_01010000, +    gf8mul_01010001, +    gf8mul_01010010, +    gf8mul_01010011, +    gf8mul_01010100, +    gf8mul_01010101, +    gf8mul_01010110, +    gf8mul_01010111, +    gf8mul_01011000, +    gf8mul_01011001, +    gf8mul_01011010, +    gf8mul_01011011, +    gf8mul_01011100, +    gf8mul_01011101, +    gf8mul_01011110, +    gf8mul_01011111, +    gf8mul_01100000, +    gf8mul_01100001, +    gf8mul_01100010, +    gf8mul_01100011, +    gf8mul_01100100, +    gf8mul_01100101, +    gf8mul_01100110, +    gf8mul_01100111, +    gf8mul_01101000, +    gf8mul_01101001, +    gf8mul_01101010, +    gf8mul_01101011, +    gf8mul_01101100, +    gf8mul_01101101, +    gf8mul_01101110, +    gf8mul_01101111, +    gf8mul_01110000, +    gf8mul_01110001, +    gf8mul_01110010, +    gf8mul_01110011, +    gf8mul_01110100, +    gf8mul_01110101, +    gf8mul_01110110, +    gf8mul_01110111, +    gf8mul_01111000, +    gf8mul_01111001, +    gf8mul_01111010, +    gf8mul_01111011, +    gf8mul_01111100, +    gf8mul_01111101, +    gf8mul_01111110, +    gf8mul_01111111, +    gf8mul_10000000, +    gf8mul_10000001, +    gf8mul_10000010, +    gf8mul_10000011, +    gf8mul_10000100, +    gf8mul_10000101, +    gf8mul_10000110, +    gf8mul_10000111, +    gf8mul_10001000, +    gf8mul_10001001, +    gf8mul_10001010, +    gf8mul_10001011, +    gf8mul_10001100, +    gf8mul_10001101, +    gf8mul_10001110, +    gf8mul_10001111, +    gf8mul_10010000, +    gf8mul_10010001, +    gf8mul_10010010, +    gf8mul_10010011, +    gf8mul_10010100, +    gf8mul_10010101, +    gf8mul_10010110, +    gf8mul_10010111, +    gf8mul_10011000, +    gf8mul_10011001, +    gf8mul_10011010, +    gf8mul_10011011, +    gf8mul_10011100, +    gf8mul_10011101, +    gf8mul_10011110, +    gf8mul_10011111, +    gf8mul_10100000, +    gf8mul_10100001, +    gf8mul_10100010, +    gf8mul_10100011, +    gf8mul_10100100, +    gf8mul_10100101, +    gf8mul_10100110, +    gf8mul_10100111, +    gf8mul_10101000, +    gf8mul_10101001, +    gf8mul_10101010, +    gf8mul_10101011, +    gf8mul_10101100, +    gf8mul_10101101, +    gf8mul_10101110, +    gf8mul_10101111, +    gf8mul_10110000, +    gf8mul_10110001, +    gf8mul_10110010, +    gf8mul_10110011, +    gf8mul_10110100, +    gf8mul_10110101, +    gf8mul_10110110, +    gf8mul_10110111, +    gf8mul_10111000, +    gf8mul_10111001, +    gf8mul_10111010, +    gf8mul_10111011, +    gf8mul_10111100, +    gf8mul_10111101, +    gf8mul_10111110, +    gf8mul_10111111, +    gf8mul_11000000, +    gf8mul_11000001, +    gf8mul_11000010, +    gf8mul_11000011, +    gf8mul_11000100, +    gf8mul_11000101, +    gf8mul_11000110, +    gf8mul_11000111, +    gf8mul_11001000, +    gf8mul_11001001, +    gf8mul_11001010, +    gf8mul_11001011, +    gf8mul_11001100, +    gf8mul_11001101, +    gf8mul_11001110, +    gf8mul_11001111, +    gf8mul_11010000, +    gf8mul_11010001, +    gf8mul_11010010, +    gf8mul_11010011, +    gf8mul_11010100, +    gf8mul_11010101, +    gf8mul_11010110, +    gf8mul_11010111, +    gf8mul_11011000, +    gf8mul_11011001, +    gf8mul_11011010, +    gf8mul_11011011, +    gf8mul_11011100, +    gf8mul_11011101, +    gf8mul_11011110, +    gf8mul_11011111, +    gf8mul_11100000, +    gf8mul_11100001, +    gf8mul_11100010, +    gf8mul_11100011, +    gf8mul_11100100, +    gf8mul_11100101, +    gf8mul_11100110, +    gf8mul_11100111, +    gf8mul_11101000, +    gf8mul_11101001, +    gf8mul_11101010, +    gf8mul_11101011, +    gf8mul_11101100, +    gf8mul_11101101, +    gf8mul_11101110, +    gf8mul_11101111, +    gf8mul_11110000, +    gf8mul_11110001, +    gf8mul_11110010, +    gf8mul_11110011, +    gf8mul_11110100, +    gf8mul_11110101, +    gf8mul_11110110, +    gf8mul_11110111, +    gf8mul_11111000, +    gf8mul_11111001, +    gf8mul_11111010, +    gf8mul_11111011, +    gf8mul_11111100, +    gf8mul_11111101, +    gf8mul_11111110, +    gf8mul_11111111 +}; diff --git a/xlators/cluster/ec/src/ec-gf.h b/xlators/cluster/ec/src/ec-gf.h new file mode 100644 index 00000000000..664feb46ce5 --- /dev/null +++ b/xlators/cluster/ec/src/ec-gf.h @@ -0,0 +1,114 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +/* + * File automatically generated on Thu Jan 26 12:08:19 2012 + * + * DO NOT MODIFY + * + * Multiplications in a GF(2^8) with modulus 0x11D using XOR's + * + */ + +#ifndef __EC_GF_H__ +#define __EC_GF_H__ + +#define EC_GF_BITS 8 +#define EC_GF_MOD 0x11D + +#define ec_gf_load(addr) \ +    do \ +    { \ +        __asm__ __volatile__ \ +        ( \ +            "\tmovdqa  0*16(%0), %%xmm0\n" \ +            "\tmovdqa  1*16(%0), %%xmm1\n" \ +            "\tmovdqa  2*16(%0), %%xmm2\n" \ +            "\tmovdqa  3*16(%0), %%xmm3\n" \ +            "\tmovdqa  4*16(%0), %%xmm4\n" \ +            "\tmovdqa  5*16(%0), %%xmm5\n" \ +            "\tmovdqa  6*16(%0), %%xmm6\n" \ +            "\tmovdqa  7*16(%0), %%xmm7\n" \ +            : \ +            : "r" (addr) \ +            : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" \ +        ); \ +    } while (0) + +#define ec_gf_store(addr) \ +    do \ +    { \ +        __asm__ __volatile__ \ +        ( \ +            "\tmovdqa  %%xmm0, 0*16(%0)\n" \ +            "\tmovdqa  %%xmm1, 1*16(%0)\n" \ +            "\tmovdqa  %%xmm2, 2*16(%0)\n" \ +            "\tmovdqa  %%xmm3, 3*16(%0)\n" \ +            "\tmovdqa  %%xmm4, 4*16(%0)\n" \ +            "\tmovdqa  %%xmm5, 5*16(%0)\n" \ +            "\tmovdqa  %%xmm6, 6*16(%0)\n" \ +            "\tmovdqa  %%xmm7, 7*16(%0)\n" \ +            : \ +            : "r" (addr) \ +            : "memory" \ +        ); \ +    } while (0) + +#define ec_gf_clear() \ +    do \ +    { \ +        __asm__ __volatile__ \ +        ( \ +            "\tpxor    %xmm0, %xmm0\n" \ +            "\tpxor    %xmm1, %xmm1\n" \ +            "\tpxor    %xmm2, %xmm2\n" \ +            "\tpxor    %xmm3, %xmm3\n" \ +            "\tpxor    %xmm4, %xmm4\n" \ +            "\tpxor    %xmm5, %xmm5\n" \ +            "\tpxor    %xmm6, %xmm6\n" \ +            "\tpxor    %xmm7, %xmm7\n" \ +            : \ +            : \ +            : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" \ +        ); \ +    } while (0) + +#define ec_gf_xor(addr) \ +    do \ +    { \ +        __asm__ __volatile__ \ +        ( \ +            "\tpxor    0*16(%0), %%xmm0\n" \ +            "\tpxor    1*16(%0), %%xmm1\n" \ +            "\tpxor    2*16(%0), %%xmm2\n" \ +            "\tpxor    3*16(%0), %%xmm3\n" \ +            "\tpxor    4*16(%0), %%xmm4\n" \ +            "\tpxor    5*16(%0), %%xmm5\n" \ +            "\tpxor    6*16(%0), %%xmm6\n" \ +            "\tpxor    7*16(%0), %%xmm7\n" \ +            : \ +            : "r" (addr) \ +            : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" \ +        ); \ +    } while (0) + +extern void (* ec_gf_mul_table[])(void); + +#endif /* __EC_GF_H__ */ diff --git a/xlators/cluster/ec/src/ec-heal.c b/xlators/cluster/ec/src/ec-heal.c new file mode 100644 index 00000000000..37264f598b9 --- /dev/null +++ b/xlators/cluster/ec/src/ec-heal.c @@ -0,0 +1,1470 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "xlator.h" +#include "defaults.h" + +#include "ec-helpers.h" +#include "ec-common.h" +#include "ec-combine.h" +#include "ec-method.h" +#include "ec-fops.h" + +#include "ec-mem-types.h" +#include "ec-data.h" + +/* FOP: heal */ + +void ec_heal_exclude(ec_heal_t * heal, uintptr_t mask) +{ +    LOCK(&heal->lock); + +    heal->bad &= ~mask; + +    UNLOCK(&heal->lock); +} + +void ec_heal_lookup_resume(ec_fop_data_t * fop) +{ +    ec_heal_t * heal = fop->data; +    ec_cbk_data_t * cbk; +    uintptr_t good = 0, bad = 0; + +    if (heal->lookup != NULL) +    { +        ec_fop_data_release(heal->lookup); +    } +    ec_fop_data_acquire(fop); + +    list_for_each_entry(cbk, &fop->cbk_list, list) +    { +        if ((cbk->op_ret < 0) && (cbk->op_errno == ENOTCONN)) +        { +            continue; +        } + +        if (cbk == fop->answer) +        { +            if (cbk->op_ret >= 0) +            { +                heal->iatt = cbk->iatt[0]; +                heal->version = cbk->version; +                heal->raw_size = cbk->size; +                heal->fop->pre_size = cbk->iatt[0].ia_size; +                heal->fop->post_size = cbk->iatt[0].ia_size; + +                if (!ec_loc_prepare(heal->xl, &heal->loc, cbk->inode, +                                    &cbk->iatt[0])) +                { +                    fop->answer = NULL; +                    fop->error = EIO; + +                    bad |= cbk->mask; + +                    continue; +                } +            } + +            good |= cbk->mask; +        } +        else +        { +            bad |= cbk->mask; +        } +    } + +    heal->good = good; +    heal->bad = bad; + +    heal->lookup = fop; + +    ec_resume_parent(fop, fop->answer != NULL ? 0 : fop->error); +} + +int32_t ec_heal_entry_lookup_cbk(call_frame_t * frame, void * cookie, +                                 xlator_t * this, int32_t op_ret, +                                 int32_t op_errno, inode_t * inode, +                                 struct iatt * buf, dict_t * xdata, +                                 struct iatt * postparent) +{ +    ec_heal_lookup_resume(cookie); + +    return 0; +} + +int32_t ec_heal_inode_lookup_cbk(call_frame_t * frame, void * cookie, +                                 xlator_t * this, int32_t op_ret, +                                 int32_t op_errno, inode_t * inode, +                                 struct iatt * buf, dict_t * xdata, +                                 struct iatt * postparent) +{ +    ec_heal_lookup_resume(cookie); + +    return 0; +} + +uintptr_t ec_heal_check(ec_fop_data_t * fop, uintptr_t * pgood) +{ +    ec_cbk_data_t * cbk; +    uintptr_t mask[2] = { 0, 0 }; + +    list_for_each_entry(cbk, &fop->cbk_list, list) +    { +        mask[cbk->op_ret >= 0] |= cbk->mask; +    } + +    if (pgood != NULL) +    { +        *pgood = mask[1]; +    } + +    return mask[0]; +} + +void ec_heal_update(ec_fop_data_t * fop, int32_t is_open) +{ +    ec_heal_t * heal = fop->data; +    uintptr_t good, bad; + +    bad = ec_heal_check(fop, &good); + +    LOCK(&heal->lock); + +    heal->bad &= ~bad; +    if (is_open) +    { +        heal->open |= good; +    } + +    UNLOCK(&heal->lock); + +    fop->error = 0; +} + +void ec_heal_avoid(ec_fop_data_t * fop) +{ +    ec_heal_t * heal = fop->data; +    uintptr_t bad; + +    bad = ec_heal_check(fop, NULL); + +    LOCK(&heal->lock); + +    heal->good &= ~bad; + +    UNLOCK(&heal->lock); +} + +int32_t ec_heal_mkdir_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                          int32_t op_ret, int32_t op_errno, inode_t * inode, +                          struct iatt * buf, struct iatt * preparent, +                          struct iatt * postparent, dict_t * xdata) +{ +    ec_heal_update(cookie, 0); + +    return 0; +} + +int32_t ec_heal_mknod_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                          int32_t op_ret, int32_t op_errno, inode_t * inode, +                          struct iatt * buf, struct iatt * preparent, +                          struct iatt * postparent, dict_t * xdata) +{ +    ec_heal_update(cookie, 0); + +    return 0; +} + +int32_t ec_heal_symlink_cbk(call_frame_t * frame, void * cookie, +                            xlator_t * this, int32_t op_ret, int32_t op_errno, +                            inode_t * inode, struct iatt * buf, +                            struct iatt * preparent, struct iatt * postparent, +                            dict_t * xdata) +{ +    ec_heal_update(cookie, 0); + +    return 0; +} + +int32_t ec_heal_create_cbk(call_frame_t * frame, void * cookie, +                           xlator_t * this, int32_t op_ret, int32_t op_errno, +                           fd_t * fd, inode_t * inode, struct iatt * buf, +                           struct iatt * preparent, struct iatt * postparent, +                           dict_t * xdata) +{ +    ec_heal_update(cookie, 1); + +    return 0; +} + +int32_t ec_heal_setattr_cbk(call_frame_t * frame, void * cookie, +                            xlator_t * this, int32_t op_ret, int32_t op_errno, +                            struct iatt * preop_stbuf, +                            struct iatt * postop_stbuf, +                            dict_t * xdata) +{ +    ec_heal_update(cookie, 0); + +    return 0; +} + +int32_t ec_heal_setxattr_cbk(call_frame_t * frame, void * cookie, +                             xlator_t * this, int32_t op_ret, int32_t op_errno, +                             dict_t * xdata) +{ +    ec_heal_update(cookie, 0); + +    return 0; +} + +int32_t ec_heal_removexattr_cbk(call_frame_t * frame, void * cookie, +                                xlator_t * this, int32_t op_ret, +                                int32_t op_errno, dict_t * xdata) +{ +    ec_heal_update(cookie, 0); + +    return 0; +} + +int32_t ec_heal_link_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                         int32_t op_ret, int32_t op_errno, inode_t * inode, +                         struct iatt * buf, struct iatt * preparent, +                         struct iatt * postparent, dict_t * xdata) +{ +    ec_fop_data_t * fop = cookie; +    ec_heal_t * heal = fop->data; +    uintptr_t good, bad; + +    bad = ec_heal_check(fop, &good); +    ec_heal_exclude(heal, good); + +    if (bad != 0) +    { +        fop->error = 0; + +        xdata = fop->xdata; +        fop = fop->parent; + +        ec_create(fop->frame, fop->xl, bad, EC_MINIMUM_ONE, +                  ec_heal_create_cbk, heal, &heal->loc, 0, +                  st_mode_from_ia(heal->iatt.ia_prot, IA_INVAL), +                  0, heal->fd, xdata); +    } + +    return 0; +} + +int32_t ec_heal_target_open_cbk(call_frame_t * frame, void * cookie, +                                xlator_t * this, int32_t op_ret, +                                int32_t op_errno, fd_t * fd, dict_t * xdata) +{ +    ec_heal_update(cookie, 1); + +    return 0; +} + +int32_t ec_heal_source_open_cbk(call_frame_t * frame, void * cookie, +                                xlator_t * this, int32_t op_ret, +                                int32_t op_errno, fd_t * fd, dict_t * xdata) +{ +    ec_heal_avoid(cookie); + +    return 0; +} + +int32_t ec_heal_reopen_cbk(call_frame_t * frame, void * cookie, +                           xlator_t * this, int32_t op_ret, int32_t op_errno, +                           fd_t * fd, dict_t * xdata) +{ +    ec_fop_data_t * fop = cookie; +    ec_fd_t * ctx; +    uintptr_t good; + +    ec_heal_check(fop, &good); + +    if (good != 0) +    { +        LOCK(&fd->lock); + +        ctx = __ec_fd_get(fd, fop->xl); +        if ((ctx != NULL) && (ctx->loc.inode != NULL)) +        { +            ctx->bad &= ~good; +            ctx->open |= good; +        } + +        UNLOCK(&fd->lock); +    } + +    return 0; +} + +int32_t ec_heal_create(ec_heal_t * heal, uintptr_t mask, int32_t try_link) +{ +    loc_t loc; +    dict_t * xdata; + +    xdata = dict_new(); +    if (xdata == NULL) +    { +        return ENOMEM; +    } + +    if (dict_set_static_bin(xdata, "gfid-req", heal->iatt.ia_gfid, +                            sizeof(uuid_t)) != 0) +    { +        dict_unref(xdata); + +        return ENOMEM; +    } + +    if ((heal->iatt.ia_type == IA_IFREG) && try_link) +    { +        memset(&loc, 0, sizeof(loc)); +        loc.inode = heal->loc.inode; +        uuid_copy(loc.gfid, heal->iatt.ia_gfid); + +        ec_link(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE, +                ec_heal_link_cbk, heal, &loc, &heal->loc, xdata); + +        dict_unref(xdata); + +        return 0; +    } + +    switch (heal->iatt.ia_type) +    { +        case IA_IFDIR: +            ec_mkdir(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE, +                     ec_heal_mkdir_cbk, heal, &heal->loc, +                     st_mode_from_ia(heal->iatt.ia_prot, IA_INVAL), +                     0, xdata); + +            break; + +        case IA_IFLNK: +            ec_symlink(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE, +                       ec_heal_symlink_cbk, heal, heal->symlink, &heal->loc, +                       0, xdata); + +            break; + +        case IA_IFREG: +            ec_create(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE, +                      ec_heal_create_cbk, heal, &heal->loc, 0, +                      st_mode_from_ia(heal->iatt.ia_prot, IA_INVAL), +                      0, heal->fd, xdata); + +            break; + +        default: +            ec_mknod(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE, +                     ec_heal_mknod_cbk, heal, &heal->loc, +                     st_mode_from_ia(heal->iatt.ia_prot, IA_INVAL), +                     heal->iatt.ia_rdev, 0, xdata); + +            break; +    } + +    dict_unref(xdata); + +    return 0; +} + +void ec_heal_recreate(ec_fop_data_t * fop) +{ +    ec_cbk_data_t * cbk; +    ec_heal_t * heal = fop->data; +    uintptr_t mask = 0; + +    if (heal->iatt.ia_type == IA_INVAL) +    { +        return; +    } + +    list_for_each_entry(cbk, &fop->cbk_list, list) +    { +        if ((cbk->op_ret >= 0) || (cbk->op_errno == ENOENT) || +            (cbk->op_errno == ENOTDIR)) +        { +            mask |= cbk->mask; +        } +    } + +    if (mask != 0) +    { +        ec_heal_create(heal, mask, 0); +    } +} + +int32_t ec_heal_rmdir_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                          int32_t op_ret, int32_t op_errno, +                          struct iatt * preparent, struct iatt * postparent, +                          dict_t * xdata) +{ +    ec_heal_update(cookie, 0); +    ec_heal_recreate(cookie); + +    return 0; +} + +int32_t ec_heal_unlink_cbk(call_frame_t * frame, void * cookie, +                           xlator_t * this, int32_t op_ret, int32_t op_errno, +                           struct iatt * preparent, struct iatt * postparent, +                           dict_t * xdata) +{ +    ec_heal_update(cookie, 0); +    ec_heal_recreate(cookie); + +    return 0; +} + +int32_t ec_heal_init(ec_fop_data_t * fop) +{ +    ec_t * ec = fop->xl->private; +    struct iobuf_pool * pool; +    inode_t * inode; +    ec_inode_t * ctx; +    ec_heal_t * heal = NULL; +    int32_t error = 0; + +    inode = fop->loc[0].inode; +    if (inode == NULL) +    { +        gf_log(fop->xl->name, GF_LOG_WARNING, "Unable to start inode healing " +                                              "because there is not enough " +                                              "information"); + +        return ENODATA; +    } + +    LOCK(&inode->lock); + +    ctx = __ec_inode_get(inode, fop->xl); +    if (ctx == NULL) +    { +        error = EIO; + +        goto out; +    } + +    if (ctx->heal != NULL) +    { +        error = EEXIST; + +        goto out; +    } + +    heal = GF_MALLOC(sizeof(ec_heal_t), ec_mt_ec_heal_t); +    if (heal == NULL) +    { +        error = ENOMEM; + +        goto out; +    } + +    memset(heal, 0, sizeof(ec_heal_t)); + +    if (loc_copy(&heal->loc, &fop->loc[0]) != 0) +    { +        error = ENOMEM; + +        goto out; +    } +    if (uuid_is_null(heal->loc.gfid)) +    { +        uuid_copy(heal->loc.gfid, heal->loc.inode->gfid); +    } + +    LOCK_INIT(&heal->lock); + +    heal->xl = fop->xl; +    heal->fop = fop; +    pool = fop->xl->ctx->iobuf_pool; +    heal->size = iobpool_default_pagesize(pool) * ec->fragments; + +    fop->data = heal; + +    ctx->heal = heal; +    heal = NULL; + +out: +    UNLOCK(&inode->lock); + +    GF_FREE(heal); + +    return error; +} + +void ec_heal_entrylk(ec_heal_t * heal, entrylk_cmd cmd) +{ +    loc_t loc; +    char * name; +    int32_t error; + +    error = ec_loc_parent(heal->xl, &heal->loc, &loc, &name); +    if (error != 0) +    { +        ec_fop_set_error(heal->fop, error); + +        return; +    } + +    ec_entrylk(heal->fop->frame, heal->xl, -1, EC_MINIMUM_ALL, NULL, NULL, +               heal->xl->name, &loc, name, cmd, ENTRYLK_WRLCK, NULL); + +    loc_wipe(&loc); +    GF_FREE(name); +} + +void ec_heal_inodelk(ec_heal_t * heal, int32_t type, int32_t use_fd, +                     off_t offset, size_t size) +{ +    struct gf_flock flock; + +    flock.l_type = type; +    flock.l_whence = SEEK_SET; +    flock.l_start = offset; +    flock.l_len = size; +    flock.l_pid = 0; +    flock.l_owner.len = 0; + +    if (use_fd) +    { +        ec_finodelk(heal->fop->frame, heal->xl, heal->fop->mask, +                    EC_MINIMUM_ALL, NULL, NULL, heal->xl->name, heal->fd, +                    F_SETLKW, &flock, NULL); +    } +    else +    { +        ec_inodelk(heal->fop->frame, heal->xl, heal->fop->mask, EC_MINIMUM_ALL, +                   NULL, NULL, heal->xl->name, &heal->loc, F_SETLKW, &flock, +                   NULL); +    } +} + +void ec_heal_lookup(ec_heal_t * heal) +{ +    dict_t * xdata; +    int32_t error = ENOMEM; + +    xdata = dict_new(); +    if (xdata == NULL) +    { +        goto out; +    } +    if (dict_set_uint64(xdata, "list-xattr", 0) != 0) +    { +        goto out; +    } + +    ec_lookup(heal->fop->frame, heal->xl, heal->fop->mask, EC_MINIMUM_MIN, +              ec_heal_inode_lookup_cbk, heal, &heal->loc, xdata); + +    error = 0; + +out: +    if (xdata != NULL) +    { +        dict_unref(xdata); +    } + +    ec_fop_set_error(heal->fop, error); +} + +void ec_heal_remove(ec_heal_t * heal, ec_cbk_data_t * cbk) +{ +    if (cbk->iatt[0].ia_type == IA_IFDIR) +    { +        // TODO: Remove directory recursively ? +        ec_rmdir(heal->fop->frame, heal->xl, cbk->mask, EC_MINIMUM_ONE, +                 ec_heal_rmdir_cbk, heal, &heal->loc, 0, NULL); +    } +    else +    { +        ec_unlink(heal->fop->frame, heal->xl, cbk->mask, EC_MINIMUM_ONE, +                  ec_heal_unlink_cbk, heal, &heal->loc, 0, NULL); +    } +} + +void ec_heal_remove_others(ec_heal_t * heal) +{ +    struct list_head * item; +    ec_cbk_data_t * cbk; + +    item = heal->lookup->cbk_list.next; +    do +    { +        item = item->next; +        cbk = list_entry(item, ec_cbk_data_t, list); + +        if (cbk->op_ret < 0) +        { +            if ((cbk->op_errno != ENOENT) && (cbk->op_errno != ENOTDIR)) +            { +                gf_log(heal->xl->name, GF_LOG_WARNING, "Don't know how to " +                                                       "remove inode with " +                                                       "error %d", +                       cbk->op_errno); +            } + +            ec_heal_exclude(heal, cbk->mask); + +            continue; +        } + +        ec_heal_remove(heal, cbk); +    } while (item->next != &heal->lookup->cbk_list); +} + +void ec_heal_prepare_others(ec_heal_t * heal) +{ +    struct list_head * item; +    ec_cbk_data_t * cbk; + +    item = heal->lookup->cbk_list.next; +    while (item->next != &heal->lookup->cbk_list) +    { +        item = item->next; +        cbk = list_entry(item, ec_cbk_data_t, list); + +        if (cbk->op_ret < 0) +        { +            if (cbk->op_errno == ENOENT) +            { +                ec_heal_create(heal, cbk->mask, 1); +            } +            else +            { +                gf_log(heal->xl->name, GF_LOG_ERROR, "Don't know how to " +                                                     "heal error %d", +                       cbk->op_errno); + +                ec_heal_exclude(heal, cbk->mask); +            } +        } +        else +        { +            if ((heal->iatt.ia_type != cbk->iatt[0].ia_type) || +                (uuid_compare(heal->iatt.ia_gfid, cbk->iatt[0].ia_gfid) != 0)) +            { +                ec_heal_remove(heal, cbk); +            } +        } +    } +} + +int32_t ec_heal_readlink_cbk(call_frame_t * frame, void * cookie, +                             xlator_t * this, int32_t op_ret, int32_t op_errno, +                             const char * path, struct iatt * buf, +                             dict_t * xdata) +{ +    ec_fop_data_t * fop = cookie; +    ec_heal_t * heal = fop->data; + +    if (op_ret >= 0) +    { +        heal->symlink = gf_strdup(path); +        if (heal->symlink != NULL) +        { +            ec_heal_prepare_others(heal); +        } +        else +        { +            ec_fop_set_error(fop, EIO); +        } +    } + +    return 0; +} + +ec_cbk_data_t * ec_heal_lookup_check(ec_heal_t * heal, uintptr_t * pgood, +                                     uintptr_t * pbad) +{ +    ec_fop_data_t * fop = heal->lookup; +    ec_cbk_data_t * cbk = NULL, * ans = NULL; +    uintptr_t good = 0, bad = 0; + +    list_for_each_entry(ans, &fop->cbk_list, list) +    { +        if ((ans->op_ret < 0) && (ans->op_errno == ENOTCONN)) +        { +            continue; +        } + +        if (ans == fop->answer) +        { +            good |= ans->mask; +            cbk = ans; +        } +        else +        { +            bad |= ans->mask; +        } +    } + +    *pgood = good; +    *pbad = bad; + +    return cbk; +} + +void ec_heal_prepare(ec_heal_t * heal) +{ +    ec_cbk_data_t * cbk; +    ec_fd_t * ctx; +    int32_t error = ENOMEM; + +    heal->available = heal->good; + +    cbk = heal->lookup->answer; +    if (cbk->op_ret < 0) +    { +        if ((cbk->op_errno == ENOENT) || (cbk->op_errno == ENOTDIR)) +        { +            ec_heal_remove_others(heal); +        } +        else +        { +            gf_log(heal->xl->name, GF_LOG_ERROR, "Don't know how to heal " +                                                 "error %d", +                   cbk->op_errno); +        } +    } +    else +    { +        if (heal->iatt.ia_type == IA_IFREG) +        { +            heal->fd = fd_create(heal->loc.inode, heal->fop->frame->root->pid); +            if (heal->fd == NULL) +            { +                gf_log(heal->xl->name, GF_LOG_ERROR, "Unable to create a new " +                                                     "file descriptor"); + +                goto out; +            } +            ctx = ec_fd_get(heal->fd, heal->xl); +            if ((ctx == NULL) || (loc_copy(&ctx->loc, &heal->loc) != 0)) +            { +                goto out; +            } + +            ctx->flags = O_RDWR; +        } + +        if (heal->iatt.ia_type == IA_IFLNK) +        { +            ec_readlink(heal->fop->frame, heal->xl, cbk->mask, EC_MINIMUM_ONE, +                        ec_heal_readlink_cbk, heal, &heal->loc, +                        heal->iatt.ia_size, NULL); +        } +        else +        { +            ec_heal_prepare_others(heal); +        } +    } + +    error = 0; + +out: +    ec_fop_set_error(heal->fop, error); +} + +int32_t ec_heal_open_others(ec_heal_t * heal) +{ +    struct list_head * item; +    ec_cbk_data_t * cbk; +    uintptr_t mask = 0, open = heal->open; + +    item = heal->lookup->cbk_list.next; +    while (item->next != &heal->lookup->cbk_list) +    { +        item = item->next; +        cbk = list_entry(item, ec_cbk_data_t, list); + +        if ((cbk->op_ret < 0) || (cbk->iatt[0].ia_type != IA_IFREG) || +            (uuid_compare(heal->iatt.ia_gfid, cbk->iatt[0].ia_gfid) != 0)) +        { +            ec_heal_exclude(heal, cbk->mask); +        } +        else +        { +            mask |= cbk->mask & ~heal->open; +        } +    } + +    if (mask != 0) +    { +        ec_open(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE, +                ec_heal_target_open_cbk, heal, &heal->loc, O_RDWR | O_TRUNC, +                heal->fd, NULL); + +        open |= mask; +    } + +    return (open != 0); +} + +void ec_heal_setxattr_others(ec_heal_t * heal) +{ +    ec_cbk_data_t * cbk; +    dict_t * xdata; +    int32_t error = ENOMEM; + +    if ((heal->good != 0) && (heal->bad != 0)) +    { +        cbk = heal->lookup->answer; +        xdata = cbk->xdata; + +        if ((cbk->iatt[0].ia_type == IA_IFREG) || +            (cbk->iatt[0].ia_type == IA_IFDIR)) +        { +            if (ec_dict_set_number(xdata, EC_XATTR_VERSION, cbk->version) != 0) +            { +                goto out; +            } +            if (cbk->iatt[0].ia_type == IA_IFREG) +            { +                if (ec_dict_set_number(xdata, EC_XATTR_SIZE, +                                       cbk->iatt[0].ia_size) != 0) +                { +                    goto out; +                } +            } +        } + +        ec_setxattr(heal->fop->frame, heal->xl, heal->bad, EC_MINIMUM_ONE, +                    ec_heal_setxattr_cbk, heal, &heal->loc, xdata, 0, NULL); +    } + +    error = 0; + +out: +    ec_fop_set_error(heal->fop, error); +} + +int32_t ec_heal_xattr_clean(dict_t * dict, char * key, data_t * data, +                            void * arg) +{ +    dict_t * base = arg; + +    if (dict_get(base, key) == NULL) +    { +        if (dict_set_static_bin(dict, key, dict, 0) != 0) +        { +            return -1; +        } +    } +    else +    { +        dict_del(dict, key); +    } + +    return 0; +} + +void ec_heal_removexattr_others(ec_heal_t * heal) +{ +    struct list_head * item; +    ec_cbk_data_t * cbk; +    dict_t * xdata; + +    if ((heal->good == 0) || (heal->bad == 0)) +    { +        return; +    } + +    xdata = heal->lookup->answer->xdata; +    item = heal->lookup->cbk_list.next; +    while (item->next != &heal->lookup->cbk_list) +    { +        item = item->next; +        cbk = list_entry(item, ec_cbk_data_t, list); + +        if (cbk->op_ret >= 0) +        { +            if (dict_foreach(cbk->xdata, ec_heal_xattr_clean, xdata) == 0) +            { +                ec_removexattr(heal->fop->frame, heal->xl, cbk->mask, +                               EC_MINIMUM_ONE, ec_heal_removexattr_cbk, heal, +                               &heal->loc, "", cbk->xdata); +            } +        } +    } +} + +void ec_heal_attr(ec_heal_t * heal) +{ +    if ((heal->good != 0) && (heal->bad != 0)) +    { +        ec_setattr(heal->fop->frame, heal->xl, heal->bad, EC_MINIMUM_ONE, +                   ec_heal_setattr_cbk, heal, &heal->loc, &heal->iatt, +                   GF_SET_ATTR_MODE | GF_SET_ATTR_UID | GF_SET_ATTR_GID | +                   GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME, NULL); +    } +} + +int32_t ec_heal_needs_data_rebuild(ec_heal_t * heal) +{ +    ec_fop_data_t * fop = heal->lookup; +    ec_cbk_data_t * cbk = NULL; +    uintptr_t bad = 0; + +    if ((heal->fop->error != 0) || (heal->good == 0) || +        (heal->iatt.ia_type != IA_IFREG)) +    { +        return 0; +    } + +    list_for_each_entry(cbk, &fop->cbk_list, list) +    { +        if ((cbk->op_ret >= 0) && +            ((cbk->size != heal->raw_size) || (cbk->version != heal->version))) +        { +            bad |= cbk->mask; +        } +    } + +    heal->bad = bad; + +    return (bad != 0); +} + +void ec_heal_open(ec_heal_t * heal) +{ +    if (!ec_heal_needs_data_rebuild(heal)) +    { +        return; +    } + +    if (ec_heal_open_others(heal)) +    { +        ec_open(heal->fop->frame, heal->xl, heal->good, EC_MINIMUM_MIN, +                ec_heal_source_open_cbk, heal, &heal->loc, O_RDONLY, heal->fd, +                NULL); +    } +} + +void ec_heal_reopen_fd(ec_heal_t * heal) +{ +    inode_t * inode; +    fd_t * fd; +    ec_fd_t * ctx; +    uintptr_t mask; +    int32_t flags; + +    inode = heal->loc.inode; + +    LOCK(&inode->lock); + +    list_for_each_entry(fd, &inode->fd_list, inode_list) +    { +        ctx = ec_fd_get(fd, heal->xl); +        if ((ctx != NULL) && (ctx->loc.inode != NULL)) +        { +            mask = heal->bad & ~ctx->open; +            if (mask != 0) +            { +                UNLOCK(&inode->lock); + +                if (heal->iatt.ia_type == IA_IFDIR) +                { +                    ec_opendir(heal->fop->frame, heal->xl, mask, +                               EC_MINIMUM_ONE, ec_heal_reopen_cbk, NULL, +                               &heal->loc, fd, NULL); +                } +                else +                { +                    flags = ctx->flags & ~O_TRUNC; +                    if ((flags & O_ACCMODE) == O_WRONLY) +                    { +                        flags &= ~O_ACCMODE; +                        flags |= O_RDWR; +                    } + +                    ec_open(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE, +                            ec_heal_reopen_cbk, NULL, &heal->loc, flags, fd, +                            NULL); +                } + +                LOCK(&inode->lock); +            } +        } +    } + +    UNLOCK(&inode->lock); +} + +int32_t ec_heal_writev_cbk(call_frame_t * frame, void * cookie, +                           xlator_t * this, int32_t op_ret, int32_t op_errno, +                           struct iatt * prebuf, struct iatt * postbuf, +                           dict_t * xdata) +{ +    ec_trace("WRITE_CBK", cookie, "ret=%d, errno=%d", op_ret, op_errno); + +    ec_heal_update(cookie, 0); + +    return 0; +} + +int32_t ec_heal_readv_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                          int32_t op_ret, int32_t op_errno, +                          struct iovec * vector, int32_t count, +                          struct iatt * stbuf, struct iobref * iobref, +                          dict_t * xdata) +{ +    ec_fop_data_t * fop = cookie; +    ec_heal_t * heal = fop->data; + +    ec_trace("READ_CBK", fop, "ret=%d, errno=%d", op_ret, op_errno); + +    ec_heal_avoid(fop); + +    if (op_ret > 0) +    { +        ec_writev(heal->fop->frame, heal->xl, heal->bad, EC_MINIMUM_ONE, +                  ec_heal_writev_cbk, heal, heal->fd, vector, count, +                  heal->offset, 0, iobref, NULL); +    } +    else +    { +        heal->done = 1; +    } + +    return 0; +} + +void ec_heal_data(ec_heal_t * heal) +{ +    ec_trace("DATA", heal->fop, "good=%lX, bad=%lX", heal->good, heal->bad); + +    if ((heal->good != 0) && (heal->bad != 0) && +        (heal->iatt.ia_type == IA_IFREG)) +    { +        ec_readv(heal->fop->frame, heal->xl, heal->good, EC_MINIMUM_MIN, +                 ec_heal_readv_cbk, heal, heal->fd, heal->size, heal->offset, +                 0, NULL); +    } +} + +void ec_heal_dispatch(ec_heal_t * heal) +{ +    ec_fop_data_t * fop = heal->fop; +    ec_cbk_data_t * cbk; +    inode_t * inode; +    ec_inode_t * ctx; +    int32_t error; + +    inode = heal->loc.inode; + +    LOCK(&inode->lock); + +    ctx = __ec_inode_get(inode, heal->xl); +    if (ctx != NULL) +    { +        ctx->bad &= ~heal->good; +        ctx->heal = NULL; +    } + +    fop->data = NULL; + +    UNLOCK(&inode->lock); + +    error = fop->error; + +    cbk = ec_cbk_data_allocate(fop->frame, heal->xl, fop, fop->id, 0, +                               error == 0 ? 0 : -1, error); +    if (cbk != NULL) +    { +        cbk->uintptr[0] = heal->available; +        cbk->uintptr[1] = heal->good; +        cbk->uintptr[2] = heal->bad; + +        ec_combine(cbk, NULL); + +        fop->answer = cbk; +    } +    else if (error == 0) +    { +        error = ENOMEM; +    } + +    if (heal->lookup != NULL) +    { +        ec_fop_data_release(heal->lookup); +    } +    if (heal->fd != NULL) +    { +        fd_unref(heal->fd); +    } +    GF_FREE(heal->symlink); +    loc_wipe(&heal->loc); + +    LOCK_DESTROY(&heal->lock); + +    GF_FREE(heal); + +    ec_fop_set_error(heal->fop, error); +} + +void ec_wind_heal(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_cbk_data_t * cbk; +    ec_heal_t * heal = fop->data; + +    ec_trace("WIND", fop, "idx=%d", idx); + +    cbk = ec_cbk_data_allocate(fop->req_frame, fop->xl, fop, EC_FOP_HEAL, idx, +                               fop->error == 0 ? 0 : -1, fop->error); +    if (cbk != NULL) +    { +        cbk->uintptr[0] = heal->available; +        cbk->uintptr[1] = heal->good; +        cbk->uintptr[2] = heal->bad; + +        ec_combine(cbk, NULL); +    } + +    ec_complete(fop); +} + +int32_t ec_manager_heal(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; +    ec_heal_t * heal = fop->data; + +    switch (state) +    { +        case EC_STATE_INIT: +            ec_owner_set(fop->frame, fop->frame->root); + +            fop->error = ec_heal_init(fop); +            if (fop->error != 0) +            { +                return EC_STATE_REPORT; +            } + +        case EC_STATE_DISPATCH: +            ec_heal_entrylk(fop->data, ENTRYLK_LOCK); + +            return EC_STATE_HEAL_ENTRY_LOOKUP; + +        case EC_STATE_HEAL_ENTRY_LOOKUP: +            ec_lookup(fop->frame, heal->xl, fop->mask, EC_MINIMUM_MIN, +                      ec_heal_entry_lookup_cbk, heal, &heal->loc, NULL); + +            return EC_STATE_HEAL_ENTRY_PREPARE; + +        case EC_STATE_HEAL_ENTRY_PREPARE: +            ec_heal_prepare(heal); + +            return EC_STATE_HEAL_PRE_INODELK_LOCK; + +        case EC_STATE_HEAL_PRE_INODELK_LOCK: +            ec_heal_inodelk(heal, F_WRLCK, 0, 0, 0); + +            return EC_STATE_HEAL_PRE_INODE_LOOKUP; + +        case EC_STATE_HEAL_PRE_INODE_LOOKUP: +            ec_heal_lookup(heal); + +            return EC_STATE_HEAL_XATTRIBUTES_REMOVE; + +        case EC_STATE_HEAL_XATTRIBUTES_REMOVE: +            ec_heal_removexattr_others(heal); + +            return EC_STATE_HEAL_XATTRIBUTES_SET; + +        case EC_STATE_HEAL_XATTRIBUTES_SET: +            ec_heal_setxattr_others(heal); + +            return EC_STATE_HEAL_ATTRIBUTES; + +        case EC_STATE_HEAL_ATTRIBUTES: +            ec_heal_attr(heal); + +            return EC_STATE_HEAL_OPEN; + +        case EC_STATE_HEAL_OPEN: +            ec_heal_open(heal); + +            return EC_STATE_HEAL_REOPEN_FD; + +        case EC_STATE_HEAL_REOPEN_FD: +            ec_heal_reopen_fd(heal); + +            return EC_STATE_HEAL_UNLOCK; + +        case -EC_STATE_HEAL_XATTRIBUTES_REMOVE: +        case -EC_STATE_HEAL_XATTRIBUTES_SET: +        case -EC_STATE_HEAL_ATTRIBUTES: +        case -EC_STATE_HEAL_OPEN: +        case -EC_STATE_HEAL_REOPEN_FD: +        case -EC_STATE_HEAL_UNLOCK: +        case EC_STATE_HEAL_UNLOCK: +            ec_heal_inodelk(heal, F_UNLCK, 0, 0, 0); + +        case -EC_STATE_HEAL_ENTRY_PREPARE: +        case -EC_STATE_HEAL_PRE_INODELK_LOCK: +        case -EC_STATE_HEAL_PRE_INODE_LOOKUP: +            ec_heal_entrylk(heal, ENTRYLK_UNLOCK); + +            if (ec_heal_needs_data_rebuild(heal)) +            { +                return EC_STATE_HEAL_DATA_LOCK; +            } + +            return EC_STATE_HEAL_DISPATCH; + +        case EC_STATE_HEAL_DATA_LOCK: +            if (heal->done) +            { +                return EC_STATE_HEAL_POST_INODELK_LOCK; +            } + +            ec_heal_inodelk(heal, F_WRLCK, 1, heal->offset, heal->size); + +            return EC_STATE_HEAL_DATA_COPY; + +        case EC_STATE_HEAL_DATA_COPY: +            ec_heal_data(heal); + +            return EC_STATE_HEAL_DATA_UNLOCK; + +        case -EC_STATE_HEAL_DATA_COPY: +        case -EC_STATE_HEAL_DATA_UNLOCK: +        case EC_STATE_HEAL_DATA_UNLOCK: +            ec_heal_inodelk(heal, F_UNLCK, 1, heal->offset, heal->size); + +            heal->offset += heal->size; + +            return EC_STATE_HEAL_DATA_LOCK; + +        case EC_STATE_HEAL_POST_INODELK_LOCK: +            ec_heal_inodelk(heal, F_WRLCK, 1, 0, 0); + +            return EC_STATE_HEAL_POST_INODE_LOOKUP; + +        case EC_STATE_HEAL_POST_INODE_LOOKUP: +            ec_heal_lookup(heal); + +            return EC_STATE_HEAL_SETATTR; + +        case EC_STATE_HEAL_SETATTR: +            ec_setattr(heal->fop->frame, heal->xl, heal->bad, EC_MINIMUM_ONE, +                       ec_heal_setattr_cbk, heal, &heal->loc, &heal->iatt, +                       GF_SET_ATTR_MODE | GF_SET_ATTR_UID | GF_SET_ATTR_GID | +                       GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME, NULL); + +            return EC_STATE_HEAL_POST_INODELK_UNLOCK; + +        case -EC_STATE_HEAL_SETATTR: +        case -EC_STATE_HEAL_POST_INODELK_UNLOCK: +        case EC_STATE_HEAL_POST_INODELK_UNLOCK: +            ec_heal_inodelk(heal, F_UNLCK, 1, 0, 0); + +            return EC_STATE_HEAL_DISPATCH; + +        case -EC_STATE_HEAL_POST_INODELK_LOCK: +        case -EC_STATE_HEAL_POST_INODE_LOOKUP: +        case -EC_STATE_HEAL_ENTRY_LOOKUP: +        case -EC_STATE_HEAL_DATA_LOCK: +        case -EC_STATE_HEAL_DISPATCH: +        case EC_STATE_HEAL_DISPATCH: +            ec_heal_dispatch(heal); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.heal != NULL) +                { +                    fop->cbks.heal(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                   cbk->op_errno, cbk->uintptr[0], +                                   cbk->uintptr[1], cbk->uintptr[2], +                                   cbk->xdata); +                } +            } +            else +            { +                if (fop->cbks.fheal != NULL) +                { +                    fop->cbks.fheal(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                    cbk->op_errno, cbk->uintptr[0], +                                    cbk->uintptr[1], cbk->uintptr[2], +                                    cbk->xdata); +                } +            } + +            return EC_STATE_END; + +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.heal != NULL) +                { +                    fop->cbks.heal(fop->req_frame, fop, fop->xl, -1, +                                   fop->error, 0, 0, 0, NULL); +                } +            } +            else +            { +                if (fop->cbks.fheal != NULL) +                { +                    fop->cbks.fheal(fop->req_frame, fop, fop->xl, -1, +                                    fop->error, 0, 0, 0, NULL); +                } +            } + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_heal(call_frame_t * frame, xlator_t * this, uintptr_t target, +             int32_t minimum, fop_heal_cbk_t func, void * data, loc_t * loc, +             dict_t * xdata) +{ +    ec_cbk_t callback = { .heal = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(HEAL) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(NULL, this, EC_FOP_HEAL, +                               EC_FLAG_UPDATE_LOC_INODE, target, minimum, +                               ec_wind_heal, ec_manager_heal, callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, 0, 0, 0, NULL); +    } +} + +/* FOP: fheal */ + +void ec_wind_fheal(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_cbk_data_t * cbk; +    ec_heal_t * heal = fop->data; + +    ec_trace("WIND", fop, "idx=%d", idx); + +    cbk = ec_cbk_data_allocate(fop->req_frame, fop->xl, fop, EC_FOP_FHEAL, idx, +                               fop->error == 0 ? 0 : -1, fop->error); +    if (cbk != NULL) +    { +        cbk->uintptr[0] = heal->available; +        cbk->uintptr[1] = heal->good; +        cbk->uintptr[2] = heal->bad; + +        ec_combine(cbk, NULL); +    } + +    ec_complete(fop); +} + +void ec_fheal(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_fheal_cbk_t func, void * data, fd_t * fd, +              dict_t * xdata) +{ +    ec_fd_t * ctx = ec_fd_get(fd, this); + +    if ((ctx != NULL) && (ctx->loc.inode != NULL)) +    { +        gf_log("ec", GF_LOG_DEBUG, "FHEAL ctx: flags=%X, open=%lX, bad=%lX", +               ctx->flags, ctx->open, ctx->bad); +        ec_heal(frame, this, target, minimum, func, data, &ctx->loc, xdata); +    } +} diff --git a/xlators/cluster/ec/src/ec-helpers.c b/xlators/cluster/ec/src/ec-helpers.c new file mode 100644 index 00000000000..771faf5b013 --- /dev/null +++ b/xlators/cluster/ec/src/ec-helpers.c @@ -0,0 +1,594 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include <libgen.h> + +#include "byte-order.h" + +#include "ec-mem-types.h" +#include "ec-fops.h" +#include "ec-helpers.h" + +#define BACKEND_D_OFF_BITS 63 +#define PRESENT_D_OFF_BITS 63 + +#define ONE 1ULL +#define MASK (~0ULL) +#define PRESENT_MASK (MASK >> (64 - PRESENT_D_OFF_BITS)) +#define BACKEND_MASK (MASK >> (64 - BACKEND_D_OFF_BITS)) + +#define TOP_BIT (ONE << (PRESENT_D_OFF_BITS - 1)) +#define SHIFT_BITS (max(0, (BACKEND_D_OFF_BITS - PRESENT_D_OFF_BITS + 1))) + +static const char * ec_fop_list[] = +{ +    [-EC_FOP_HEAL] = "HEAL" +}; + +const char * ec_bin(char * str, size_t size, uint64_t value, int32_t digits) +{ +    str += size; + +    if (size-- < 1) +    { +        goto failed; +    } +    *--str = 0; + +    while ((value != 0) || (digits > 0)) +    { +        if (size-- < 1) +        { +            goto failed; +        } +        *--str = '0' + (value & 1); +        digits--; +        value >>= 1; +    } + +    return str; + +failed: +    return "<buffer too small>"; +} + +const char * ec_fop_name(int32_t id) +{ +    if (id >= 0) +    { +        return gf_fop_list[id]; +    } + +    return ec_fop_list[-id]; +} + +void ec_trace(const char * event, ec_fop_data_t * fop, const char * fmt, ...) +{ +    char str1[32], str2[32], str3[32]; +    char * msg; +    ec_t * ec = fop->xl->private; +    va_list args; +    int32_t ret; + +    va_start(args, fmt); +    ret = vasprintf(&msg, fmt, args); +    va_end(args); + +    if (ret < 0) +    { +        msg = "<memory allocation error>"; +    } + +    gf_log("ec", GF_LOG_TRACE, "%s(%s) %p(%p) [refs=%d, winds=%d, jobs=%d] " +                               "frame=%p/%p, min/exp=%d/%d, err=%d state=%d " +                               "{%s:%s:%s} %s", +           event, ec_fop_name(fop->id), fop, fop->parent, fop->refs, +           fop->winds, fop->jobs, fop->req_frame, fop->frame, fop->minimum, +           fop->expected, fop->error, fop->state, +           ec_bin(str1, sizeof(str1), fop->mask, ec->nodes), +           ec_bin(str2, sizeof(str2), fop->remaining, ec->nodes), +           ec_bin(str3, sizeof(str3), fop->bad, ec->nodes), msg); + +    if (ret >= 0) +    { +        free(msg); +    } +} + +uint64_t ec_itransform(ec_t * ec, int32_t idx, uint64_t offset) +{ +    int32_t bits; + +    if (offset == -1ULL) +    { +        return -1ULL; +    } + +    bits = ec->bits_for_nodes; +    if ((offset & ~(PRESENT_MASK >> (bits + 1))) != 0) +    { +        return TOP_BIT | ((offset >> SHIFT_BITS) & (MASK << bits)) | idx; +    } + +    return (offset * ec->nodes) + idx; +} + +uint64_t ec_deitransform(ec_t * ec, int32_t * idx, uint64_t offset) +{ +    uint64_t mask = 0; + +    if ((offset & TOP_BIT) != 0) +    { +        mask = MASK << ec->bits_for_nodes; + +        *idx = offset & ~mask; +        return ((offset & ~TOP_BIT) & mask) << SHIFT_BITS; +    } + +    *idx = offset % ec->nodes; + +    return offset / ec->nodes; +} + +int32_t ec_bits_count(uint64_t n) +{ +    n -= (n >> 1) & 0x5555555555555555ULL; +    n = ((n >> 2) & 0x3333333333333333ULL) + (n & 0x3333333333333333ULL); +    n = (n + (n >> 4)) & 0x0F0F0F0F0F0F0F0FULL; +    n += n >> 8; +    n += n >> 16; +    n += n >> 32; + +    return n & 0xFF; +} + +int32_t ec_bits_index(uint64_t n) +{ +    return ffsll(n) - 1; +} + +int32_t ec_bits_consume(uint64_t * n) +{ +    uint64_t tmp; + +    tmp = *n; +    tmp &= -tmp; +    *n ^= tmp; + +    return ffsll(tmp) - 1; +} + +size_t ec_iov_copy_to(void * dst, struct iovec * vector, int32_t count, +                      off_t offset, size_t size) +{ +    int32_t i = 0; +    size_t total = 0, len = 0; + +    while (i < count) +    { +        if (offset < vector[i].iov_len) +        { +            while ((i < count) && (size > 0)) +            { +                len = size; +                if (len > vector[i].iov_len - offset) +                { +                    len = vector[i].iov_len - offset; +                } +                memcpy(dst, vector[i++].iov_base + offset, len); +                offset = 0; +                dst += len; +                total += len; +                size -= len; +            } + +            break; +        } + +        offset -= vector[i].iov_len; +        i++; +    } + +    return total; +} + +int32_t ec_dict_set_number(dict_t * dict, char * key, uint64_t value) +{ +    uint64_t * ptr; + +    ptr = GF_MALLOC(sizeof(value), gf_common_mt_char); +    if (ptr == NULL) +    { +        return -1; +    } + +    *ptr = hton64(value); + +    return dict_set_bin(dict, key, ptr, sizeof(value)); +} + +int32_t ec_dict_del_number(dict_t * dict, char * key, uint64_t * value) +{ +    void * ptr; +    int32_t len; + +    if ((dict == NULL) || (dict_get_ptr_and_len(dict, key, &ptr, &len) != 0) || +        (len != sizeof(uint64_t))) +    { +        return -1; +    } + +    *value = ntoh64(*(uint64_t *)ptr); + +    dict_del(dict, key); + +    return 0; +} + +int32_t ec_loc_gfid_check(xlator_t * xl, uuid_t dst, uuid_t src) +{ +    if (uuid_is_null(src)) +    { +        return 1; +    } + +    if (uuid_is_null(dst)) +    { +        uuid_copy(dst, src); + +        return 1; +    } + +    if (uuid_compare(dst, src) != 0) +    { +        gf_log(xl->name, GF_LOG_WARNING, "Mismatching GFID's in loc"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_loc_parent(xlator_t * xl, loc_t * loc, loc_t * parent, char ** name) +{ +    char * str = NULL; +    int32_t error = 0; + +    memset(parent, 0, sizeof(loc_t)); + +    if (loc->path == NULL) +    { +        gf_log(xl->name, GF_LOG_ERROR, "inode path missing in loc_t: %p", loc->parent); + +        return EINVAL; +    } + +    if (loc->parent == NULL) +    { +        if ((loc->inode == NULL) || !__is_root_gfid(loc->inode->gfid) || +            (strcmp(loc->path, "/") != 0)) +        { +            gf_log(xl->name, GF_LOG_ERROR, "Parent inode missing for " +                                           "loc_t (path=%s, name=%s)", +                   loc->path, loc->name); + +            return EINVAL; +        } + +        if (loc_copy(parent, loc) != 0) +        { +            return ENOMEM; +        } + +        parent->name = NULL; + +        if (name != NULL) +        { +            *name = NULL; +        } +    } +    else +    { +        if (uuid_is_null(loc->parent->gfid) && (uuid_is_null(loc->pargfid))) +        { +            gf_log(xl->name, GF_LOG_ERROR, "Invalid parent inode " +                                           "(path=%s, name=%s)", +                   loc->path, loc->name); + +            return EINVAL; +        } +        uuid_copy(parent->gfid, loc->pargfid); + +        str = gf_strdup(loc->path); +        if (str == NULL) +        { +            gf_log(xl->name, GF_LOG_ERROR, "Unable to duplicate path " +                                           "'%s'", str); + +            return ENOMEM; +        } +        if (name != NULL) +        { +            *name = gf_strdup(basename(str)); +            if (*name == NULL) +            { +                gf_log(xl->name, GF_LOG_ERROR, "Unable to get basename " +                                               "of '%s'", str); + +                error = ENOMEM; + +                goto out; +            } +            strcpy(str, loc->path); +        } +        parent->path = gf_strdup(dirname(str)); +        if (parent->path == NULL) +        { +            gf_log(xl->name, GF_LOG_ERROR, "Unable to get dirname of " +                                           "'%s'", str); + +            error = ENOMEM; + +            goto out; +        } +        parent->name = strrchr(parent->path, '/'); +        if (parent->name == NULL) +        { +            gf_log(xl->name, GF_LOG_ERROR, "Invalid path name (%s)", +                   parent->path); + +            error = EINVAL; + +            goto out; +        } +        parent->name++; +        parent->inode = inode_ref(loc->parent); +    } + +    if ((loc->inode == NULL) || +        ec_loc_gfid_check(xl, loc->gfid, loc->inode->gfid)) +    { +        parent = NULL; +    } + +out: +    GF_FREE(str); + +    if (parent != NULL) +    { +        loc_wipe(parent); +    } + +    return error; +} + +int32_t ec_loc_prepare(xlator_t * xl, loc_t * loc, inode_t * inode, +                       struct iatt * iatt) +{ +    if ((inode != NULL) && (loc->inode != inode)) +    { +        if (loc->inode != NULL) +        { +            inode_unref(loc->inode); +        } +        loc->inode = inode_ref(inode); + +        uuid_copy(loc->gfid, inode->gfid); +    } +    else if (loc->inode != NULL) +    { +        if (!ec_loc_gfid_check(xl, loc->gfid, loc->inode->gfid)) +        { +            return 0; +        } +    } + +    if (iatt != NULL) +    { +        if (!ec_loc_gfid_check(xl, loc->gfid, iatt->ia_gfid)) +        { +            return 0; +        } +    } + +    if (loc->parent != NULL) +    { +        if (!ec_loc_gfid_check(xl, loc->pargfid, loc->parent->gfid)) +        { +            return 0; +        } + +    } + +    if (uuid_is_null(loc->gfid)) +    { +        gf_log(xl->name, GF_LOG_WARNING, "GFID not available for inode"); +    } + +    return 1; +} + +int32_t ec_loc_from_fd(xlator_t * xl, loc_t * loc, fd_t * fd) +{ +    ec_fd_t * ctx; + +    memset(loc, 0, sizeof(*loc)); + +    ctx = ec_fd_get(fd, xl); +    if (ctx != NULL) +    { +        if (loc_copy(loc, &ctx->loc) != 0) +        { +            return 0; +        } +    } + +    if (ec_loc_prepare(xl, loc, fd->inode, NULL)) +    { +        return 1; +    } + +    loc_wipe(loc); + +    return 0; +} + +int32_t ec_loc_from_loc(xlator_t * xl, loc_t * dst, loc_t * src) +{ +    memset(dst, 0, sizeof(*dst)); + +    if (loc_copy(dst, src) != 0) +    { +        return 0; +    } + +    if (ec_loc_prepare(xl, dst, NULL, NULL)) +    { +        return 1; +    } + +    loc_wipe(dst); + +    return 0; +} + +void ec_owner_set(call_frame_t * frame, void * owner) +{ +    set_lk_owner_from_ptr(&frame->root->lk_owner, owner); +} + +void ec_owner_copy(call_frame_t * frame, gf_lkowner_t * owner) +{ +    frame->root->lk_owner.len = owner->len; +    memcpy(frame->root->lk_owner.data, owner->data, owner->len); +} + +ec_inode_t * __ec_inode_get(inode_t * inode, xlator_t * xl) +{ +    ec_inode_t * ctx = NULL; +    uint64_t value = 0; + +    if ((__inode_ctx_get(inode, xl, &value) != 0) || (value == 0)) +    { +        ctx = GF_MALLOC(sizeof(*ctx), ec_mt_ec_inode_t); +        if (ctx != NULL) +        { +            memset(ctx, 0, sizeof(*ctx)); + +            value = (uint64_t)(uintptr_t)ctx; +            if (__inode_ctx_set(inode, xl, &value) != 0) +            { +                GF_FREE(ctx); + +                return NULL; +            } +        } +    } +    else +    { +        ctx = (ec_inode_t *)(uintptr_t)value; +    } + +    return ctx; +} + +ec_inode_t * ec_inode_get(inode_t * inode, xlator_t * xl) +{ +    ec_inode_t * ctx = NULL; + +    LOCK(&inode->lock); + +    ctx = __ec_inode_get(inode, xl); + +    UNLOCK(&inode->lock); + +    return ctx; +} + +ec_fd_t * __ec_fd_get(fd_t * fd, xlator_t * xl) +{ +    ec_fd_t * ctx = NULL; +    uint64_t value = 0; + +    if ((__fd_ctx_get(fd, xl, &value) != 0) || (value == 0)) +    { +        ctx = GF_MALLOC(sizeof(*ctx), ec_mt_ec_fd_t); +        if (ctx != NULL) +        { +            memset(ctx, 0, sizeof(*ctx)); + +            value = (uint64_t)(uintptr_t)ctx; +            if (__fd_ctx_set(fd, xl, value) != 0) +            { +                GF_FREE(ctx); + +                return NULL; +            } +        } +    } +    else +    { +        ctx = (ec_fd_t *)(uintptr_t)value; +    } + +    return ctx; +} + +ec_fd_t * ec_fd_get(fd_t * fd, xlator_t * xl) +{ +    ec_fd_t * ctx = NULL; + +    LOCK(&fd->lock); + +    ctx = __ec_fd_get(fd, xl); + +    UNLOCK(&fd->lock); + +    return ctx; +} + +size_t ec_adjust_offset(ec_t * ec, off_t * offset, int32_t scale) +{ +    size_t head, tmp; + +    tmp = *offset; +    head = tmp % ec->stripe_size; +    tmp -= head; +    if (scale) +    { +        tmp /= ec->fragments; +    } + +    *offset = tmp; + +    return head; +} + +size_t ec_adjust_size(ec_t * ec, size_t size, int32_t scale) +{ +    size += ec->stripe_size - 1; +    size -= size % ec->stripe_size; +    if (scale) +    { +        size /= ec->fragments; +    } + +    return size; +} diff --git a/xlators/cluster/ec/src/ec-helpers.h b/xlators/cluster/ec/src/ec-helpers.h new file mode 100644 index 00000000000..6625ade4b08 --- /dev/null +++ b/xlators/cluster/ec/src/ec-helpers.h @@ -0,0 +1,59 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef __EC_HELPERS_H__ +#define __EC_HELPERS_H__ + +#include "ec-data.h" + +const char * ec_bin(char * str, size_t size, uint64_t value, int32_t digits); +const char * ec_fop_name(int32_t id); +void ec_trace(const char * event, ec_fop_data_t * fop, const char * fmt, ...); +uint64_t ec_itransform(ec_t * ec, int32_t idx, uint64_t offset); +uint64_t ec_deitransform(ec_t * ec, int32_t * idx, uint64_t offset); +int32_t ec_bits_count(uint64_t n); +int32_t ec_bits_index(uint64_t n); +int32_t ec_bits_consume(uint64_t * n); +size_t ec_iov_copy_to(void * dst, struct iovec * vector, int32_t count, +                      off_t offset, size_t size); + +int32_t ec_dict_set_number(dict_t * dict, char * key, uint64_t value); +int32_t ec_dict_del_number(dict_t * dict, char * key, uint64_t * value); + +int32_t ec_loc_parent(xlator_t * xl, loc_t * loc, loc_t * parent, +                      char ** name); +int32_t ec_loc_prepare(xlator_t * xl, loc_t * loc, inode_t * inode, +                       struct iatt * iatt); + +int32_t ec_loc_from_fd(xlator_t * xl, loc_t * loc, fd_t * fd); +int32_t ec_loc_from_loc(xlator_t * xl, loc_t * dst, loc_t * src); + +void ec_owner_set(call_frame_t * frame, void * owner); +void ec_owner_copy(call_frame_t * frame, gf_lkowner_t * owner); + +ec_inode_t * __ec_inode_get(inode_t * inode, xlator_t * xl); +ec_inode_t * ec_inode_get(inode_t * inode, xlator_t * xl); +ec_fd_t * __ec_fd_get(fd_t * fd, xlator_t * xl); +ec_fd_t * ec_fd_get(fd_t * fd, xlator_t * xl); + +size_t ec_adjust_offset(ec_t * ec, off_t * offset, int32_t scale); +size_t ec_adjust_size(ec_t * ec, size_t size, int32_t scale); + +#endif /* __EC_HELPERS_H__ */ diff --git a/xlators/cluster/ec/src/ec-inode-read.c b/xlators/cluster/ec/src/ec-inode-read.c new file mode 100644 index 00000000000..b1db9c9fbb7 --- /dev/null +++ b/xlators/cluster/ec/src/ec-inode-read.c @@ -0,0 +1,1764 @@ + +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "xlator.h" +#include "defaults.h" + +#include "ec-helpers.h" +#include "ec-common.h" +#include "ec-combine.h" +#include "ec-method.h" +#include "ec-fops.h" + +/* FOP: access */ + +int32_t ec_access_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                      int32_t op_ret, int32_t op_errno, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    if (!ec_dispatch_one_retry(fop, idx, op_ret, op_errno)) +    { +        if (fop->cbks.access != NULL) +        { +            fop->cbks.access(fop->req_frame, fop, this, op_ret, op_errno, +                             xdata); +        } +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_access(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_access_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->access, +                      &fop->loc[0], fop->int32, fop->xdata); +} + +int32_t ec_manager_access(ec_fop_data_t * fop, int32_t state) +{ +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_DISPATCH: +            ec_dispatch_one(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case -EC_STATE_REPORT: +            if (fop->cbks.access != NULL) +            { +                fop->cbks.access(fop->req_frame, fop, fop->xl, -1, fop->error, +                                 NULL); +            } + +        case EC_STATE_REPORT: +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_access(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_access_cbk_t func, void * data, +               loc_t * loc, int32_t mask, dict_t * xdata) +{ +    ec_cbk_t callback = { .access = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(ACCESS) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_ACCESS, 0, target, minimum, +                               ec_wind_access, ec_manager_access, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = mask; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL); +    } +} + +/* FOP: getxattr */ + +int32_t ec_combine_getxattr(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                            ec_cbk_data_t * src) +{ +    if (!ec_dict_compare(dst->dict, src->dict)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching dictionary in " +                                             "answers of 'GF_FOP_GETXATTR'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_getxattr_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                        int32_t op_ret, int32_t op_errno, dict_t * dict, +                        dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_GETXATTR, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (dict != NULL) +            { +                cbk->dict = dict_ref(dict); +                if (cbk->dict == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                     "dictionary."); + +                    goto out; +                } +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_getxattr); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_getxattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_getxattr_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->getxattr, +                      &fop->loc[0], fop->str[0], fop->xdata); +} + +int32_t ec_manager_getxattr(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_inode(fop, &fop->loc[0]); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA) || +                    ((cbk->op_ret >= 0) && !ec_dict_combine(cbk, +                                                            EC_COMBINE_DICT))) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    if (cbk->xdata != NULL) +                    { +                        dict_del(cbk->xdata, EC_XATTR_SIZE); +                        dict_del(cbk->xdata, EC_XATTR_VERSION); +                    } +                    if (cbk->dict != NULL) +                    { +                        dict_del(cbk->dict, EC_XATTR_SIZE); +                        dict_del(cbk->dict, EC_XATTR_VERSION); +                    } +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.getxattr != NULL) +            { +                fop->cbks.getxattr(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                   cbk->op_errno, cbk->dict, cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.getxattr != NULL) +            { +                fop->cbks.getxattr(fop->req_frame, fop, fop->xl, -1, +                                   fop->error, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_getxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_getxattr_cbk_t func, void * data, +                 loc_t * loc, const char * name, dict_t * xdata) +{ +    ec_cbk_t callback = { .getxattr = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(GETXATTR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_GETXATTR, +                               EC_FLAG_UPDATE_LOC_INODE, target, minimum, +                               ec_wind_getxattr, ec_manager_getxattr, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (name != NULL) +    { +        fop->str[0] = gf_strdup(name); +        if (fop->str[0] == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a string."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} + +/* FOP: fgetxattr */ + +int32_t ec_fgetxattr_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                         int32_t op_ret, int32_t op_errno, dict_t * dict, +                         dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FGETXATTR, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (dict != NULL) +            { +                cbk->dict = dict_ref(dict); +                if (cbk->dict == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                     "dictionary."); + +                    goto out; +                } +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_getxattr); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_fgetxattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_fgetxattr_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->fgetxattr, +                      fop->fd, fop->str[0], fop->xdata); +} + +void ec_fgetxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                  int32_t minimum, fop_fgetxattr_cbk_t func, void * data, +                  fd_t * fd, const char * name, dict_t * xdata) +{ +    ec_cbk_t callback = { .fgetxattr = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FGETXATTR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FGETXATTR, +                               EC_FLAG_UPDATE_FD_INODE, target, minimum, +                               ec_wind_fgetxattr, ec_manager_getxattr, +                               callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (name != NULL) +    { +        fop->str[0] = gf_strdup(name); +        if (fop->str[0] == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a string."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} + +/* FOP: open */ + +int32_t ec_combine_open(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                        ec_cbk_data_t * src) +{ +    if (dst->fd != src->fd) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching fd in answers " +                                             "of 'GF_FOP_OPEN': %p <-> %p", +               dst->fd, src->fd); + +        return 0; +    } + +    return 1; +} + +int32_t ec_open_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                    int32_t op_ret, int32_t op_errno, fd_t * fd, +                    dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_OPEN, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (fd != NULL) +            { +                cbk->fd = fd_ref(fd); +                if (cbk->fd == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                     "file descriptor."); + +                    goto out; +                } +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_open); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_open(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_open_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->open, +                      &fop->loc[0], fop->int32, fop->fd, fop->xdata); +} + +int32_t ec_manager_open(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; +    ec_fd_t * ctx; + +    switch (state) +    { +        case EC_STATE_INIT: +            LOCK(&fop->fd->lock); + +            ctx = __ec_fd_get(fop->fd, fop->xl); +            if ((ctx == NULL) || !ec_loc_from_loc(fop->xl, &ctx->loc, +                &fop->loc[0])) +            { +                UNLOCK(&fop->fd->lock); + +                fop->error = EIO; + +                return EC_STATE_REPORT; +            } + +            if (ctx->flags == 0) +            { +                ctx->flags = fop->int32; +            } + +            UNLOCK(&fop->fd->lock); + +            if ((fop->int32 & O_ACCMODE) == O_WRONLY) +            { +                fop->int32 &= ~O_ACCMODE; +                fop->int32 |= O_RDWR; +            } + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_loc_prepare(fop->xl, &fop->loc[0], cbk->fd->inode, +                                   NULL); + +                    LOCK(&fop->fd->lock); + +                    ctx = __ec_fd_get(fop->fd, fop->xl); +                    if (ctx != NULL) +                    { +                        ctx->open |= cbk->mask; +                    } + +                    UNLOCK(&fop->fd->lock); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.open != NULL) +            { +                fop->cbks.open(fop->req_frame, fop, fop->xl, cbk->op_ret, +                               cbk->op_errno, cbk->fd, cbk->xdata); +            } + +            return EC_STATE_END; + +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.open != NULL) +            { +                fop->cbks.open(fop->req_frame, fop, fop->xl, -1, fop->error, +                               NULL, NULL); +            } + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_open(call_frame_t * frame, xlator_t * this, uintptr_t target, +             int32_t minimum, fop_open_cbk_t func, void * data, loc_t * loc, +             int32_t flags, fd_t * fd, dict_t * xdata) +{ +    ec_cbk_t callback = { .open = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(OPEN) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_OPEN, EC_FLAG_UPDATE_FD, +                               target, minimum, ec_wind_open, ec_manager_open, +                               callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = flags; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} + +/* FOP: readlink */ + +int32_t ec_combine_readlink(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                            ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 1)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_READLINK'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_readlink_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                        int32_t op_ret, int32_t op_errno, const char * path, +                        struct iatt * buf, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    if (op_ret > 0) +    { +        ec_iatt_rebuild(fop->xl->private, buf, 1, 1); +    } + +    if (!ec_dispatch_one_retry(fop, idx, op_ret, op_errno)) +    { +        if (fop->cbks.readlink != NULL) +        { +            fop->cbks.readlink(fop->req_frame, fop, this, op_ret, op_errno, +                               path, buf, xdata); +        } +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_readlink(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_readlink_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->readlink, +                      &fop->loc[0], fop->size, fop->xdata); +} + +int32_t ec_manager_readlink(ec_fop_data_t * fop, int32_t state) +{ +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_DISPATCH: +            ec_dispatch_one(fop); + +            return EC_STATE_REPORT; + +        case -EC_STATE_REPORT: +            if (fop->cbks.readlink != NULL) +            { +                fop->cbks.readlink(fop->req_frame, fop, fop->xl, -1, +                                   fop->error, NULL, NULL, NULL); +            } + +        case EC_STATE_REPORT: +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_readlink(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_readlink_cbk_t func, void * data, +                 loc_t * loc, size_t size, dict_t * xdata) +{ +    ec_cbk_t callback = { .readlink = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(READLINK) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_READLINK, 0, target, +                               minimum, ec_wind_readlink, ec_manager_readlink, +                               callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->size = size; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL); +    } +} + +/* FOP: readv */ + +int32_t ec_readv_rebuild(ec_t * ec, ec_fop_data_t * fop, ec_cbk_data_t * cbk) +{ +    ec_cbk_data_t * ans = NULL; +    struct iobuf_pool * pool = NULL; +    struct iobref * iobref = NULL; +    struct iobuf * iobuf = NULL; +    uint8_t * ptr = NULL, * buff = NULL; +    size_t fsize = 0, size = 0, max = 0, slice = 0; +    int32_t i = 0; + +    if (cbk->op_ret < 0) +    { +        goto out; +    } + +    cbk->iatt[0].ia_size = fop->pre_size; + +    if (cbk->op_ret > 0) +    { +        struct iovec vector[cbk->int32 * cbk->count]; +        uint8_t * blocks[cbk->count]; +        uint32_t values[cbk->count]; + +        fsize = cbk->op_ret; +        size = fsize * ec->fragments; +        ptr = GF_MALLOC(size + EC_BUFFER_ALIGN_SIZE - 1, gf_common_mt_char); +        if (ptr == NULL) +        { +            goto out; +        } +        buff = GF_ALIGN_BUF(ptr, EC_BUFFER_ALIGN_SIZE); + +        iobref = iobref_new(); +        if (iobref == NULL) +        { +            goto out; +        } + +        for (i = 0, ans = cbk; ans != NULL; i++, ans = ans->next) +        { +            values[i] = ans->idx; +            blocks[i] = buff; +            buff += ec_iov_copy_to(buff, ans->vector, ans->int32, 0, fsize); +        } + +        pool = fop->xl->ctx->iobuf_pool; +        max = iobpool_default_pagesize(pool) / ec->stripe_size; +        max *= ec->fragment_size; +        i = 0; +        do +        { +            iobuf = iobuf_get(pool); +            if (iobuf == NULL) +            { +                goto out; +            } +            if (iobref_add(iobref, iobuf) != 0) +            { +                goto out; +            } + +            slice = fsize; +            if (slice > max) +            { +                slice = max; +            } +            fsize -= slice; + +            vector[i].iov_base = iobuf->ptr; +            vector[i].iov_len = ec_method_decode(slice, ec->fragments, values, +                                                 blocks, iobuf->ptr); +            i++; + +            iobuf_unref(iobuf); +        } while (fsize > 0); + +        GF_FREE(ptr); +        ptr = NULL; + +        vector[0].iov_base += fop->head; +        vector[0].iov_len -= fop->head; + +        max = fop->offset * ec->fragments + size; +        if (max > cbk->iatt[0].ia_size) +        { +            max = cbk->iatt[0].ia_size; +        } +        max -= fop->offset * ec->fragments + fop->head; +        if (max > fop->user_size) +        { +            max = fop->user_size; +        } +        size -= fop->head; +        while (size > max) +        { +            if (size - max >= vector[i - 1].iov_len) +            { +                size -= vector[--i].iov_len; +            } +            else +            { +                vector[i - 1].iov_len -= size - max; +                size = max; +            } +        } + +        cbk->op_ret = size; +        cbk->int32 = i; + +        iobref_unref(cbk->buffers); +        cbk->buffers = iobref; + +        GF_FREE(cbk->vector); +        cbk->vector = iov_dup(vector, i); +        if (cbk->vector == NULL) +        { +            cbk->op_ret = -1; +            cbk->op_errno = EIO; + +            return 0; +        } +    } + +    return 1; + +out: +    if (iobuf != NULL) +    { +        iobuf_unref(iobuf); +    } +    if (iobref != NULL) +    { +        iobref_unref(iobref); +    } +    GF_FREE(ptr); + +    return 0; +} + +int32_t ec_combine_readv(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                         ec_cbk_data_t * src) +{ +    if (!ec_vector_compare(dst->vector, dst->int32, src->vector, src->int32)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching vector in " +                                             "answers of 'GF_FOP_READ'"); + +        return 0; +    } + +    if (!ec_iatt_combine(dst->iatt, src->iatt, 1)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_READ'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_readv_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                     int32_t op_ret, int32_t op_errno, struct iovec * vector, +                     int32_t count, struct iatt * stbuf, +                     struct iobref * iobref, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    ec_t * ec = this->private; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_READ, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            cbk->int32 = count; + +            if (count > 0) +            { +                cbk->vector = iov_dup(vector, count); +                if (cbk->vector == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a " +                                                     "vector list."); + +                    goto out; +                } +                cbk->int32 = count; +            } +            if (stbuf != NULL) +            { +                cbk->iatt[0] = *stbuf; +            } +            if (iobref != NULL) +            { +                cbk->buffers = iobref_ref(iobref); +                if (cbk->buffers == NULL) +                { +                    gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                     "buffer."); + +                    goto out; +                } +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        if ((op_ret > 0) && ((op_ret % ec->fragment_size) != 0)) +        { +            cbk->op_ret = -1; +            cbk->op_errno = EIO; +        } + +        ec_combine(cbk, ec_combine_readv); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_readv(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_readv_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->readv, fop->fd, +                      fop->size, fop->offset, fop->uint32, fop->xdata); +} + +int32_t ec_manager_readv(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +            fop->user_size = fop->size; +            fop->head = ec_adjust_offset(fop->xl->private, &fop->offset, 1); +            fop->size = ec_adjust_size(fop->xl->private, fop->size + fop->head, +                                       1); + +        case EC_STATE_LOCK: +            ec_lock_fd(fop, fop->fd); + +            return EC_STATE_GET_SIZE_AND_VERSION; + +        case EC_STATE_GET_SIZE_AND_VERSION: +            ec_get_size_version(fop); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_min(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 1, +                                    cbk->count); + +                    if (!ec_readv_rebuild(fop->xl->private, fop, cbk)) +                    { +                        ec_fop_set_error(fop, EIO); +                    } +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.readv != NULL) +            { +                fop->cbks.readv(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                cbk->op_errno, cbk->vector, cbk->int32, +                                &cbk->iatt[0], cbk->buffers, cbk->xdata); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_GET_SIZE_AND_VERSION: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.readv != NULL) +            { +                fop->cbks.readv(fop->req_frame, fop, fop->xl, -1, fop->error, +                                NULL, 0, NULL, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_readv(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_readv_cbk_t func, void * data, fd_t * fd, +              size_t size, off_t offset, uint32_t flags, dict_t * xdata) +{ +    ec_cbk_t callback = { .readv = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(READ) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_READ, EC_FLAG_UPDATE_FD, +                               target, minimum, ec_wind_readv, +                               ec_manager_readv, callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->size = size; +    fop->offset = offset; +    fop->uint32 = flags; + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, 0, NULL, NULL, NULL); +    } +} + +/* FOP: stat */ + +int32_t ec_combine_stat(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                        ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 1)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_STAT'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_stat_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                    int32_t op_ret, int32_t op_errno, struct iatt * buf, +                    dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_STAT, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (buf != NULL) +            { +                cbk->iatt[0] = *buf; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_stat); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_stat(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_stat_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->stat, +                      &fop->loc[0], fop->xdata); +} + +int32_t ec_manager_stat(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_inode(fop, &fop->loc[0]); + +            return EC_STATE_GET_SIZE_AND_VERSION; + +        case EC_STATE_GET_SIZE_AND_VERSION: +            ec_get_size_version(fop); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 1, +                                    cbk->count); + +                    cbk->iatt[0].ia_size = fop->pre_size; +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.stat != NULL) +                { +                    fop->cbks.stat(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                   cbk->op_errno, &cbk->iatt[0], cbk->xdata); +                } +            } +            else +            { +                if (fop->cbks.fstat != NULL) +                { +                    fop->cbks.fstat(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                    cbk->op_errno, &cbk->iatt[0], cbk->xdata); +                } +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_GET_SIZE_AND_VERSION: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.stat != NULL) +                { +                    fop->cbks.stat(fop->req_frame, fop, fop->xl, -1, +                                   fop->error, NULL, NULL); +                } +            } +            else +            { +                if (fop->cbks.fstat != NULL) +                { +                    fop->cbks.fstat(fop->req_frame, fop, fop->xl, -1, +                                    fop->error, NULL, NULL); +                } +            } + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_stat(call_frame_t * frame, xlator_t * this, uintptr_t target, +             int32_t minimum, fop_stat_cbk_t func, void * data, loc_t * loc, +             dict_t * xdata) +{ +    ec_cbk_t callback = { .stat = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(STAT) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_STAT, +                               EC_FLAG_UPDATE_LOC_INODE, target, minimum, +                               ec_wind_stat, ec_manager_stat, callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} + +/* FOP: fstat */ + +int32_t ec_fstat_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                     int32_t op_ret, int32_t op_errno, struct iatt * buf, +                     dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FSTAT, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (buf != NULL) +            { +                cbk->iatt[0] = *buf; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_stat); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_fstat(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_fstat_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->fstat, fop->fd, +                      fop->xdata); +} + +void ec_fstat(call_frame_t * frame, xlator_t * this, uintptr_t target, +              int32_t minimum, fop_fstat_cbk_t func, void * data, fd_t * fd, +              dict_t * xdata) +{ +    ec_cbk_t callback = { .fstat = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FSTAT) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FSTAT, +                               EC_FLAG_UPDATE_FD_INODE, target, minimum, +                               ec_wind_fstat, ec_manager_stat, callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} diff --git a/xlators/cluster/ec/src/ec-inode-write.c b/xlators/cluster/ec/src/ec-inode-write.c new file mode 100644 index 00000000000..a3c4ae5d8f2 --- /dev/null +++ b/xlators/cluster/ec/src/ec-inode-write.c @@ -0,0 +1,2235 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "xlator.h" +#include "defaults.h" + +#include "ec-helpers.h" +#include "ec-common.h" +#include "ec-combine.h" +#include "ec-method.h" +#include "ec-fops.h" + +/* FOP: removexattr */ + +int32_t ec_removexattr_cbk(call_frame_t * frame, void * cookie, +                           xlator_t * this, int32_t op_ret, int32_t op_errno, +                           dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_REMOVEXATTR, idx, +                               op_ret, op_errno); +    if (cbk != NULL) +    { +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, NULL); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_removexattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_removexattr_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->removexattr, +                      &fop->loc[0], fop->str[0], fop->xdata); +} + +int32_t ec_manager_removexattr(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_inode(fop, &fop->loc[0]); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.removexattr != NULL) +                { +                    fop->cbks.removexattr(fop->req_frame, fop, fop->xl, +                                          cbk->op_ret, cbk->op_errno, +                                          cbk->xdata); +                } +            } +            else +            { +                if (fop->cbks.fremovexattr != NULL) +                { +                    fop->cbks.fremovexattr(fop->req_frame, fop, fop->xl, +                                           cbk->op_ret, cbk->op_errno, +                                           cbk->xdata); +                } +            } + +            if (cbk->op_ret >= 0) +            { +                return EC_STATE_UPDATE_SIZE_AND_VERSION; +            } +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.removexattr != NULL) +                { +                    fop->cbks.removexattr(fop->req_frame, fop, fop->xl, -1, +                                          fop->error, NULL); +                } +            } +            else +            { +                if (fop->cbks.fremovexattr != NULL) +                { +                    fop->cbks.fremovexattr(fop->req_frame, fop, fop->xl, -1, +                                           fop->error, NULL); +                } +            } + +            return EC_STATE_UNLOCK; + +        case EC_STATE_UPDATE_SIZE_AND_VERSION: +            ec_update_size_version(fop); + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UPDATE_SIZE_AND_VERSION: +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_removexattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                    int32_t minimum, fop_removexattr_cbk_t func, void * data, +                    loc_t * loc, const char * name, dict_t * xdata) +{ +    ec_cbk_t callback = { .removexattr = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(REMOVEXATTR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_REMOVEXATTR, +                               EC_FLAG_UPDATE_LOC_INODE, target, minimum, +                               ec_wind_removexattr, ec_manager_removexattr, +                               callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (name != NULL) +    { +        fop->str[0] = gf_strdup(name); +        if (fop->str[0] == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a string."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL); +    } +} + +/* FOP: fremovexattr */ + +int32_t ec_fremovexattr_cbk(call_frame_t * frame, void * cookie, +                            xlator_t * this, int32_t op_ret, int32_t op_errno, +                            dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FREMOVEXATTR, idx, +                               op_ret, op_errno); +    if (cbk != NULL) +    { +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, NULL); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_fremovexattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_fremovexattr_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->fremovexattr, +                      fop->fd, fop->str[0], fop->xdata); +} + +void ec_fremovexattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                     int32_t minimum, fop_fremovexattr_cbk_t func, void * data, +                     fd_t * fd, const char * name, dict_t * xdata) +{ +    ec_cbk_t callback = { .fremovexattr = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FREMOVEXATTR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FREMOVEXATTR, +                               EC_FLAG_UPDATE_FD_INODE, target, minimum, +                               ec_wind_fremovexattr, ec_manager_removexattr, +                               callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (name != NULL) +    { +        fop->str[0] = gf_strdup(name); +        if (fop->str[0] == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a string."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL); +    } +} + +/* FOP: setattr */ + +int32_t ec_combine_setattr(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                           ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 2)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_SETATTR'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_setattr_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                       int32_t op_ret, int32_t op_errno, +                       struct iatt * preop_stbuf, struct iatt * postop_stbuf, +                       dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_SETATTR, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (preop_stbuf != NULL) +            { +                cbk->iatt[0] = *preop_stbuf; +            } +            if (postop_stbuf != NULL) +            { +                cbk->iatt[1] = *postop_stbuf; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_setattr); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_setattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_setattr_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->setattr, +                      &fop->loc[0], &fop->iatt, fop->int32, fop->xdata); +} + +int32_t ec_manager_setattr(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_inode(fop, &fop->loc[0]); + +            return EC_STATE_GET_SIZE_AND_VERSION; + +        case EC_STATE_GET_SIZE_AND_VERSION: +            ec_get_size_version(fop); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 2, +                                    cbk->count); + +                    cbk->iatt[0].ia_size = fop->pre_size; +                    cbk->iatt[1].ia_size = fop->pre_size; +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.setattr != NULL) +                { +                    fop->cbks.setattr(fop->req_frame, fop, fop->xl, +                                      cbk->op_ret, cbk->op_errno, +                                      &cbk->iatt[0], &cbk->iatt[1], +                                      cbk->xdata); +                } +            } +            else +            { +                if (fop->cbks.fsetattr != NULL) +                { +                    fop->cbks.fsetattr(fop->req_frame, fop, fop->xl, +                                       cbk->op_ret, cbk->op_errno, +                                       &cbk->iatt[0], &cbk->iatt[1], +                                       cbk->xdata); +                } +            } + +            if (cbk->op_ret >= 0) +            { +                return EC_STATE_UPDATE_SIZE_AND_VERSION; +            } +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_GET_SIZE_AND_VERSION: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.setattr != NULL) +                { +                    fop->cbks.setattr(fop->req_frame, fop, fop->xl, -1, +                                      fop->error, NULL, NULL, NULL); +                } +            } +            else +            { +                if (fop->cbks.fsetattr != NULL) +                { +                    fop->cbks.fsetattr(fop->req_frame, fop, fop->xl, -1, +                                       fop->error, NULL, NULL, NULL); +                } +            } + +            return EC_STATE_UNLOCK; + +        case EC_STATE_UPDATE_SIZE_AND_VERSION: +            ec_update_size_version(fop); + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UPDATE_SIZE_AND_VERSION: +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_setattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_setattr_cbk_t func, void * data, +                loc_t * loc, struct iatt * stbuf, int32_t valid, +                dict_t * xdata) +{ +    ec_cbk_t callback = { .setattr = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(SETATTR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_SETATTR, +                               EC_FLAG_UPDATE_LOC_INODE, target, minimum, +                               ec_wind_setattr, ec_manager_setattr, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = valid; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (stbuf != NULL) +    { +        fop->iatt = *stbuf; +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL); +    } +} + +/* FOP: fsetattr */ + +int32_t ec_fsetattr_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                        int32_t op_ret, int32_t op_errno, +                        struct iatt * preop_stbuf, struct iatt * postop_stbuf, +                        dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FSETATTR, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (preop_stbuf != NULL) +            { +                cbk->iatt[0] = *preop_stbuf; +            } +            if (postop_stbuf != NULL) +            { +                cbk->iatt[1] = *postop_stbuf; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_setattr); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_fsetattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_fsetattr_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->fsetattr, +                      fop->fd, &fop->iatt, fop->int32, fop->xdata); +} + +void ec_fsetattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_fsetattr_cbk_t func, void * data, +                 fd_t * fd, struct iatt * stbuf, int32_t valid, dict_t * xdata) +{ +    ec_cbk_t callback = { .fsetattr = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FSETATTR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FSETATTR, +                               EC_FLAG_UPDATE_FD_INODE, target, minimum, +                               ec_wind_fsetattr, ec_manager_setattr, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = valid; + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (stbuf != NULL) +    { +        fop->iatt = *stbuf; +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL); +    } +} + +/* FOP: setxattr */ + +int32_t ec_setxattr_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                        int32_t op_ret, int32_t op_errno, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_SETXATTR, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, NULL); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_setxattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_setxattr_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->setxattr, +                      &fop->loc[0], fop->dict, fop->int32, fop->xdata); +} + +int32_t ec_manager_setxattr(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +        case EC_STATE_LOCK: +            ec_lock_inode(fop, &fop->loc[0]); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.setxattr != NULL) +                { +                    fop->cbks.setxattr(fop->req_frame, fop, fop->xl, +                                       cbk->op_ret, cbk->op_errno, cbk->xdata); +                } +            } +            else +            { +                if (fop->cbks.fsetxattr != NULL) +                { +                    fop->cbks.fsetxattr(fop->req_frame, fop, fop->xl, +                                        cbk->op_ret, cbk->op_errno, +                                        cbk->xdata); +                } +            } + +            if (cbk->op_ret >= 0) +            { +                return EC_STATE_UPDATE_SIZE_AND_VERSION; +            } +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.setxattr != NULL) +                { +                    fop->cbks.setxattr(fop->req_frame, fop, fop->xl, -1, +                                       fop->error, NULL); +                } +            } +            else +            { +                if (fop->cbks.fsetxattr != NULL) +                { +                    fop->cbks.fsetxattr(fop->req_frame, fop, fop->xl, -1, +                                        fop->error, NULL); +                } +            } + +            return EC_STATE_UNLOCK; + +        case EC_STATE_UPDATE_SIZE_AND_VERSION: +            ec_update_size_version(fop); + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UPDATE_SIZE_AND_VERSION: +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_setxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_setxattr_cbk_t func, void * data, +                 loc_t * loc, dict_t * dict, int32_t flags, dict_t * xdata) +{ +    ec_cbk_t callback = { .setxattr = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(SETXATTR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_SETXATTR, +                               EC_FLAG_UPDATE_LOC_INODE, target, minimum, +                               ec_wind_setxattr, ec_manager_setxattr, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = flags; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (dict != NULL) +    { +        fop->dict = dict_ref(dict); +        if (fop->dict == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL); +    } +} + +/* FOP: fsetxattr */ + +int32_t ec_fsetxattr_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                         int32_t op_ret, int32_t op_errno, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FSETXATTR, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, NULL); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_fsetxattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_fsetxattr_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->fsetxattr, +                      fop->fd, fop->dict, fop->int32, fop->xdata); +} + +void ec_fsetxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, +                  int32_t minimum, fop_fsetxattr_cbk_t func, void * data, +                  fd_t * fd, dict_t * dict, int32_t flags, dict_t * xdata) +{ +    ec_cbk_t callback = { .fsetxattr = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FSETXATTR) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FSETXATTR, +                               EC_FLAG_UPDATE_FD_INODE, target, minimum, +                               ec_wind_fsetxattr, ec_manager_setxattr, +                               callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = flags; + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (dict != NULL) +    { +        fop->dict = dict_ref(dict); +        if (fop->dict == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL); +    } +} + +/* FOP: truncate */ + +int32_t ec_truncate_write(ec_fop_data_t * fop, uintptr_t mask) +{ +    ec_t * ec = fop->xl->private; +    struct iobref * iobref = NULL; +    struct iobuf * iobuf = NULL; +    struct iovec vector; +    int32_t ret = 0; + +    iobref = iobref_new(); +    if (iobref == NULL) +    { +        goto out; +    } +    iobuf = iobuf_get(fop->xl->ctx->iobuf_pool); +    if (iobuf == NULL) +    { +        goto out; +    } +    if (iobref_add(iobref, iobuf) != 0) +    { +        goto out; +    } + +    vector.iov_base = iobuf->ptr; +    vector.iov_len = fop->offset * ec->fragments - fop->user_size; + +    memset(iobuf->ptr, 0, vector.iov_len); + +    iobuf = NULL; + +    ec_writev(fop->frame, fop->xl, mask, fop->minimum, NULL, NULL, fop->fd, +              &vector, 1, fop->user_size, 0, iobref, NULL); + +    ret = 1; + +out: +    if (iobuf != NULL) +    { +        iobuf_unref(iobuf); +    } +    if (iobref != NULL) +    { +        iobref_unref(iobref); +    } + +    return ret; +} + +int32_t ec_truncate_open_cbk(call_frame_t * frame, void * cookie, +                             xlator_t * this, int32_t op_ret, int32_t op_errno, +                             fd_t * fd, dict_t * xdata) +{ +    ec_fop_data_t * fop = cookie; + +    if (op_ret >= 0) +    { +        if (!ec_truncate_write(fop->parent, fop->answer->mask)) +        { +            fop->error = EIO; +        } +    } + +    return 0; +} + +int32_t ec_truncate_clean(ec_fop_data_t * fop) +{ +    ec_fd_t * ctx; + +    if (fop->fd == NULL) +    { +        fop->fd = fd_create(fop->loc[0].inode, fop->frame->root->pid); +        if (fop->fd == NULL) +        { +            return 0; +        } +        ctx = ec_fd_get(fop->fd, fop->xl); +        if ((ctx == NULL) || (loc_copy(&ctx->loc, &fop->loc[0]) != 0)) +        { +            return 0; +        } + +        ctx->flags = O_RDWR; + +        ec_open(fop->frame, fop->xl, fop->answer->mask, fop->minimum, +                ec_truncate_open_cbk, fop, &fop->loc[0], O_RDWR, fop->fd, +                NULL); + +        return 1; +    } +    else +    { +        return ec_truncate_write(fop, fop->answer->mask); +    } +} + +int32_t ec_combine_truncate(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                            ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 2)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_TRUNCATE'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_truncate_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                        int32_t op_ret, int32_t op_errno, struct iatt * prebuf, +                        struct iatt * postbuf, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_TRUNCATE, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (prebuf != NULL) +            { +                cbk->iatt[0] = *prebuf; +            } +            if (postbuf != NULL) +            { +                cbk->iatt[1] = *postbuf; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_truncate); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_truncate(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_truncate_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->truncate, +                      &fop->loc[0], fop->offset, fop->xdata); +} + +int32_t ec_manager_truncate(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +            fop->user_size = fop->offset; +            fop->offset = ec_adjust_size(fop->xl->private, fop->offset, 1); + +        case EC_STATE_LOCK: +            ec_lock_inode(fop, &fop->loc[0]); + +            return EC_STATE_GET_SIZE_AND_VERSION; + +        case EC_STATE_GET_SIZE_AND_VERSION: +            ec_get_size_version(fop); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 2, +                                    cbk->count); + +                    cbk->iatt[0].ia_size = fop->pre_size; +                    cbk->iatt[1].ia_size = fop->user_size; +                    fop->post_size = fop->user_size; +                    if ((fop->pre_size > fop->post_size) && +                        (fop->user_size != fop->offset)) +                    { +                        if (!ec_truncate_clean(fop)) +                        { +                            ec_fop_set_error(fop, EIO); +                        } +                    } +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.truncate != NULL) +                { +                    fop->cbks.truncate(fop->req_frame, fop, fop->xl, +                                       cbk->op_ret, cbk->op_errno, +                                       &cbk->iatt[0], &cbk->iatt[1], +                                       cbk->xdata); +                } +            } +            else +            { +                if (fop->cbks.ftruncate != NULL) +                { +                    fop->cbks.ftruncate(fop->req_frame, fop, fop->xl, +                                        cbk->op_ret, cbk->op_errno, +                                        &cbk->iatt[0], &cbk->iatt[1], +                                        cbk->xdata); +                } +            } + +            if (cbk->op_ret >= 0) +            { +                return EC_STATE_UPDATE_SIZE_AND_VERSION; +            } +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_GET_SIZE_AND_VERSION: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.truncate != NULL) +                { +                    fop->cbks.truncate(fop->req_frame, fop, fop->xl, -1, +                                       fop->error, NULL, NULL, NULL); +                } +            } +            else +            { +                if (fop->cbks.ftruncate != NULL) +                { +                    fop->cbks.ftruncate(fop->req_frame, fop, fop->xl, -1, +                                        fop->error, NULL, NULL, NULL); +                } +            } + +            return EC_STATE_UNLOCK; + +        case EC_STATE_UPDATE_SIZE_AND_VERSION: +            ec_update_size_version(fop); + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UPDATE_SIZE_AND_VERSION: +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_truncate(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_truncate_cbk_t func, void * data, +                 loc_t * loc, off_t offset, dict_t * xdata) +{ +    ec_cbk_t callback = { .truncate = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(TRUNCATE) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_TRUNCATE, +                               EC_FLAG_UPDATE_LOC_INODE, target, minimum, +                               ec_wind_truncate, ec_manager_truncate, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->offset = offset; + +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL); +    } +} + +/* FOP: ftruncate */ + +int32_t ec_ftruncate_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                         int32_t op_ret, int32_t op_errno, +                         struct iatt * prebuf, struct iatt * postbuf, +                         dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FTRUNCATE, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (prebuf != NULL) +            { +                cbk->iatt[0] = *prebuf; +            } +            if (postbuf != NULL) +            { +                cbk->iatt[1] = *postbuf; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        ec_combine(cbk, ec_combine_truncate); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_ftruncate(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_ftruncate_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->ftruncate, +                      fop->fd, fop->offset, fop->xdata); +} + +void ec_ftruncate(call_frame_t * frame, xlator_t * this, uintptr_t target, +                  int32_t minimum, fop_ftruncate_cbk_t func, void * data, +                  fd_t * fd, off_t offset, dict_t * xdata) +{ +    ec_cbk_t callback = { .ftruncate = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FTRUNCATE) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FTRUNCATE, +                               EC_FLAG_UPDATE_FD_INODE, target, minimum, +                               ec_wind_ftruncate, ec_manager_truncate, +                               callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->offset = offset; + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL); +    } +} + +/* FOP: writev */ + +int32_t ec_writev_init(ec_fop_data_t * fop) +{ +    ec_t * ec = fop->xl->private; +    struct iobref * iobref = NULL; +    struct iobuf * iobuf = NULL; +    void * ptr = NULL; +    ec_fd_t * ctx; + +    ctx = ec_fd_get(fop->fd, fop->xl); +    if (ctx != NULL) +    { +        if ((ctx->flags & O_ACCMODE) == O_RDONLY) +        { +            return EBADF; +        } +    } + +    fop->user_size = iov_length(fop->vector, fop->int32); +    fop->head = ec_adjust_offset(ec, &fop->offset, 0); +    fop->size = ec_adjust_size(ec, fop->user_size + fop->head, 0); + +    iobref = iobref_new(); +    if (iobref == NULL) +    { +        goto out; +    } +    iobuf = iobuf_get2(fop->xl->ctx->iobuf_pool, fop->size); +    if (iobuf == NULL) +    { +        goto out; +    } +    if (iobref_add(iobref, iobuf) != 0) +    { +        goto out; +    } + +    ptr = iobuf->ptr + fop->head; +    ec_iov_copy_to(ptr, fop->vector, fop->int32, 0, fop->user_size); + +    fop->vector[0].iov_base = iobuf->ptr; +    fop->vector[0].iov_len = fop->size; + +    iobuf_unref(iobuf); + +    iobref_unref(fop->buffers); +    fop->buffers = iobref; + +    return 0; + +out: +    if (iobuf != NULL) +    { +        iobuf_unref(iobuf); +    } +    if (iobref != NULL) +    { +        iobref_unref(iobref); +    } + +    return EIO; +} + +int32_t ec_writev_merge_tail(call_frame_t * frame, void * cookie, +                             xlator_t * this, int32_t op_ret, int32_t op_errno, +                             struct iovec * vector, int32_t count, +                             struct iatt * stbuf, struct iobref * iobref, +                             dict_t * xdata) +{ +    ec_t * ec = this->private; +    ec_fop_data_t * fop = frame->local; +    size_t size, base, tmp; + +    if (op_ret >= 0) +    { +        tmp = 0; +        size = fop->size - fop->user_size - fop->head; +        base = ec->stripe_size - size; +        if (op_ret > base) +        { +            tmp = min(op_ret - base, size); +            ec_iov_copy_to(fop->vector[0].iov_base + fop->size - size, vector, +                           count, base, tmp); + +            size -= tmp; +        } + +        if (size > 0) +        { +            memset(fop->vector[0].iov_base + fop->size - size, 0, size); +        } +    } + +    return 0; +} + +int32_t ec_writev_merge_head(call_frame_t * frame, void * cookie, +                             xlator_t * this, int32_t op_ret, int32_t op_errno, +                             struct iovec * vector, int32_t count, +                             struct iatt * stbuf, struct iobref * iobref, +                             dict_t * xdata) +{ +    ec_t * ec = this->private; +    ec_fop_data_t * fop = frame->local; +    size_t size, base; + +    if (op_ret >= 0) +    { +        size = fop->head; +        base = 0; + +        if (op_ret > 0) +        { +            base = min(op_ret, size); +            ec_iov_copy_to(fop->vector[0].iov_base, vector, count, 0, base); + +            size -= base; +        } + +        if (size > 0) +        { +            memset(fop->vector[0].iov_base + base, 0, size); +        } + +        size = fop->size - fop->user_size - fop->head; +        if ((size > 0) && (fop->size == ec->stripe_size)) +        { +            ec_writev_merge_tail(frame, cookie, this, op_ret, op_errno, vector, +                                 count, stbuf, iobref, xdata); +        } +    } + +    return 0; +} + +void ec_writev_start(ec_fop_data_t * fop) +{ +    ec_t * ec = fop->xl->private; +    size_t tail; + +    if (fop->head > 0) +    { +        ec_readv(fop->frame, fop->xl, -1, EC_MINIMUM_MIN, ec_writev_merge_head, +                 NULL, fop->fd, ec->stripe_size, fop->offset, 0, NULL); +    } +    tail = fop->size - fop->user_size - fop->head; +    if ((tail > 0) && ((fop->head == 0) || (fop->size > ec->stripe_size))) +    { +        if (fop->pre_size > fop->offset + fop->head + fop->user_size) +        { +            ec_readv(fop->frame, fop->xl, -1, EC_MINIMUM_MIN, +                     ec_writev_merge_tail, NULL, fop->fd, ec->stripe_size, +                     fop->offset + fop->size - ec->stripe_size, 0, NULL); +        } +        else +        { +            memset(fop->vector[0].iov_base + fop->size - tail, 0, tail); +        } +    } +} + +int32_t ec_combine_writev(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                          ec_cbk_data_t * src) +{ +    if (!ec_iatt_combine(dst->iatt, src->iatt, 2)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " +                                             "answers of 'GF_FOP_WRITE'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_writev_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                      int32_t op_ret, int32_t op_errno, struct iatt * prebuf, +                      struct iatt * postbuf, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    ec_t * ec = this->private; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_WRITE, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        if (op_ret >= 0) +        { +            if (prebuf != NULL) +            { +                cbk->iatt[0] = *prebuf; +            } +            if (postbuf != NULL) +            { +                cbk->iatt[1] = *postbuf; +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        if ((op_ret > 0) && ((op_ret % ec->fragment_size) != 0)) +        { +            cbk->op_ret = -1; +            cbk->op_errno = EIO; +        } + +        ec_combine(cbk, ec_combine_writev); +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_writev(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    struct iovec vector[fop->int32]; +    struct iobuf_pool * pool = NULL; +    struct iobref * iobref = NULL; +    struct iobuf * iobuf = NULL; +    uint8_t * ptr = NULL; +    ssize_t size = 0, slice = 0, pagesize = 0, maxsize = 0; +    int32_t count = 0; + +    pool = fop->xl->ctx->iobuf_pool; + +    pagesize = iobpool_default_pagesize(pool); +    maxsize = pagesize * ec->fragments; + +    iobref = iobref_new(); +    if (iobref == NULL) +    { +        goto out; +    } + +    ptr = fop->vector[0].iov_base; +    size = fop->vector[0].iov_len; + +    count = 0; +    while (size > 0) +    { +        iobuf = iobuf_get(pool); +        if (iobuf == NULL) +        { +            goto out; +        } +        if (iobref_add(iobref, iobuf) != 0) +        { +            goto out; +        } + +        slice = size; +        if (slice > maxsize) +        { +            slice = maxsize; +        } + +        ec_method_encode(slice, ec->fragments, idx, ptr, iobuf->ptr); +        ptr += slice; + +        vector[count].iov_base = iobuf->ptr; +        vector[count].iov_len = slice / ec->fragments; +        count++; + +        iobuf_unref(iobuf); + +        size -= slice; +    } + +    STACK_WIND_COOKIE(fop->frame, ec_writev_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->writev, +                      fop->fd, vector, count, fop->offset / ec->fragments, +                      fop->uint32, iobref, fop->xdata); + +    iobref_unref(iobref); + +    return; + +out: +    if (iobuf != NULL) +    { +        iobuf_unref(iobuf); +    } +    if (iobref != NULL) +    { +        iobref_unref(iobref); +    } + +    ec_writev_cbk(fop->frame, (void *)(uintptr_t)idx, fop->xl, -1, EIO, NULL, +                  NULL, NULL); +} + +int32_t ec_manager_writev(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +            fop->error = ec_writev_init(fop); +            if (fop->error != 0) +            { +                return EC_STATE_REPORT; +            } + +        case EC_STATE_LOCK: +            ec_lock_fd(fop, fop->fd); + +            return EC_STATE_GET_SIZE_AND_VERSION; + +        case EC_STATE_GET_SIZE_AND_VERSION: +            ec_get_size_version(fop); + +            return EC_STATE_DISPATCH; + +        case EC_STATE_DISPATCH: +            ec_writev_start(fop); + +            return EC_STATE_WRITE_START; + +        case EC_STATE_WRITE_START: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if (cbk != NULL) +            { +                if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) +                { +                    if (cbk->op_ret >= 0) +                    { +                        cbk->op_ret = -1; +                        cbk->op_errno = EIO; +                    } +                } +                if (cbk->op_ret < 0) +                { +                    ec_fop_set_error(fop, cbk->op_errno); +                } +                else +                { +                    ec_t * ec = fop->xl->private; +                    size_t size; + +                    ec_iatt_rebuild(fop->xl->private, cbk->iatt, 2, +                                    cbk->count); + +                    size = fop->offset + fop->head + fop->user_size; +                    if (size > fop->pre_size) +                    { +                        fop->post_size = size; +                    } + +                    cbk->iatt[0].ia_size = fop->pre_size; +                    cbk->iatt[1].ia_size = fop->post_size; + +                    cbk->op_ret *= ec->fragments; +                    if (cbk->op_ret < fop->head) +                    { +                        cbk->op_ret = 0; +                    } +                    else +                    { +                        cbk->op_ret -= fop->head; +                    } +                    if (cbk->op_ret > fop->user_size) +                    { +                        cbk->op_ret = fop->user_size; +                    } +                } +            } +            else +            { +                ec_fop_set_error(fop, EIO); +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.writev != NULL) +            { +                fop->cbks.writev(fop->req_frame, fop, fop->xl, cbk->op_ret, +                                 cbk->op_errno, &cbk->iatt[0], &cbk->iatt[1], +                                 cbk->xdata); +            } + +            if (cbk->op_ret >= 0) +            { +                return EC_STATE_UPDATE_SIZE_AND_VERSION; +            } +            return EC_STATE_UNLOCK; + +        case -EC_STATE_LOCK: +        case -EC_STATE_GET_SIZE_AND_VERSION: +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.writev != NULL) +            { +                fop->cbks.writev(fop->req_frame, fop, fop->xl, -1, fop->error, +                                 NULL, NULL, NULL); +            } + +            return EC_STATE_UNLOCK; + +        case EC_STATE_UPDATE_SIZE_AND_VERSION: +            ec_update_size_version(fop); + +            return EC_STATE_UNLOCK; + +        case -EC_STATE_UPDATE_SIZE_AND_VERSION: +        case -EC_STATE_UNLOCK: +        case EC_STATE_UNLOCK: +            ec_unlock(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_writev(call_frame_t * frame, xlator_t * this, uintptr_t target, +               int32_t minimum, fop_writev_cbk_t func, void * data, fd_t * fd, +               struct iovec * vector, int32_t count, off_t offset, +               uint32_t flags, struct iobref * iobref, dict_t * xdata) +{ +    ec_cbk_t callback = { .writev = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(WRITE) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_WRITE, +                               EC_FLAG_UPDATE_FD_INODE, target, minimum, +                               ec_wind_writev, ec_manager_writev, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = count; +    fop->offset = offset; +    fop->uint32 = flags; + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (count > 0) +    { +        fop->vector = iov_dup(vector, count); +        if (fop->vector == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a " +                                             "vector list."); + +            goto out; +        } +        fop->int32 = count; +    } +    if (iobref != NULL) +    { +        fop->buffers = iobref_ref(iobref); +        if (fop->buffers == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "buffer."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL, NULL); +    } +} diff --git a/xlators/cluster/ec/src/ec-locks.c b/xlators/cluster/ec/src/ec-locks.c new file mode 100644 index 00000000000..96c1e03f8ec --- /dev/null +++ b/xlators/cluster/ec/src/ec-locks.c @@ -0,0 +1,1292 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "xlator.h" +#include "defaults.h" + +#include "ec-helpers.h" +#include "ec-common.h" +#include "ec-combine.h" +#include "ec-method.h" +#include "ec-fops.h" + +#define EC_LOCK_MODE_NONE 0 +#define EC_LOCK_MODE_INC  1 +#define EC_LOCK_MODE_ALL  2 + +int32_t ec_lock_check(ec_fop_data_t * fop, ec_cbk_data_t ** cbk, +                      uintptr_t * mask) +{ +    ec_t * ec = fop->xl->private; +    ec_cbk_data_t * ans = NULL; +    uintptr_t locked = 0, notlocked = 0; +    int32_t error = -1; + +    list_for_each_entry(ans, &fop->cbk_list, list) +    { +        if (ans->op_ret >= 0) +        { +            if (locked != 0) +            { +                error = EIO; +            } +            locked |= ans->mask; +            *cbk = ans; +        } +        else if (ans->op_errno == EAGAIN) +        { +            notlocked |= ans->mask; +        } +    } + +    if (error == -1) +    { +        if (ec_bits_count(locked | notlocked) >= ec->fragments) +        { +            if (notlocked == 0) +            { +                fop->answer = *cbk; + +                ec_update_bad(fop, locked); + +                error = 0; +            } +            else +            { +                if (fop->uint32 == EC_LOCK_MODE_NONE) +                { +                    error = EAGAIN; +                } +                else +                { +                    fop->uint32 = EC_LOCK_MODE_INC; +                } +            } +        } +        else +        { +            error = EIO; +        } +    } + +    *mask = locked; + +    return error; +} + +uintptr_t ec_lock_handler(ec_fop_data_t * fop, ec_cbk_data_t * cbk, +                          ec_combine_f combine) +{ +    uintptr_t mask = 0; + +    if (fop->uint32 == EC_LOCK_MODE_INC) +    { +        if (cbk->op_ret < 0) +        { +            if (cbk->op_errno != ENOTCONN) +            { +                mask = fop->mask & ~fop->remaining & ~cbk->mask; +                fop->remaining = 0; +            } +        } +    } + +    ec_combine(cbk, combine); + +    return mask; +} + +int32_t ec_lock_unlocked(call_frame_t * frame, void * cookie, +                         xlator_t * this, int32_t op_ret, int32_t op_errno, +                         dict_t * xdata) +{ +    if (op_ret < 0) +    { +        gf_log(this->name, GF_LOG_WARNING, "Failed to unlock an entry/inode"); +    } + +    return 0; +} + +int32_t ec_lock_lk_unlocked(call_frame_t * frame, void * cookie, +                            xlator_t * this, int32_t op_ret, int32_t op_errno, +                            struct gf_flock * flock, dict_t * xdata) +{ +    if (op_ret < 0) +    { +        gf_log(this->name, GF_LOG_WARNING, "Failed to unlock an lk"); +    } + +    return 0; +} + +/* FOP: entrylk */ + +int32_t ec_entrylk_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                       int32_t op_ret, int32_t op_errno, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_ENTRYLK, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        uintptr_t mask; + +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        mask = ec_lock_handler(fop, cbk, NULL); +        if (mask != 0) +        { +            ec_entrylk(fop->req_frame, fop->xl, mask, 1, ec_lock_unlocked, +                       NULL, fop->str[0], &fop->loc[0], fop->str[1], +                       ENTRYLK_UNLOCK, fop->entrylk_type, fop->xdata); +        } +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_entrylk(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_entrylk_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->entrylk, +                      fop->str[0], &fop->loc[0], fop->str[1], fop->entrylk_cmd, +                      fop->entrylk_type, fop->xdata); +} + +int32_t ec_manager_entrylk(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +            if (fop->entrylk_cmd == ENTRYLK_LOCK) +            { +                fop->uint32 = EC_LOCK_MODE_ALL; +                fop->entrylk_cmd = ENTRYLK_LOCK_NB; +            } + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if ((cbk == NULL) || +                ((cbk->op_ret < 0) && (cbk->op_errno == EAGAIN))) +            { +                uintptr_t mask; + +                fop->error = ec_lock_check(fop, &cbk, &mask); +                if (fop->error != 0) +                { +                    if (mask != 0) +                    { +                        if (fop->fd == NULL) +                        { +                            ec_entrylk(fop->req_frame, fop->xl, mask, 1, +                                       ec_lock_unlocked, NULL, fop->str[0], +                                       &fop->loc[0], fop->str[1], +                                       ENTRYLK_UNLOCK, fop->entrylk_type, +                                       fop->xdata); +                        } +                        else +                        { +                            ec_fentrylk(fop->req_frame, fop->xl, mask, 1, +                                        ec_lock_unlocked, NULL, fop->str[0], +                                        fop->fd, fop->str[1], ENTRYLK_UNLOCK, +                                        fop->entrylk_type, fop->xdata); +                        } +                    } +                    if (fop->error > 0) +                    { +                        return EC_STATE_REPORT; +                    } + +                    fop->error = 0; + +                    fop->entrylk_cmd = ENTRYLK_LOCK; + +                    ec_dispatch_inc(fop); + +                    return EC_STATE_PREPARE_ANSWER; +                } +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.entrylk != NULL) +                { +                    fop->cbks.entrylk(fop->req_frame, fop, fop->xl, +                                      cbk->op_ret, cbk->op_errno, cbk->xdata); +                } +            } +            else +            { +                if (fop->cbks.fentrylk != NULL) +                { +                    fop->cbks.fentrylk(fop->req_frame, fop, fop->xl, +                                       cbk->op_ret, cbk->op_errno, cbk->xdata); +                } +            } + +            ec_wait_winds(fop); + +            return EC_STATE_END; + +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.entrylk != NULL) +                { +                    fop->cbks.entrylk(fop->req_frame, fop, fop->xl, -1, +                                      fop->error, NULL); +                } +            } +            else +            { +                if (fop->cbks.fentrylk != NULL) +                { +                    fop->cbks.fentrylk(fop->req_frame, fop, fop->xl, -1, +                                       fop->error, NULL); +                } +            } + +            ec_wait_winds(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_entrylk(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_entrylk_cbk_t func, void * data, +                const char * volume, loc_t * loc, const char * basename, +                entrylk_cmd cmd, entrylk_type type, dict_t * xdata) +{ +    ec_cbk_t callback = { .entrylk = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(ENTRYLK) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_ENTRYLK, +                               EC_FLAG_UPDATE_LOC_INODE, target, minimum, +                               ec_wind_entrylk, ec_manager_entrylk, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->entrylk_cmd = cmd; +    fop->entrylk_type = type; + +    if (volume != NULL) +    { +        fop->str[0] = gf_strdup(volume); +        if (fop->str[0] == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a string."); + +            goto out; +        } +    } +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (basename != NULL) +    { +        fop->str[1] = gf_strdup(basename); +        if (fop->str[1] == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a string."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL); +    } +} + +/* FOP: fentrylk */ + +int32_t ec_fentrylk_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                        int32_t op_ret, int32_t op_errno, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FENTRYLK, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        uintptr_t mask; + +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        mask = ec_lock_handler(fop, cbk, NULL); +        if (mask != 0) +        { +            ec_fentrylk(fop->req_frame, fop->xl, mask, 1, ec_lock_unlocked, +                        NULL, fop->str[0], fop->fd, fop->str[1], +                        ENTRYLK_UNLOCK, fop->entrylk_type, fop->xdata); +        } +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_fentrylk(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_fentrylk_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->fentrylk, +                      fop->str[0], fop->fd, fop->str[1], fop->entrylk_cmd, +                      fop->entrylk_type, fop->xdata); +} + +void ec_fentrylk(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_fentrylk_cbk_t func, void * data, +                 const char * volume, fd_t * fd, const char * basename, +                 entrylk_cmd cmd, entrylk_type type, dict_t * xdata) +{ +    ec_cbk_t callback = { .fentrylk = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FENTRYLK) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FENTRYLK, +                               EC_FLAG_UPDATE_FD_INODE, target, minimum, +                               ec_wind_fentrylk, ec_manager_entrylk, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->entrylk_cmd = cmd; +    fop->entrylk_type = type; + +    if (volume != NULL) +    { +        fop->str[0] = gf_strdup(volume); +        if (fop->str[0] == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a string."); + +            goto out; +        } +    } +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (basename != NULL) +    { +        fop->str[1] = gf_strdup(basename); +        if (fop->str[1] == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a string."); + +            goto out; +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL); +    } +} + +/* FOP: inodelk */ + +int32_t ec_inodelk_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                       int32_t op_ret, int32_t op_errno, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_INODELK, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        uintptr_t mask; + +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        mask = ec_lock_handler(fop, cbk, NULL); +        if (mask != 0) +        { +            ec_t * ec = fop->xl->private; +            struct gf_flock flock; + +            flock.l_type = F_UNLCK; +            flock.l_whence = fop->flock.l_whence; +            flock.l_start = fop->flock.l_start * ec->fragments; +            flock.l_len = fop->flock.l_len * ec->fragments; +            flock.l_pid = 0; +            flock.l_owner.len = 0; + +            ec_inodelk(fop->req_frame, fop->xl, mask, 1, ec_lock_unlocked, +                       NULL, fop->str[0], &fop->loc[0], F_SETLK, &flock, +                       fop->xdata); +        } +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_inodelk(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_inodelk_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->inodelk, +                      fop->str[0], &fop->loc[0], fop->int32, &fop->flock, +                      fop->xdata); +} + +int32_t ec_manager_inodelk(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +            fop->flock.l_len += ec_adjust_offset(fop->xl->private, +                                                 &fop->flock.l_start, 1); +            fop->flock.l_len = ec_adjust_size(fop->xl->private, +                                              fop->flock.l_len, 1); +            if ((fop->int32 == F_SETLKW) && (fop->flock.l_type != F_UNLCK)) +            { +                fop->uint32 = EC_LOCK_MODE_ALL; +                fop->int32 = F_SETLK; +            } + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if ((cbk == NULL) || +                ((cbk->op_ret < 0) && (cbk->op_errno == EAGAIN))) +            { +                uintptr_t mask; + +                fop->error = ec_lock_check(fop, &cbk, &mask); +                if (fop->error != 0) +                { +                    if (mask != 0) +                    { +                        ec_t * ec = fop->xl->private; +                        struct gf_flock flock; + +                        flock.l_type = F_UNLCK; +                        flock.l_whence = fop->flock.l_whence; +                        flock.l_start = fop->flock.l_start * ec->fragments; +                        flock.l_len = fop->flock.l_len * ec->fragments; +                        flock.l_pid = 0; +                        flock.l_owner.len = 0; + +                        if (fop->fd == NULL) +                        { +                            ec_inodelk(fop->req_frame, fop->xl, mask, 1, +                                       ec_lock_unlocked, NULL, fop->str[0], +                                       &fop->loc[0], F_SETLK, &flock, +                                       fop->xdata); +                        } +                        else +                        { +                            ec_finodelk(fop->req_frame, fop->xl, mask, 1, +                                        ec_lock_unlocked, NULL, fop->str[0], +                                        fop->fd, F_SETLK, &flock, fop->xdata); +                        } +                    } +                    if (fop->error > 0) +                    { +                        return EC_STATE_REPORT; +                    } + +                    fop->error = 0; + +                    fop->int32 = F_SETLKW; + +                    ec_dispatch_inc(fop); + +                    return EC_STATE_PREPARE_ANSWER; +                } +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.inodelk != NULL) +                { +                    fop->cbks.inodelk(fop->req_frame, fop, fop->xl, +                                      cbk->op_ret, cbk->op_errno, cbk->xdata); +                } +            } +            else +            { +                if (fop->cbks.finodelk != NULL) +                { +                    fop->cbks.finodelk(fop->req_frame, fop, fop->xl, +                                       cbk->op_ret, cbk->op_errno, cbk->xdata); +                } +            } + +            ec_wait_winds(fop); + +            return EC_STATE_END; + +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->fd == NULL) +            { +                if (fop->cbks.inodelk != NULL) +                { +                    fop->cbks.inodelk(fop->req_frame, fop, fop->xl, -1, +                                      fop->error, NULL); +                } +            } +            else +            { +                if (fop->cbks.finodelk != NULL) +                { +                    fop->cbks.finodelk(fop->req_frame, fop, fop->xl, -1, +                                       fop->error, NULL); +                } +            } + +            ec_wait_winds(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_inodelk(call_frame_t * frame, xlator_t * this, uintptr_t target, +                int32_t minimum, fop_inodelk_cbk_t func, void * data, +                const char * volume, loc_t * loc, int32_t cmd, +                struct gf_flock * flock, dict_t * xdata) +{ +    ec_cbk_t callback = { .inodelk = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(INODELK) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_INODELK, +                               EC_FLAG_UPDATE_LOC_INODE, target, minimum, +                               ec_wind_inodelk, ec_manager_inodelk, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = cmd; + +    if (volume != NULL) +    { +        fop->str[0] = gf_strdup(volume); +        if (fop->str[0] == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a string."); + +            goto out; +        } +    } +    if (loc != NULL) +    { +        if (loc_copy(&fop->loc[0], loc) != 0) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to copy a location."); + +            goto out; +        } +    } +    if (flock != NULL) +    { +        fop->flock.l_type = flock->l_type; +        fop->flock.l_whence = flock->l_whence; +        fop->flock.l_start = flock->l_start; +        fop->flock.l_len = flock->l_len; +        fop->flock.l_pid = flock->l_pid; +        fop->flock.l_owner.len = flock->l_owner.len; +        if (flock->l_owner.len > 0) +        { +            memcpy(fop->flock.l_owner.data, flock->l_owner.data, +                   flock->l_owner.len); +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL); +    } +} + +/* FOP: finodelk */ + +int32_t ec_finodelk_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                        int32_t op_ret, int32_t op_errno, dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FINODELK, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        uintptr_t mask; + +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        mask = ec_lock_handler(fop, cbk, NULL); +        if (mask != 0) +        { +            ec_t * ec = fop->xl->private; +            struct gf_flock flock; + +            flock.l_type = F_UNLCK; +            flock.l_whence = fop->flock.l_whence; +            flock.l_start = fop->flock.l_start * ec->fragments; +            flock.l_len = fop->flock.l_len * ec->fragments; +            flock.l_pid = 0; +            flock.l_owner.len = 0; + +            ec_finodelk(fop->req_frame, fop->xl, mask, 1, ec_lock_unlocked, +                        NULL, fop->str[0], fop->fd, F_SETLK, &flock, +                        fop->xdata); +        } +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_finodelk(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_finodelk_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->finodelk, +                      fop->str[0], fop->fd, fop->int32, &fop->flock, +                      fop->xdata); +} + +void ec_finodelk(call_frame_t * frame, xlator_t * this, uintptr_t target, +                 int32_t minimum, fop_finodelk_cbk_t func, void * data, +                 const char * volume, fd_t * fd, int32_t cmd, +                 struct gf_flock * flock, dict_t * xdata) +{ +    ec_cbk_t callback = { .finodelk = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(FINODELK) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_FINODELK, +                               EC_FLAG_UPDATE_FD_INODE, target, minimum, +                               ec_wind_finodelk, ec_manager_inodelk, callback, +                               data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = cmd; + +    if (volume != NULL) +    { +        fop->str[0] = gf_strdup(volume); +        if (fop->str[0] == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to duplicate a string."); + +            goto out; +        } +    } +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (flock != NULL) +    { +        fop->flock.l_type = flock->l_type; +        fop->flock.l_whence = flock->l_whence; +        fop->flock.l_start = flock->l_start; +        fop->flock.l_len = flock->l_len; +        fop->flock.l_pid = flock->l_pid; +        fop->flock.l_owner.len = flock->l_owner.len; +        if (flock->l_owner.len > 0) +        { +            memcpy(fop->flock.l_owner.data, flock->l_owner.data, +                   flock->l_owner.len); +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL); +    } +} + +/* FOP: lk */ + +int32_t ec_combine_lk(ec_fop_data_t * fop, ec_cbk_data_t * dst, +                      ec_cbk_data_t * src) +{ +    if (!ec_flock_compare(&dst->flock, &src->flock)) +    { +        gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching lock in " +                                             "answers of 'GF_FOP_LK'"); + +        return 0; +    } + +    return 1; +} + +int32_t ec_lk_cbk(call_frame_t * frame, void * cookie, xlator_t * this, +                  int32_t op_ret, int32_t op_errno, struct gf_flock * flock, +                  dict_t * xdata) +{ +    ec_fop_data_t * fop = NULL; +    ec_cbk_data_t * cbk = NULL; +    int32_t idx = (int32_t)(uintptr_t)cookie; + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, frame->local, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = frame->local; + +    ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, +             frame, op_ret, op_errno); + +    cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_LK, idx, op_ret, +                               op_errno); +    if (cbk != NULL) +    { +        uintptr_t mask; + +        if (op_ret >= 0) +        { +            if (flock != NULL) +            { +                cbk->flock.l_type = flock->l_type; +                cbk->flock.l_whence = flock->l_whence; +                cbk->flock.l_start = flock->l_start; +                cbk->flock.l_len = flock->l_len; +                cbk->flock.l_pid = flock->l_pid; +                cbk->flock.l_owner.len = flock->l_owner.len; +                if (flock->l_owner.len > 0) +                { +                    memcpy(cbk->flock.l_owner.data, flock->l_owner.data, +                           flock->l_owner.len); +                } +            } +        } +        if (xdata != NULL) +        { +            cbk->xdata = dict_ref(xdata); +            if (cbk->xdata == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                                 "dictionary."); + +                goto out; +            } +        } + +        mask = ec_lock_handler(fop, cbk, ec_combine_lk); +        if (mask != 0) +        { +            ec_t * ec = fop->xl->private; +            struct gf_flock flock; + +            flock.l_type = F_UNLCK; +            flock.l_whence = fop->flock.l_whence; +            flock.l_start = fop->flock.l_start * ec->fragments; +            flock.l_len = fop->flock.l_len * ec->fragments; +            flock.l_pid = 0; +            flock.l_owner.len = 0; + +            ec_lk(fop->req_frame, fop->xl, mask, 1, ec_lock_lk_unlocked, NULL, +                  fop->fd, F_SETLK, &flock, fop->xdata); +        } +    } + +out: +    if (fop != NULL) +    { +        ec_complete(fop); +    } + +    return 0; +} + +void ec_wind_lk(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +{ +    ec_trace("WIND", fop, "idx=%d", idx); + +    STACK_WIND_COOKIE(fop->frame, ec_lk_cbk, (void *)(uintptr_t)idx, +                      ec->xl_list[idx], ec->xl_list[idx]->fops->lk, fop->fd, +                      fop->int32, &fop->flock, fop->xdata); +} + +int32_t ec_manager_lk(ec_fop_data_t * fop, int32_t state) +{ +    ec_cbk_data_t * cbk; + +    switch (state) +    { +        case EC_STATE_INIT: +            fop->flock.l_len += ec_adjust_offset(fop->xl->private, +                                                 &fop->flock.l_start, 1); +            fop->flock.l_len = ec_adjust_size(fop->xl->private, +                                              fop->flock.l_len, 1); +            if ((fop->int32 == F_SETLKW) && (fop->flock.l_type != F_UNLCK)) +            { +                fop->uint32 = EC_LOCK_MODE_ALL; +                fop->int32 = F_SETLK; +            } + +        case EC_STATE_DISPATCH: +            ec_dispatch_all(fop); + +            return EC_STATE_PREPARE_ANSWER; + +        case EC_STATE_PREPARE_ANSWER: +            cbk = fop->answer; +            if ((cbk == NULL) || +                ((cbk->op_ret < 0) && (cbk->op_errno == EAGAIN))) +            { +                uintptr_t mask; + +                fop->error = ec_lock_check(fop, &cbk, &mask); +                if (fop->error != 0) +                { +                    if (mask != 0) +                    { +                        ec_t * ec = fop->xl->private; +                        struct gf_flock flock; + +                        flock.l_type = F_UNLCK; +                        flock.l_whence = fop->flock.l_whence; +                        flock.l_start = fop->flock.l_start * ec->fragments; +                        flock.l_len = fop->flock.l_len * ec->fragments; +                        flock.l_pid = 0; +                        flock.l_owner.len = 0; + +                        ec_lk(fop->req_frame, fop->xl, mask, 1, +                              ec_lock_lk_unlocked, NULL, fop->fd, F_SETLK, +                              &flock, fop->xdata); +                    } +                    if (fop->error > 0) +                    { +                        return EC_STATE_REPORT; +                    } + +                    fop->error = 0; + +                    fop->int32 = F_SETLKW; + +                    ec_dispatch_inc(fop); + +                    return EC_STATE_PREPARE_ANSWER; +                } +            } + +            return EC_STATE_REPORT; + +        case EC_STATE_REPORT: +            cbk = fop->answer; + +            GF_ASSERT(cbk != NULL); + +            if (fop->cbks.lk != NULL) +            { +                fop->cbks.lk(fop->req_frame, fop, fop->xl, cbk->op_ret, +                             cbk->op_errno, &cbk->flock, cbk->xdata); +            } + +            ec_wait_winds(fop); + +            return EC_STATE_END; + +        case -EC_STATE_DISPATCH: +        case -EC_STATE_PREPARE_ANSWER: +        case -EC_STATE_REPORT: +            GF_ASSERT(fop->error != 0); + +            if (fop->cbks.lk != NULL) +            { +                fop->cbks.lk(fop->req_frame, fop, fop->xl, -1, fop->error, +                             NULL, NULL); +            } + +            ec_wait_winds(fop); + +            return EC_STATE_END; + +        default: +            gf_log(fop->xl->name, GF_LOG_ERROR, "Unhandled state %d for %s", +                   state, ec_fop_name(fop->id)); + +            return EC_STATE_END; +    } +} + +void ec_lk(call_frame_t * frame, xlator_t * this, uintptr_t target, +           int32_t minimum, fop_lk_cbk_t func, void * data, fd_t * fd, +           int32_t cmd, struct gf_flock * flock, dict_t * xdata) +{ +    ec_cbk_t callback = { .lk = func }; +    ec_fop_data_t * fop = NULL; +    int32_t error = EIO; + +    gf_log("ec", GF_LOG_TRACE, "EC(LK) %p", frame); + +    VALIDATE_OR_GOTO(this, out); +    GF_VALIDATE_OR_GOTO(this->name, frame, out); +    GF_VALIDATE_OR_GOTO(this->name, this->private, out); + +    fop = ec_fop_data_allocate(frame, this, GF_FOP_LK, EC_FLAG_UPDATE_FD_INODE, +                               target, minimum, ec_wind_lk, ec_manager_lk, +                               callback, data); +    if (fop == NULL) +    { +        goto out; +    } + +    fop->int32 = cmd; + +    if (fd != NULL) +    { +        fop->fd = fd_ref(fd); +        if (fop->fd == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "file descriptor."); + +            goto out; +        } +    } +    if (flock != NULL) +    { +        fop->flock.l_type = flock->l_type; +        fop->flock.l_whence = flock->l_whence; +        fop->flock.l_start = flock->l_start; +        fop->flock.l_len = flock->l_len; +        fop->flock.l_pid = flock->l_pid; +        fop->flock.l_owner.len = flock->l_owner.len; +        if (flock->l_owner.len > 0) +        { +            memcpy(fop->flock.l_owner.data, flock->l_owner.data, +                   flock->l_owner.len); +        } +    } +    if (xdata != NULL) +    { +        fop->xdata = dict_ref(xdata); +        if (fop->xdata == NULL) +        { +            gf_log(this->name, GF_LOG_ERROR, "Failed to reference a " +                                             "dictionary."); + +            goto out; +        } +    } + +    error = 0; + +out: +    if (fop != NULL) +    { +        ec_manager(fop, error); +    } +    else +    { +        func(frame, NULL, this, -1, EIO, NULL, NULL); +    } +} diff --git a/xlators/cluster/ec/src/ec-mem-types.h b/xlators/cluster/ec/src/ec-mem-types.h new file mode 100644 index 00000000000..f312d1e333f --- /dev/null +++ b/xlators/cluster/ec/src/ec-mem-types.h @@ -0,0 +1,39 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef __EC_MEM_TYPES_H__ +#define __EC_MEM_TYPES_H__ + +#include "mem-types.h" + +enum gf_ec_mem_types_ +{ +    ec_mt_ec_t = gf_common_mt_end + 1, +    ec_mt_xlator_t, +    ec_mt_ec_fop_data_t, +    ec_mt_ec_cbk_data_t, +    ec_mt_ec_inode_t, +    ec_mt_ec_fd_t, +    ec_mt_ec_lock_t, +    ec_mt_ec_heal_t, +    ec_mt_end +}; + +#endif /* __EC_MEM_TYPES_H__ */ diff --git a/xlators/cluster/ec/src/ec-method.c b/xlators/cluster/ec/src/ec-method.c new file mode 100644 index 00000000000..deedf2a21f2 --- /dev/null +++ b/xlators/cluster/ec/src/ec-method.c @@ -0,0 +1,182 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include <string.h> +#include <inttypes.h> + +#include "ec-method.h" + +#define EC_METHOD_WORD_SIZE 16 + +static uint32_t GfPow[EC_METHOD_SIZE << 1]; +static uint32_t GfLog[EC_METHOD_SIZE << 1]; + +void ec_method_initialize(void) +{ +    uint32_t i; + +    GfPow[0] = 1; +    GfLog[0] = EC_METHOD_SIZE; +    for (i = 1; i < EC_METHOD_SIZE; i++) +    { +        GfPow[i] = GfPow[i - 1] << 1; +        if (GfPow[i] >= EC_METHOD_SIZE) +        { +            GfPow[i] ^= EC_GF_MOD; +        } +        GfPow[i + EC_METHOD_SIZE - 1] = GfPow[i]; +        GfLog[GfPow[i] + EC_METHOD_SIZE - 1] = GfLog[GfPow[i]] = i; +    } +} + +static uint32_t ec_method_mul(uint32_t a, uint32_t b) +{ +    if (a && b) +    { +        return GfPow[GfLog[a] + GfLog[b]]; +    } +    return 0; +} + +static uint32_t ec_method_div(uint32_t a, uint32_t b) +{ +    if (b) +    { +        if (a) +        { +            return GfPow[EC_METHOD_SIZE - 1 + GfLog[a] - GfLog[b]]; +        } +        return 0; +    } +    return EC_METHOD_SIZE; +} + +size_t ec_method_encode(size_t size, uint32_t columns, uint32_t row, +                        uint8_t * in, uint8_t * out) +{ +    uint32_t i, j; + +    size /= EC_METHOD_CHUNK_SIZE * columns; +    row++; +    for (j = 0; j < size; j++) +    { +        ec_gf_load(in); +        in += EC_METHOD_CHUNK_SIZE; +        for (i = 1; i < columns; i++) +        { +            ec_gf_mul_table[row](); +            ec_gf_xor(in); +            in += EC_METHOD_CHUNK_SIZE; +        } +        ec_gf_store(out); +        out += EC_METHOD_CHUNK_SIZE; +    } + +    return size * EC_METHOD_CHUNK_SIZE; +} + +size_t ec_method_decode(size_t size, uint32_t columns, uint32_t * rows, +                        uint8_t ** in, uint8_t * out) +{ +    uint32_t i, j, k; +    uint32_t f, off, mask; +    uint8_t inv[EC_METHOD_MAX_FRAGMENTS][EC_METHOD_MAX_FRAGMENTS + 1]; +    uint8_t mtx[EC_METHOD_MAX_FRAGMENTS][EC_METHOD_MAX_FRAGMENTS]; +    uint8_t * p[EC_METHOD_MAX_FRAGMENTS]; + +    size /= EC_METHOD_CHUNK_SIZE; + +    memset(inv, 0, sizeof(inv)); +    memset(mtx, 0, sizeof(mtx)); +    mask = 0; +    for (i = 0; i < columns; i++) +    { +        inv[i][i] = 1; +        inv[i][columns] = 1; +    } +    k = 0; +    for (i = 0; i < columns; i++) +    { +        while ((mask & 1) != 0) +        { +            k++; +            mask >>= 1; +        } +        mtx[k][columns - 1] = 1; +        for (j = columns - 1; j > 0; j--) +        { +            mtx[k][j - 1] = ec_method_mul(mtx[k][j], rows[i] + 1); +        } +        p[k] = in[i]; +        k++; +        mask >>= 1; +    } + +    for (i = 0; i < columns; i++) +    { +        f = mtx[i][i]; +        for (j = 0; j < columns; j++) +        { +            mtx[i][j] = ec_method_div(mtx[i][j], f); +            inv[i][j] = ec_method_div(inv[i][j], f); +        } +        for (j = 0; j < columns; j++) +        { +            if (i != j) +            { +                f = mtx[j][i]; +                for (k = 0; k < columns; k++) +                { +                    mtx[j][k] ^= ec_method_mul(mtx[i][k], f); +                    inv[j][k] ^= ec_method_mul(inv[i][k], f); +                } +            } +        } +    } +    off = 0; +    for (f = 0; f < size; f++) +    { +        for (i = 0; i < columns; i++) +        { +            ec_gf_load(p[0] + off); +            j = 0; +            while (j < columns) +            { +                k = j + 1; +                while (inv[i][k] == 0) +                { +                    k++; +                } +                ec_gf_mul_table[ec_method_div(inv[i][j], inv[i][k])](); +                if (k < columns) +                { +                    ec_gf_xor(p[k] + off); +                } +                j = k; +            } +            ec_gf_store(out); +            out += EC_METHOD_CHUNK_SIZE; +            in[i] += EC_METHOD_CHUNK_SIZE; +        } +        off += EC_METHOD_CHUNK_SIZE; +    } + +    return size * EC_METHOD_CHUNK_SIZE * columns; +} diff --git a/xlators/cluster/ec/src/ec-method.h b/xlators/cluster/ec/src/ec-method.h new file mode 100644 index 00000000000..64e724ff3f0 --- /dev/null +++ b/xlators/cluster/ec/src/ec-method.h @@ -0,0 +1,42 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef __EC_METHOD_H__ +#define __EC_METHOD_H__ + +#include "ec-gf.h" + +#define EC_METHOD_MAX_FRAGMENTS 16 + +#define EC_METHOD_WORD_SIZE 16 + +#define EC_BUFFER_ALIGN_SIZE EC_METHOD_WORD_SIZE + +#define EC_METHOD_BITS EC_GF_BITS +#define EC_METHOD_SIZE (1 << (EC_METHOD_BITS)) +#define EC_METHOD_CHUNK_SIZE (EC_METHOD_WORD_SIZE * EC_METHOD_BITS) + +void ec_method_initialize(void); +size_t ec_method_encode(size_t size, uint32_t columns, uint32_t row, +                        uint8_t * in, uint8_t * out); +size_t ec_method_decode(size_t size, uint32_t columns, uint32_t * rows, +                        uint8_t ** in, uint8_t * out); + +#endif /* __EC_METHOD_H__ */ diff --git a/xlators/cluster/ec/src/ec.c b/xlators/cluster/ec/src/ec.c new file mode 100644 index 00000000000..3290df55732 --- /dev/null +++ b/xlators/cluster/ec/src/ec.c @@ -0,0 +1,904 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "defaults.h" + +#include "ec-mem-types.h" +#include "ec-common.h" +#include "ec-fops.h" +#include "ec-method.h" +#include "ec.h" + +#define EC_MAX_FRAGMENTS EC_METHOD_MAX_FRAGMENTS +/* The maximum number of nodes is derived from the maximum allowed fragments + * using the rule that redundancy cannot be equal or greater than the number + * of fragments. + */ +#define EC_MAX_NODES     (EC_MAX_FRAGMENTS + ((EC_MAX_FRAGMENTS - 1) / 2)) + +int32_t ec_parse_options(xlator_t * this) +{ +    ec_t * ec = this->private; +    int32_t error = EINVAL; +    uintptr_t mask; + +    GF_OPTION_INIT("redundancy", ec->redundancy, int32, out); +    ec->fragments = ec->nodes - ec->redundancy; +    if ((ec->redundancy < 1) || (ec->redundancy >= ec->fragments) || +        (ec->fragments > EC_MAX_FRAGMENTS)) +    { +        gf_log(this->name, GF_LOG_ERROR, "Invalid redundancy (must be between " +                                         "1 and %d)", (ec->nodes - 1) / 2); + +        goto out; +    } + +    ec->bits_for_nodes = 1; +    mask = 2; +    while (ec->nodes > mask) +    { +        ec->bits_for_nodes++; +        mask <<= 1; +    } +    ec->node_mask = (1ULL << ec->nodes) - 1ULL; +    ec->fragment_size = EC_METHOD_CHUNK_SIZE; +    ec->stripe_size = ec->fragment_size * ec->fragments; + +    gf_log("ec", GF_LOG_DEBUG, "Initialized with: nodes=%u, fragments=%u, " +                               "stripe_size=%u, node_mask=%lX", +           ec->nodes, ec->fragments, ec->stripe_size, ec->node_mask); + +    error = 0; + +out: +    return error; +} + +int32_t ec_prepare_childs(xlator_t * this) +{ +    ec_t * ec = this->private; +    xlator_list_t * child = NULL; +    int32_t count = 0; + +    for (child = this->children; child != NULL; child = child->next) +    { +        count++; +    } +    if (count > EC_MAX_NODES) +    { +        gf_log(this->name, GF_LOG_ERROR, "Too many subvolumes"); + +        return EINVAL; +    } +    ec->nodes = count; + +    ec->xl_list = GF_CALLOC(count, sizeof(ec->xl_list[0]), ec_mt_xlator_t); +    if (ec->xl_list == NULL) +    { +        gf_log(this->name, GF_LOG_ERROR, "Allocation of xlator list failed"); + +        return ENOMEM; +    } +    ec->xl_up = 0; +    ec->xl_up_count = 0; + +    count = 0; +    for (child = this->children; child != NULL; child = child->next) +    { +        ec->xl_list[count++] = child->xlator; +    } + +    return 0; +} + +void __ec_destroy_private(xlator_t * this) +{ +    ec_t * ec = this->private; + +    if (ec != NULL) +    { +        LOCK(&ec->lock); + +        if (ec->timer != NULL) +        { +            gf_timer_call_cancel(this->ctx, ec->timer); +            ec->timer = NULL; +        } + +        UNLOCK(&ec->lock); + +        /* There is a race with timer because there is no way to know if +         * timer callback has really been cancelled or it has been scheduled +         * for execution. If it has been scheduled, it will crash if we +         * destroy ec too fast. +         * +         * Not sure how this can be solved without using global variables or +         * having support from gf_timer_call_cancel() +         */ +        sleep(2); + +        this->private = NULL; +        if (ec->xl_list != NULL) +        { +            GF_FREE(ec->xl_list); +            ec->xl_list = NULL; +        } + +        if (ec->fop_pool != NULL) +        { +            mem_pool_destroy(ec->fop_pool); +        } + +        if (ec->cbk_pool != NULL) +        { +            mem_pool_destroy(ec->cbk_pool); +        } + +        LOCK_DESTROY(&ec->lock); + +        GF_FREE(ec); +    } +} + +int32_t mem_acct_init(xlator_t * this) +{ +    if (xlator_mem_acct_init(this, ec_mt_end + 1) != 0) +    { +        gf_log(this->name, GF_LOG_ERROR, "Memory accounting initialization " +                                         "failed."); + +        return -1; +    } + +    return 0; +} + +int32_t reconfigure(xlator_t * this, dict_t * options) +{ +    gf_log(this->name, GF_LOG_ERROR, "Online volume reconfiguration is not " +                                     "supported."); + +    return -1; +} + +void ec_up(xlator_t * this, ec_t * ec) +{ +    if (ec->timer != NULL) +    { +        gf_timer_call_cancel(this->ctx, ec->timer); +        ec->timer = NULL; +    } + +    if (!ec->up && (ec->xl_up_count >= ec->fragments)) +    { +        if (ec->xl_up_count < ec->nodes) +        { +            gf_log("ec", GF_LOG_WARNING, "Starting volume with only %d bricks", +                   ec->xl_up_count); +        } + +        ec->up = 1; +        gf_log(this->name, GF_LOG_INFO, "Going UP"); + +        default_notify(this, GF_EVENT_CHILD_UP, NULL); +    } +} + +void ec_down(xlator_t * this, ec_t * ec) +{ +    if (ec->timer != NULL) +    { +        gf_timer_call_cancel(this->ctx, ec->timer); +        ec->timer = NULL; +    } + +    if (ec->up) +    { +        ec->up = 0; +        gf_log(this->name, GF_LOG_INFO, "Going DOWN"); + +        default_notify(this, GF_EVENT_CHILD_DOWN, NULL); +    } +} + +void ec_notify_up_cbk(void * data) +{ +    ec_t * ec = data; + +    LOCK(&ec->lock); + +    if (ec->timer != NULL) +    { +        ec_up(ec->xl, ec); +    } + +    UNLOCK(&ec->lock); +} + +int32_t ec_notify_up(xlator_t * this, ec_t * ec, int32_t idx) +{ +    struct timespec delay = {0, }; + +    if (((ec->xl_up >> idx) & 1) == 0) +    { +        ec->xl_up |= 1ULL << idx; +        ec->xl_up_count++; + +        gf_log("ec", GF_LOG_DEBUG, "Child %d is UP (%lX, %u)", idx, ec->xl_up, +               ec->xl_up_count); + +        if (ec->xl_up_count == ec->fragments) +        { +            gf_log("ec", GF_LOG_DEBUG, "Initiating up timer"); + +            delay.tv_sec = 5; +            delay.tv_nsec = 0; +            ec->timer = gf_timer_call_after(this->ctx, delay, ec_notify_up_cbk, +                                            ec); +            if (ec->timer == NULL) +            { +                gf_log(this->name, GF_LOG_ERROR, "Cannot create timer for " +                                                 "delayed initialization"); + +                return ENOMEM; +            } +        } +        else if (ec->xl_up_count == ec->nodes) +        { +            ec_up(this, ec); +        } +    } + +    return EAGAIN; +} + +int32_t ec_notify_down(xlator_t * this, ec_t * ec, int32_t idx) +{ +    if (((ec->xl_up >> idx) & 1) != 0) +    { +        gf_log("ec", GF_LOG_DEBUG, "Child %d is DOWN", idx); + +        ec->xl_up ^= 1ULL << idx; +        if (ec->xl_up_count-- == ec->fragments) +        { +            ec_down(this, ec); +        } +    } + +    return EAGAIN; +} + +int32_t notify(xlator_t * this, int32_t event, void * data, ...) +{ +    ec_t * ec = this->private; +    int32_t idx = 0; +    int32_t error = 0; + +    LOCK(&ec->lock); + +    for (idx = 0; idx < ec->nodes; idx++) +    { +        if (ec->xl_list[idx] == data) +        { +            break; +        } +    } + +    gf_log("ec", GF_LOG_TRACE, "NOTIFY(%d): %p, %d", event, data, idx); + +    if (idx < ec->nodes) +    { +        if (event == GF_EVENT_CHILD_UP) +        { +            error = ec_notify_up(this, ec, idx); +        } +        else if (event == GF_EVENT_CHILD_DOWN) +        { +            error = ec_notify_down(this, ec, idx); +        } +    } + +    UNLOCK(&ec->lock); + +    if (error == 0) +    { +        return default_notify(this, event, data); +    } + +    return 0; +} + +int32_t init(xlator_t * this) +{ +    ec_t * ec; + +    if (this->parents == NULL) +    { +        gf_log(this->name, GF_LOG_WARNING, "Volume does not have parents."); +    } + +    ec = GF_MALLOC(sizeof(*ec), ec_mt_ec_t); +    if (ec == NULL) +    { +        gf_log(this->name, GF_LOG_ERROR, "Failed to allocate private memory."); + +        return -1; +    } +    memset(ec, 0, sizeof(*ec)); + +    this->private = ec; + +    ec->xl = this; +    LOCK_INIT(&ec->lock); + +    ec->fop_pool = mem_pool_new(ec_fop_data_t, 1024); +    ec->cbk_pool = mem_pool_new(ec_cbk_data_t, 4096); +    if ((ec->fop_pool == NULL) || (ec->cbk_pool == NULL)) +    { +        gf_log(this->name, GF_LOG_ERROR, "Failed to create memory pools."); + +        goto failed; +    } + +    if (ec_prepare_childs(this) != 0) +    { +        gf_log(this->name, GF_LOG_ERROR, "Failed to initialize xlator"); + +        goto failed; +    } + +    if (ec_parse_options(this) != 0) +    { +        gf_log(this->name, GF_LOG_ERROR, "Failed to parse xlator options"); + +        goto failed; +    } + +    ec_method_initialize(); + +    gf_log(this->name, GF_LOG_DEBUG, "Disperse translator initialized."); + +    return 0; + +failed: +    __ec_destroy_private(this); + +    return -1; +} + +void fini(xlator_t * this) +{ +    __ec_destroy_private(this); +} + +int32_t ec_gf_access(call_frame_t * frame, xlator_t * this, loc_t * loc, +                     int32_t mask, dict_t * xdata) +{ +    ec_access(frame, this, -1, EC_MINIMUM_ONE, default_access_cbk, NULL, loc, +              mask, xdata); + +    return 0; +} + +int32_t ec_gf_create(call_frame_t * frame, xlator_t * this, loc_t * loc, +                     int32_t flags, mode_t mode, mode_t umask, fd_t * fd, +                     dict_t * xdata) +{ +    ec_create(frame, this, -1, EC_MINIMUM_MIN, default_create_cbk, NULL, loc, +              flags, mode, umask, fd, xdata); + +    return 0; +} + +int32_t ec_gf_discard(call_frame_t * frame, xlator_t * this, fd_t * fd, +                      off_t offset, size_t len, dict_t * xdata) +{ +    default_discard_failure_cbk(frame, ENOTSUP); + +    return 0; +} + +int32_t ec_gf_entrylk(call_frame_t * frame, xlator_t * this, +                      const char * volume, loc_t * loc, const char * basename, +                      entrylk_cmd cmd, entrylk_type type, dict_t * xdata) +{ +    ec_entrylk(frame, this, -1, EC_MINIMUM_ALL, default_entrylk_cbk, NULL, +               volume, loc, basename, cmd, type, xdata); + +    return 0; +} + +int32_t ec_gf_fentrylk(call_frame_t * frame, xlator_t * this, +                       const char * volume, fd_t * fd, const char * basename, +                       entrylk_cmd cmd, entrylk_type type, dict_t * xdata) +{ +    ec_fentrylk(frame, this, -1, EC_MINIMUM_ALL, default_fentrylk_cbk, NULL, +                volume, fd, basename, cmd, type, xdata); + +    return 0; +} + +int32_t ec_gf_fallocate(call_frame_t * frame, xlator_t * this, fd_t * fd, +                        int32_t keep_size, off_t offset, size_t len, +                        dict_t * xdata) +{ +    default_fallocate_failure_cbk(frame, ENOTSUP); + +    return 0; +} + +int32_t ec_gf_flush(call_frame_t * frame, xlator_t * this, fd_t * fd, +                    dict_t * xdata) +{ +    ec_flush(frame, this, -1, EC_MINIMUM_MIN, default_flush_cbk, NULL, fd, +             xdata); + +    return 0; +} + +int32_t ec_gf_fsync(call_frame_t * frame, xlator_t * this, fd_t * fd, +                    int32_t datasync, dict_t * xdata) +{ +    ec_fsync(frame, this, -1, EC_MINIMUM_MIN, default_fsync_cbk, NULL, fd, +             datasync, xdata); + +    return 0; +} + +int32_t ec_gf_fsyncdir(call_frame_t * frame, xlator_t * this, fd_t * fd, +                       int32_t datasync, dict_t * xdata) +{ +    ec_fsyncdir(frame, this, -1, EC_MINIMUM_MIN, default_fsyncdir_cbk, NULL, +                fd, datasync, xdata); + +    return 0; +} + +int32_t ec_gf_getxattr(call_frame_t * frame, xlator_t * this, loc_t * loc, +                       const char * name, dict_t * xdata) +{ +    ec_getxattr(frame, this, -1, EC_MINIMUM_MIN, default_getxattr_cbk, NULL, +                loc, name, xdata); + +    return 0; +} + +int32_t ec_gf_fgetxattr(call_frame_t * frame, xlator_t * this, fd_t * fd, +                        const char * name, dict_t * xdata) +{ +    ec_fgetxattr(frame, this, -1, EC_MINIMUM_MIN, default_fgetxattr_cbk, NULL, +                 fd, name, xdata); + +    return 0; +} + +int32_t ec_gf_inodelk(call_frame_t * frame, xlator_t * this, +                      const char * volume, loc_t * loc, int32_t cmd, +                      struct gf_flock * flock, dict_t * xdata) +{ +    ec_inodelk(frame, this, -1, EC_MINIMUM_ALL, default_inodelk_cbk, NULL, +               volume, loc, cmd, flock, xdata); + +    return 0; +} + +int32_t ec_gf_finodelk(call_frame_t * frame, xlator_t * this, +                       const char * volume, fd_t * fd, int32_t cmd, +                       struct gf_flock * flock, dict_t * xdata) +{ +    ec_finodelk(frame, this, -1, EC_MINIMUM_ALL, default_finodelk_cbk, NULL, +                volume, fd, cmd, flock, xdata); + +    return 0; +} + +int32_t ec_gf_link(call_frame_t * frame, xlator_t * this, loc_t * oldloc, +                   loc_t * newloc, dict_t * xdata) +{ +    ec_link(frame, this, -1, EC_MINIMUM_MIN, default_link_cbk, NULL, oldloc, +            newloc, xdata); + +    return 0; +} + +int32_t ec_gf_lk(call_frame_t * frame, xlator_t * this, fd_t * fd, +                 int32_t cmd, struct gf_flock * flock, dict_t * xdata) +{ +    ec_lk(frame, this, -1, EC_MINIMUM_ALL, default_lk_cbk, NULL, fd, cmd, +          flock, xdata); + +    return 0; +} + +int32_t ec_gf_lookup(call_frame_t * frame, xlator_t * this, loc_t * loc, +                     dict_t * xdata) +{ +    ec_lookup(frame, this, -1, EC_MINIMUM_MIN, default_lookup_cbk, NULL, loc, +              xdata); + +    return 0; +} + +int32_t ec_gf_mkdir(call_frame_t * frame, xlator_t * this, loc_t * loc, +                    mode_t mode, mode_t umask, dict_t * xdata) +{ +    ec_mkdir(frame, this, -1, EC_MINIMUM_MIN, default_mkdir_cbk, NULL, loc, +             mode, umask, xdata); + +    return 0; +} + +int32_t ec_gf_mknod(call_frame_t * frame, xlator_t * this, loc_t * loc, +                    mode_t mode, dev_t rdev, mode_t umask, dict_t * xdata) +{ +    ec_mknod(frame, this, -1, EC_MINIMUM_MIN, default_mknod_cbk, NULL, loc, +             mode, rdev, umask, xdata); + +    return 0; +} + +int32_t ec_gf_open(call_frame_t * frame, xlator_t * this, loc_t * loc, +                   int32_t flags, fd_t * fd, dict_t * xdata) +{ +    ec_open(frame, this, -1, EC_MINIMUM_MIN, default_open_cbk, NULL, loc, +            flags, fd, xdata); + +    return 0; +} + +int32_t ec_gf_opendir(call_frame_t * frame, xlator_t * this, loc_t * loc, +                      fd_t * fd, dict_t * xdata) +{ +    ec_opendir(frame, this, -1, EC_MINIMUM_MIN, default_opendir_cbk, NULL, loc, +               fd, xdata); + +    return 0; +} + +int32_t ec_gf_readdir(call_frame_t * frame, xlator_t * this, fd_t * fd, +                      size_t size, off_t offset, dict_t * xdata) +{ +    ec_readdir(frame, this, -1, EC_MINIMUM_ONE, default_readdir_cbk, NULL, fd, +               size, offset, xdata); + +    return 0; +} + +int32_t ec_gf_readdirp(call_frame_t * frame, xlator_t * this, fd_t * fd, +                       size_t size, off_t offset, dict_t * xdata) +{ +    ec_readdirp(frame, this, -1, EC_MINIMUM_ONE, default_readdirp_cbk, NULL, +                fd, size, offset, xdata); + +    return 0; +} + +int32_t ec_gf_readlink(call_frame_t * frame, xlator_t * this, loc_t * loc, +                       size_t size, dict_t * xdata) +{ +    ec_readlink(frame, this, -1, EC_MINIMUM_ONE, default_readlink_cbk, NULL, +                loc, size, xdata); + +    return 0; +} + +int32_t ec_gf_readv(call_frame_t * frame, xlator_t * this, fd_t * fd, +                    size_t size, off_t offset, uint32_t flags, dict_t * xdata) +{ +    ec_readv(frame, this, -1, EC_MINIMUM_MIN, default_readv_cbk, NULL, fd, +             size, offset, flags, xdata); + +    return 0; +} + +int32_t ec_gf_removexattr(call_frame_t * frame, xlator_t * this, loc_t * loc, +                          const char * name, dict_t * xdata) +{ +    ec_removexattr(frame, this, -1, EC_MINIMUM_MIN, default_removexattr_cbk, +                   NULL, loc, name, xdata); + +    return 0; +} + +int32_t ec_gf_fremovexattr(call_frame_t * frame, xlator_t * this, fd_t * fd, +                           const char * name, dict_t * xdata) +{ +    ec_fremovexattr(frame, this, -1, EC_MINIMUM_MIN, default_fremovexattr_cbk, +                    NULL, fd, name, xdata); + +    return 0; +} + +int32_t ec_gf_rename(call_frame_t * frame, xlator_t * this, loc_t * oldloc, +                     loc_t * newloc, dict_t * xdata) +{ +    ec_rename(frame, this, -1, EC_MINIMUM_MIN, default_rename_cbk, NULL, +              oldloc, newloc, xdata); + +    return 0; +} + +int32_t ec_gf_rmdir(call_frame_t * frame, xlator_t * this, loc_t * loc, +                    int xflags, dict_t * xdata) +{ +    ec_rmdir(frame, this, -1, EC_MINIMUM_MIN, default_rmdir_cbk, NULL, loc, +             xflags, xdata); + +    return 0; +} + +int32_t ec_gf_setattr(call_frame_t * frame, xlator_t * this, loc_t * loc, +                      struct iatt * stbuf, int32_t valid, dict_t * xdata) +{ +    ec_setattr(frame, this, -1, EC_MINIMUM_MIN, default_setattr_cbk, NULL, loc, +               stbuf, valid, xdata); + +    return 0; +} + +int32_t ec_gf_fsetattr(call_frame_t * frame, xlator_t * this, fd_t * fd, +                       struct iatt * stbuf, int32_t valid, dict_t * xdata) +{ +    ec_fsetattr(frame, this, -1, EC_MINIMUM_MIN, default_fsetattr_cbk, NULL, +                fd, stbuf, valid, xdata); + +    return 0; +} + +int32_t ec_gf_setxattr(call_frame_t * frame, xlator_t * this, loc_t * loc, +                       dict_t * dict, int32_t flags, dict_t * xdata) +{ +    ec_setxattr(frame, this, -1, EC_MINIMUM_MIN, default_setxattr_cbk, NULL, +                loc, dict, flags, xdata); + +    return 0; +} + +int32_t ec_gf_fsetxattr(call_frame_t * frame, xlator_t * this, fd_t * fd, +                        dict_t * dict, int32_t flags, dict_t * xdata) +{ +    ec_fsetxattr(frame, this, -1, EC_MINIMUM_MIN, default_fsetxattr_cbk, NULL, +                 fd, dict, flags, xdata); + +    return 0; +} + +int32_t ec_gf_stat(call_frame_t * frame, xlator_t * this, loc_t * loc, +                   dict_t * xdata) +{ +    ec_stat(frame, this, -1, EC_MINIMUM_MIN, default_stat_cbk, NULL, loc, +            xdata); + +    return 0; +} + +int32_t ec_gf_fstat(call_frame_t * frame, xlator_t * this, fd_t * fd, +                    dict_t * xdata) +{ +    ec_fstat(frame, this, -1, EC_MINIMUM_MIN, default_fstat_cbk, NULL, fd, +             xdata); + +    return 0; +} + +int32_t ec_gf_statfs(call_frame_t * frame, xlator_t * this, loc_t * loc, +                     dict_t * xdata) +{ +    ec_statfs(frame, this, -1, EC_MINIMUM_MIN, default_statfs_cbk, NULL, loc, +              xdata); + +    return 0; +} + +int32_t ec_gf_symlink(call_frame_t * frame, xlator_t * this, +                      const char * linkname, loc_t * loc, mode_t umask, +                      dict_t * xdata) +{ +    ec_symlink(frame, this, -1, EC_MINIMUM_MIN, default_symlink_cbk, NULL, +               linkname, loc, umask, xdata); + +    return 0; +} + +int32_t ec_gf_truncate(call_frame_t * frame, xlator_t * this, loc_t * loc, +                       off_t offset, dict_t * xdata) +{ +    ec_truncate(frame, this, -1, EC_MINIMUM_MIN, default_truncate_cbk, NULL, +                loc, offset, xdata); + +    return 0; +} + +int32_t ec_gf_ftruncate(call_frame_t * frame, xlator_t * this, fd_t * fd, +                        off_t offset, dict_t * xdata) +{ +    ec_ftruncate(frame, this, -1, EC_MINIMUM_MIN, default_ftruncate_cbk, NULL, +                 fd, offset, xdata); + +    return 0; +} + +int32_t ec_gf_unlink(call_frame_t * frame, xlator_t * this, loc_t * loc, +                     int xflags, dict_t * xdata) +{ +    ec_unlink(frame, this, -1, EC_MINIMUM_MIN, default_unlink_cbk, NULL, loc, +              xflags, xdata); + +    return 0; +} + +int32_t ec_gf_writev(call_frame_t * frame, xlator_t * this, fd_t * fd, +                     struct iovec * vector, int32_t count, off_t offset, +                     uint32_t flags, struct iobref * iobref, dict_t * xdata) +{ +    ec_writev(frame, this, -1, EC_MINIMUM_MIN, default_writev_cbk, NULL, fd, +              vector, count, offset, flags, iobref, xdata); + +    return 0; +} + +int32_t ec_gf_xattrop(call_frame_t * frame, xlator_t * this, loc_t * loc, +                      gf_xattrop_flags_t optype, dict_t * xattr, +                      dict_t * xdata) +{ +    ec_xattrop(frame, this, -1, EC_MINIMUM_MIN, default_xattrop_cbk, NULL, loc, +               optype, xattr, xdata); + +    return 0; +} + +int32_t ec_gf_fxattrop(call_frame_t * frame, xlator_t * this, fd_t * fd, +                       gf_xattrop_flags_t optype, dict_t * xattr, +                       dict_t * xdata) +{ +    ec_fxattrop(frame, this, -1, EC_MINIMUM_MIN, default_fxattrop_cbk, NULL, +                fd, optype, xattr, xdata); + +    return 0; +} + +int32_t ec_gf_zerofill(call_frame_t * frame, xlator_t * this, fd_t * fd, +                       off_t offset, off_t len, dict_t * xdata) +{ +    default_zerofill_failure_cbk(frame, ENOTSUP); + +    return 0; +} + +void __ec_gf_release_fd(xlator_t * this, fd_t * fd) +{ +    uint64_t value = 0; +    ec_fd_t * ctx = NULL; + +    if ((fd_ctx_del(fd, this, &value) == 0) && (value != 0)) +    { +        ctx = (ec_fd_t *)(uintptr_t)value; +        loc_wipe(&ctx->loc); +        GF_FREE(ctx); +    } +} + +void __ec_gf_release_inode(xlator_t * this, inode_t * inode) +{ +    uint64_t value = 0; +    ec_inode_t * ctx = NULL; + +    if ((inode_ctx_del(inode, this, &value) == 0) && (value != 0)) +    { +        ctx = (ec_inode_t *)(uintptr_t)value; +        GF_FREE(ctx); +    } +} + +int32_t ec_gf_forget(xlator_t * this, inode_t * inode) +{ +    __ec_gf_release_inode(this, inode); + +    return 0; +} + +int32_t ec_gf_invalidate(xlator_t * this, inode_t * inode) +{ +    __ec_gf_release_inode(this, inode); + +    return 0; +} + +int32_t ec_gf_release(xlator_t * this, fd_t * fd) +{ +    __ec_gf_release_fd(this, fd); + +    return 0; +} + +int32_t ec_gf_releasedir(xlator_t * this, fd_t * fd) +{ +    __ec_gf_release_fd(this, fd); + +    return 0; +} + +struct xlator_fops fops = +{ +    .lookup       = ec_gf_lookup, +    .stat         = ec_gf_stat, +    .fstat        = ec_gf_fstat, +    .truncate     = ec_gf_truncate, +    .ftruncate    = ec_gf_ftruncate, +    .access       = ec_gf_access, +    .readlink     = ec_gf_readlink, +    .mknod        = ec_gf_mknod, +    .mkdir        = ec_gf_mkdir, +    .unlink       = ec_gf_unlink, +    .rmdir        = ec_gf_rmdir, +    .symlink      = ec_gf_symlink, +    .rename       = ec_gf_rename, +    .link         = ec_gf_link, +    .create       = ec_gf_create, +    .open         = ec_gf_open, +    .readv        = ec_gf_readv, +    .writev       = ec_gf_writev, +    .flush        = ec_gf_flush, +    .fsync        = ec_gf_fsync, +    .opendir      = ec_gf_opendir, +    .readdir      = ec_gf_readdir, +    .readdirp     = ec_gf_readdirp, +    .fsyncdir     = ec_gf_fsyncdir, +    .statfs       = ec_gf_statfs, +    .setxattr     = ec_gf_setxattr, +    .getxattr     = ec_gf_getxattr, +    .fsetxattr    = ec_gf_fsetxattr, +    .fgetxattr    = ec_gf_fgetxattr, +    .removexattr  = ec_gf_removexattr, +    .fremovexattr = ec_gf_fremovexattr, +    .lk           = ec_gf_lk, +    .inodelk      = ec_gf_inodelk, +    .finodelk     = ec_gf_finodelk, +    .entrylk      = ec_gf_entrylk, +    .fentrylk     = ec_gf_fentrylk, +    .xattrop      = ec_gf_xattrop, +    .fxattrop     = ec_gf_fxattrop, +    .setattr      = ec_gf_setattr, +    .fsetattr     = ec_gf_fsetattr, +    .fallocate    = ec_gf_fallocate, +    .discard      = ec_gf_discard, +    .zerofill     = ec_gf_zerofill +}; + +struct xlator_cbks cbks = +{ +    .forget            = ec_gf_forget, +    .release           = ec_gf_release, +    .releasedir        = ec_gf_releasedir, +    .invalidate        = ec_gf_invalidate, +    .client_destroy    = NULL, +    .client_disconnect = NULL +}; + +struct volume_options options[] = +{ +    { +        .key = { "redundancy" }, +        .type = GF_OPTION_TYPE_INT, +        .description = "Maximum number of bricks that can fail " +                       "simultaneously without losing data." +    }, +    { } +}; diff --git a/xlators/cluster/ec/src/ec.h b/xlators/cluster/ec/src/ec.h new file mode 100644 index 00000000000..85c430e2045 --- /dev/null +++ b/xlators/cluster/ec/src/ec.h @@ -0,0 +1,54 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS is distributed in the hope +  that it will be useful, but WITHOUT ANY WARRANTY; without even the +  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +  PURPOSE. See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef __EC_H__ +#define __EC_H__ + +#include "xlator.h" +#include "timer.h" + +#define EC_XATTR_SIZE    "trusted.ec.size" +#define EC_XATTR_VERSION "trusted.ec.version" + +struct _ec; +typedef struct _ec ec_t; + +struct _ec +{ +    xlator_t *        xl; +    int32_t           nodes; +    int32_t           bits_for_nodes; +    int32_t           fragments; +    int32_t           redundancy; +    uint32_t          fragment_size; +    uint32_t          stripe_size; +    int32_t           up; +    uint32_t          idx; +    uint32_t          xl_up_count; +    uintptr_t         xl_up; +    uintptr_t         node_mask; +    xlator_t **       xl_list; +    gf_lock_t         lock; +    gf_timer_t *      timer; +    struct mem_pool * fop_pool; +    struct mem_pool * cbk_pool; +}; + +#endif /* __EC_H__ */  | 
