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 /xlators/cluster/ec/src/ec.c | |
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>
Diffstat (limited to 'xlators/cluster/ec/src/ec.c')
-rw-r--r-- | xlators/cluster/ec/src/ec.c | 904 |
1 files changed, 904 insertions, 0 deletions
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." + }, + { } +}; |