diff options
| author | Amar Tumballi <amar@gluster.com> | 2010-09-28 06:11:07 +0000 | 
|---|---|---|
| committer | Vijay Bellur <vijay@dev.gluster.com> | 2010-09-29 06:17:42 -0700 | 
| commit | 9406c06522f9e8ef8ee73f6da55937cb1fa04d22 (patch) | |
| tree | 97e30c3ba65fe11ecf45b9a88fb8ab1b9f3afc58 /xlators/features/quiesce/src | |
| parent | 3702814c02c0789d8b65b4f096cd0d37947eef3f (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/quiesce/src')
| -rw-r--r-- | xlators/features/quiesce/src/Makefile.am | 14 | ||||
| -rw-r--r-- | xlators/features/quiesce/src/quiesce-mem-types.h | 30 | ||||
| -rw-r--r-- | xlators/features/quiesce/src/quiesce.c | 1569 | ||||
| -rw-r--r-- | xlators/features/quiesce/src/quiesce.h | 37 | 
4 files changed, 1650 insertions, 0 deletions
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  | 
