summaryrefslogtreecommitdiffstats
path: root/xlators/features
diff options
context:
space:
mode:
authorAmar Tumballi <amar@gluster.com>2010-09-28 06:11:07 +0000
committerVijay Bellur <vijay@dev.gluster.com>2010-09-29 06:17:42 -0700
commit9406c06522f9e8ef8ee73f6da55937cb1fa04d22 (patch)
tree97e30c3ba65fe11ecf45b9a88fb8ab1b9f3afc58 /xlators/features
parent3702814c02c0789d8b65b4f096cd0d37947eef3f (diff)
features/quiesce: new translator
'Quiesce' is used to describe pausing or altering the state of running processes on a computer In GlusterFS context, this translator looks for CHILD_DOWN/CHILD_UP events, and will hold the requests for some time if the child node is in disconnected state current timeout is 20seconds, will be made tunable soon Signed-off-by: Amar Tumballi <amar@gluster.com> Signed-off-by: Vijay Bellur <vijay@dev.gluster.com> BUG: 1500 (Mount point should not be in-accessible between reconnect to server) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1500
Diffstat (limited to 'xlators/features')
-rw-r--r--xlators/features/Makefile.am2
-rw-r--r--xlators/features/quiesce/Makefile.am3
-rw-r--r--xlators/features/quiesce/src/Makefile.am14
-rw-r--r--xlators/features/quiesce/src/quiesce-mem-types.h30
-rw-r--r--xlators/features/quiesce/src/quiesce.c1569
-rw-r--r--xlators/features/quiesce/src/quiesce.h37
6 files changed, 1654 insertions, 1 deletions
diff --git a/xlators/features/Makefile.am b/xlators/features/Makefile.am
index 6496f3ab0c9..8b23b939b0e 100644
--- a/xlators/features/Makefile.am
+++ b/xlators/features/Makefile.am
@@ -1,3 +1,3 @@
-SUBDIRS = locks trash quota read-only access-control mac-compat #path-converter # filter
+SUBDIRS = locks trash quota read-only access-control mac-compat quiesce #path-converter # filter
CLEANFILES =
diff --git a/xlators/features/quiesce/Makefile.am b/xlators/features/quiesce/Makefile.am
new file mode 100644
index 00000000000..a985f42a877
--- /dev/null
+++ b/xlators/features/quiesce/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = src
+
+CLEANFILES =
diff --git a/xlators/features/quiesce/src/Makefile.am b/xlators/features/quiesce/src/Makefile.am
new file mode 100644
index 00000000000..e8ab4cb2417
--- /dev/null
+++ b/xlators/features/quiesce/src/Makefile.am
@@ -0,0 +1,14 @@
+xlator_LTLIBRARIES = quiesce.la
+xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features
+
+quiesce_la_LDFLAGS = -module -avoidversion
+
+quiesce_la_SOURCES = quiesce.c
+quiesce_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
+
+noinst_HEADERS = quiesce.h quiesce-mem-types.h
+
+AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS) \
+ -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS)
+
+CLEANFILES =
diff --git a/xlators/features/quiesce/src/quiesce-mem-types.h b/xlators/features/quiesce/src/quiesce-mem-types.h
new file mode 100644
index 00000000000..07f2e97c65b
--- /dev/null
+++ b/xlators/features/quiesce/src/quiesce-mem-types.h
@@ -0,0 +1,30 @@
+/*
+ Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ 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.
+
+ 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 this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifndef __QUIESCE_MEM_TYPES_H__
+#define __QUIESCE_MEM_TYPES_H__
+
+#include "mem-types.h"
+
+enum gf_quiesce_mem_types_ {
+ gf_quiesce_mt_priv_t = gf_common_mt_end + 1,
+ gf_quiesce_mt_end
+};
+#endif
diff --git a/xlators/features/quiesce/src/quiesce.c b/xlators/features/quiesce/src/quiesce.c
new file mode 100644
index 00000000000..8d062cb5105
--- /dev/null
+++ b/xlators/features/quiesce/src/quiesce.c
@@ -0,0 +1,1569 @@
+/*
+ Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ 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.
+
+ 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 this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "quiesce.h"
+#include "defaults.h"
+#include "call-stub.h"
+
+/* Quiesce Specific Functions */
+call_stub_t *
+gf_quiesce_dequeue (quiesce_priv_t *priv)
+{
+ call_stub_t *stub = NULL;
+
+ if (list_empty (&priv->req))
+ return NULL;
+
+ LOCK (&priv->lock);
+ {
+ stub = list_entry (priv->req.next, call_stub_t, list);
+ list_del_init (&stub->list);
+ priv->queue_size--;
+ }
+ UNLOCK (&priv->lock);
+
+ return stub;
+}
+
+
+void
+gf_quiesce_enqueue (quiesce_priv_t *priv, call_stub_t *stub)
+{
+ LOCK (&priv->lock);
+ {
+ list_add_tail (&stub->list, &priv->req);
+ priv->queue_size++;
+ }
+ UNLOCK (&priv->lock);
+
+ return;
+}
+
+
+void *
+gf_quiesce_dequeue_start (void *data)
+{
+ xlator_t *this = NULL;
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ this = data;
+ priv = this->private;
+ THIS = this;
+
+ while (!list_empty (&priv->req)) {
+ stub = gf_quiesce_dequeue (priv);
+ if (stub) {
+ call_resume (stub);
+ }
+ }
+
+ return 0;
+}
+
+
+void
+gf_quiesce_timeout (void *data)
+{
+ xlator_t *this = NULL;
+ quiesce_priv_t *priv = NULL;
+ int need_dequeue = 0;
+
+ this = data;
+ priv = this->private;
+ THIS = this;
+
+ LOCK (&priv->lock);
+ {
+ priv->pass_through = _gf_true;
+ need_dequeue = (priv->queue_size)? 1:0;
+ }
+ UNLOCK (&priv->lock);
+
+ gf_quiesce_dequeue_start (this);
+
+ return;
+}
+
+/* FOP */
+
+int32_t
+quiesce_fgetxattr (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ const char *name)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_fgetxattr_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fgetxattr,
+ fd,
+ name);
+ return 0;
+ }
+
+ stub = fop_fgetxattr_stub (frame, default_fgetxattr_resume, fd, name);
+ if (!stub) {
+ STACK_UNWIND_STRICT (fgetxattr, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_fsetxattr (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ dict_t *dict,
+ int32_t flags)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_fsetxattr_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fsetxattr,
+ fd,
+ dict,
+ flags);
+ return 0;
+ }
+
+ stub = fop_fsetxattr_stub (frame, default_fsetxattr_resume,
+ fd, dict, flags);
+ if (!stub) {
+ STACK_UNWIND_STRICT (fsetxattr, frame, -1, ENOMEM);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_setxattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *dict,
+ int32_t flags)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_setxattr_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->setxattr,
+ loc,
+ dict,
+ flags);
+ return 0;
+ }
+
+ stub = fop_setxattr_stub (frame, default_setxattr_resume,
+ loc, dict, flags);
+ if (!stub) {
+ STACK_UNWIND_STRICT (setxattr, frame, -1, ENOMEM);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_statfs (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_statfs_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->statfs,
+ loc);
+ return 0;
+ }
+
+ stub = fop_statfs_stub (frame, default_statfs_resume, loc);
+ if (!stub) {
+ STACK_UNWIND_STRICT (statfs, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_fsyncdir (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t flags)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_fsyncdir_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fsyncdir,
+ fd,
+ flags);
+ return 0;
+ }
+
+ stub = fop_fsyncdir_stub (frame, default_fsyncdir_resume, fd, flags);
+ if (!stub) {
+ STACK_UNWIND_STRICT (fsyncdir, frame, -1, ENOMEM);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_opendir (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc, fd_t *fd)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_opendir_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->opendir,
+ loc, fd);
+ return 0;
+ }
+
+ stub = fop_opendir_stub (frame, default_opendir_resume, loc, fd);
+ if (!stub) {
+ STACK_UNWIND_STRICT (opendir, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_fstat (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_fstat_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fstat,
+ fd);
+ return 0;
+ }
+
+ stub = fop_fstat_stub (frame, default_fstat_resume, fd);
+ if (!stub) {
+ STACK_UNWIND_STRICT (fstat, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_fsync (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t flags)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_fsync_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fsync,
+ fd,
+ flags);
+ return 0;
+ }
+
+ stub = fop_fsync_stub (frame, default_fsync_resume, fd, flags);
+ if (!stub) {
+ STACK_UNWIND_STRICT (fsync, frame, -1, ENOMEM, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_flush (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_flush_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->flush,
+ fd);
+ return 0;
+ }
+
+ stub = fop_flush_stub (frame, default_flush_resume, fd);
+ if (!stub) {
+ STACK_UNWIND_STRICT (flush, frame, -1, ENOMEM);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_writev (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ struct iovec *vector,
+ int32_t count,
+ off_t off,
+ struct iobref *iobref)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_writev_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->writev,
+ fd,
+ vector,
+ count,
+ off,
+ iobref);
+ return 0;
+ }
+
+ stub = fop_writev_stub (frame, default_writev_resume,
+ fd, vector, count, off, iobref);
+ if (!stub) {
+ STACK_UNWIND_STRICT (writev, frame, -1, ENOMEM, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_readv (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t offset)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_readv_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->readv,
+ fd,
+ size,
+ offset);
+ return 0;
+ }
+
+ stub = fop_readv_stub (frame, default_readv_resume, fd, size, offset);
+ if (!stub) {
+ STACK_UNWIND_STRICT (readv, frame, -1, ENOMEM,
+ NULL, 0, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+
+int32_t
+quiesce_open (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flags, fd_t *fd,
+ int32_t wbflags)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_open_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->open,
+ loc, flags, fd, wbflags);
+ return 0;
+ }
+
+ stub = fop_open_stub (frame, default_open_resume, loc,
+ flags, fd, wbflags);
+ if (!stub) {
+ STACK_UNWIND_STRICT (open, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_create (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, int32_t flags, mode_t mode,
+ fd_t *fd, dict_t *params)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame, default_create_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->create,
+ loc, flags, mode, fd, params);
+ return 0;
+ }
+
+ stub = fop_create_stub (frame, default_create_resume,
+ loc, flags, mode, fd, params);
+ if (!stub) {
+ STACK_UNWIND_STRICT (create, frame, -1, ENOMEM,
+ NULL, NULL, NULL, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_link (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_link_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->link,
+ oldloc, newloc);
+ return 0;
+ }
+
+ stub = fop_link_stub (frame, default_link_resume, oldloc, newloc);
+ if (!stub) {
+ STACK_UNWIND_STRICT (link, frame, -1, ENOMEM,
+ NULL, NULL, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_rename (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_rename_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->rename,
+ oldloc, newloc);
+ return 0;
+ }
+
+ stub = fop_rename_stub (frame, default_rename_resume, oldloc, newloc);
+ if (!stub) {
+ STACK_UNWIND_STRICT (rename, frame, -1, ENOMEM,
+ NULL, NULL, NULL, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+
+int
+quiesce_symlink (call_frame_t *frame, xlator_t *this,
+ const char *linkpath, loc_t *loc, dict_t *params)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame, default_symlink_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->symlink,
+ linkpath, loc, params);
+ return 0;
+ }
+
+ stub = fop_symlink_stub (frame, default_symlink_resume,
+ linkpath, loc, params);
+ if (!stub) {
+ STACK_UNWIND_STRICT (symlink, frame, -1, ENOMEM,
+ NULL, NULL, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_rmdir (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_rmdir_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->rmdir,
+ loc);
+ return 0;
+ }
+
+ stub = fop_rmdir_stub (frame, default_rmdir_resume, loc);
+ if (!stub) {
+ STACK_UNWIND_STRICT (rmdir, frame, -1, ENOMEM, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_unlink (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_unlink_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->unlink,
+ loc);
+ return 0;
+ }
+
+ stub = fop_unlink_stub (frame, default_unlink_resume, loc);
+ if (!stub) {
+ STACK_UNWIND_STRICT (unlink, frame, -1, ENOMEM, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int
+quiesce_mkdir (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, mode_t mode, dict_t *params)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame, default_mkdir_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->mkdir,
+ loc, mode, params);
+ return 0;
+ }
+
+ stub = fop_mkdir_stub (frame, default_mkdir_resume,
+ loc, mode, params);
+ if (!stub) {
+ STACK_UNWIND_STRICT (mkdir, frame, -1, ENOMEM,
+ NULL, NULL, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+
+int
+quiesce_mknod (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, mode_t mode, dev_t rdev, dict_t *parms)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame, default_mknod_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->mknod,
+ loc, mode, rdev, parms);
+ return 0;
+ }
+
+ stub = fop_mknod_stub (frame, default_mknod_resume,
+ loc, mode, rdev, parms);
+ if (!stub) {
+ STACK_UNWIND_STRICT (mknod, frame, -1, ENOMEM,
+ NULL, NULL, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_readlink (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ size_t size)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_readlink_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->readlink,
+ loc,
+ size);
+ return 0;
+ }
+
+ stub = fop_readlink_stub (frame, default_readlink_resume, loc, size);
+ if (!stub) {
+ STACK_UNWIND_STRICT (readlink, frame, -1, ENOMEM, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+
+int32_t
+quiesce_access (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t mask)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_access_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->access,
+ loc,
+ mask);
+ return 0;
+ }
+
+ stub = fop_access_stub (frame, default_access_resume, loc, mask);
+ if (!stub) {
+ STACK_UNWIND_STRICT (access, frame, -1, ENOMEM);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_ftruncate (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ off_t offset)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_ftruncate_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->ftruncate,
+ fd,
+ offset);
+ return 0;
+ }
+
+ stub = fop_ftruncate_stub (frame, default_ftruncate_resume, fd, offset);
+ if (!stub) {
+ STACK_UNWIND_STRICT (ftruncate, frame, -1, ENOMEM, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_getxattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_getxattr_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->getxattr,
+ loc,
+ name);
+ return 0;
+ }
+
+ stub = fop_getxattr_stub (frame, default_getxattr_resume, loc, name);
+ if (!stub) {
+ STACK_UNWIND_STRICT (getxattr, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+
+int32_t
+quiesce_xattrop (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ gf_xattrop_flags_t flags,
+ dict_t *dict)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_xattrop_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->xattrop,
+ loc,
+ flags,
+ dict);
+ return 0;
+ }
+
+ stub = fop_xattrop_stub (frame, default_xattrop_resume,
+ loc, flags, dict);
+ if (!stub) {
+ STACK_UNWIND_STRICT (xattrop, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_fxattrop (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ gf_xattrop_flags_t flags,
+ dict_t *dict)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_fxattrop_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fxattrop,
+ fd,
+ flags,
+ dict);
+ return 0;
+ }
+
+ stub = fop_fxattrop_stub (frame, default_fxattrop_resume,
+ fd, flags, dict);
+ if (!stub) {
+ STACK_UNWIND_STRICT (fxattrop, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_removexattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_removexattr_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->removexattr,
+ loc,
+ name);
+ return 0;
+ }
+
+ stub = fop_removexattr_stub (frame, default_removexattr_resume,
+ loc, name);
+ if (!stub) {
+ STACK_UNWIND_STRICT (removexattr, frame, -1, ENOMEM);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_lk (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t cmd,
+ struct flock *lock)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_lk_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->lk,
+ fd,
+ cmd,
+ lock);
+ return 0;
+ }
+
+ stub = fop_lk_stub (frame, default_lk_resume, fd, cmd, lock);
+ if (!stub) {
+ STACK_UNWIND_STRICT (lk, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+
+int32_t
+quiesce_inodelk (call_frame_t *frame, xlator_t *this,
+ const char *volume, loc_t *loc, int32_t cmd,
+ struct flock *lock)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_inodelk_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->inodelk,
+ volume, loc, cmd, lock);
+ return 0;
+ }
+
+ stub = fop_inodelk_stub (frame, default_inodelk_resume,
+ volume, loc, cmd, lock);
+ if (!stub) {
+ STACK_UNWIND_STRICT (inodelk, frame, -1, ENOMEM);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_finodelk (call_frame_t *frame, xlator_t *this,
+ const char *volume, fd_t *fd, int32_t cmd, struct flock *lock)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_finodelk_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->finodelk,
+ volume, fd, cmd, lock);
+ return 0;
+ }
+
+ stub = fop_finodelk_stub (frame, default_finodelk_resume,
+ volume, fd, cmd, lock);
+ if (!stub) {
+ STACK_UNWIND_STRICT (finodelk, frame, -1, ENOMEM);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_entrylk (call_frame_t *frame, xlator_t *this,
+ const char *volume, loc_t *loc, const char *basename,
+ entrylk_cmd cmd, entrylk_type type)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame, default_entrylk_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->entrylk,
+ volume, loc, basename, cmd, type);
+ return 0;
+ }
+
+ stub = fop_entrylk_stub (frame, default_entrylk_resume,
+ volume, loc, basename, cmd, type);
+ if (!stub) {
+ STACK_UNWIND_STRICT (entrylk, frame, -1, ENOMEM);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_fentrylk (call_frame_t *frame, xlator_t *this,
+ const char *volume, fd_t *fd, const char *basename,
+ entrylk_cmd cmd, entrylk_type type)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame, default_fentrylk_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fentrylk,
+ volume, fd, basename, cmd, type);
+ return 0;
+ }
+
+ stub = fop_fentrylk_stub (frame, default_fentrylk_resume,
+ volume, fd, basename, cmd, type);
+ if (!stub) {
+ STACK_UNWIND_STRICT (fentrylk, frame, -1, ENOMEM);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_rchecksum (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd, off_t offset,
+ int32_t len)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_rchecksum_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->rchecksum,
+ fd, offset, len);
+ return 0;
+ }
+
+ stub = fop_rchecksum_stub (frame, default_rchecksum_resume,
+ fd, offset, len);
+ if (!stub) {
+ STACK_UNWIND_STRICT (rchecksum, frame, -1, ENOMEM, 0, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+
+int32_t
+quiesce_readdir (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t off)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_readdir_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->readdir,
+ fd, size, off);
+ return 0;
+ }
+
+ stub = fop_readdir_stub (frame, default_readdir_resume, fd, size, off);
+ if (!stub) {
+ STACK_UNWIND_STRICT (readdir, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+
+int32_t
+quiesce_readdirp (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t off)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_readdirp_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->readdirp,
+ fd, size, off);
+ return 0;
+ }
+
+ stub = fop_readdirp_stub (frame, default_readdirp_resume, fd, size, off);
+ if (!stub) {
+ STACK_UNWIND_STRICT (readdirp, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_setattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ struct iatt *stbuf,
+ int32_t valid)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_setattr_cbk,
+ FIRST_CHILD (this),
+ FIRST_CHILD (this)->fops->setattr,
+ loc, stbuf, valid);
+ return 0;
+ }
+
+ stub = fop_setattr_stub (frame, default_setattr_resume,
+ loc, stbuf, valid);
+ if (!stub) {
+ STACK_UNWIND_STRICT (setattr, frame, -1, ENOMEM, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_truncate (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ off_t offset)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_truncate_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->truncate,
+ loc,
+ offset);
+ return 0;
+ }
+
+ stub = fop_truncate_stub (frame, default_truncate_resume, loc, offset);
+ if (!stub) {
+ STACK_UNWIND_STRICT (truncate, frame, -1, ENOMEM, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_stat (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_stat_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->stat,
+ loc);
+ return 0;
+ }
+
+ stub = fop_stat_stub (frame, default_stat_resume, loc);
+ if (!stub) {
+ STACK_UNWIND_STRICT (stat, frame, -1, ENOMEM, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_lookup (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *xattr_req)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_lookup_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->lookup,
+ loc,
+ xattr_req);
+ return 0;
+ }
+
+ stub = fop_lookup_stub (frame, default_lookup_resume, loc, xattr_req);
+ if (!stub) {
+ STACK_UNWIND_STRICT (lookup, frame, -1, ENOMEM,
+ NULL, NULL, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+quiesce_fsetattr (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ struct iatt *stbuf,
+ int32_t valid)
+{
+ quiesce_priv_t *priv = NULL;
+ call_stub_t *stub = NULL;
+
+ priv = this->private;
+
+ if (priv->pass_through) {
+ STACK_WIND (frame,
+ default_fsetattr_cbk,
+ FIRST_CHILD (this),
+ FIRST_CHILD (this)->fops->fsetattr,
+ fd, stbuf, valid);
+ return 0;
+ }
+
+ stub = fop_fsetattr_stub (frame, default_fsetattr_resume,
+ fd, stbuf, valid);
+ if (!stub) {
+ STACK_UNWIND_STRICT (fsetattr, frame, -1, ENOMEM, NULL, NULL);
+ return 0;
+ }
+
+ gf_quiesce_enqueue (priv, stub);
+
+ return 0;
+}
+
+int32_t
+mem_acct_init (xlator_t *this)
+{
+ int ret = -1;
+
+ ret = xlator_mem_acct_init (this, gf_quiesce_mt_end + 1);
+
+ return ret;
+}
+
+int
+init (xlator_t *this)
+{
+ int ret = -1;
+ quiesce_priv_t *priv = NULL;
+
+ if (!this->children || this->children->next) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "'quiesce' 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_quiesce_mt_priv_t);
+ if (!priv)
+ goto out;
+
+ LOCK_INIT (&priv->lock);
+ priv->pass_through = _gf_false;
+
+ INIT_LIST_HEAD (&priv->req);
+
+ this->private = priv;
+ ret = 0;
+out:
+ return ret;
+}
+
+void
+fini (xlator_t *this)
+{
+ quiesce_priv_t *priv = NULL;
+
+ priv = this->private;
+ if (!priv)
+ goto out;
+ this->private = NULL;
+
+ LOCK_DESTROY (&priv->lock);
+ GF_FREE (priv);
+out:
+ return;
+}
+
+int
+notify (xlator_t *this, int event, void *data, ...)
+{
+ int ret = 0;
+ quiesce_priv_t *priv = NULL;
+ struct timeval timeout = {0,};
+
+ priv = this->private;
+ if (!priv)
+ goto out;
+
+ switch (event) {
+ case GF_EVENT_CHILD_UP:
+ {
+ ret = pthread_create (&priv->thr, NULL, gf_quiesce_dequeue_start,
+ this);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to create the quiesce-dequeue thread");
+ }
+
+ LOCK (&priv->lock);
+ {
+ priv->pass_through = _gf_true;
+ }
+ UNLOCK (&priv->lock);
+ break;
+ }
+ case GF_EVENT_CHILD_DOWN:
+ LOCK (&priv->lock);
+ {
+ priv->pass_through = _gf_false;
+ }
+ UNLOCK (&priv->lock);
+
+ if (!priv->timer) {
+ timeout.tv_sec = 20;
+ timeout.tv_usec = 0;
+
+ gf_timer_call_cancel (this->ctx, priv->timer);
+ priv->timer = gf_timer_call_after (this->ctx,
+ timeout,
+ gf_quiesce_timeout,
+ (void *) this);
+
+ if (priv->timer == NULL) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Cannot create timer");
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ ret = default_notify (this, event, data);
+out:
+ return ret;
+}
+
+
+struct xlator_fops fops = {
+ .lookup = quiesce_lookup,
+ .mknod = quiesce_mknod,
+ .create = quiesce_create,
+ .stat = quiesce_stat,
+ .fstat = quiesce_fstat,
+ .truncate = quiesce_truncate,
+ .ftruncate = quiesce_ftruncate,
+ .access = quiesce_access,
+ .readlink = quiesce_readlink,
+ .setxattr = quiesce_setxattr,
+ .getxattr = quiesce_getxattr,
+ .removexattr = quiesce_removexattr,
+ .open = quiesce_open,
+ .readv = quiesce_readv,
+ .writev = quiesce_writev,
+ .flush = quiesce_flush,
+ .fsync = quiesce_fsync,
+ .statfs = quiesce_statfs,
+ .lk = quiesce_lk,
+ .opendir = quiesce_opendir,
+ .readdir = quiesce_readdir,
+ .readdirp = quiesce_readdirp,
+ .fsyncdir = quiesce_fsyncdir,
+ .symlink = quiesce_symlink,
+ .unlink = quiesce_unlink,
+ .link = quiesce_link,
+ .mkdir = quiesce_mkdir,
+ .rmdir = quiesce_rmdir,
+ .rename = quiesce_rename,
+ .inodelk = quiesce_inodelk,
+ .finodelk = quiesce_finodelk,
+ .entrylk = quiesce_entrylk,
+ .fentrylk = quiesce_fentrylk,
+ .xattrop = quiesce_xattrop,
+ .fxattrop = quiesce_fxattrop,
+ .setattr = quiesce_setattr,
+ .fsetattr = quiesce_fsetattr,
+};
+
+struct xlator_dumpops dumpops = {
+};
+
+
+struct xlator_cbks cbks = {
+};
+
+
+struct volume_options options[] = {
+ { .key = {NULL} },
+};
diff --git a/xlators/features/quiesce/src/quiesce.h b/xlators/features/quiesce/src/quiesce.h
new file mode 100644
index 00000000000..2ff7032ef00
--- /dev/null
+++ b/xlators/features/quiesce/src/quiesce.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ 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.
+
+ 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 this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifndef __QUIESCE_H__
+#define __QUIESCE_H__
+
+#include "quiesce-mem-types.h"
+#include "xlator.h"
+#include "timer.h"
+
+typedef struct {
+ gf_timer_t *timer;
+ gf_boolean_t pass_through;
+ gf_lock_t lock;
+ struct list_head req;
+ int queue_size;
+ pthread_t thr;
+} quiesce_priv_t;
+
+#endif