diff options
| author | Junaid <junaid@gluster.com> | 2011-01-27 05:23:31 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2011-01-27 03:16:57 -0800 | 
| commit | a2a92b99fc031544ff8a87861d34b2bbbdd2753c (patch) | |
| tree | a6487aba2d552a583e514ea9e6a2714ec395b3bb /xlators | |
| parent | 73bce15b61755509de23d32646135254d369a2f6 (diff) | |
adding marker translator
Signed-off-by: Junaid <junaid@gluster.com>
Signed-off-by: Csaba Henk <csaba@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 2310 (georeplication)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2310
Diffstat (limited to 'xlators')
| -rw-r--r-- | xlators/features/Makefile.am | 4 | ||||
| -rw-r--r-- | xlators/features/marker/Makefile.am | 3 | ||||
| -rw-r--r-- | xlators/features/marker/src/Makefile.am | 15 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker-mem-types.h | 32 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker.c | 1420 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker.h | 65 | 
6 files changed, 1537 insertions, 2 deletions
diff --git a/xlators/features/Makefile.am b/xlators/features/Makefile.am index 8b23b939b0e..96e503938a8 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 quiesce #path-converter # filter +SUBDIRS = locks trash quota read-only access-control mac-compat quiesce marker#path-converter # filter -CLEANFILES =  +CLEANFILES = diff --git a/xlators/features/marker/Makefile.am b/xlators/features/marker/Makefile.am new file mode 100644 index 00000000000..a985f42a877 --- /dev/null +++ b/xlators/features/marker/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src + +CLEANFILES = diff --git a/xlators/features/marker/src/Makefile.am b/xlators/features/marker/src/Makefile.am new file mode 100644 index 00000000000..58b12b3f594 --- /dev/null +++ b/xlators/features/marker/src/Makefile.am @@ -0,0 +1,15 @@ +xlator_LTLIBRARIES = marker.la +xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features + +marker_la_LDFLAGS = -module -avoidversion + +marker_la_SOURCES = marker.c +marker_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la + +noinst_HEADERS = marker-mem-types.h marker.h $(top_builddir)/xlators/lib/src/libxlator.h + +AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -fno-strict-aliasing -D$(GF_HOST_OS) \ +        -I$(top_srcdir)/libglusterfs/src -I$(top_srcdir)/xlators/lib/src $(GF_CFLAGS) -shared -nostartfiles + +CLEANFILES = + diff --git a/xlators/features/marker/src/marker-mem-types.h b/xlators/features/marker/src/marker-mem-types.h new file mode 100644 index 00000000000..3936ef794fc --- /dev/null +++ b/xlators/features/marker/src/marker-mem-types.h @@ -0,0 +1,32 @@ +/* +   Copyright (c) 2008-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 Affero 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 +   Affero General Public License for more details. + +   You should have received a copy of the GNU Affero General Public License +   along with this program.  If not, see +   <http://www.gnu.org/licenses/>. +*/ + +#ifndef __MARKER_MEM_TYPES_H__ +#define __MARKER_MEM_TYPES_H__ + +#include "mem-types.h" + +enum gf_marker_mem_types_ { +        gf_marker_mt_marker_local_t = gf_common_mt_end + 1, +        gf_marker_mt_marker_conf_t, +        gf_marker_mt_loc_t, +        gf_marker_mt_volume_mark, +        gf_marker_mt_end +}; +#endif diff --git a/xlators/features/marker/src/marker.c b/xlators/features/marker/src/marker.c new file mode 100644 index 00000000000..a66b0fd03e0 --- /dev/null +++ b/xlators/features/marker/src/marker.c @@ -0,0 +1,1420 @@ +/*Copyright (c) 2008-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 "xlator.h" +#include "defaults.h" +#include "libxlator.h" +#include "marker.h" +#include "marker-mem-types.h" + +void +fini (xlator_t *this); + +int32_t +marker_start_setxattr (call_frame_t *, xlator_t *); + +int +marker_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path) +{ +        int     ret = -1; + +        if (!loc) +                return ret; + +        if (inode) { +                loc->inode = inode_ref (inode); +                loc->ino = inode->ino; +        } + +        if (parent) +                loc->parent = inode_ref (parent); + +        loc->path = gf_strdup (path); +        if (!loc->path) { +                gf_log ("loc fill", GF_LOG_ERROR, "strdup failed"); +                goto loc_wipe; +        } + +        loc->name = strrchr (loc->path, '/'); +        if (loc->name) +                loc->name++; +        else +                goto loc_wipe; + +        ret = 0; +loc_wipe: +        if (ret < 0) +                loc_wipe (loc); + +        return ret; +} + +int +marker_inode_loc_fill (inode_t *inode, loc_t *loc) +{ +        char            *resolvedpath = NULL; +        inode_t         *parent       = NULL; +        int              ret          = -1; + +        if ((!inode) || (!loc)) +                return ret; + +        if ((inode) && (inode->ino == 1)) { +                loc->parent = NULL; +                goto ignore_parent; +        } + +        parent = inode_parent (inode, 0, NULL); +        if (!parent) { +                goto err; +        } + +ignore_parent: +        ret = inode_path (inode, NULL, &resolvedpath); +        if (ret < 0) +                goto err; + +        ret = marker_loc_fill (loc, inode, parent, resolvedpath); +        if (ret < 0) +                goto err; + +err: +        if (parent) +                inode_unref (parent); + +        if (resolvedpath) +                GF_FREE (resolvedpath); + +        return ret; +} + +int32_t +marker_trav_parent (marker_local_t *local) +{ +        int32_t ret = 0; +        loc_t   loc = {0, }; + +        ret = marker_inode_loc_fill (local->loc.parent, &loc); + +        if (ret == -1) +                goto out; + +        loc_wipe (&local->loc); + +        local->loc = loc; +out: +        return ret; +} + +int32_t +marker_error_handler (xlator_t *this) +{ +        marker_conf_t *priv = NULL; + +        priv = (marker_conf_t *) this->private; + +        unlink (priv->timestamp_file); + +        return 0; +} + +int32_t +marker_free_local (marker_local_t *local) +{ +        loc_wipe (&local->loc); + +        GF_FREE (local); + +        return 0; +} + +int32_t +stat_stampfile (xlator_t *this, marker_conf_t *priv, struct volume_mark **status) +{ +        struct stat          buf; +        struct volume_mark  *vol_mark; + +        vol_mark = GF_CALLOC (sizeof (struct volume_mark), 1, +                               gf_marker_mt_volume_mark); + +        vol_mark->major = 1; +        vol_mark->minor = 0; + +        GF_ASSERT (sizeof (priv->volume_uuid_bin) == 16); +        memcpy (vol_mark->uuid, priv->volume_uuid_bin, 16); + +        if (stat (priv->timestamp_file, &buf) != -1) { +                vol_mark->retval = 0; +                vol_mark->sec = htonl (buf.st_ctime); +                vol_mark->usec = htonl (ST_CTIM_NSEC (&buf)/1000); +        } else +                vol_mark->retval = 0; + +        *status = vol_mark; + +        return 0; +} + +int32_t +marker_getxattr_stampfile_cbk (call_frame_t *frame, xlator_t *this, +                                const char *name, struct volume_mark *vol_mark) +{ +        int32_t   ret; +        dict_t   *dict = NULL; + +        if (vol_mark == NULL){ +                STACK_UNWIND_STRICT (getxattr, frame, -1, ENOMEM, NULL); + +                goto out; +        } + +        dict = dict_new (); + +        ret = dict_set_bin (dict, (char *)name, vol_mark, +                              sizeof (struct volume_mark)); + +        STACK_UNWIND_STRICT (getxattr, frame, 0, 0, dict); + +        dict_unref (dict); +out: +        return 0; +} + +int32_t +call_from_special_client (call_frame_t *frame, xlator_t *this, const char *name) +{ +        struct volume_mark     *vol_mark   = NULL; +        marker_conf_t          *priv       = NULL; +        gf_boolean_t            ret        = _gf_true; + +        priv = (marker_conf_t *)this->private; + +        if (frame->root->pid != -1 || name == NULL || +            strcmp (name, MARKER_XATTR_PREFIX "." VOLUME_MARK) != 0) { +                ret = _gf_false; +                goto out; +        } + +        stat_stampfile (this, priv, &vol_mark); + +        marker_getxattr_stampfile_cbk (frame, this, name, vol_mark); +out: +        return ret; +} + +int32_t +marker_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                      int32_t op_ret, int32_t op_errno, dict_t *dict) +{ +        STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict); +        return 0; +} + +int32_t +marker_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, +                 const char *name) +{ +        gf_boolean_t ret; + +        gf_log (this->name, GF_LOG_DEBUG, "USER:PID = %d", frame->root->pid); + +        ret = call_from_special_client (frame, this, name); + +        if (ret == _gf_false) +                STACK_WIND (frame, marker_getxattr_cbk, FIRST_CHILD(this), +                            FIRST_CHILD(this)->fops->getxattr, loc, name); + +        return 0; +} + + +int32_t +marker_setxattr_done (call_frame_t *frame) +{ +        marker_local_t *local = NULL; + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_DESTROY (frame->root); + +        marker_free_local (local); + +        return 0; +} + +int +marker_specific_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                              int32_t op_ret, int32_t op_errno) +{ +        int32_t         ret   = 0; +        int32_t         done  = 0; +        marker_local_t *local = NULL; + +        local = (marker_local_t*) frame->local; + +        if (op_ret == -1 && op_errno == ENOSPC) { +                marker_error_handler (this); +                done = 1; +                goto out; +        } + +        if (strcmp (local->loc.path, "/") == 0) { +                done = 1; +                goto out; +        } + +        ret = marker_trav_parent (local); + +        if (ret == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "Error occured " +                        "while traversing to the parent, stopping marker"); + +                done = 1; + +                goto out; +        } + +        marker_start_setxattr (frame, this); + +out: +        if (done) { +                marker_setxattr_done (frame); +        } + +        return 0; +} + +int32_t +marker_start_setxattr (call_frame_t *frame, xlator_t *this) +{ +        int32_t          ret   = 0; +        dict_t          *dict  = NULL; +        marker_local_t  *local = NULL; +        marker_conf_t   *priv  = NULL; + +        priv = this->private; + +        local = (marker_local_t*) frame->local; + +        dict = dict_new (); + +        ret = dict_set_static_bin (dict, priv->marker_xattr, +                                   (void *)local->timebuf, 8); + +        gf_log (this->name, GF_LOG_DEBUG, "path = %s", local->loc.path); + +        STACK_WIND (frame, marker_specific_setxattr_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->setxattr, &local->loc, dict, 0); + +        dict_unref (dict); + +        return 0; +} + +void +marker_gettimeofday (marker_local_t *local) +{ +        struct timeval tv; + +        gettimeofday (&tv, NULL); + +        local->timebuf [0] = htonl (tv.tv_sec); +        local->timebuf [1] = htonl (tv.tv_usec); + +        return; +} + +int32_t +marker_create_frame (xlator_t *this, marker_local_t *local) +{ +        call_frame_t *frame = NULL; + +        frame = create_frame (this, this->ctx->pool); + +        frame->local = (void *) local; + +        marker_start_setxattr (frame, this); + +        return 0; +} + +int32_t +update_marks (xlator_t *this, marker_local_t *local, int32_t ret) +{ +        if (ret == -1 || local->pid < 0) +                marker_free_local (local); +        else { +                marker_gettimeofday (local); + +                marker_create_frame (this, local); +        } + +        return 0; +} + +int32_t +marker_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                   int32_t op_ret, int32_t op_errno, inode_t *inode, +                   struct iatt *buf, struct iatt *preparent, +                   struct iatt *postparent) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "error occurred " +                        "while Creating a file %s", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (mkdir, frame, op_ret, op_errno, inode, +                             buf, preparent, postparent); + +        update_marks (this, local, ret); + +        return 0; +} + +int +marker_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, +              dict_t *params) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_mkdir_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->mkdir, loc, mode, params); + +        return 0; +err: +        STACK_UNWIND_STRICT (mkdir, frame, -1, ENOMEM, NULL, +                             NULL, NULL, NULL); +        return 0; +} + +int32_t +marker_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                    int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode, +                    struct iatt *buf, struct iatt *preparent, +                    struct iatt *postparent) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "error occurred " +                        "while Creating a file %s", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (create, frame, op_ret, op_errno, fd, inode, buf, +                             preparent, postparent); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, +                mode_t mode, fd_t *fd, dict_t *params) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_create_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->create, loc, flags, mode, fd, +                    params); +        return 0; +err: +        STACK_UNWIND_STRICT (create, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, NULL); + +        return 0; +} + +int32_t +marker_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) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "error occurred " +                        "while write, %s", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, prebuf, postbuf); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_writev (call_frame_t *frame, +                        xlator_t *this, +                        fd_t *fd, +                        struct iovec *vector, +                        int32_t count, +                        off_t offset, +                        struct iobref *iobref) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = marker_inode_loc_fill (fd->inode, &local->loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_writev_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->writev, fd, vector, count, offset, +                    iobref); +        return 0; +err: +        STACK_UNWIND_STRICT (writev, frame, -1, ENOMEM, NULL, NULL); + +        return 0; +} + +int32_t +marker_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) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "error occurred " +                        "rmdir %s", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (rmdir, frame, op_ret, op_errno, preparent, +                             postparent); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_rmdir_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->rmdir, loc, flags); +        return 0; +err: +        STACK_UNWIND_STRICT (rmdir, frame, -1, ENOMEM, NULL, NULL); + +        return 0; +} + +int32_t +marker_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) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, +                        "%s occurred in unlink", strerror (op_errno)); + +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno, preparent, +                             postparent); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_unlink_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->unlink, loc); +        return 0; +err: +        STACK_UNWIND_STRICT (unlink, frame, -1, ENOMEM, NULL, NULL); + +        return 0; +} + +int32_t +marker_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                  int32_t op_ret, int32_t op_errno, inode_t *inode, +                  struct iatt *buf, struct iatt *preparent, +                  struct iatt *postparent) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "%s occured while " +                        "linking a file ", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (link, frame, op_ret, op_errno, inode, buf, +                             preparent, postparent); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, newloc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_link_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->link, oldloc, newloc); +        return 0; +err: +        STACK_UNWIND_STRICT (link, frame, -1, ENOMEM, NULL, NULL, NULL, NULL); + +        return 0; +} + +int32_t +marker_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) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "%s occured while " +                        "renaming a file ", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (rename, frame, op_ret, op_errno, buf, preoldparent, +                             postoldparent, prenewparent, postnewparent); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, +                loc_t *newloc) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, newloc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_rename_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->rename, oldloc, newloc); +        return 0; +err: +        STACK_UNWIND_STRICT (rename, frame, -1, ENOMEM, NULL, +                                NULL, NULL, NULL, NULL); + +        return 0; +} + +int32_t +marker_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) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "%s occured while " +                        "truncating a file ", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno, prebuf, +                             postbuf); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_truncate_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->truncate, loc, offset); +        return 0; +err: +        STACK_UNWIND_STRICT (truncate, frame, -1, ENOMEM, NULL, NULL); + +        return 0; +} + +int32_t +marker_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) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "%s occured while " +                        "truncating a file ", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (ftruncate, frame, op_ret, op_errno, prebuf, +                             postbuf); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = marker_inode_loc_fill (fd->inode, &local->loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_ftruncate_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->ftruncate, fd, offset); +        return 0; +err: +        STACK_UNWIND_STRICT (ftruncate, frame, -1, ENOMEM, NULL, NULL); + +        return 0; +} + +int32_t +marker_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                     int32_t op_ret, int32_t op_errno, inode_t *inode, +                     struct iatt *buf, struct iatt *preparent, +                     struct iatt *postparent) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "%s occured while " +                        "creating symlinks ", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (symlink, frame, op_ret, op_errno, inode, buf, +                             preparent, postparent); + +        update_marks (this, local, ret); + +        return 0; +} + +int +marker_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, +                 loc_t *loc, dict_t *params) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_symlink_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->symlink, linkpath, loc, params); +        return 0; +err: +        STACK_UNWIND_STRICT (symlink, frame, -1, ENOMEM, NULL, +                                NULL, NULL, NULL); +        return 0; +} + +int32_t +marker_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                   int32_t op_ret, int32_t op_errno, inode_t *inode, +                   struct iatt *buf, struct iatt *preparent, +                   struct iatt *postparent) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "%s occured while " +                        "creating symlinks ", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (mknod, frame, op_ret, op_errno, inode, +                             buf, preparent, postparent); + +        update_marks (this, local, ret); + +        return 0; +} + +int +marker_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, +               dev_t rdev, dict_t *parms) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_mknod_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, parms); +        return 0; +err: +        STACK_UNWIND_STRICT (mknod, frame, -1, ENOMEM, NULL, +                             NULL, NULL, NULL); +        return 0; +} + +/* when a call from the special client is received on + * key trusted.glusterfs.volume-mark with value "RESET" + * or if the value is 0length, update the change the + * access time and modification time via touching the + * timestamp file. + */ +int32_t +call_from_sp_client_to_reset_tmfile (call_frame_t *frame, +                                     xlator_t     *this, +                                     dict_t       *dict) +{ +        int32_t          fd       = 0; +        int32_t          op_ret   = 0; +        int32_t          op_errno = 0; +        data_t          *data     = NULL; +        marker_conf_t   *priv     = NULL; + +        if (frame == NULL || this == NULL || dict == NULL) +                return -1; + +        priv = this->private; + +        data = dict_get (dict, "trusted.glusterfs.volume-mark"); +        if (data == NULL) +                return -1; + +        if (frame->root->pid != -1) { +                op_ret = -1; +                op_errno = EPERM; + +                goto out; +        } + +        if (data->len == 0 || (data->len == 5 && +            memcmp (data->data, "RESET", 5) == 0)) { +                fd = open (priv->timestamp_file, O_WRONLY); +                if (fd != -1) { +                        /* this call is needed because of the unsurity +                         * whether the O_TRUNC would update the timestamps +                         * on a zero length file as well. Hence updating it +                         * manually. +                         */ +                        futimens (fd, NULL); +                        close (fd); +                } + +                if (fd != -1 || errno == ENOENT) { +                        op_ret = 0; +                        op_errno = 0; +                } else { +                        op_ret = -1; +                        op_errno = errno; +                } +        } else { +                op_ret = -1; +                op_errno = EINVAL; +        } +out: +        STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno); + +        return 0; +} + +int32_t +marker_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                      int32_t op_ret, int32_t op_errno) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "%s occured while " +                        "creating symlinks ", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, +                  int32_t flags) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ret = call_from_sp_client_to_reset_tmfile (frame, this, dict); +        if (ret == 0) +                return 0; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_setxattr_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->setxattr, loc, dict, flags); +        return 0; +err: +        STACK_UNWIND_STRICT (setxattr, frame, -1, ENOMEM); + +        return 0; +} + +int32_t +marker_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                       int32_t op_ret, int32_t op_errno) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "%s occured while " +                        "creating symlinks ", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, +                   int32_t flags) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ret = call_from_sp_client_to_reset_tmfile (frame, this, dict); +        if (ret == 0) +                return 0; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = marker_inode_loc_fill (fd->inode, &local->loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_fsetxattr_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags); +        return 0; +err: +        STACK_UNWIND_STRICT (fsetxattr, frame, -1, ENOMEM); + +        return 0; +} + +int32_t +marker_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                      int32_t op_ret, int32_t op_errno, struct iatt *statpre, +                      struct iatt *statpost) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "%s occured while " +                        "creating symlinks ", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (fsetattr, frame, op_ret, op_errno, statpre, +                             statpost); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, +                  struct iatt *stbuf, int32_t valid) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = marker_inode_loc_fill (fd->inode, &local->loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_fsetattr_cbk, FIRST_CHILD (this), +                    FIRST_CHILD (this)->fops->fsetattr, fd, stbuf, valid); +        return 0; +err: +        STACK_UNWIND_STRICT (fsetattr, frame, -1, ENOMEM, NULL, NULL); + +        return 0; +} + +int32_t +marker_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                     int32_t op_ret, int32_t op_errno, struct iatt *statpre, +                     struct iatt *statpost) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "%s occured while " +                        "creating symlinks ", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (setattr, frame, op_ret, op_errno, statpre, +                             statpost); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, +                 struct iatt *stbuf, int32_t valid) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_setattr_cbk, FIRST_CHILD (this), +                    FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid); +        return 0; +err: +        STACK_UNWIND_STRICT (setattr, frame, -1, ENOMEM, NULL, NULL); + +        return 0; +} + +int32_t +marker_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                         int32_t op_ret, int32_t op_errno) +{ +        int32_t             ret     = 0; +        marker_local_t     *local   = NULL; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "%s occured while " +                        "creating symlinks ", strerror (op_errno)); +                ret = -1; +        } + +        local = (marker_local_t *) frame->local; + +        frame->local = NULL; + +        STACK_UNWIND_STRICT (removexattr, frame, op_ret, op_errno); + +        update_marks (this, local, ret); + +        return 0; +} + +int32_t +marker_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, +                     const char *name) +{ +        int32_t          ret   = 0; +        marker_local_t  *local = NULL; + +        ALLOCATE_OR_GOTO (local, marker_local_t, err); + +        MARKER_INIT_LOCAL (frame, local); + +        ret = loc_copy (&local->loc, loc); + +        if (ret == -1) +                goto err; + +        STACK_WIND (frame, marker_removexattr_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->removexattr, loc, name); +        return 0; +err: +        STACK_UNWIND_STRICT (removexattr, frame, -1, ENOMEM); + +        return 0; +} + +int32_t +mem_acct_init (xlator_t *this) +{ +        int     ret = -1; + +        if (!this) +                return ret; + +        ret = xlator_mem_acct_init (this, gf_marker_mt_end + 1); + +        if (ret != 0) { +                gf_log(this->name, GF_LOG_ERROR, "Memory accounting init" +                                "failed"); +                return ret; +        } + +        return ret; +} + +int32_t +init (xlator_t *this) +{ +        dict_t        *options = NULL; +        data_t        *data    = NULL; +        int32_t        ret     = 0; +        marker_conf_t *priv    = NULL; + +        if (!this->children) { +                gf_log (this->name, GF_LOG_ERROR, +                        "marker translator needs subvolume defined."); +                return -1; +        } + +        if (!this->parents) { +                gf_log (this->name, GF_LOG_WARNING, +                        "Volume is dangling."); +                return -1; +        } + +        options = this->options; + +        ALLOCATE_OR_GOTO (this->private, marker_conf_t, err); + +        priv = this->private; + +        if( (data = dict_get (options, VOLUME_UUID)) != NULL) { +                priv->volume_uuid = data->data; + +                ret = uuid_parse (priv->volume_uuid, priv->volume_uuid_bin); +                if (ret == -1) { +                        gf_log (this->name, GF_LOG_ERROR, "invalid volume uuid %s", priv->volume_uuid); +                        goto err; +                } + +                ret = gf_asprintf (& (priv->marker_xattr), "%s.%s.%s", +                                   MARKER_XATTR_PREFIX, priv->volume_uuid, XTIME); + +                if (ret == -1){ +                        priv->marker_xattr = NULL; + +                        gf_log (this->name, GF_LOG_ERROR, +                                "Failed to allocate memory"); +                        goto err; +                } + +                gf_log (this->name, GF_LOG_DEBUG, +                        "the volume-uuid = %s", priv->volume_uuid); +        } else { +                priv->volume_uuid = NULL; + +                gf_log (this->name, GF_LOG_ERROR, +                        "please specify the volume-uuid" +                        "in the translator options"); + +                return -1; +        } + +        if ((data = dict_get (options, TIMESTAMP_FILE)) != NULL) { +                priv->timestamp_file = data->data; + +                gf_log (this->name, GF_LOG_DEBUG, +                        "the timestamp-file is = %s", +                        priv->timestamp_file); + +        } else { +                priv->timestamp_file = NULL; + +                gf_log (this->name, GF_LOG_ERROR, +                        "please specify the timestamp-file" +                        "in the translator options"); + +                goto err; +        } + +        return 0; +err: +        fini (this); + +        return -1; +} + +void +fini (xlator_t *this) +{ +        marker_conf_t *priv = NULL; + +        priv = (marker_conf_t *) this->private; + +        if (priv == NULL) +                goto out; + +        if (priv->volume_uuid != NULL) +                GF_FREE (priv->volume_uuid); + +        if (priv->timestamp_file != NULL) +                GF_FREE (priv->timestamp_file); + +        if (priv->marker_xattr != NULL) +                GF_FREE (priv->marker_xattr); + +        GF_FREE (priv); +out: +        return ; +} + +struct xlator_fops fops = { +        .create      = marker_create, +        .unlink      = marker_unlink, +        .link        = marker_link, +        .mkdir       = marker_mkdir, +        .rmdir       = marker_rmdir, +        .writev      = marker_writev, +        .rename      = marker_rename, +        .truncate    = marker_truncate, +        .ftruncate   = marker_ftruncate, +        .symlink     = marker_symlink, +        .mknod       = marker_mknod, +        .setxattr    = marker_setxattr, +        .fsetxattr   = marker_fsetxattr, +        .setattr     = marker_setattr, +        .fsetattr    = marker_fsetattr, +        .removexattr = marker_removexattr, +        .getxattr    = marker_getxattr +}; + +struct xlator_cbks cbks = { +}; + +struct volume_options options[] = { +        {.key = {"volume-uuid"}}, +        {.key = {"timestamp-file"}}, +        {.key = {NULL}} +}; diff --git a/xlators/features/marker/src/marker.h b/xlators/features/marker/src/marker.h new file mode 100644 index 00000000000..60567c3b828 --- /dev/null +++ b/xlators/features/marker/src/marker.h @@ -0,0 +1,65 @@ +/*Copyright (c) 2008-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 "xlator.h" +#include "defaults.h" +#include "uuid.h" + +#define MARKER_XATTR_PREFIX "trusted.glusterfs" +#define XTIME               "xtime" +#define VOLUME_MARK         "volume-mark" +#define VOLUME_UUID         "volume-uuid" +#define TIMESTAMP_FILE      "timestamp-file" + +/*initialize the local variable*/ +#define MARKER_INIT_LOCAL(_frame,_local) do {                   \ +                _frame->local = _local;                         \ +                _local->pid = _frame->root->pid;                \ +                memset (&_local->loc, 0, sizeof (loc_t));       \ +        } while (0) + +/* try alloc and if it fails, goto label */ +#define ALLOCATE_OR_GOTO(var, type, label) do {                  \ +                var = GF_CALLOC (sizeof (type), 1,               \ +                                 gf_marker_mt_##type);           \ +                if (!var) {                                      \ +                        gf_log (this->name, GF_LOG_ERROR,        \ +                                "out of memory :(");             \ +                        goto label;                              \ +                }                                                \ +        } while (0) + +struct marker_local{ +        uint32_t        timebuf[2]; +        pid_t           pid; +        loc_t           loc; +}; +typedef struct marker_local marker_local_t; + +struct marker_conf{ +        char        *volume_uuid; +        uuid_t      volume_uuid_bin; +        char        *timestamp_file; +        char        *marker_xattr; +}; +typedef struct marker_conf marker_conf_t;  | 
