summaryrefslogtreecommitdiffstats
path: root/libglusterfs
diff options
context:
space:
mode:
authorAmar Tumballi <amarts@redhat.com>2017-11-28 14:44:46 +0530
committerKaushal M <kaushal@redhat.com>2017-11-30 09:16:13 +0000
commit5b4b25c697f93d3dfe352013a442f2ec73fd3b8b (patch)
treef9bf3452741e702cf5774924fc70eb82d7831d2e /libglusterfs
parent3460b8cfc550f272bdae588e8929b75b105ab06b (diff)
xlator: provide a xlator_api_t structure to include all exported options
each translator from now on can have just 1 symbol exported called 'xlator_api', which has all the required fields in it. Updates: #164 Change-Id: I48d54f5ec59fee842b1d55877e3ac5e9ec9b6bdd Signed-off-by: Amar Tumballi <amarts@redhat.com>
Diffstat (limited to 'libglusterfs')
-rw-r--r--libglusterfs/src/defaults-tmpl.c7
-rw-r--r--libglusterfs/src/defaults.h4
-rw-r--r--libglusterfs/src/xlator.c220
-rw-r--r--libglusterfs/src/xlator.h74
4 files changed, 268 insertions, 37 deletions
diff --git a/libglusterfs/src/defaults-tmpl.c b/libglusterfs/src/defaults-tmpl.c
index 0ef14d5c68e..d311972f0c0 100644
--- a/libglusterfs/src/defaults-tmpl.c
+++ b/libglusterfs/src/defaults-tmpl.c
@@ -223,3 +223,10 @@ default_mem_acct_init (xlator_t *this)
return ret;
}
+
+void
+default_fini (xlator_t *this)
+{
+ if (this && this->private)
+ GF_FREE (this->private);
+}
diff --git a/libglusterfs/src/defaults.h b/libglusterfs/src/defaults.h
index 50f1909b90b..9b4f4828e91 100644
--- a/libglusterfs/src/defaults.h
+++ b/libglusterfs/src/defaults.h
@@ -1297,4 +1297,8 @@ default_setactivelk_failure_cbk (call_frame_t *frame, int32_t op_errno);
int32_t
default_mem_acct_init (xlator_t *this);
+
+void
+default_fini (xlator_t *this);
+
#endif /* _DEFAULTS_H */
diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c
index e371038f2c7..ed1d95d01e1 100644
--- a/libglusterfs/src/xlator.c
+++ b/libglusterfs/src/xlator.c
@@ -40,6 +40,10 @@ xlator_init_unlock (void)
(void) pthread_mutex_unlock (&xlator_init_mutex);
}
+static struct xlator_cbks default_cbks = { };
+struct volume_options default_options[] = {
+ { .key = {NULL} },
+};
static void
fill_defaults (xlator_t *xl)
@@ -102,10 +106,16 @@ fill_defaults (xlator_t *xl)
SET_DEFAULT_FOP (getspec);
+ if (!xl->cbks)
+ xl->cbks = &default_cbks;
+
SET_DEFAULT_CBK (release);
SET_DEFAULT_CBK (releasedir);
SET_DEFAULT_CBK (forget);
+ if (!xl->fini)
+ xl->fini = default_fini;
+
if (!xl->notify)
xl->notify = default_notify;
@@ -136,9 +146,10 @@ int
xlator_volopt_dynload (char *xlator_type, void **dl_handle,
volume_opt_list_t *opt_list)
{
- int ret = -1;
- char *name = NULL;
- void *handle = NULL;
+ int ret = -1;
+ char *name = NULL;
+ void *handle = NULL;
+ xlator_api_t *xlapi = NULL;
GF_VALIDATE_OR_GOTO ("xlator", xlator_type, out);
@@ -163,11 +174,28 @@ xlator_volopt_dynload (char *xlator_type, void **dl_handle,
goto out;
}
- if (!(opt_list->given_opt = dlsym (handle, "options"))) {
- dlerror ();
- gf_msg ("xlator", GF_LOG_ERROR, 0, LG_MSG_LOAD_FAILED,
- "Failed to load xlator opt table");
- goto out;
+ /* check new struct first, and then check this */
+ xlapi = dlsym (handle, "xlator_api");
+ if (!xlapi) {
+ gf_msg ("xlator", GF_LOG_DEBUG, 0, LG_MSG_DLSYM_ERROR,
+ "dlsym(xlator_api) on %s. "
+ "Fall back to old symbols", dlerror ());
+ /* This case is not an error for now, so allow it
+ to fall back to old methods. */
+ opt_list->given_opt = dlsym (handle, "options");
+ if (!opt_list->given_opt) {
+ dlerror ();
+ gf_msg ("xlator", GF_LOG_ERROR, 0, LG_MSG_LOAD_FAILED,
+ "Failed to load xlator opt table");
+ goto out;
+ }
+ } else {
+ opt_list->given_opt = xlapi->options;
+ if (!opt_list->given_opt) {
+ gf_msg ("xlator", GF_LOG_ERROR, 0, LG_MSG_LOAD_FAILED,
+ "Failed to load xlator options table");
+ goto out;
+ }
}
*dl_handle = handle;
@@ -184,44 +212,24 @@ xlator_volopt_dynload (char *xlator_type, void **dl_handle,
}
-
-int
-xlator_dynload (xlator_t *xl)
+int xlator_dynload_oldway (xlator_t *xl)
{
int ret = -1;
- char *name = NULL;
void *handle = NULL;
volume_opt_list_t *vol_opt = NULL;
class_methods_t *vtbl = NULL;
- GF_VALIDATE_OR_GOTO ("xlator", xl, out);
-
- INIT_LIST_HEAD (&xl->volume_options);
-
- ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xl->type);
- if (-1 == ret) {
- goto out;
- }
-
- ret = -1;
-
- gf_msg_trace ("xlator", 0, "attempt to load file %s", name);
-
- handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL);
- if (!handle) {
- gf_msg ("xlator", GF_LOG_WARNING, 0, LG_MSG_DLOPEN_FAILED,
- "%s", dlerror ());
- goto out;
- }
- xl->dlhandle = handle;
+ handle = xl->dlhandle;
- if (!(xl->fops = dlsym (handle, "fops"))) {
+ xl->fops = dlsym (handle, "fops");
+ if (!xl->fops) {
gf_msg ("xlator", GF_LOG_WARNING, 0, LG_MSG_DLSYM_ERROR,
"dlsym(fops) on %s", dlerror ());
goto out;
}
- if (!(xl->cbks = dlsym (handle, "cbks"))) {
+ xl->cbks = dlsym (handle, "cbks");
+ if (!xl->cbks) {
gf_msg ("xlator", GF_LOG_WARNING, 0, LG_MSG_DLSYM_ERROR,
"dlsym(cbks) on %s", dlerror ());
goto out;
@@ -276,20 +284,158 @@ xlator_dynload (xlator_t *xl)
}
vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t),
- gf_common_mt_volume_opt_list_t);
+ gf_common_mt_volume_opt_list_t);
if (!vol_opt) {
goto out;
}
if (!(vol_opt->given_opt = dlsym (handle, "options"))) {
- dlerror ();
gf_msg_trace (xl->name, 0, "Strict option validation not "
- "enforced -- neglecting");
+ "enforced -- neglecting (%s)", dlerror ());
+ }
+ INIT_LIST_HEAD (&vol_opt->list);
+ list_add_tail (&vol_opt->list, &xl->volume_options);
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+int xlator_dynload_newway (xlator_t *xl)
+{
+ int ret = -1;
+ void *handle = NULL;
+ volume_opt_list_t *vol_opt = NULL;
+ xlator_api_t *xlapi = NULL;
+
+ handle = xl->dlhandle;
+
+ xlapi = dlsym (handle, "xlator_api");
+ if (!xlapi) {
+ gf_msg ("xlator", GF_LOG_INFO, 0, LG_MSG_DLSYM_ERROR,
+ "dlsym(xlator_api) on %s. "
+ "Fall back to old symbols", dlerror ());
+ /* This case is not an error for now, so allow it
+ to fall back to old methods. */
+ ret = 1;
+ goto out;
+ }
+
+ xl->fops = xlapi->fops;
+ if (!xl->fops) {
+ gf_msg ("xlator", GF_LOG_WARNING, 0, LG_MSG_DLSYM_ERROR,
+ "%s: struct missing (fops)", xl->name);
+ goto out;
+ }
+
+ xl->cbks = xlapi->cbks;
+ if (!xl->cbks) {
+ gf_msg_trace ("xlator", 0, "%s: struct missing (cbks)",
+ xl->name);
+ }
+
+ xl->init = xlapi->init;
+ if (!xl->init) {
+ gf_msg ("xlator", GF_LOG_WARNING, 0, LG_MSG_DLSYM_ERROR,
+ "%s: method missing (init)", xl->name);
+ goto out;
+ }
+
+ xl->fini = xlapi->fini;
+ if (!xl->fini) {
+ gf_msg_trace ("xlator", 0, "%s: method missing (fini)",
+ xl->name);
+ }
+
+ xl->reconfigure = xlapi->reconfigure;
+ if (!xl->reconfigure) {
+ gf_msg_trace ("xlator", 0, "%s: method missing (reconfigure)",
+ xl->name);
+ }
+ xl->notify = xlapi->notify;
+ if (!xl->notify) {
+ gf_msg_trace ("xlator", 0, "%s: method missing (notify)",
+ xl->name);
+ }
+ xl->dumpops = xlapi->dumpops;
+ if (!xl->dumpops) {
+ gf_msg_trace ("xlator", 0, "%s: method missing (dumpops)",
+ xl->name);
+ }
+ xl->mem_acct_init = xlapi->mem_acct_init;
+ if (!xl->mem_acct_init) {
+ gf_msg_trace ("xlator", 0, "%s: method missing (mem_acct_init)",
+ xl->name);
+ }
+
+ vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t),
+ gf_common_mt_volume_opt_list_t);
+ if (!vol_opt) {
+ goto out;
}
+
+ vol_opt->given_opt = xlapi->options;
+ if (!vol_opt->given_opt) {
+ gf_msg ("xlator", GF_LOG_INFO, 0, LG_MSG_DLSYM_ERROR,
+ "%s: options not provided, using default", xl->name);
+ vol_opt->given_opt = default_options;
+ }
+
INIT_LIST_HEAD (&vol_opt->list);
list_add_tail (&vol_opt->list, &xl->volume_options);
+ xl->id = xlapi->xlator_id;
+ xl->flags = xlapi->flags;
+ xl->identifier = xlapi->identifier;
+ memcpy (xl->op_version, xlapi->op_version,
+ sizeof (uint32_t) * GF_MAX_RELEASES);
+
+ ret = 0;
+out:
+ return ret;
+}
+
+
+int
+xlator_dynload (xlator_t *xl)
+{
+ int ret = -1;
+ char *name = NULL;
+ void *handle = NULL;
+
+ GF_VALIDATE_OR_GOTO ("xlator", xl, out);
+
+ INIT_LIST_HEAD (&xl->volume_options);
+
+ ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xl->type);
+ if (-1 == ret) {
+ goto out;
+ }
+
+ ret = -1;
+
+ gf_msg_trace ("xlator", 0, "attempt to load file %s", name);
+
+ handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL);
+ if (!handle) {
+ gf_msg ("xlator", GF_LOG_WARNING, 0, LG_MSG_DLOPEN_FAILED,
+ "%s", dlerror ());
+ goto out;
+ }
+ xl->dlhandle = handle;
+
+ ret = xlator_dynload_newway (xl);
+ if (-1 == ret)
+ goto out;
+ if (1 == ret) {
+ /* it means we don't find the new symbol in xlator code */
+ ret = xlator_dynload_oldway (xl);
+ if (-1 == ret)
+ goto out;
+ }
+
fill_defaults (xl);
ret = 0;
diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h
index 7f9d483ccb3..de353fe702d 100644
--- a/libglusterfs/src/xlator.h
+++ b/libglusterfs/src/xlator.h
@@ -991,6 +991,18 @@ struct _xlator {
/* Its used as an index to inode_ctx*/
uint32_t xl_id;
+
+ /* op_version: initialized in xlator code itself */
+ uint32_t op_version[GF_MAX_RELEASES];
+
+ /* flags: initialized in xlator code itself */
+ uint32_t flags;
+
+ /* id: unique, initialized in xlator code itself */
+ uint32_t id;
+
+ /* identifier: a full string which can unique identify the xlator */
+ char *identifier;
};
typedef struct {
@@ -1001,6 +1013,68 @@ typedef struct {
event_notify_fn_t notify;
} class_methods_t;
+/* This would be the only structure which needs to be exported by
+ the translators. For the backward compatibility, in 4.x series
+ even the old exported fields will be supported */
+typedef struct {
+ /* init(): mandatory method, will be called during the
+ graph initialization */
+ int32_t (*init) (xlator_t *this);
+
+ /* fini(): optional method, will be initialized to default
+ method which would just free the 'xlator->private' variable.
+ This method is called when the graph is no more in use, and
+ is being destroyed. Also when SIGTERM is received */
+ void (*fini) (xlator_t *this);
+
+ /* reconfigure(): optional method, will be initialized to default
+ method in case not provided by xlator. This method is called
+ when there are only option changes in xlator, and no graph change.
+ eg., a 'gluster volume set' command */
+ int32_t (*reconfigure) (xlator_t *this, dict_t *options);
+
+ /* mem_acct_init(): used for memory accounting inside of the xlator.
+ optional. called during translator initialization */
+ int32_t (*mem_acct_init) (xlator_t *this);
+
+ /* notify(): used for handling the notification of events from either
+ the parent or child in the graph. optional. */
+ event_notify_fn_t notify;
+
+ /* struct fops: mandatory. provides all the filesystem operations
+ methods of the xlator */
+ struct xlator_fops *fops;
+ /* struct cbks: optional. provides methods to handle
+ inode forgets, and fd releases */
+ struct xlator_cbks *cbks;
+
+ /* dumpops: a structure again, with methods to dump the details.
+ optional. */
+ struct xlator_dumpops *dumpops;
+
+ /* struct options: if the translator takes any 'options' from the
+ volume file, then that should be defined here. optional. */
+ volume_option_t *options;
+
+ /* op_version: will be used by volume generation logic to figure
+ out whether to insert it in graph or no, based on cluster's
+ operating version.
+ default value: 0, which means good to insert always */
+ uint32_t op_version[GF_MAX_RELEASES];
+
+ /* flags: will be used by volume generation logic to optimize the
+ placements etc.
+ default value: 0, which means don't treat it specially */
+ uint32_t flags;
+
+ /* xlator_id: unique per xlator. make sure to have no collission
+ in this ID */
+ uint32_t xlator_id;
+
+ /* identifier: a string constant */
+ char *identifier;
+} xlator_api_t;
+
#define xlator_has_parent(xl) (xl->parents != NULL)
#define XLATOR_NOTIFY(_xl, params ...) \