diff options
author | Jeff Darcy <jdarcy@redhat.com> | 2014-04-22 15:37:09 +0000 |
---|---|---|
committer | Jeff Darcy <jdarcy@redhat.com> | 2014-04-22 15:37:09 +0000 |
commit | a827c5eab32a43ade5551259ea56a6a1af7e861b (patch) | |
tree | e6707df68f72baa8645210ba931272285116ad85 /xlators/features | |
parent | 46d333783a968ab39e0beade9c7a1eec8035f8b1 (diff) | |
parent | 99bfc2a2a1689da1e173cb2f8ef54d2b09ef3a5d (diff) |
Merge branch 'upstream'
Conflicts:
glusterfs.spec.in
xlators/mgmt/glusterd/src/Makefile.am
xlators/mgmt/glusterd/src/glusterd-utils.c
xlators/mgmt/glusterd/src/glusterd.h
Change-Id: I27bdcf42b003cfc42d6ad981bd2bf8180176806d
Diffstat (limited to 'xlators/features')
19 files changed, 841 insertions, 28 deletions
diff --git a/xlators/features/Makefile.am b/xlators/features/Makefile.am index d2f5ef192..1fdd474c2 100644 --- a/xlators/features/Makefile.am +++ b/xlators/features/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = locks quota read-only mac-compat quiesce marker index \ +SUBDIRS = locks quota read-only mac-compat quiesce marker index barrier \ protect compress changelog gfid-access $(GLUPY_SUBDIR) qemu-block # trash path-converter # filter CLEANFILES = diff --git a/xlators/features/barrier/Makefile.am b/xlators/features/barrier/Makefile.am new file mode 100644 index 000000000..a985f42a8 --- /dev/null +++ b/xlators/features/barrier/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src + +CLEANFILES = diff --git a/xlators/features/barrier/src/Makefile.am b/xlators/features/barrier/src/Makefile.am new file mode 100644 index 000000000..8859be328 --- /dev/null +++ b/xlators/features/barrier/src/Makefile.am @@ -0,0 +1,16 @@ +xlator_LTLIBRARIES = barrier.la +xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features + +barrier_la_LDFLAGS = -module -avoid-version + +barrier_la_SOURCES = barrier.c + +barrier_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la + +noinst_HEADERS = barrier.h barrier-mem-types.h + +AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src + +AM_CFLAGS = -Wall $(GF_CFLAGS) + +CLEANFILES = diff --git a/xlators/features/barrier/src/barrier-mem-types.h b/xlators/features/barrier/src/barrier-mem-types.h new file mode 100644 index 000000000..36647a669 --- /dev/null +++ b/xlators/features/barrier/src/barrier-mem-types.h @@ -0,0 +1,20 @@ +/* + Copyright (c) 2014 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __BARRIER_MEM_TYPES_H__ +#define __BARRIER_MEM_TYPES_H__ + +#include "mem-types.h" + +enum gf_barrier_mem_types_ { + gf_barrier_mt_priv_t = gf_common_mt_end + 1, + gf_barrier_mt_end +}; +#endif diff --git a/xlators/features/barrier/src/barrier.c b/xlators/features/barrier/src/barrier.c new file mode 100644 index 000000000..e5465d1b4 --- /dev/null +++ b/xlators/features/barrier/src/barrier.c @@ -0,0 +1,600 @@ +/* + Copyright (c) 2014 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "barrier.h" +#include "defaults.h" +#include "call-stub.h" + +#include "statedump.h" + +int32_t +barrier_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) +{ + BARRIER_FOP_CBK (writev, out, frame, this, op_ret, op_errno, + prebuf, postbuf, xdata); +out: + return 0; +} + +int32_t +barrier_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + BARRIER_FOP_CBK (fremovexattr, out, frame, this, op_ret, op_errno, + xdata); +out: + return 0; +} + +int32_t +barrier_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + BARRIER_FOP_CBK (removexattr, out, frame, this, op_ret, op_errno, + xdata); +out: + return 0; +} + +int32_t +barrier_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) +{ + BARRIER_FOP_CBK (truncate, out, frame, this, op_ret, op_errno, prebuf, + postbuf, xdata); +out: + return 0; +} + +int32_t +barrier_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) +{ + BARRIER_FOP_CBK (ftruncate, out, frame, this, op_ret, op_errno, prebuf, + postbuf, xdata); +out: + return 0; +} + +int32_t +barrier_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) +{ + BARRIER_FOP_CBK (rename, out, frame, this, op_ret, op_errno, buf, + preoldparent, postoldparent, prenewparent, + postnewparent, xdata); +out: + return 0; +} + +int32_t +barrier_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) +{ + BARRIER_FOP_CBK (rmdir, out, frame, this, op_ret, op_errno, preparent, + postparent, xdata); +out: + return 0; +} + +int32_t +barrier_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) +{ + BARRIER_FOP_CBK (unlink, out, frame, this, op_ret, op_errno, preparent, + postparent, xdata); +out: + return 0; +} + +int32_t +barrier_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) +{ + BARRIER_FOP_CBK (fsync, out, frame, this, op_ret, op_errno, + prebuf, postbuf, xdata); +out: + return 0; +} + +int32_t +barrier_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iovec *vector, int32_t count, off_t off, uint32_t flags, + struct iobref *iobref, dict_t *xdata) +{ + if (!(flags & O_SYNC)) { + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->writev, + fd, vector, count, off, flags, iobref, xdata); + + return 0; + } + + STACK_WIND (frame, barrier_writev_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->writev, fd, vector, count, + off, flags, iobref, xdata); + return 0; +} + +int32_t +barrier_fremovexattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) +{ + STACK_WIND (frame, barrier_fremovexattr_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fremovexattr, + fd, name, xdata); + return 0; +} + +int32_t +barrier_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) +{ + STACK_WIND (frame, barrier_removexattr_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->removexattr, + loc, name, xdata); + return 0; +} + +int32_t +barrier_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, + off_t offset, dict_t *xdata) +{ + STACK_WIND (frame, barrier_truncate_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->truncate, + loc, offset, xdata); + return 0; +} + +int32_t +barrier_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc, dict_t *xdata) +{ + STACK_WIND (frame, barrier_rename_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->rename, + oldloc, newloc, xdata); + return 0; +} + +int +barrier_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, + dict_t *xdata) +{ + STACK_WIND (frame, barrier_rmdir_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->rmdir, + loc, flags, xdata); + return 0; +} + +int32_t +barrier_unlink (call_frame_t *frame, xlator_t *this, + loc_t *loc, int xflag, dict_t *xdata) +{ + STACK_WIND (frame, barrier_unlink_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->unlink, + loc, xflag, xdata); + return 0; +} + +int32_t +barrier_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, dict_t *xdata) +{ + STACK_WIND (frame, barrier_ftruncate_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->ftruncate, + fd, offset, xdata); + return 0; +} + +int32_t +barrier_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t flags, dict_t *xdata) +{ + STACK_WIND (frame, barrier_fsync_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fsync, + fd, flags, xdata); + return 0; +} + +call_stub_t * +__barrier_dequeue (xlator_t *this, struct list_head *queue) +{ + call_stub_t *stub = NULL; + barrier_priv_t *priv = NULL; + + priv = this->private; + GF_ASSERT (priv); + + if (list_empty (queue)) + goto out; + + stub = list_entry (queue->next, call_stub_t, list); + list_del_init (&stub->list); + +out: + return stub; +} + +void +barrier_dequeue_all (xlator_t *this, struct list_head *queue) +{ + call_stub_t *stub = NULL; + + gf_log (this->name, GF_LOG_INFO, "Dequeuing all the barriered fops"); + + /* TODO: Start the below task in a new thread */ + while ((stub = __barrier_dequeue (this, queue))) + call_resume (stub); + + gf_log (this->name, GF_LOG_INFO, "Dequeuing the barriered fops is " + "finished"); + return; +} + +void +barrier_timeout (void *data) +{ + xlator_t *this = NULL; + barrier_priv_t *priv = NULL; + struct list_head queue = {0,}; + + this = data; + THIS = this; + priv = this->private; + + INIT_LIST_HEAD (&queue); + + gf_log (this->name, GF_LOG_CRITICAL, "Disabling barrier because of " + "the barrier timeout."); + + LOCK (&priv->lock); + { + __barrier_disable (this, &queue); + } + UNLOCK (&priv->lock); + + barrier_dequeue_all (this, &queue); + + return; +} + +void +__barrier_enqueue (xlator_t *this, call_stub_t *stub) +{ + barrier_priv_t *priv = NULL; + + priv = this->private; + GF_ASSERT (priv); + + list_add_tail (&stub->list, &priv->queue); + priv->queue_size++; + + return; +} + +void +__barrier_disable (xlator_t *this, struct list_head *queue) +{ + GF_UNUSED int ret = 0; + barrier_priv_t *priv = NULL; + + priv = this->private; + GF_ASSERT (priv); + + if (priv->timer) { + ret = gf_timer_call_cancel (this->ctx, priv->timer); + priv->timer = NULL; + } + + list_splice_init (&priv->queue, queue); + priv->queue_size = 0; + priv->barrier_enabled = _gf_false; +} + +int +__barrier_enable (xlator_t *this, barrier_priv_t *priv) +{ + int ret = -1; + + priv->timer = gf_timer_call_after (this->ctx, priv->timeout, + barrier_timeout, (void *) this); + if (!priv->timer) { + gf_log (this->name, GF_LOG_CRITICAL, "Couldn't add barrier " + "timeout event."); + goto out; + } + + priv->barrier_enabled = _gf_true; + ret = 0; +out: + return ret; +} + +int +reconfigure (xlator_t *this, dict_t *options) +{ + barrier_priv_t *priv = NULL; + gf_boolean_t past = _gf_false; + int ret = -1; + gf_boolean_t barrier_enabled = _gf_false; + uint32_t timeout = {0,}; + struct list_head queue = {0,}; + + priv = this->private; + GF_ASSERT (priv); + + GF_OPTION_RECONF ("barrier", barrier_enabled, options, bool, out); + GF_OPTION_RECONF ("timeout", timeout, options, time, out); + + INIT_LIST_HEAD (&queue); + + LOCK (&priv->lock); + { + past = priv->barrier_enabled; + + switch (past) { + case _gf_false: + if (barrier_enabled) { + ret = __barrier_enable (this, priv); + if (ret) + goto unlock; + + } else { + gf_log (this->name, GF_LOG_ERROR, + "Already disabled"); + goto unlock; + } + break; + + case _gf_true: + if (!barrier_enabled) { + __barrier_disable (this, &queue); + + } else { + gf_log (this->name, GF_LOG_ERROR, + "Already enabled"); + goto unlock; + } + break; + } + + priv->timeout.tv_sec = timeout; + + ret = 0; + } +unlock: + UNLOCK (&priv->lock); + + if (!list_empty (&queue)) + barrier_dequeue_all (this, &queue); + +out: + return ret; +} + +int32_t +mem_acct_init (xlator_t *this) +{ + int ret = -1; + + ret = xlator_mem_acct_init (this, gf_barrier_mt_end + 1); + if (ret) + gf_log (this->name, GF_LOG_ERROR, "Memory accounting " + "initialization failed."); + + return ret; +} + +int +init (xlator_t *this) +{ + int ret = -1; + barrier_priv_t *priv = NULL; + uint32_t timeout = {0,}; + + if (!this->children || this->children->next) { + gf_log (this->name, GF_LOG_ERROR, + "'barrier' not configured with exactly one child"); + goto out; + } + + if (!this->parents) + gf_log (this->name, GF_LOG_WARNING, + "dangling volume. check volfile "); + + priv = GF_CALLOC (1, sizeof (*priv), gf_barrier_mt_priv_t); + if (!priv) + goto out; + + LOCK_INIT (&priv->lock); + + GF_OPTION_INIT ("barrier", priv->barrier_enabled, bool, out); + GF_OPTION_INIT ("timeout", timeout, time, out); + priv->timeout.tv_sec = timeout; + + INIT_LIST_HEAD (&priv->queue); + + if (priv->barrier_enabled) { + ret = __barrier_enable (this, priv); + if (ret == -1) + goto out; + } + + this->private = priv; + ret = 0; +out: + return ret; +} + +void +fini (xlator_t *this) +{ + barrier_priv_t *priv = NULL; + struct list_head queue = {0,}; + + priv = this->private; + if (!priv) + goto out; + + INIT_LIST_HEAD (&queue); + + gf_log (this->name, GF_LOG_INFO, "Disabling barriering and dequeuing " + "all the queued fops"); + LOCK (&priv->lock); + { + __barrier_disable (this, &queue); + } + UNLOCK (&priv->lock); + + if (!list_empty (&queue)) + barrier_dequeue_all (this, &queue); + + this->private = NULL; + + LOCK_DESTROY (&priv->lock); + GF_FREE (priv); +out: + return; +} + +static void +barrier_dump_stub (call_stub_t *stub, char *prefix) +{ + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + + gf_proc_dump_build_key (key, prefix, "fop"); + gf_proc_dump_write (key, "%s", gf_fop_list[stub->fop]); + + gf_proc_dump_build_key (key, prefix, "gfid"); + gf_proc_dump_write (key, "%s", uuid_utoa (stub->args.loc.gfid)); + + if (stub->args.loc.path) { + gf_proc_dump_build_key (key, prefix, "path"); + gf_proc_dump_write (key, "%s", stub->args.loc.path); + } + if (stub->args.loc.name) { + gf_proc_dump_build_key (key, prefix, "name"); + gf_proc_dump_write (key, "%s", stub->args.loc.name); + } + + return; +} + +static void +__barrier_dump_queue (barrier_priv_t *priv) +{ + call_stub_t *stub = NULL; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int i = 0; + + GF_VALIDATE_OR_GOTO ("barrier", priv, out); + + list_for_each_entry (stub, &priv->queue, list) { + snprintf (key, sizeof (key), "stub.%d", i++); + gf_proc_dump_add_section (key); + barrier_dump_stub(stub, key); + } + +out: + return; +} + +int +barrier_dump_priv (xlator_t *this) +{ + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + barrier_priv_t *priv = NULL; + + GF_VALIDATE_OR_GOTO ("barrier", this, out); + + priv = this->private; + if (!priv) + return 0; + + gf_proc_dump_build_key (key, "xlator.features.barrier", "priv"); + gf_proc_dump_add_section (key); + + LOCK (&priv->lock); + { + gf_proc_dump_build_key (key, "barrier", "enabled"); + gf_proc_dump_write (key, "%d", priv->barrier_enabled); + gf_proc_dump_build_key (key, "barrier", "timeout"); + gf_proc_dump_write (key, "%"PRId64, priv->timeout.tv_sec); + if (priv->barrier_enabled) { + gf_proc_dump_build_key (key, "barrier", "queue_size"); + gf_proc_dump_write (key, "%d", priv->queue_size); + __barrier_dump_queue (priv); + } + } + UNLOCK (&priv->lock); + +out: + return ret; +} + +struct xlator_fops fops = { + + /* Barrier Class fops */ + .rmdir = barrier_rmdir, + .unlink = barrier_unlink, + .rename = barrier_rename, + .removexattr = barrier_removexattr, + .fremovexattr = barrier_fremovexattr, + .truncate = barrier_truncate, + .ftruncate = barrier_ftruncate, + .fsync = barrier_fsync, + + /* Writes with only O_SYNC flag */ + .writev = barrier_writev, +}; + +struct xlator_dumpops dumpops = { + .priv = barrier_dump_priv, +}; + +struct xlator_cbks cbks; + +struct volume_options options[] = { + { .key = {"barrier"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "off", + .description = "When \"on\", blocks acknowledgements to application " + "for file operations such as rmdir, rename, unlink, " + "removexattr, fremovexattr, truncate, ftruncate, " + "write (with O_SYNC), fsync. It is turned \"off\" by " + "default." + }, + { .key = {"timeout"}, + .type = GF_OPTION_TYPE_TIME, + .default_value = "120", + .description = "After 'timeout' seconds since the time 'barrier' " + "option was set to \"on\", acknowledgements to file " + "operations are no longer blocked and previously " + "blocked acknowledgements are sent to the application" + }, + { .key = {NULL} }, +}; diff --git a/xlators/features/barrier/src/barrier.h b/xlators/features/barrier/src/barrier.h new file mode 100644 index 000000000..8face9f65 --- /dev/null +++ b/xlators/features/barrier/src/barrier.h @@ -0,0 +1,91 @@ +/* + Copyright (c) 2014 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __BARRIER_H__ +#define __BARRIER_H__ + +#include "barrier-mem-types.h" +#include "xlator.h" +#include "timer.h" +#include "call-stub.h" + +#define BARRIER_SAFE_ASSIGN(lock, to, value) \ + do { \ + LOCK (&(lock)); \ + { \ + to = value; \ + } \ + UNLOCK (&(lock)); \ + } while (0) + +#define BARRIER_FOP_CBK(fop_name, label, frame, this, params ...) \ + do { \ + barrier_priv_t *_priv = NULL; \ + call_stub_t *_stub = NULL; \ + gf_boolean_t _barrier_enabled= _gf_false; \ + struct list_head queue = {0, }; \ + \ + INIT_LIST_HEAD (&queue); \ + \ + _priv = this->private; \ + GF_ASSERT (_priv); \ + \ + LOCK (&_priv->lock); \ + { \ + if (_priv->barrier_enabled) { \ + _barrier_enabled = _priv->barrier_enabled;\ + \ + _stub = fop_##fop_name##_cbk_stub \ + (frame, \ + default_##fop_name##_cbk_resume,\ + params); \ + if (!_stub) { \ + __barrier_disable (this, &queue);\ + goto unlock; \ + } \ + \ + __barrier_enqueue (this, _stub); \ + } \ + } \ +unlock: \ + UNLOCK (&_priv->lock); \ + \ + if (_stub) \ + goto label; \ + \ + if (_barrier_enabled && !_stub) { \ + gf_log (this->name, GF_LOG_CRITICAL, \ + "Failed to barrier FOPs, disabling " \ + "barrier. FOP: %s, ERROR: %s", \ + #fop_name, strerror (ENOMEM)); \ + barrier_dequeue_all (this, &queue); \ + } \ + \ + STACK_UNWIND_STRICT (fop_name, frame, params); \ + goto label; \ + } while (0) + +typedef struct { + gf_timer_t *timer; + gf_boolean_t barrier_enabled; + gf_lock_t lock; + struct list_head queue; + struct timespec timeout; + uint32_t queue_size; +} barrier_priv_t; + +int __barrier_enable (xlator_t *this, barrier_priv_t *priv); +void __barrier_enqueue (xlator_t *this, call_stub_t *stub); +void __barrier_disable (xlator_t *this, struct list_head *queue); +void barrier_timeout (void *data); +void barrier_dequeue_all (xlator_t *this, struct list_head *queue); +call_stub_t *__barrier_dequeue (xlator_t *this, struct list_head *queue); + +#endif diff --git a/xlators/features/compress/src/cdc-mem-types.h b/xlators/features/compress/src/cdc-mem-types.h index efa008059..ead2c70ba 100644 --- a/xlators/features/compress/src/cdc-mem-types.h +++ b/xlators/features/compress/src/cdc-mem-types.h @@ -17,6 +17,7 @@ enum gf_cdc_mem_types { gf_cdc_mt_priv_t = gf_common_mt_end + 1, gf_cdc_mt_vec_t = gf_common_mt_end + 2, gf_cdc_mt_gzip_trailer_t = gf_common_mt_end + 3, + gf_cdc_mt_end = gf_common_mt_end + 4, }; #endif diff --git a/xlators/features/compress/src/cdc.c b/xlators/features/compress/src/cdc.c index a334c7e06..67fc52505 100644 --- a/xlators/features/compress/src/cdc.c +++ b/xlators/features/compress/src/cdc.c @@ -190,6 +190,25 @@ cdc_writev (call_frame_t *frame, } int32_t +mem_acct_init (xlator_t *this) +{ + int ret = -1; + + if (!this) + return ret; + + ret = xlator_mem_acct_init (this, gf_cdc_mt_end); + + if (ret != 0) { + gf_log(this->name, GF_LOG_ERROR, "Memory accounting init" + "failed"); + return ret; + } + + return ret; +} + +int32_t init (xlator_t *this) { int ret = -1; diff --git a/xlators/features/gfid-access/src/gfid-access.c b/xlators/features/gfid-access/src/gfid-access.c index 8e614397c..5cb6ecfbd 100644 --- a/xlators/features/gfid-access/src/gfid-access.c +++ b/xlators/features/gfid-access/src/gfid-access.c @@ -593,18 +593,19 @@ ga_virtual_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) { - int j = 0; - int i = 0; - int ret = 0; - uint64_t temp_ino = 0; - inode_t *cbk_inode = NULL; - inode_t *true_inode = NULL; - uuid_t random_gfid = {0,}; + int j = 0; + int i = 0; + int ret = 0; + uint64_t temp_ino = 0; + inode_t *cbk_inode = NULL; + inode_t *true_inode = NULL; + uuid_t random_gfid = {0,}; + inode_t *linked_inode = NULL; if (frame->local) cbk_inode = frame->local; else - cbk_inode = inode; + cbk_inode = inode_ref (inode); frame->local = NULL; if (op_ret) @@ -619,6 +620,10 @@ ga_virtual_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if its just previously discover()'d inode */ true_inode = inode_find (inode->table, buf->ia_gfid); if (!true_inode) { + /* This unref is for 'inode_ref()' done in beginning. + This is needed as cbk_inode is allocated new inode + whose unref is taken at the end*/ + inode_unref (cbk_inode); cbk_inode = inode_new (inode->table); if (!cbk_inode) { @@ -630,7 +635,8 @@ ga_virtual_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, path is not yet looked up. Use the current inode itself for now */ - inode_link (inode, NULL, NULL, buf); + linked_inode = inode_link (inode, NULL, NULL, buf); + inode = linked_inode; } else { /* 'inode_ref()' has been done in inode_find() */ inode = true_inode; @@ -674,6 +680,10 @@ unwind: STACK_UNWIND_STRICT (lookup, frame, op_ret, op_errno, cbk_inode, buf, xdata, postparent); + /* Also handles inode_unref of frame->local if done in ga_lookup */ + if (cbk_inode) + inode_unref (cbk_inode); + return 0; } @@ -819,6 +829,8 @@ ga_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) /* time do another lookup and update the context with proper inode */ op_errno = ESTALE; + /* 'inode_ref()' done in inode_find */ + inode_unref (true_inode); goto err; } @@ -833,7 +845,7 @@ discover: /* if revalidate, then we need to have the proper reference */ if (inode) { tmp_loc.inode = inode_ref (inode); - frame->local = loc->inode; + frame->local = inode_ref (loc->inode); } else { tmp_loc.inode = inode_ref (loc->inode); } diff --git a/xlators/features/glupy/Makefile.am b/xlators/features/glupy/Makefile.am index a985f42a8..060429ecf 100644 --- a/xlators/features/glupy/Makefile.am +++ b/xlators/features/glupy/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = src +SUBDIRS = src examples CLEANFILES = diff --git a/xlators/features/glupy/examples/Makefile.am b/xlators/features/glupy/examples/Makefile.am new file mode 100644 index 000000000..c26abeaaf --- /dev/null +++ b/xlators/features/glupy/examples/Makefile.am @@ -0,0 +1,5 @@ +xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features + +glupyexamplesdir = $(xlatordir)/glupy + +glupyexamples_PYTHON = negative.py helloworld.py debug-trace.py diff --git a/xlators/features/glupy/src/debug-trace.py b/xlators/features/glupy/examples/debug-trace.py index 53e76546b..6eef1b58b 100644 --- a/xlators/features/glupy/src/debug-trace.py +++ b/xlators/features/glupy/examples/debug-trace.py @@ -2,12 +2,13 @@ import sys import stat from uuid import UUID from time import strftime, localtime -from gluster import * +from gluster.glupy import * + # This translator was written primarily to test the fop entry point definitions -# and structure definitions in 'gluster.py'. -# It is similar to the debug-trace translator, one of the already available -# translator types written in C, that logs the arguments passed to the fops and -# their corresponding cbk functions. +# and structure definitions in 'glupy.py'. + +# It is similar to the C language debug-trace translator, which logs the +# arguments passed to the fops and their corresponding cbk functions. dl.get_id.restype = c_long dl.get_id.argtypes = [ POINTER(call_frame_t) ] diff --git a/xlators/features/glupy/src/helloworld.py b/xlators/features/glupy/examples/helloworld.py index 8fe403711..b565a4e5b 100644 --- a/xlators/features/glupy/src/helloworld.py +++ b/xlators/features/glupy/examples/helloworld.py @@ -1,5 +1,5 @@ import sys -from gluster import * +from gluster.glupy import * class xlator (Translator): diff --git a/xlators/features/glupy/src/negative.py b/xlators/features/glupy/examples/negative.py index 1023602b9..e7a4fc07c 100644 --- a/xlators/features/glupy/src/negative.py +++ b/xlators/features/glupy/examples/negative.py @@ -1,6 +1,6 @@ import sys from uuid import UUID -from gluster import * +from gluster.glupy import * # Negative-lookup-caching example. If a file wasn't there the last time we # looked, it's probably still not there. This translator keeps track of @@ -89,4 +89,3 @@ class xlator (Translator): dl.unwind_create(frame,cookie,this,op_ret,op_errno,fd,inode,buf, preparent,postparent,xdata) return 0 - diff --git a/xlators/features/glupy/src/Makefile.am b/xlators/features/glupy/src/Makefile.am index 21b91a164..ae7b6d14d 100644 --- a/xlators/features/glupy/src/Makefile.am +++ b/xlators/features/glupy/src/Makefile.am @@ -1,11 +1,12 @@ xlator_LTLIBRARIES = glupy.la +# Ensure GLUSTER_PYTHON_PATH is passed to glupy.so xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features - glupydir = $(xlatordir)/glupy +AM_CPPFLAGS = $(PYTHONDEV_CPPFLAGS) $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src -isystem $(BUILD_PYTHON_INC) +AM_CFLAGS = $(PYTHONDEV_CFLAGS) -Wall -fno-strict-aliasing -DGLUSTER_PYTHON_PATH=\"$(glupydir)\" $(GF_CFLAGS) -glupy_PYTHON = gluster.py negative.py helloworld.py debug-trace.py - +# Flags to build glupy.so with glupy_la_LDFLAGS = $(PYTHONDEV_LDFLAGS) -module -avoid-version -shared -nostartfiles glupy_la_SOURCES = glupy.c glupy_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ @@ -13,8 +14,8 @@ glupy_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ noinst_HEADERS = glupy.h -AM_CPPFLAGS = $(PYTHONDEV_CPPFLAGS) $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src -isystem $(BUILD_PYTHON_INC) - -AM_CFLAGS = $(PYTHONDEV_CFLAGS) -Wall -fno-strict-aliasing -DGLUSTER_PYTHON_PATH=\"$(glupydir)\" $(GF_CFLAGS) +# Install glupy.py into the Python site-packages area +pyglupydir = $(pythondir)/gluster +pyglupy_PYTHON = glupy.py CLEANFILES = diff --git a/xlators/features/glupy/src/glupy.c b/xlators/features/glupy/src/glupy.c index dc86c0071..7492124dd 100644 --- a/xlators/features/glupy/src/glupy.c +++ b/xlators/features/glupy/src/glupy.c @@ -2314,6 +2314,25 @@ get_rootunique (call_frame_t *frame) } int32_t +mem_acct_init (xlator_t *this) +{ + int ret = -1; + + if (!this) + return ret; + + ret = xlator_mem_acct_init (this, gf_glupy_mt_end); + + if (ret != 0) { + gf_log(this->name, GF_LOG_ERROR, "Memory accounting init" + " failed"); + return ret; + } + + return ret; +} + +int32_t init (xlator_t *this) { glupy_private_t *priv = NULL; @@ -2365,7 +2384,7 @@ init (xlator_t *this) goto *err_cleanup; } - gf_log (this->name, GF_LOG_ERROR, "py_mod_name = %s", module_name); + gf_log (this->name, GF_LOG_DEBUG, "py_mod_name = %s", module_name); priv->py_module = PyImport_Import(py_mod_name); Py_DECREF(py_mod_name); if (!priv->py_module) { @@ -2375,6 +2394,7 @@ init (xlator_t *this) } goto *err_cleanup; } + gf_log (this->name, GF_LOG_INFO, "Import of %s succeeded", module_name); err_cleanup = &&err_deref_module; py_init_func = PyObject_GetAttrString(priv->py_module, "xlator"); @@ -2407,7 +2427,7 @@ init (xlator_t *this) } goto *err_cleanup; } - gf_log (this->name, GF_LOG_INFO, "init returned %p", priv->py_xlator); + gf_log (this->name, GF_LOG_DEBUG, "init returned %p", priv->py_xlator); return 0; diff --git a/xlators/features/glupy/src/gluster.py b/xlators/features/glupy/src/glupy.py index a5daa77d3..a5daa77d3 100644 --- a/xlators/features/glupy/src/gluster.py +++ b/xlators/features/glupy/src/glupy.py diff --git a/xlators/features/glupy/src/setup.py.in b/xlators/features/glupy/src/setup.py.in new file mode 100644 index 000000000..1aea9875f --- /dev/null +++ b/xlators/features/glupy/src/setup.py.in @@ -0,0 +1,24 @@ +from distutils.core import setup + +DESC = """GlusterFS is a clustered file-system capable of scaling to +several petabytes. It aggregates various storage bricks over Infiniband +RDMA or TCP/IP interconnect into one large parallel network file system. +GlusterFS is one of the most sophisticated file systems in terms of +features and extensibility. It borrows a powerful concept called +Translators from GNU Hurd kernel. Much of the code in GlusterFS is in +user space and easily manageable. + +This package contains Glupy, the Python translator interface for GlusterFS.""" + +setup( + name='glusterfs-glupy', + version='@PACKAGE_VERSION@', + description='Glupy is the Python translator interface for GlusterFS', + long_description=DESC, + author='Gluster Community', + author_email='gluster-devel@nongnu.org', + license='LGPLv3', + url='http://gluster.org/', + package_dir={'gluster':''}, + packages=['gluster'] +) diff --git a/xlators/features/locks/src/entrylk.c b/xlators/features/locks/src/entrylk.c index ea6995627..dc86512be 100644 --- a/xlators/features/locks/src/entrylk.c +++ b/xlators/features/locks/src/entrylk.c @@ -62,6 +62,7 @@ new_entrylk_lock (pl_inode_t *pinode, const char *basename, entrylk_type type, newlock->volume = domain; newlock->owner = frame->root->lk_owner; newlock->frame = frame; + newlock->this = frame->this; if (conn_id) { newlock->connection_id = gf_strdup (conn_id); |