/* Copyright (c) 2013 Red Hat, Inc. This file is licensed to you under your choice of the GNU Lesser General Public License, version 3 or any later version (LGPLv3 or later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H #define _CONFIG_H #include "config.h" #endif #include "call-stub.h" #include "defaults.h" #include "timer.h" #include "xlator.h" #include "jbr-messages.h" #include "jbrc.h" #include "statedump.h" #define SCAR_LIMIT 20 #define HILITE(x) (""x"") /* * The fops are actually generated by gen-fops.py; the rest was mostly copied * from defaults.c (commit cd253754 on 27 August 2013). */ enum gf_dht_mem_types_ { gf_mt_jbrc_private_t = gf_common_mt_end + 1, gf_mt_jbrc_end }; char *JBRC_XATTR = "user.jbr.active"; static inline xlator_t * ACTIVE_CHILD (xlator_t *parent) { jbrc_private_t *priv = parent->private; return priv ? priv->active : FIRST_CHILD(parent); } xlator_t * next_xlator (xlator_t *this, xlator_t *prev) { xlator_list_t *trav; for (trav = this->children; trav; trav = trav->next) { if (trav->xlator == prev) { return trav->next ? trav->next->xlator : this->children->xlator; } } return NULL; } void jbrc_retry_cb (void *cb_arg) { jbrc_local_t *local = cb_arg; gf_msg (__func__, GF_LOG_INFO, 0, J_MSG_RETRY_MSG, HILITE("retrying %p"), local); call_resume_wind(local->stub); } #pragma generate int32_t jbrc_forget (xlator_t *this, inode_t *inode) { gf_msg_callingfn (this->name, GF_LOG_WARNING, 0, J_MSG_INIT_FAIL, "xlator does not implement forget_cbk"); return 0; } int32_t jbrc_releasedir (xlator_t *this, fd_t *fd) { gf_msg_callingfn (this->name, GF_LOG_WARNING, 0, J_MSG_INIT_FAIL, "xlator does not implement releasedir_cbk"); return 0; } int32_t jbrc_release (xlator_t *this, fd_t *fd) { gf_msg_callingfn (this->name, GF_LOG_WARNING, 0, J_MSG_INIT_FAIL, "xlator does not implement release_cbk"); return 0; } struct xlator_fops fops = { .lookup = jbrc_lookup, .stat = jbrc_stat, .fstat = jbrc_fstat, .truncate = jbrc_truncate, .ftruncate = jbrc_ftruncate, .access = jbrc_access, .readlink = jbrc_readlink, .mknod = jbrc_mknod, .mkdir = jbrc_mkdir, .unlink = jbrc_unlink, .rmdir = jbrc_rmdir, .symlink = jbrc_symlink, .rename = jbrc_rename, .link = jbrc_link, .create = jbrc_create, .open = jbrc_open, .readv = jbrc_readv, .writev = jbrc_writev, .flush = jbrc_flush, .fsync = jbrc_fsync, .opendir = jbrc_opendir, .readdir = jbrc_readdir, .readdirp = jbrc_readdirp, .fsyncdir = jbrc_fsyncdir, .statfs = jbrc_statfs, .setxattr = jbrc_setxattr, .getxattr = jbrc_getxattr, .fsetxattr = jbrc_fsetxattr, .fgetxattr = jbrc_fgetxattr, .removexattr = jbrc_removexattr, .fremovexattr = jbrc_fremovexattr, .lk = jbrc_lk, .inodelk = jbrc_inodelk, .finodelk = jbrc_finodelk, .entrylk = jbrc_entrylk, .fentrylk = jbrc_fentrylk, .rchecksum = jbrc_rchecksum, .xattrop = jbrc_xattrop, .fxattrop = jbrc_fxattrop, .setattr = jbrc_setattr, .fsetattr = jbrc_fsetattr, .fallocate = jbrc_fallocate, .discard = jbrc_discard, }; struct xlator_cbks cbks = { }; int32_t mem_acct_init (xlator_t *this) { int ret = -1; GF_VALIDATE_OR_GOTO ("jbrc", this, out); ret = xlator_mem_acct_init (this, gf_mt_jbrc_end + 1); if (ret != 0) { gf_msg (this->name, GF_LOG_ERROR, ENOMEM, J_MSG_MEM_ERR, "Memory accounting init failed"); return ret; } out: return ret; } int32_t jbrc_init (xlator_t *this) { jbrc_private_t *priv = NULL; xlator_list_t *trav = NULL; this->local_pool = mem_pool_new (jbrc_local_t, 128); if (!this->local_pool) { gf_msg (this->name, GF_LOG_ERROR, ENOMEM, J_MSG_MEM_ERR, "failed to create jbrc_local_t pool"); goto err; } priv = GF_CALLOC (1, sizeof (*priv), gf_mt_jbrc_private_t); if (!priv) { goto err; } for (trav = this->children; trav; trav = trav->next) { ++(priv->n_children); } priv->active = FIRST_CHILD(this); this->private = priv; return 0; err: if (priv) { GF_FREE(priv); } return -1; } void jbrc_fini (xlator_t *this) { GF_FREE(this->private); } int jbrc_get_child_index (xlator_t *this, xlator_t *kid) { xlator_list_t *trav; int retval = -1; for (trav = this->children; trav; trav = trav->next) { ++retval; if (trav->xlator == kid) { return retval; } } return -1; } uint8_t jbrc_count_up_kids (jbrc_private_t *priv) { uint8_t retval = 0; uint8_t i; for (i = 0; i < priv->n_children; ++i) { if (priv->kid_state & (1 << i)) { ++retval; } } return retval; } int32_t jbrc_notify (xlator_t *this, int32_t event, void *data, ...) { int32_t ret = 0; int32_t index = 0; jbrc_private_t *priv = NULL; GF_VALIDATE_OR_GOTO (THIS->name, this, out); priv = this->private; GF_VALIDATE_OR_GOTO (this->name, priv, out); switch (event) { case GF_EVENT_CHILD_UP: index = jbrc_get_child_index(this, data); if (index >= 0) { priv->kid_state |= (1 << index); priv->up_children = jbrc_count_up_kids(priv); gf_msg (this->name, GF_LOG_INFO, 0, J_MSG_GENERIC, "got CHILD_UP for %s, now %u kids", ((xlator_t *)data)->name, priv->up_children); } ret = default_notify (this, event, data); break; case GF_EVENT_CHILD_DOWN: index = jbrc_get_child_index(this, data); if (index >= 0) { priv->kid_state &= ~(1 << index); priv->up_children = jbrc_count_up_kids(priv); gf_msg (this->name, GF_LOG_INFO, 0, J_MSG_GENERIC, "got CHILD_DOWN for %s, now %u kids", ((xlator_t *)data)->name, priv->up_children); } break; default: ret = default_notify (this, event, data); } out: return ret; } int jbrc_priv_dump (xlator_t *this) { jbrc_private_t *priv = NULL; char key_prefix[GF_DUMP_MAX_BUF_LEN]; xlator_list_t *trav = NULL; int32_t i = -1; GF_VALIDATE_OR_GOTO (THIS->name, this, out); priv = this->private; GF_VALIDATE_OR_GOTO (this->name, priv, out); snprintf(key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.%s", this->type, this->name); gf_proc_dump_add_section(key_prefix); gf_proc_dump_write("up_children", "%u", priv->up_children); for (trav = this->children, i = 0; trav; trav = trav->next, i++) { snprintf(key_prefix, GF_DUMP_MAX_BUF_LEN, "child_%d", i); gf_proc_dump_write(key_prefix, "%s", trav->xlator->name); } out: return 0; } struct xlator_dumpops dumpops = { .priv = jbrc_priv_dump, }; class_methods_t class_methods = { .init = jbrc_init, .fini = jbrc_fini, .notify = jbrc_notify, }; struct volume_options options[] = { { .key = {NULL} }, };